2016-07-11 1 views
0

У меня есть приложение, которое запускает запланированные задачи на Azure Service Fabric. Мое приложение должно запускать от тридцати до сорока задач одновременно, поэтому я использую асинхронное программирование. У меня есть некоторые вопросы:Azure Service Fabric Scaling

Вы рекомендуете выполнять задачи асинхронно? Если нет, должен ли я запускать задачу синхронно и масштабироваться? Как увеличить масштаб? Мне не нужно возвращать информацию из запуска задачи.

Должен ли я разделять очередность и удаление в отдельные службы с сохранением состояния? Если да, то как эти службы будут общаться друг с другом?

Вот мой код:

internal sealed class JMATaskRunner : StatefulService 
    { 
    public JMATaskRunner(StatefulServiceContext context) 
     : base(context) 
    { } 

    /// <summary> 
    /// Optional override to create listeners (e.g., HTTP, Service Remoting, WCF, etc.) for this service replica to handle client or user requests. 
    /// </summary> 
    /// <remarks> 
    /// For more information on service communication, see http://aka.ms/servicefabricservicecommunication 
    /// </remarks> 
    /// <returns>A collection of listeners.</returns> 
    protected override IEnumerable<ServiceReplicaListener> CreateServiceReplicaListeners() 
    { 
     return new ServiceReplicaListener[0]; 
    } 


    public async Task<List<JMATask>> GetMessagesAsync() 
    { 
     await AddTasks(); 

     List<JMATask> ts = new List<JMATask>(); 

     IReliableQueue<JMATask> tasks = 
      await this.StateManager.GetOrAddAsync<IReliableQueue<JMATask>>("JMATasks"); 

     using (ITransaction tx = this.StateManager.CreateTransaction()) 
     { 
      var messagesEnumerable = await tasks.CreateEnumerableAsync(tx); 

      using (var enumerator = messagesEnumerable.GetAsyncEnumerator()) 
      { 
       while (await enumerator.MoveNextAsync(CancellationToken.None)) 
       { 
        ts.Add(enumerator.Current); 
       } 
      } 
     } 

     return ts; 
     //return messagesEnumerable.ToList(); 
    } 

    public async Task AddMessageAsync(JMATask task) 
    { 
     IReliableQueue<JMATask> tasks = 
      await this.StateManager.GetOrAddAsync<IReliableQueue<JMATask>>("JMATasks"); 

     using (ITransaction tx = this.StateManager.CreateTransaction()) 
     { 
      await tasks.EnqueueAsync(tx, task); 
      await tx.CommitAsync(); 
     } 
    } 

    /// <summary> 
    /// This is the main entry point for your service replica. 
    /// This method executes when this replica of your service becomes primary and has write status. 
    /// </summary> 
    /// <param name="cancellationToken">Canceled when Service Fabric needs to shut down this service replica.</param> 
    protected override async Task RunAsync(CancellationToken cancellationToken) 
    { 
     // TODO: Replace the following sample code with your own logic 
     //  or remove this RunAsync override if it's not needed in your service. 

     IReliableQueue<JMATask> tasks = 
      await this.StateManager.GetOrAddAsync<IReliableQueue<JMATask>>("JMATasks"); 

     while (true) 
     { 
      cancellationToken.ThrowIfCancellationRequested(); 

      var messagesEnumerable = await GetMessagesAsync(); 

      using (ITransaction tx = this.StateManager.CreateTransaction()) 
      { 
       foreach (var message in messagesEnumerable) 
       { 
        var result = await tasks.TryDequeueAsync(tx); 
        await PerformTask(result.Value); 
       } 

       await tx.CommitAsync(); 
       await Task.Delay(TimeSpan.FromSeconds(2), cancellationToken); 
      } 
     } 


    } 

    async Task<JMATask> PerformTask(JMATask task) 
    { 
     await Task.Run(() => Perform(task)); 
     return task; 
    } 

    void Perform(JMATask task) 
    { 
     Thread.Sleep(50000); 
    } 

    async Task<JMATask> AddTasks() 
    { 
     m_TaskProvider = JMATaskFactory.Get(conString); 

     //List<JMATask> tasks = m_TaskProvider.GetAllTasks(); 

     //foreach(JMATask task in tasks) 
     //{ 
     // await AddMessageAsync(task); 
     //} 

     JMATask task = m_TaskProvider.GetJMATask(80); 
     JMATask task2 = m_TaskProvider.GetJMATask(97); 

     await AddMessageAsync(task); 
     await AddMessageAsync(task2); 
     return new JMATask(); 
    } 
} 

ответ

1

Для обслуживания ткани (и других систем актерской основы), вы обычно хотите масштабирования в отличие от расширения [Scaling Up против Scaling Out] см. (http://www.vtagion.com/scalability-scale-up-scale-out-care/)

Azure Article при масштабировании вверх и вниз (небольшое неправильное обозначение).

По сути, сервис ткань берет на себя большую часть забот вокруг отказа, балансировки нагрузки и т.д.

В документации о том, как масштабировать кластеры хорошо стоит читать.

Документация по адресу reliable actors также входит в «потолочную» модель системы, которая, по сути, является асинхронной.

+0

Считаете ли вы, что я должен использовать шаблон актера в своем программном обеспечении? –

+0

@ Сервисная ткань @JosephAnderson построена на шаблоне актера под капотом, вы даже можете использовать свои встроенные типы актеров! – Clint

+1

Актерский шаблон поддерживается в Service Fabric, но это надежные услуги. Оба являются действительными подходами, и один из них действительно полагается на то, что вам нужно выполнить. Прежде чем совершать этот звонок, я предлагаю прочитать актеры в сервисе Fabric по адресу https://azure.microsoft.com/en-us/documentation/articles/service-fabric-reliable-actors-introduction/. – MikeWo

1

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

Service Fabric позволяет вам очень быстро масштабировать рабочие нагрузки на разных машинах - подумайте о своих машинах как о пуле ресурсов. Если каждая виртуальная машина имеет 4 физических потока, то с 5 машинами вы можете иметь пул из 20 физических потоков.

Способ сделать это с помощью секционированного обслуживания с сохранением состояния. Каждый раздел службы обрабатывает подмножество общей рабочей нагрузки, которая распределяется на основе ключа раздела для каждой создаваемой единицы работы. См. Здесь, чтобы начать разбиение: https://azure.microsoft.com/en-us/documentation/articles/service-fabric-concepts-partitioning/

+0

Но что делать, если мне нужно все данные в одном месте в один момент? Должен ли я проходить через все разделы, получать данные из каждого и объединять их в другом месте? Если да, будет ли это немного медленнее? Я имею в виду, чтобы передавать данные со всех места для одного. – cassandrad

+0

Возможно, вы неправильно определили проблему? В идеале каждая задача должна быть изолирована от любой другой задачи, и все, что вам нужно сделать, это отправить простой результат в службу слияния или редуктора, которая отвечает за объединение результатов. пример в документации для расчета PI, который может помочь. –

+0

@NickRandell, спасибо, Ник. Это то, что я хотел знать - мне нужно слияние или есть другой способ сделать это правильно. – cassandrad

0

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

 Смежные вопросы

  • Нет связанных вопросов^_^