2012-07-05 3 views
5

Я недавно работал над генератором динамических изображений aspx в C#, который в своем самом базовом состоянии принимает значение querystring из «t» и записывает эту строку в изображение, а затем возвращает JPG.C# Image Generator - медленная производительность

Он работал безупречно локально, а на тестовом сервере - изображения возвращались мгновенно.

Но когда на балансированных нагрузкой живых серверах иногда работает нормально. Но чаще, чем часто, время истекает/занимает минуту, чтобы вернуть изображение.

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

Ниже очень обтекаемый вариант генератора (который также имеет те же проблемы тайм-аута)

protected void Page_Load(object sender, EventArgs e) 
{ 

    // Set global stage dimensions 
    const int stageWidth = 500; 
    const int stageHeight = 200; 

    // Create Bitmap placeholder for new image  
    Bitmap createdImage = new Bitmap(stageWidth, stageHeight); 

    // Draw new blank image 
    Graphics imageCanvas = Graphics.FromImage(createdImage); 

    // Add text 
    if (!string.IsNullOrEmpty(Request.QueryString["t"])) 
    { 
     string imageText = Uri.UnescapeDataString(Request.QueryString["t"]).Trim(); 
     Font font = new Font("Arial", 22); 
     imageCanvas.DrawString(imageText, font, Brushes.White, 0, 0);    
    } 

    // Save 
    MemoryStream memStream = new MemoryStream(); 
    createdImage.Save(memStream, ImageFormat.Jpeg); 
    imageCanvas.Dispose(); 
    createdImage.Dispose(); 

    // Set filename/image format 
    Response.AppendHeader("content-disposition", "filename=MyImage"); 
    Response.ContentType = "image/jpeg";   

    // Send output to client 
    memStream.WriteTo(Response.OutputStream); 
    memStream.Dispose(); 
    Response.Flush(); 
} 
+0

Это тайм-аут на серверах * из-за большой нагрузки *? Свет сервера загружается? Вы подчеркивали это на своем локальном сервере? –

+8

Кроме того, заверните все, что реализует 'IDisposable' в блоке' using'. Если исключение вызывается по какой-либо причине, прежде чем вы вызываете '.Dispose()', вы будете утечка ресурсов ... что было бы плохо при загрузке. –

+2

Он не объясняет тайм-ауты, но я использовал бы простой HttpHandler для этого вместо использования экземпляра страницы, и, если вы не делаете что-то необычное, вам, вероятно, не нужен вызов UnescapeDataString. – bmm6o

ответ

3

Есть некоторые вещи, которые я буду менять:

  • Surrond потоки с использование ключевого слова using.
  • Вместо этого используйте обработчик ashx. Похоже, вы используете файл aspx. Для такого рода сценариев лучше использовать обработчик http, поскольку он имеет меньший жизненный цикл. Я использовал это много раз, чтобы показывать миниатюры изображений.
  • Используйте некоторое кэширование. Возможно, вы можете воспользоваться преимуществами кеш-функций asp.net, вы можете узнать, есть ли повторяющиеся значения для t, поэтому вы сохраняете полученное изображение в кеше и избегаете записи и создания некоторых пар каждый раз
  • Последнее, но не менее важное , попробуйте проверить, имеет ли сервер последние обновления и обновления. В некоторых случаях приложение будет вести себя странно, если есть определенные пропуски обновлений,

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

Надеюсь, это поможет.

1

Вы можете сэкономить память и, возможно, получить производительность за счет экономии непосредственно в выходной поток вместо того, чтобы использовать поток памяти:

createdImage.Save(Response.OutputStream, ImageFormat.Jpeg); 

Другой вопрос, может быть, что ваш код на странице .aspx. Это может быть перекомпилировано слишком часто. Я хотел бы предложить http-обработчик:

public class MyHttpHandler : IHttpHandler 
{ 
    public void ProcessRequest(HttpContext context) 
    { 
     // prepare image like you did 
     memStream.WriteTo(context.Response.OutputStream); 
    } 

    // Override the IsReusable property. 
    public bool IsReusable 
    { 
     get { return true; } 
    } 
} 
Смежные вопросы