| Author: | Евгений Охотников |
|---|---|
| Contact: | eao197 at intervale dot ru; eao197 at yahoo dot com |
| Version: | 0.1 |
| Date: | 2007.11.25 |
Данный текст появился в результате пересечения двух идей:
В текущей версии SObjectizer 4.4.0 многопоточную работу агента можно обеспечить только за счет преобразования его событий в insend-события. Такие события гарантированно вызываются внутри so_4::api::send_msg() на контексте той нити, которая обращается к send_msg(). Это приведет к тому, что если несколько агентов на своих нитях отсылают сообщения ключевому агенту, то события ключевого агента стартуют параллельно на контексте каждого инициатора сообщения.
У решения с insend-событиями есть свои минусы:
Примечание. Данное предложение является всего лишь первым шагом в решении описанной выше задачи. Здесь обозначенны лишь общие наметки предполагаемого подхода. Поэтому с течением времени возможен серьезный пересмотр и переработка изложенных ниже идей.
Суть предлагаемого подхода в том, чтобы позволить регистрировать в SObjectizer нескольких одинаковых агентов под одним именем. При этом агенты должны быть полностью одинаковыми -- принадлежать одному типу и выполнять одинаковую подписку.
Каждому из агентов-близнецов SObjectizer выделяет собственный контекст. При этом предполагается, что контекст для близнецов может предоставлять специальный диспетчер, обеспечивающий пассивным агентам не одну, а N рабочих нитей.
Когда агентам-близнецам по их общему имени отсылается сообщение, то возможны следующие результаты:
Управлять способами доставки сообщений агентам-близнецам должен специальный объект-балансировщик. Этот объект реализуется разработчиком агентов-близнецов в соответствии с логикой работы близнецов.
Библиотека MBAPI содержит специального агента-маршрутизатора mbapi-сообщений. Этот агент отвечает за:
Как раз работу по сериализации и отсылке результирующих сообщений в коммуникационные каналы могут выполнять агенты-близнецы. Для этого нужно, чтобы объект-балансировщик доставлял им исходные mbapi-сообщение поочереди.
Аналогичная ситуация и с сообщением msg_client_connected с информацией о появлении очередного коммуникационного канала. Его достаточно доставить любому из близнецов, чтобы он отослал в канал список локальных mbox-ов.
Однако, такие сообщения, как msg_client_disconnected (о закрытии коммуникационного канала), список удаленных mbox-ов или сообщение о появлении/исчезновении локального mbox-а, должны доставляться сразу всем агентам-близнецам. Тогда все они смогут поддерживать одинаковые копии таблиц маршрутизации, хотя это и будут собственные копии каждого агента-близнеца.
Если приложение серьезно использует криптографические механизмы, особенно на основе ассиметричной криптографии, то для выполнения ряда криптографических операций может быть выделен специальный агент, в задачи которого может входить:
При большом потоке запросов к этому агенту он легко может стать узким местом. Поэтому такой криптографический агент может быть заменен несколькими агентами-близнецами, нагрузка на которых будет балансироваться.
В случае использования специализированных криптоустройств, подключаемых тем или иным образом к компьютеру (SmartCard, HSM, крипто-платы), количество криптографических агентов-близнецов может выбираться исходя из количества доступных криптоустройств, а не из количества ядер/процессоров.
Ниже приводятся некоторые предварительные соображения о том, как работа с агентами-близнецами может выглядеть на уровне программного кода.
При регистрации агентов-близнецов SObjectizer нужно будет передать объект, реализующий следующий интерфейс:
class twin_agents_controller_t
{
public :
//! Создание нужного количества агентов-близнецов.
/*!
* Может быть создано любое их количество.
* Аргумент desired_count задает только оптимальное с
* точки зрения диспетчера число.
*/
virtual std::vector< so_4::rt::agent_t * >
create(
//! Общее имя для создаваемых агентов.
const std::string & common_name,
//! Оптимальное с точки зрения диспетчера число агентов-близнецов.
unsigned int desired_count ) = 0;
//! Выбор получателя очередного сообщения.
/*!
* Этот метод вызывается при получении сообщения, которое
* адресуется кому-то из агентов-близнецов.
*
* Данный метод отвечает за выбор конкретного агента, который будет
* обрабатывать данное сообщение. Метод может выбрать любого агента
* или всех агентов сразу.
*/
virtual std::vector< so_4::rt::agent_t * >
select_message_target(
//! Описание сообщения.
const message_routing_info_t & message,
//! Список агентов-близнецов, из которых нужно делать выбор.
const std::vector< so_4::rt::agent_t * > & twins_list ) = 0;
};
При этом SObjectizer будет поступать с агентами-близнецами следующим образом.
Подобный подход обеспечивает прозрачность агентов-близнецов для:
Единственное место, которое знает детали работы агентов-близнецов -- это место создания twin_agents_controller_t и регистрация агентов-близнецов в SObjectizer.