2016-06-27 10 views
1

В моем api (C#), я в настоящее время отвечаю на большой запрос (15-20 секунд). Теперь я хочу отправить данные в центр событий для некоторых целей. Но я не хочу задерживать пользователя для отправки данных в концентратор событий azure. Так что мне нужно сделать запрос async на хаб хау событий, пока мое приложение отправляет данные в azure, я не хочу, чтобы пользователь ждал моего ответа. Мне нужно отправить ответ как можно быстрее, лазурь может длиться 2-3 секунды.отправить async azure event hub data method

Как я могу добиться успеха? Я сделал что-то, но не получил то, что хочу. Мой код:

public static async Task<string> SendEvents(List<object> messages) 
{ 
    string eventHubName = "rcmds"; 

    var connectionString = GetServiceBusConnectionString(); 

    CreateEventHub(eventHubName, connectionString); 

    var eventHubClient = EventHubClient.CreateFromConnectionString(connectionString, eventHubName); 

    try 
    { 
     List<Task> tasks = new List<Task>(); 

     for (int i = 0; i < messages.Count; i++) 
     { 
      var serializedMessage = JsonConvert.SerializeObject(messages[i]); 

      EventData data = new EventData(Encoding.UTF8.GetBytes(serializedMessage)); 

      // Mesajları Event Hub a yolla 
      tasks.Add(eventHubClient.SendAsync(data)); 
     } 

     Task.WaitAll(tasks.ToArray()); 
     System.Threading.Thread.Sleep(7000); 
    } 
    catch (Exception ex) 
    { 
     new ExceptionHandler(ex, "Event Hub Library Sender - SendEvents"); 
    } 
    finally 
    { 
     eventHubClient.CloseAsync().Wait(); 
    } 
    return ""; 
} 

и я называю этот метод, как:

static async void method() 


{ 
      List<object> list = new List<object>(); 
      list.Add("dogrudur"); 
      await Utilities.EventHub.Sender.SendEvents(list); 
     } 

Как вы можете видеть, есть "thread.sleed" код, но я ждал 7 секунд:/

ответ

0

Я думаю, вам нужно узнать больше о том, как реально использовать async/await в хорошей манере. Вы смешиваете асинхронный код с кодом блокировки.

Правильный код должен быть что-то вроде этого:

public static async Task<string> SendEvents(List<object> messages) 
{ 
    string eventHubName = "rcmds"; 

    var connectionString = GetServiceBusConnectionString(); 

    CreateEventHub(eventHubName, connectionString); 

    var eventHubClient = EventHubClient.CreateFromConnectionString(connectionString, eventHubName); 

    try 
    { 
     List<Task> tasks = new List<Task>(); 

     for (int i = 0; i < messages.Count; i++) 
     { 
      var serializedMessage = JsonConvert.SerializeObject(messages[i]); 

      EventData data = new EventData(Encoding.UTF8.GetBytes(serializedMessage)); 

      // Mesajları Event Hub a yolla 
      tasks.Add(eventHubClient.SendAsync(data)); 
     } 

     await Task.WhenAll(tasks.ToArray()); 
     System.Threading.Thread.Sleep(7000); 
    } 
    catch (Exception ex) 
    { 
     new ExceptionHandler(ex, "Event Hub Library Sender - SendEvents"); 
    } 
    finally 
    { 
     await eventHubClient.CloseAsync(); 
    } 

    return ""; 
} 

Вызывающий код должен быть:

static async Task method() 
{ 
     List<object> list = new List<object>(); 
     list.Add("dogrudur"); 
     await Utilities.EventHub.Sender.SendEvents(list); 
    } 

Теперь вернемся к вопросу. Текущий код ожидает до тех пор, пока все сообщения не будут отправлены в концентратор событий и не будет спать в течение 7 секунд. В методе вы ожидаете метод SendEvents, поэтому, конечно, ваше приложение займет 7 секунд + время, необходимое для отправки данных в концентратор событий.

Что вы можете сделать, это реализовать какой-то механизм огня и забывания. Удалите Thread.Sleep в коде и изменить метод вызова, как это:

static void method() 
{ 
    List<object> list = new List<object>(); 
    list.Add("dogrudur"); 
    Utilities.EventHub.Sender.SendEvents(list); 
} 

Метод теперь будет больше ждать, прежде чем продолжить, но взамен вы никогда не будете знать, когда событие, отправка будет завершена. В общем, следует избегать методов огня и забывания.

Еще один важный шаг, который вы можете предпринять для повышения производительности, - это отправить события пакетами. В настоящее время каждое событие отправляется с использованием eventHubClient.SendAsync, но есть также метод eventHubClient.SendBatchAsync (https://msdn.microsoft.com/en-us/library/microsoft.servicebus.messaging.eventhubclient.sendbatchasync.aspx), поэтому вместо отправки большого количества небольших сообщений вы можете отправлять меньше сообщений большего размера, чем более одного события. Помните, что есть максимальный размер сообщения.

Для примера осуществления отправки события с использованием партии см метода private async Task SendAutoSizedBatchAsync(IEnumerable collection) в этом файле https://github.com/DeHeerSoftware/SemanticLogging.EventHub/blob/master/SemanticLogging.EventHub/EventHubAmqpSink.cs