Stomp 1.2 ActiveMQ 5.15-收到没有确认的ACK ID的ACK

时间:2018-06-19 13:27:50

标签: c activemq stomp

我建立了一个c函数,该函数应该通过stomp库从ActiveMQ中读取。此代码在RECEIPT之前读取了其他MESSAGE(这是我所期望的)。请告知为什么第二个MESSAGE帧之前我的RECEIPT帧不出现。另外请注意,我将此代码包装在BEGIN和COMMIT框架中,这可能是最佳实践,也可能不是最佳实践。

谢谢。

int receive_from_queue_ack( MQDEF *mqdef, int transaction ) {
    apr_status_t rc;
    stomp_frame frame_write;
    stomp_frame* frame_read = NULL;
    char transaction_str[37];
    char* ack = NULL;
    char* protocol = NULL;
    char* receipt_id = NULL;
    char* message_id = NULL;
    char* message = NULL;
    char* seq = NULL;
    uuid_t uuid;
    char receipt_id_begin_uuid[37];
    char receipt_id_commit_uuid[37];
    char receipt_id_ack_uuid[37];
    char id_uuid[37];
    int receipt_flag = 1;

    uuid_generate_random(uuid);
    uuid_unparse_lower(uuid, transaction_str);

    uuid_generate_random(uuid);
    uuid_unparse_lower(uuid, receipt_id_begin_uuid);

    uuid_generate_random(uuid);
    uuid_unparse_lower(uuid, id_uuid);

    uuid_generate_random(uuid);
    uuid_unparse_lower(uuid, receipt_id_commit_uuid);


    uuid_generate_random(uuid);
    uuid_unparse_lower(uuid, receipt_id_ack_uuid);

    fprintf(stdout, "1) *** Transaction BEGIN - (receive_from_queue)\n");
    frame_write.command = "BEGIN";
    frame_write.headers = apr_hash_make((apr_pool_t *)mqdef->pool);
    apr_hash_set(frame_write.headers, "transaction", APR_HASH_KEY_STRING, transaction_str); 
    frame_write.body_length = -1;
    frame_write.body = NULL;
    rc = stomp_write(mqdef->amqConnection, &frame_write, (apr_pool_t *)mqdef->pool);
    if ( rc != APR_SUCCESS ) {
        return FAILURE;
    }

    printf("3) Subscribe begin\n");
    frame_write.command = "SUBSCRIBE";
    frame_write.headers = apr_hash_make((apr_pool_t *)mqdef->pool);
    apr_hash_set(frame_write.headers, "destination", APR_HASH_KEY_STRING, mqdef->queueName);
    apr_hash_set(frame_write.headers, "ack", APR_HASH_KEY_STRING, "client");
    apr_hash_set(frame_write.headers, "id", APR_HASH_KEY_STRING, "client-123");
    apr_hash_set(frame_write.headers, "activemq.prefetchSize", APR_HASH_KEY_STRING, "1");
    frame_write.body_length = -1;
    frame_write.body = NULL;
    rc = stomp_write(mqdef->amqConnection, &frame_write, (apr_pool_t *)mqdef->pool);
    if ( rc != APR_SUCCESS ) {
        return FAILURE;
    }
    frame_read = NULL;
    rc = stomp_read(mqdef->amqConnection, &frame_read, (apr_pool_t *)mqdef->pool);
    if ( rc != APR_SUCCESS ) {
        return FAILURE;
    }
    ack = NULL;
    if( frame_read != NULL && strncmp(frame_read->command, "MESSAGE", 7) == 0 ) {
        ack = (char*) apr_hash_get(frame_read->headers, "ack", APR_HASH_KEY_STRING);
        printf("5) ack=<%s>\n", ack);
        if( ack == NULL ) {
            printf("ack being null is a problem\n");
            exit(1);
        }
        message_id = (char*) apr_hash_get(frame_read->headers, "message-id", APR_HASH_KEY_STRING);
        printf("5) message_id=<%s>\n", message_id);
        printf("5) command=<%s>, body=<%s>\n", frame_read->command, frame_read->body);
    } else if( frame_read != NULL && strncmp(frame_read->command, "ERROR", 5) == 0 ) {
        message_id = (char*) apr_hash_get(frame_read->headers, "message-id", APR_HASH_KEY_STRING);
        printf("5) message_id=<%s>\n", message_id);
        printf("5) command=<%s>, body=<%s>\n", frame_read->command, frame_read->body);
        exit(1);
    } else {
        message_id = (char*) apr_hash_get(frame_read->headers, "message-id", APR_HASH_KEY_STRING);
        printf("5) message_id=<%s>\n", message_id);
        printf("5) command=<%s>, body=<%s>\n", frame_read->command, frame_read->body);
        printf("5) should never get here.\n");
        exit(1);
    }
    frame_write.command = "ACK";
    frame_write.headers = apr_hash_make((apr_pool_t *)mqdef->pool);
    apr_hash_set(frame_write.headers, "transaction", APR_HASH_KEY_STRING, transaction_str);
    apr_hash_set(frame_write.headers, "id", APR_HASH_KEY_STRING, ack);
    apr_hash_set(frame_write.headers, "receipt-id", APR_HASH_KEY_STRING, receipt_id_ack_uuid);
    printf("set id =<%s>\n", ack);
    frame_write.body_length = -1;
    frame_write.body = NULL;
    rc = stomp_write(mqdef->amqConnection, &frame_write, (apr_pool_t *)mqdef->pool);
    if ( rc != APR_SUCCESS ) {
        return FAILURE;
    }
    frame_read = NULL;
    rc = stomp_read(mqdef->amqConnection, &frame_read, (apr_pool_t *)mqdef->pool);
    if ( rc != APR_SUCCESS ) {
        return FAILURE;
    }
    if( frame_read != NULL && strncmp(frame_read->command, "RECEIPT", 7) == 0 ) {
        message_id = (char*) apr_hash_get(frame_read->headers, "message-id", APR_HASH_KEY_STRING);
        receipt_id = (char*) apr_hash_get(frame_read->headers, "receipt-id", APR_HASH_KEY_STRING);
        printf("7) receipt-id=<%s>\n", receipt_id);
        printf("7) message-id=<%s>\n", message_id);
        printf("7) command=<%s>, body=<%s>\n", frame_read->command, frame_read->body);
    } else if( frame_read != NULL && strncmp(frame_read->command, "ERROR", 5) == 0 ) {
        message_id = (char*) apr_hash_get(frame_read->headers, "message_id", APR_HASH_KEY_STRING);
        receipt_id = (char*) apr_hash_get(frame_read->headers, "receipt-id", APR_HASH_KEY_STRING);
        printf("7) receipt-id=<%s>\n", receipt_id);
        printf("7) message-id=<%s>\n", message_id);
        printf("7) command=<%s>, body=<%s>\n", frame_read->command, frame_read->body);
        exit(1);
    } else {
        message_id = (char*) apr_hash_get(frame_read->headers, "message_id", APR_HASH_KEY_STRING);
        printf("7) message-id=<%s>\n", message_id);
        printf("7) command=<%s>, body=<%s>\n", frame_read->command, frame_read->body);
        ack = (char*) apr_hash_get(frame_read->headers, "ack", APR_HASH_KEY_STRING);
        printf("5) ack=<%s>\n", ack);
        printf("this is a failure\n");
        frame_write.command = "ACK";
        frame_write.headers = apr_hash_make((apr_pool_t *)mqdef->pool);
        apr_hash_set(frame_write.headers, "transaction", APR_HASH_KEY_STRING, transaction_str);
        apr_hash_set(frame_write.headers, "id", APR_HASH_KEY_STRING, ack);
        apr_hash_set(frame_write.headers, "receipt-id", APR_HASH_KEY_STRING, receipt_id_ack_uuid);
        rc = stomp_write(mqdef->amqConnection, &frame_write, (apr_pool_t *)mqdef->pool);
        if ( rc != APR_SUCCESS ) {
            return FAILURE;
        }
    }

    frame_write.command = "COMMIT";
    frame_write.headers = apr_hash_make((apr_pool_t *)mqdef->pool);
    apr_hash_set(frame_write.headers, "transaction", APR_HASH_KEY_STRING, transaction_str);
    frame_write.body_length = -1;
    frame_write.body = NULL;
    rc = stomp_write(mqdef->amqConnection, &frame_write, (apr_pool_t *)mqdef->pool);
    if ( rc != APR_SUCCESS ) {
        return FAILURE;
    }
    fprintf(stdout, "12) *** Transaction Complete - (receive_from_queue)\n\n");
}

1 个答案:

答案 0 :(得分:1)

您没有在确认中使用正确的STOMP标头来指示ACK ID,因此代理告诉您您做错了。 STOMP规范是一个开始学习在每个表演中添加内容的好地方,在这种情况下,标头是“ id”而不是“ message-id”

像往常一样,对于C代码来说,很难阅读,因此使用一些注释或上下文在上面重新编写代码会有所帮助,但到目前为止,我还没有看到客户端代码从传入消息中获取“ ack”标头的位置,并且将其传输到实际的“ ACK”帧,因此可能是问题所在。

根据规格:

  

如果从需要显式确认的订阅(客户端或客户端个人模式)接收到消息,则MESSAGE帧还必须包含带有任意值的ack头。此标头将用于将消息与后续的ACK或NACK帧相关。

请参阅STOMP specification以了解更多信息