Как отслеживать, существует ли сервер ZeroMQ?

Я хочу проверить существование (состояние) сервера перед отправкой запроса ZeroMQ, но я понятия не имею, как это сделать.


person Yacheng Zhou    schedule 30.10.2019    source источник
comment
Отправьте приветственный запрос или просто пропингуйте сервер. Однако сетевые протоколы высокого уровня могут гарантировать или не гарантировать успешную доставку пакетов (например, TCP гарантирует, а UDP — нет).   -  person f4f    schedule 30.10.2019
comment
@f4f Вы, возможно, знаете, что ZeroMQ уже имеет интеллектуальное низкоуровневое сердцебиение обнаружение на уровне проводов RFC: ZMTP (скрыто) спецификация протокола. Добавление теста уровня L3/4 для обнаружения, но проверка видимости в пределах прямой видимости не, по-видимому, решает проблему обнаружения приложений. уровень Live-or-Dead Agent-test, так что это заставило меня серьезно усомниться в том, стоит ли когда-нибудь реализовывать что-то в направлении, которое вы предложили для продолжения O/P. Каковы, по вашему мнению, преимущества оплаты любых затрат за то, чтобы не получить ничего полезного, на что можно было бы положиться? Я что-то упустил?   -  person user3666197    schedule 31.10.2019
comment
Вы правильно заметили, что видимость на уровне приложения и на уровне сети совершенно разные. Но я понятия не имею о дизайне распределенной системы, используемом автором темы, поэтому просто упомянул, что разнообразие возможных решений сильно различается (чтобы услышать от него какие-то дополнительные требования или ограничения). Отправка данных, не зная, получены ли они, также может быть полезной. Например, используется для некоторых низкоуровневых датчиков и подключенных устройств (когда поток данных постоянный и дополнительная логика на стороне отправителя дорого обходится). Модель ZMQ PUB/SUB разработана примерно таким образом.   -  person f4f    schedule 31.10.2019


Ответы (2)


В : Я хочу проверить существование (состояние) сервера перед отправкой запроса ZeroMQ

Решение состоит в том, чтобы настроить и использовать службы zmq_socket_monitor()

// Read one event off the monitor socket; return value and address
// by reference, if not null, and event number by value. Returns -1
// in case of error.

static int
get_monitor_event ( void  *monitor,
                    int   *value,
                    char **address
                    )
{   
    zmq_msg_t msg;
    zmq_msg_init ( &msg );                                       // First frame in message contains event number and value
    if ( zmq_msg_recv ( &msg, monitor, 0 ) == -1 ) return -1;    // Interrupted, presumably
    assert ( zmq_msg_more ( &msg )              & "REASON: Frame #1 FAILED TO SIG 2nd, EXPECTED, FRAME TO COME" );

    uint8_t  *data  =  ( uint8_t  * ) zmq_msg_data ( &msg );
    uint16_t  event = *( uint16_t * ) ( data );

    if ( value )
        *value = *( uint32_t * ) ( data + 2 );


    zmq_msg_init ( &msg );                                      // Second frame in message contains event address
    if ( zmq_msg_recv ( &msg, monitor, 0 ) == -1 ) return -1;   // Interrupted, presumably
    assert ( !zmq_msg_more ( &msg )             & "REASON: Frame #2 FAILED TO SIG more, NOT EXPECTED, FRAMEs TO COME" );

    if ( address ) {
        uint8_t *data = ( uint8_t * ) zmq_msg_data ( &msg );
        size_t   size =               zmq_msg_size ( &msg );
        *address = ( char * ) malloc ( size + 1 );
        memcpy ( *address, data, size );
        ( *address )[size] = 0;
    }
    return event;
}

int main ( void )
{   
    void    *ctx = zmq_ctx_new ();
    assert ( ctx                                & "REASON: Context FAILED to instantiate" );

    void    *client = zmq_socket ( ctx, ZMQ_DEALER );
    assert ( client                             & "REASON: Socket FAILED to instantiate" );

 // Socket monitoring only works over inproc://
    int      rc = zmq_socket_monitor ( client, "inproc://monitor-client-side", ZMQ_EVENT_ALL );
    assert ( rc == 0                            & "REASON: socket_monitor FAILED to instantiate over INPROC:// transport-class" );

 // Create socket for collecting monitor events
    void    *client_side_mon = zmq_socket ( ctx, ZMQ_PAIR );
    assert ( client_side_mon                    & "REASON: socket_monitor receiving Socket FAILED to instantiate " );

 // Connect these to the inproc endpoints so they'll get events
             rc = zmq_connect ( client_side_mon, "inproc://monitor-client-side" );
    assert ( rc == 0                            & "REASON: .connect()-method FAILED to get connected" );

 // Now do whatever you need
    ...

 // Close client
    close_zero_linger ( client );

 // --------------------------------------------------------------------
 // How to collect and check events from socket_monitor:
    int  event =  get_monitor_event ( client_side_mon, NULL, NULL );

    if ( event == ZMQ_EVENT_CONNECT_DELAYED )
         event =  get_monitor_event ( client_side_mon, NULL, NULL );

    assert ( event == ZMQ_EVENT_CONNECTED       & "REASON: [client]-socket still not in an expected, .connect()-ed, state" );
    ...

    ...
    event = get_monitor_event ( client_side_mon, NULL, NULL );
    assert ( event == ZMQ_EVENT_MONITOR_STOPPED & "REASON: [client]-socket not in an expected, .close()-ed, state" );

 // --------------------------------------------------------------------
 // FINALLY:
 // --------------------------------------------------------------------
 // Close down the sockets
    close_zero_linger ( client_side_mon );

    zmq_ctx_term ( ctx );

    return 0;
    }

(входит в состав API начиная с версии 3.2+)

person user3666197    schedule 30.10.2019
comment
Я попытался использовать get_monitor_event для мониторинга клиента REQ в потоке и сделать это в цикле while, но похоже, что другие запросы к текущему процессу будут заблокированы. - person Yacheng Zhou; 30.10.2019
comment
Никогда не используйте вызов в режиме блокировки где-либо за пределами примера из школьного учебника - person user3666197; 30.10.2019

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

Н.Б. Если сокет не закрыт, сообщения могут накапливаться в очереди отправки ZMQ и рискуют переполнить сервер большим количеством сообщений ACK, когда сервер, наконец, подключится.

person John Jefferies    schedule 30.10.2019
comment
Вы уверены, что это рекомендуемая практика? ZeroMQ уже имеет интеллектуальное низкоуровневое сердцебиение обнаружение внутри RFC:ZMTP на уровне проводов (скрыто) спецификация протокола. Добавление сложности на уровне приложения для выполнения уже выполненной задачи, по-видимому, не корректирует затраты (и побочные эффекты) на это, поэтому это заставило меня серьезно усомниться в том, стоит ли когда-либо реализовывать что-то в направлении, которое вы предложили. О/П, чтобы продолжить. Каковы, на ваш взгляд, преимущества в том, чтобы платить более чем в два раза больше за то, чтобы не получить ничего больше, чем вы уже имеете? Я что-то упустил? - person user3666197; 31.10.2019
comment
AIUI низкоуровневое сердцебиение в ZMTP недоступно клиентам напрямую, но используется для возврата событий подключения и отключения в монитор сокетов. Я по-прежнему считаю, что проще разработать собственный протокол, чтобы определить, жив ли сокет после попытки его подключения. - person John Jefferies; 01.11.2019