Как создать веб-сервер изображения?

Мне нужен был WrapPanel, который может растягивать его содержимое, поэтому на основе https://stackoverflow.com/a/7747002/121122 и некоторой тряски я придумал это:

public class AlignableWrapPanel : Panel
{
    public HorizontalAlignment HorizontalContentAlignment
    {
        get => (HorizontalAlignment)GetValue(HorizontalContentAlignmentProperty);
        set => SetValue(HorizontalContentAlignmentProperty, value);
    }

    public static readonly DependencyProperty HorizontalContentAlignmentProperty = DependencyProperty.Register(
        nameof(HorizontalContentAlignment),
        typeof(HorizontalAlignment),
        typeof(AlignableWrapPanel),
        new FrameworkPropertyMetadata(HorizontalAlignment.Left, FrameworkPropertyMetadataOptions.AffectsArrange));

    protected override Size MeasureOverride(Size constraint)
    {
        var curLineSize = new Size();
        var panelSize = new Size();

        var children = InternalChildren;

        for (var i = 0; i < children.Count; i++)
        {
            var child = children[i];

            // flow passes its own constraint to children
            child.Measure(constraint);
            var sz = child.DesiredSize;

            if (curLineSize.Width + sz.Width > constraint.Width) // need to switch to another line
            {
                panelSize.Width = Math.Max(curLineSize.Width, panelSize.Width);
                panelSize.Height += curLineSize.Height;
                curLineSize = sz;

                if (sz.Width > constraint.Width) // if the element is wider then the constraint - give it a separate line                    
                {
                    panelSize.Width = Math.Max(sz.Width, panelSize.Width);
                    panelSize.Height += sz.Height;
                    curLineSize = new Size();
                }
            }
            else // continue to add to the line
            {
                curLineSize.Width += sz.Width;
                curLineSize.Height = Math.Max(sz.Height, curLineSize.Height);
            }
        }

        // the last line size, if any need to be added
        panelSize.Width = Math.Max(curLineSize.Width, panelSize.Width);
        panelSize.Height += curLineSize.Height;

        return panelSize;
    }

    protected override Size ArrangeOverride(Size arrangeBounds)
    {
        var firstInLine = 0;
        var curLineSize = new Size();
        var accumulatedHeight = 0D;
        var children = InternalChildren;

        for (var i = 0; i < children.Count; i++)
        {
            var desiredSize = children[i].DesiredSize;

            if (curLineSize.Width + desiredSize.Width > arrangeBounds.Width) // need to switch to another line
            {
                ArrangeLine(accumulatedHeight, curLineSize, arrangeBounds.Width, firstInLine, i);

                accumulatedHeight += curLineSize.Height;
                curLineSize = desiredSize;

                if(
                    desiredSize.Width > arrangeBounds.Width || 
                    children[i] is FrameworkElement element && element.HorizontalAlignment == HorizontalAlignment.Stretch)
                {
                    // the element is wider then the constraint or it stretches - give it a separate line
                    ArrangeLine(accumulatedHeight, desiredSize, arrangeBounds.Width, i, ++i);
                    accumulatedHeight += desiredSize.Height;
                    curLineSize = new Size();
                }
                firstInLine = i;
            }
            else // continue to add to the line
            {
                curLineSize.Width += desiredSize.Width;
                curLineSize.Height = Math.Max(desiredSize.Height, curLineSize.Height);
            }
        }

        if (firstInLine < children.Count)
        {
            ArrangeLine(accumulatedHeight, curLineSize, arrangeBounds.Width, firstInLine, children.Count);
        }

        return arrangeBounds;
    }

    private void ArrangeLine(double y, Size lineSize, double boundsWidth, int start, int end)
    {
        var children = InternalChildren;

        var x = 0D;
        if (HorizontalContentAlignment == HorizontalAlignment.Center)
        {
            x = (boundsWidth - lineSize.Width) / 2;
        }
        else if (HorizontalContentAlignment == HorizontalAlignment.Right)
        {
            x = boundsWidth - lineSize.Width;
        }

        var stretchChildren = new List();
        for (var i = start; i < end; i++)
        {
            var child = children[i];
            if (child is FrameworkElement element && element.HorizontalAlignment == HorizontalAlignment.Stretch)
            {
                stretchChildren.Add(child);
            }
        }

        var spaceAvailableForStretchChildren = boundsWidth - lineSize.Width;
        var spaceAvailablePerStretchChild = 0D;
        if (stretchChildren.Any())
        {
            x = 0; // all available space will be filled so start at 0
            spaceAvailablePerStretchChild = spaceAvailableForStretchChildren / stretchChildren.Count;
            spaceAvailablePerStretchChild = spaceAvailablePerStretchChild >= 0 ? spaceAvailablePerStretchChild : 0;
        }

        for (var i = start; i < end; i++)
        {
            var child = children[i];
            double itemWidth;
            if(stretchChildren.Contains(child))
            {
                itemWidth = child.DesiredSize.Width + spaceAvailablePerStretchChild;
            }
            else
            {
                itemWidth = child.DesiredSize.Width;
            }

            child.Arrange(new Rect(x, y, itemWidth, lineSize.Height));
            x += itemWidth;
        }
    }
}

11
задан Eric 9 June 2009 в 21:50
поделиться

4 ответа

Определенно найдите хорошую службу доставки. Наиболее известен Akamai.

Если вы действительно хотите сделать это самостоятельно, забудьте об Apache / IIS. гораздо более подходящими являются «легкие» веб-серверы. Два очень хороших - это lighthttp и NginX ( wiki ). В частности, NginX имеет действительно солидную производительность.

Править : Сети распространения контента (CDN) процветают в последние несколько лет, и гораздо проще найти более простые и дешевые. В частности, довольно просто разместить статический контент в Amazon S3 и использовать CloudFront .

8
ответ дан 3 December 2019 в 08:31
поделиться

Если вы хотите создать самый быстрый веб-сервер статических файлов с наименьшей задержкой, вот как я бы это сделал.

  1. Используйте цикл событий, чтобы определить, какие сокеты готовы.
  2. Поместите эти сокеты in a queue
  3. Создайте стек потоков для работы с сокетами (по 1 на каждое ядро). Когда они закончат, поместите их обратно в стек.
  4. Назначьте работу потокам.
  5. Кэшируйте все файлы изображений в памяти.

По сути, это порты завершения ввода-вывода без кэширования файлов. Эта модель доступна в Windows и Solaris.

http://technet.microsoft.com/en-us/sysinternals/bb963891.aspx

alt text
(источник: microsoft.com )

3
ответ дан 3 December 2019 в 08:31
поделиться

С таким количеством клиентов, вы можете изучить возможность использования сети доставки контента (например, Akamai). На первый взгляд это может показаться дорогим, но если вы действительно посмотрите на стоимость обслуживания оборудования и, в частности, на стоимость полосы пропускания, это начинает иметь экономический смысл.

2
ответ дан 3 December 2019 в 08:31
поделиться

Как подавать изображения? Изображения генерируются на лету? или они статичны и хранятся в файловой системе как .jpg или другой формат?

В любом случае, я бы использовал ASP.NET .ashx (общие обработчики) и классы System.Drawing.

Вы будете также хотите настроить балансировку сетевой нагрузки TCP / IP для http://support.microsoft.com/kb/323431

1
ответ дан 3 December 2019 в 08:31
поделиться
Другие вопросы по тегам:

Похожие вопросы: