Есть ли способ присвоить номер int различным экземплярам служб без сохранения состояния?

Я создаю решение, в котором у нас будет служба без сохранения состояния (service-fabric), развернутая на K экземплярах. На эту службу возложена некоторая рабочая нагрузка (например, запросы), и я хочу разделить рабочую нагрузку между ними как можно более равномерно, и я хочу сделать это динамическим решением, что означает, если я решу завтра перейти от K экземпляров к N экземплярам , я хочу, чтобы разделение рабочей нагрузки происходило таким образом, чтобы теперь нагрузка автоматически распределялась между N экземплярами. У меня нет разделов, указанных для этой службы.

В качестве примера -

Допустим, я хочу запросить базу данных для получения определенного фрагмента записей. У меня 5 узлов. Я хочу, чтобы эти 5 узлов извлекали разные 1/5 набора записей. Этого можно добиться с помощью некоторой логики запроса, например (row_id % N == K), где N — общее количество экземпляров, а K — уникальный instance_number.

Я надеялся использовать FabricRuntime.GetNodeContext().NodeId, но это возвращает руководство, которое не слишком полезно.

Я ищу способ, где я могу детерминистически сказать, что это номер экземпляра M из N (мне нужно иметь возможность называть экземпляры через 1..N) - поэтому я могу установить свою логику запроса в соответствии с этим. Одним из требований является то, что если этот экземпляр выходит из строя / дает сбой и т. д., когда SF автоматически перезапускает его, он все равно должен идентифицироваться как один и тот же идентификатор экземпляра, чтобы 2 или более узлов не запрашивали один и тот же набор результатов.

Что лучше всего решает эту проблему? Есть ли решение, предполагающее чистую настройку через ApplicationManifest.xml или ServiceManifest.xml?


person Mavi Domates    schedule 19.12.2018    source источник


Ответы (1)


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

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

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

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

Поэлементно, вы помещаете одно сообщение в очередь для каждого обрабатываемого элемента, это простой способ обработки работы, и каждый экземпляр обрабатывает одно сообщение за раз или несколько сообщений параллельно.

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

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

Что касается проблемы с идентификатором, вариант может быть InstanceId реплики, на которой вы находитесь, вы можете получить с помощью StatelessService.Context.InstanceId, это не последовательный идентификатор, а случайное число. Это лучше, чем использовать идентификатор узла, потому что у вас может быть несколько разделов на одном узле, и идентификаторы будут конфликтовать друг с другом. Если вы решите использовать именованные разделы, вы можете вместо этого использовать порядок в имени раздела, чтобы каждый раздел имел последовательное имя.

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

person Diego Mendes    schedule 19.12.2018
comment
Спасибо за ответ Диего! Не возражаете ли вы добавить документацию по именованным разделам, потому что похоже, что мы могли бы назвать разделы и, по крайней мере, использовать эти имена для вывода 1..N. Я знаю о шаблонах Q / CC - это был первоначальный план, но из-за некоторых дополнительных ограничений я предпочитаю двигаться не с ними, а с этим дизайном. - person Mavi Domates; 19.12.2018
comment
Я почти уверен, что для этого нет документации, лучшее, что вы можете найти, это это. Это так же просто, как эта команда: Update-ServiceFabricService -Stateless -ServiceName "fabric:/app/service" -PartitionNamesToAdd "1","2","3" - person Diego Mendes; 19.12.2018