Rabbit的五种工作模式例子(C++)

CMakeLists.txt

cmake_minimum_required(VERSION 3.20)
project(demo)

set(CMAKE_CXX_STANDARD 17)

set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)

SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17 -pthread -ldl")


# 设置头文件地址
set(INC_DIR /usr/)

# 设置动态库地址
set(LINK_DIR /usr/)

include_directories(${INC_DIR})

link_directories(${LINK_DIR})


# 生产者
add_executable(messageProducer helloworld/MessageProducer.cpp)
add_executable(messageConsumer helloworld/MessageConsumer.cpp)

add_executable(workProducer workqueue/WorkProducer.cpp)
add_executable(worker1 workqueue/WorkComsumer.cpp)
add_executable(worker2 workqueue/WorkComsumer.cpp)

add_executable(MessageProducer publishandsubscribe/MessageProducer.cpp)
add_executable(MessageConsumer1 publishandsubscribe/MessageConsumer1.cpp)
add_executable(MessageConsumer2 publishandsubscribe/MessageConsumer2.cpp)

add_executable(RoutingProducer routing/MessageProducer.cpp)
add_executable(RoutingConsumer1 routing/MessageConsumer1.cpp)
add_executable(RoutingConsumer2 routing/MessageConsumer2.cpp)

add_executable(TopicProducer topic/MessageProducer.cpp)
add_executable(TopicConsumer1 topic/MessageConsumer1.cpp)
add_executable(TopicConsumer2 topic/MessageConsumer2.cpp)
add_executable(TopicConsumer3 topic/MessageConsumer3.cpp)

add_executable(RpcServer rpc/RpcServer.cpp)
add_executable(RpcClient rpc/RpcClient.cpp)

add_executable(DeadLetterConsumer deadletter/DeadLetterConsumer.cpp)
add_executable(Producer deadletter/MessageProducer.cpp)
add_executable(Consumer deadletter/MessageConsumer.cpp)


# 将库连接到项目中
target_link_libraries(messageProducer libamqpcpp.so libevent_core.so)
target_link_libraries(messageConsumer libamqpcpp.so libevent_core.so)

target_link_libraries(workProducer libamqpcpp.so libevent_core.so)
target_link_libraries(worker1 libamqpcpp.so libevent_core.so)
target_link_libraries(worker2 libamqpcpp.so libevent_core.so)

target_link_libraries(MessageProducer libamqpcpp.so libevent_core.so)
target_link_libraries(MessageConsumer1 libamqpcpp.so libevent_core.so)
target_link_libraries(MessageConsumer2 libamqpcpp.so libevent_core.so)

target_link_libraries(RoutingProducer libamqpcpp.so libevent_core.so)
target_link_libraries(RoutingConsumer1 libamqpcpp.so libevent_core.so)
target_link_libraries(RoutingConsumer2 libamqpcpp.so libevent_core.so)

target_link_libraries(TopicProducer libamqpcpp.so libevent_core.so)
target_link_libraries(TopicConsumer1 libamqpcpp.so libevent_core.so)
target_link_libraries(TopicConsumer2 libamqpcpp.so libevent_core.so)
target_link_libraries(TopicConsumer3 libamqpcpp.so libevent_core.so)

target_link_libraries(RpcServer libamqpcpp.so libevent_core.so)
target_link_libraries(RpcClient libamqpcpp.so libevent_core.so)

target_link_libraries(DeadLetterConsumer libamqpcpp.so libevent_core.so)
target_link_libraries(Producer libamqpcpp.so libevent_core.so)
target_link_libraries(Consumer libamqpcpp.so libevent_core.so)

conn_handler

#include <functional>
#include <unistd.h>
#include <event2/event.h>
#include <amqpcpp/libevent.h>

class LibEventHandlerMyError : public AMQP::LibEventHandler
{
public:
    LibEventHandlerMyError(struct event_base *evbase)
        : LibEventHandler(evbase), evbase_(evbase_) {}
    
    void onError(AMQP::TcpConnection *connection, const char *msg) override
    {
        std::cout << "Error: " << msg << std::endl;
        event_base_loopbreak(evbase_);
    }
    
private:
    struct event_base *evbase_ = nullptr;
};

class ConnHandler
{
public:
    using EventBasePtrT = std::unique_ptr<struct event_base, std::function<void(struct event_base *)>>;
    using EventPtrT = std::unique_ptr<struct event, std::function<void(struct event *)>>;
    
    ConnHandler()
        : evbase_(event_base_new(), event_base_free),
        // event_base_new是libevent库中的一个函数,用于创建一个新的事件基础(event base)对象。
        // event_base_free是libevent库中的一个函数,用于释放之前通过event_base_new创建的事件基础对象所占用的内存。
    	  stdin_event_(event_new(evbase_.get(), STDIN_FILENO, EV_READ, stop, evbase_.get()), event_free),
        // event_new是libevent库中的一个函数,用于创建一个新的事件对象。
        // event_free是libevent库中的一个函数,用于释放之前通过event_new创建的事件对象所占用的内存。
    	  evhandler_(evbase_.get())
	{
    	event_add(stdin_event_.get(), nullptr);  
	}
    
    void Start()
    {
        std::cout << "Waiting for message. Press enter to exit." << std::endl;
        event_base_dispatch(evbase_.get());
        // event_base_dispatch是libevent库中的一个关键函数,主要用于启动和运行事件循环。
    }
    
    void Stop()
    {
        event_base_loopbreak(evbase_.get());
        // event_base_loopbreak是libevent库中的一个函数,用于终止当前运行的事件循环。
    }
    
    operator AMQP::TcpHandler *()
    {
        return &evhandler_;
    }
    
private:
    static void stop(evutil_socket_t fd, short what, void *evbase)
    {
        std::cout << "Safely breaking event loop." << std::endl;
        event_base_loopbreak(reinterpret_cast<event_base *>(evbase));
        // event_base_loopbreak是libevent库中的一个函数,用于终止当前运行的事件循环。
    }
    
    EventBasePtrT evbase_;
    EventPtrT stdin_event_;
    LibEventHandlerMyError evhandler_;
};

简单模式

image-20231123162543251

一个生产者,一个消费者,一个队列,采用默认交换机。可以理解为生产者P发送消息到队列Q,一个消费者C接收。

MessageProducer

#include <iostream>
#include <thread>
#include <chrono>
#include <amqpcpp.h>
#include "conn_handler.h"

int main()
{
    auto evbase = event_base_new();
    LibEventHandlerMyError handl(evbase);
    
    // 建立连接
    // TCP连接,是客户端与消息中间件建立通信的重要部分
    AMQP::TcpConnection conn(&handl, AMQP::Address("amqp://guanjiaa:Zjc20020221.@81.71.97.27:5672//"));
    // 服务地址格式为 amqp://username:password@host:port/vhost
    
    // 建立通道
    // 代表了在客户端与消息中间件之间建立的一条TCP连接上的一个信道
    AMQP::TcpChannel channel(&conn);
    channel.onError([&evbase](const char *msg){
        std::cout << "Channel error: " << msg << std::endl;
        event_base_loopbreak(evbase);
    });
    
    // 声明消息队列
    channel.declareQueue("hello_queue", AMQP::passive).onSuccess([](const std::string &name,
            				uint32_t messagecount,
             				uint32_t consumercount) {
		std::cout << "Queue: " << name << std::endl;
	}).onFinalize([&conn]() {
		std::cout << "Finalize." << std::endl;
        conn.close();
	});
    
    // 发送消息到消息队列
    channel.publish("", "hello_queue", "Hello, World!");
    
    event_base_dispatch(evbase);
    event_base_free(evbase);
    
    return 0;
}

MessageConsumer

#include <iostream>
#include <thread>
#include <chrono>
#include <amqpcpp.h>
#include "conn_handler.h"

int main()
{
    ConnHandler handler;
    AMQP::TcpConnection conn(handler, AMQP::Address("amqp://guanjiaa:Zjc20020221.@81.71.97.27:5672//"));
    AMQP::TcpChannel channel(&conn);
    channel.onError([&handler](const char *msg){
        std::cout << "Channel error: " << msg << std::endl;
        handler.Stop();
    });
    channel.setQos(1);
    // 设定最小交付信息次数为最少一次
    channel.declareQueue("hello_queue", AMQP::durable);
    channel.consume("hello_queue").onReceived([&channel](const AMQP::Message &msg, uint64_t tag, bool redelivered){
       std::cout << "Received: " << msg.body() << std::endl;
        channel.ack(tag);
    });
    
    handler.Start();
    std::cout << "Closing connection." << std::endl;
    connection.close();
    return 0;
}

工作模式

image-20231123162707719

一个生产者,多个消费者,一个队列,采用默认交换机。可以理解为生产者P发送消息到队列Q,可以由多个消费者C1、C2进行接收。

WorkProducer

#include <iostream>
#include <thread>
#include <chrono>
#include <amqpcpp.h>
#include "conn_handler.h"

int main()
{
    auto evbase = event_base_new();
    LibEventHandlerMyError handl(evbase);
    
    // 创建连接
    AMQP::TcpConnection conn(&handl, AMQP::Address("amqp://guanjiaa:Zjc20020221.@81.71.97.27:5672//"));
    
    // 建立通道
    AMQP::TcpChannel channel(&conn);
    channel.onError([&evbase](const char *msg){
        std::cout << "Channel error: " << msg << std::endl;
        event_base_loopbreak(evbase);
    });
    
    // 声明消息队列
    channel.declareQueue("task_queue", AMQP::passive).onSuccess([](const std::string &name, uint32_t messagecount, uint32_t consumercount){
        std::cout << "Queue: " << name << std::endl;
    }).onFinalize([&conn](){
        std::cout << "Finalize." << std::endl;
        conn.close();
    });
    
    // 发送消息到消息队列
    for(int i = 0; i < 10; ++i) {
        channel.publish("", "task_queue", "hello client this is a work message");
    }
    
    event_base_dispatch(evbase);
    event_base_free(evbase);
    
    return 0;
}

WorkComsumer

#include <iostream>
#include <thread>
#include <chrono>
#include <amqpcpp.h>
#include "conn_handler.h"

int main()
{
    ConnHandler handler;
    
    // 创建连接
    AMQP::TcpConnection conn(handler, AMQP::Address("amqp://guanjiaa:Zjc20020221.@81.71.97.27:5672//"));
    
    // 建立通道
    AMQP::TcpChannel channel(&conn);
    channel.onError([&handler](const char *msg){
        std::cout << "channel error: " << message << std::endl;
        handler.Stop();
    });
    
    // 声明消息队列
    channel.setQos(1);
    channel.declareQueue("task_queue", AMQP::durable);
    channel.consume("task_queue").onReceived([&channel](const AMQP::Message &msg, uint64_t tag, bool redelivered){
        // 处理消息
        std::cout << "Worker1 Received: " << msg.body() << std::endl;
        // 回复ack
        channel.ack(tag);
        // 消费失败可回复reject
    });
    
    handler.Start();
    std::cout << "Closing connection. " << std::endl;
    conn.close();
    return 0;
}

发布/订阅模式(fanout)

image-20231123170140700

一个生产者、一个 fanout 类型的交换机、多个队列、多个消费者。一个生产者发送的消息会被多个消费者获取。其中 fanout 类型就是发布订阅模式,只有订阅该生产者的消费者会收到消息。

MessageProducer

#include <iostream>
#include <thread>
#include <amqpcpp.h>
#include "conn_handler.h"

int main()
{
    auto evbase = event_base_new();
    LibEventHandlerMyError handl(evbase);
    
    // 建立连接
    AMQP::TcpConnection conn(&handl, AMQP::Address("amqp://guanjiaa:Zjc20020221.@81.71.97.27:5672//"));
    
    // 建立通道
    AMQP::TcpChannel channel(&conn);
    channel.onError([&evbase](const char *msg){
        std::cout << "Channel error: " << msg << std::endl;
        event_base_loopbreak(evbase);
    });
    
    // 声明交换机
    channel.declareExchange("ps_exchange", AMQP::ExchangeType::fanout);
    
    // 发送消息到交换机
    for(int i = 0; i < 10; ++i) {
        channel.publish("ps_exchange", "", "Hello client this is a ps message");
    }
    
    event_base_dispatch(evbase);
    event_base_free(evbase);
    
    return 0;
}

MessageConsumer1

#include <iostream>
#include <thread>
#include <chrono>
#include <amqpcpp.h>
#include "conn_handler.h"

int main()
{
    ConnHandler handler;
    
    // 建立连接
    AMQP::TcpConnection conn(handler, AMQP::Address("amqp://guanjiaa:Zjc20020221.@81.71.97.27:5672//"));
    
    // 建立通道
    AMQP::TcpChannel channel(&conn);
    channel.onError([&handler](const char *msg){
        std::cout << "Channel error: " << msg << std::endl;
        handler.Stop();
    });
    
    // 声明交换机
    channel.declareExchange("ps_change", AMQP::ExchangeType::fanout);
    
    // 声明消息队列
    channel.declareQueue("ps_queue", AMQP::durable);
    
    // 绑定消息队列到交换机
    channel.bindQueue("ps_exchange", "ps_queue", "");
    channel.setQos(1);
    
    // 订阅消息
    channel.consume("ps_queue").onReceived([&channel](const AMQP::Message &msg, uint64_t tag, bool redelivered){
        // 处理消息
        std::cout << "Received: " << msg.body() << std::endl;
        // 回复ack
        channel.ack(tag);
    });
    handler.Start();
    
    std::cout << "Closing connection." << std::endl;
    conn.close();
    
    return 0;
}

MessageConsumer2

#include <iostream>
#include <thread>
#include <chrono>
#include <amqpcpp.h>
#include "../conn_handler.h"

int main()
{
    ConnHandler handler;
    
    // 建立连接
    AMQP::TcpConnection conn(handler, AMQP::Address("amqp://guanjiaa:Zjc20020221.@81.71.97.27:5672//"));
    
    // 建立通道
    AMQP::TcpChannel channel(&conn);
    channel.onError([&handler](const char *msg){
        std::cout << "Channel error: " << msg << std::endl;
        handler.Stop();
    });
    
    // 声明交换机
    channel.declareExchange("ps_change", AMQP::ExchangeType::fanout);
    
    // 声明消息队列
    channel.declareQueue("ps_queue1", AMQP::durable);
    
    // 绑定消息队列到交换机
    channel.bindQueue("ps_exchange", "ps_queue1", "");
    channel.setQos(1);
    
    // 订阅消息
    channel.consume("ps_queue1").onReceived([&channel](const AMQP::Message &msg, uint64_t tag, bool redelivered){
        // 处理消息
        std::cout << "Received: " << msg.body() << std::endl;
        // 回复ack
        channel.ack(tag);
    });
    handler.Start();
    
    std::cout << "Closing connection." << std::endl;
    conn.close();
    
    return 0;
}

路由模式(direct)

image-20231123192553132

一个生产者,一个 direct 类型的交换机,多个队列,交换机与队列之间通过 routing-key 进行关联绑定,多个消费者。生产者发送消息到交换机并且要指定routing-key,然后消息根据这交换机与队列之间的 routing-key 绑定规则进行路由被指定消费者消费。

MessageProducer

#include <iostream>
#include <thread>
#include <amqpcpp.h>
#include "conn_handler.h"

int main() {
    auto evbase = event_base_new();
    LibEventHandlerMyError hndl(evbase);

    // 建立连接
    AMQP::TcpConnection connection(&hndl, AMQP::Address(
            "amqp://guanjiaa:Zjc20020221.@81.71.97.27:5672//"));

    // 建立通道
    AMQP::TcpChannel channel(&connection);
    channel.onError([&evbase](const char *message) {
        std::cout << "Channel error: " << message << std::endl;
        event_base_loopbreak(evbase);
    });

    // 声明交换机
    channel.declareExchange("direct_exchange", AMQP::ExchangeType::direct);

    // 发送消息到交换机
    channel.publish("direct_exchange", "error", "Hello client this is a error message");
    channel.publish("direct_exchange", "info", "Hello client this is a info message");
    channel.publish("direct_exchange", "waring", "Hello client this is a waring message");

    event_base_dispatch(evbase);
    event_base_free(evbase);

    return 0;
}

MessageConsumer1

#include <iostream>
#include <thread>
#include <chrono>
#include <amqpcpp.h>
#include "conn_handler.h"

int main()
{
    ConnHandler handler;
    
    // 建立连接
    AMQP::TcpConnection conn(handler, AMQP::Address("amqp://guanjiaa:Zjc20020221.@81.71.97.27:5672//"));
    
    // 建立通道
    AMQP::TcpChannel channel(&conn);
    channel.onError([&handler](const char *msg){
        std::cout << "Channel error: " << msg << std::endl;
        handler.Stop();
    });
    
    // 声明交换机
    channel.declareExchange("ps_change", AMQP::ExchangeType::fanout);
    
    // 声明消息队列
    channel.declareQueue("ps_queue", AMQP::durable);
    
    // 绑定消息队列到交换机
    channel.bindQueue("ps_exchange", "ps_queue", "");
    channel.setQos(1);
    
    // 订阅消息
    channel.consume("ps_queue").onReceived([&channel](const AMQP::Message &msg, uint64_t tag, bool redelivered){
        // 处理消息
        std::cout << "Received: " << msg.body() << std::endl;
        // 回复ack
        channel.ack(tag);
    });
    handler.Start();
    
    std::cout << "Closing connection." << std::endl;
    conn.close();
    
    return 0;
}

MessageConsumer2

#include <iostream>
#include <thread>
#include <chrono>
#include <amqpcpp.h>
#include "conn_handler.h"

int main()
{
    ConnHandler handler;
    
    // 建立连接
    AMQP::TcpConnection conn(handler, AMQP::Address("amqp://guanjiaa:Zjc20020221.@81.71.97.27:5672//"));
    
    // 建立通道
    AMQP::TcpChannel channel(&conn);
    channel.onError([&handler](const char *msg){
        std::cout << "Channel error: " << msg << std::endl;
        handler.Stop();
    });
    
    // 声明交换机
    channel.declareExchange("ps_change", AMQP::ExchangeType::fanout);
    
    // 声明消息队列
    channel.declareQueue("ps_queue1", AMQP::durable);
    
    // 绑定消息队列到交换机
    channel.bindQueue("ps_exchange", "ps_queue1", "");
    channel.setQos(1);
    
    // 订阅消息
    channel.consume("ps_queue1").onReceived([&channel](const AMQP::Message &msg, uint64_t tag, bool redelivered){
        // 处理消息
        std::cout << "Received: " << msg.body() << std::endl;
        // 回复ack
        channel.ack(tag);
    });
    handler.Start();
    
    std::cout << "Closing connection." << std::endl;
    conn.close();
    
    return 0;
}

主题模式(topic)

image-20231123192658380

一个生产者,一个 topic 类型的交换机,多个队列,交换机与队列之间通过 routing-key 进行关联绑定,多个消费者。生产者发送消息到交换机并且要指定 routing-key,然后消息根据这交换机与队列之间的 routing-key 绑定规则进行路由被指定消费者消费。与路由模式不同是 routing-key 有指定的队则,可以更加的通用,满足更过的场景。routing-key 的规则如下:

  • #:匹配一个或者多个词,例如lazy.# 可以匹配 lazy.xxx 或者 lazy.xxx.xxx
  • *:只能匹配一个词,例如lazy.* 只能匹配 lazy.xxx

MessageProducer

#include <iostream>
#include <thread>
#include <amqpcpp.h>
#include "../conn_handler.h"

int main() {
    auto evbase = event_base_new();
    LibEventHandlerMyError hndl(evbase);

    // 建立连接
    AMQP::TcpConnection connection(&hndl, AMQP::Address(
            "amqp://guanjiaa:Zjc20020221.@81.71.97.27:5672//"));
    // 建立通道
    AMQP::TcpChannel channel(&connection);
    channel.onError([&evbase](const char *message) {
        std::cout << "Channel error: " << message << std::endl;
        event_base_loopbreak(evbase);
    });

    // 声明交换机
    channel.declareExchange("topic_exchange", AMQP::ExchangeType::topic);

    // 发送消息到交换机
    channel.publish("topic_exchange", "aaa.bbb.ccc", "Hello client this is a aaa.bbb.ccc message");
    channel.publish("topic_exchange", "ccc.bbb.aaa", "Hello client this is a ccc.bbb.aaa message");
    channel.publish("topic_exchange", "aaa.aaa.aaa", "Hello client this is a aaa.aaa.aaa message");
    channel.publish("topic_exchange", "aaa.yyy.zzz", "Hello client this is a aaa.yyy.zzz message");
    channel.publish("topic_exchange", "xxx.yyy.zzz", "Hello client this is a xxx.yyy.zzz message");

    event_base_dispatch(evbase);
    event_base_free(evbase);

    return 0;
}

MessageConsumer1

#include <iostream>
#include <thread>
#include <chrono>
#include <amqpcpp.h>
#include "../conn_handler.h"

int main() {
    ConnHandler handler;
    // 建立连接
    AMQP::TcpConnection connection(handler,
                                   AMQP::Address("amqp://guanjiaa:Zjc20020221.@81.71.97.27:5672//"));
    // 建立通道
    AMQP::TcpChannel channel(&connection);
    channel.onError([&handler](const char *message) {
        std::cout << "Channel error: " << message << std::endl;
        handler.Stop();
    });

    // 声明交换机
    channel.declareExchange("topic_exchange", AMQP::ExchangeType::topic);
    // 生命消息队列
    channel.declareQueue("topic_queue", AMQP::durable);
    // 绑定消息队列到交换机
    channel.bindQueue("topic_exchange", "topic_queue", "*.bbb.*");
    channel.bindQueue("topic_exchange", "topic_queue", "aaa.#");
    channel.bindQueue("topic_exchange", "topic_queue", "*.*.aaa");
    channel.setQos(1);
    // 订阅消息
    channel.consume("topic_queue")
            .onReceived
                    (
                            [&channel](const AMQP::Message &msg, uint64_t tag, bool redelivered) {
                                std::cout << "Received: " << msg.body() << std::endl;
                                channel.ack(tag);
                            }
                    );
    handler.Start();
    std::cout << "Closing connection." << std::endl;
    connection.close();
    return 0;
}

MessageConsumer2

#include <iostream>
#include <thread>
#include <chrono>
#include <amqpcpp.h>
#include "../conn_handler.h"

int main() {
    ConnHandler handler;
    // 建立连接
    AMQP::TcpConnection connection(handler,
                                   AMQP::Address("amqp://guanjiaa:Zjc20020221.@81.71.97.27:5672//"));
    // 建立通道
    AMQP::TcpChannel channel(&connection);
    channel.onError([&handler](const char *message) {
        std::cout << "Channel error: " << message << std::endl;
        handler.Stop();
    });

    // 声明交换机
    channel.declareExchange("topic_exchange", AMQP::ExchangeType::topic);
    // 声明消息队列
    channel.declareQueue("topic_queue1", AMQP::durable);
    // 绑定消息队列到指定交换机
    channel.bindQueue("topic_exchange", "topic_queue1", "*.*.aaa");
    channel.setQos(1);
    // 订阅消息
    channel.consume("topic_queue1")
            .onReceived
                    (
                            [&channel](const AMQP::Message &msg, uint64_t tag, bool redelivered) {
                                std::cout << "Received: " << msg.body() << std::endl;
                                channel.ack(tag);
                            }
                    );
    handler.Start();
    std::cout << "Closing connection." << std::endl;
    connection.close();
    return 0;
}

MessageConsumer3

#include <iostream>
#include <thread>
#include <chrono>
#include <amqpcpp.h>
#include "../conn_handler.h"

int main() {
    ConnHandler handler;
    // 建立连接
    AMQP::TcpConnection connection(handler,
                                   AMQP::Address("amqp://guanjiaa:Zjc20020221.@81.71.97.27:5672//"));
    // 建立通道
    AMQP::TcpChannel channel(&connection);
    channel.onError([&handler](const char *message) {
        std::cout << "Channel error: " << message << std::endl;
        handler.Stop();
    });

    // 声明交换机
    channel.declareExchange("topic_exchange", AMQP::ExchangeType::topic);
    // 声明消息队列
    channel.declareQueue("topic_queue2", AMQP::durable);
    // 绑定消息队列到交换机
    channel.bindQueue("topic_exchange", "topic_queue2", "*.*.zzz");
    channel.setQos(1);
    // 订阅消息
    channel.consume("topic_queue2")
            .onReceived
                    (
                            [&channel](const AMQP::Message &msg, uint64_t tag, bool redelivered) {
                                std::cout << "Received: " << msg.body() << std::endl;
                                channel.ack(tag);
                            }
                    );
    handler.Start();
    std::cout << "Closing connection." << std::endl;
    connection.close();
    return 0;
}

RPC模式

image-20231123194227098

RpcServer

#include <iostream>
#include <thread>
#include <chrono>
#include <amqpcpp.h>
#include "conn_handler.h"

// 模拟rpc业务
int fib(int n) {
    switch (n) {
        case 0:
            return 0;
        case 1:
            return 1;
        default:
            return fib(n - 1) + fib(n - 2);
    }
}

int main() {
    ConnHandler handler;
    // 建立连接
    AMQP::TcpConnection connection(handler,
                                   AMQP::Address("amqp://guanjiaa:Zjc20020221.@81.71.97.27:5672//"));
    // 建立通道
    AMQP::TcpChannel channel(&connection);
    channel.onError([&handler](const char *message) {
        std::cout << "Channel error: " << message << std::endl;
        handler.Stop();
    });
    channel.setQos(1);
    // 声明消息队列
    channel.declareQueue("rpc_queue");
    // 消费消息
    channel.consume("")
            .onReceived
                    (
                            [&channel](const AMQP::Message &m, uint64_t tag, bool) {
                                std::cout << "fib(" << m.body() << ")" << std::endl;
                                // 处理业务
                                std::string body = std::to_string(fib(std::stoi(m.body())));
                                AMQP::Envelope envelope(body.data(), sizeof(body.data()));
                                envelope.setCorrelationID(m.correlationID());
                                // 回复rpc
                                channel.publish("", m.replyTo(), envelope);
                                channel.ack(tag);
                            }
                    );
    handler.Start();
    std::cout << "Closing connection." << std::endl;
    connection.close();
    return 0;
}

RpcClient

#include <iostream>
#include <thread>
#include <sstream>
#include <chrono>
#include <amqpcpp.h>
#include "conn_handler.h"

int main() {
    std::stringstream ss;
    ss << std::chrono::duration_cast<std::chrono::microseconds>(
            std::chrono::high_resolution_clock::now().time_since_epoch()).count();
    std::string correlation = ss.str();
    ConnHandler handler;
    // 创建连接
    AMQP::TcpConnection connection(handler,
                                   AMQP::Address("amqp://guanjiaa:Zjc20020221.@81.71.97.27:5672//"));
    // 建立通道
    AMQP::TcpChannel channel(&connection);
    channel.onError([&handler](const char *message) {
        std::cout << "Channel error: " << message << std::endl;
        handler.Stop();
    });
    // 声明消息队列
    channel.declareQueue(AMQP::exclusive)
            .onSuccess
                    (
                            [&channel, correlation](const std::string &name, int, int) {
                                std::string body = "30";
                                AMQP::Envelope env(body.data(), sizeof(body.data()));
                                env.setCorrelationID(correlation);
                                env.setReplyTo(name);
                                channel.publish("", "rpc_queue", env);
                                std::cout << "Requesting fib(30)" << std::endl;
                            }
                    );
    // 消费消息
    channel.consume("", AMQP::noack)
            .onReceived
                    (
                            [correlation, &handler](const AMQP::Message &m, uint64_t, bool) {
                                if (m.correlationID() != correlation)
                                    return; // just skip it
                                std::cout << "Got " << m.body() << std::endl;
                                handler.Stop();
                            }
                    );
    handler.Start();
    std::cout << "Closing connection." << std::endl;
    connection.close();
    return 0;
}
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值