简介
InputMessenger类是服务端、客户端处理socket中接收消息后的处理类
类结构
InputMessageBase:是消息的基类,也是Io线程与工作线程(bthred)交互的桥梁,底层是通过SocketUniquePtr,_process是在工作线程中要做的处理,_arg表示处理时的参数。MongoContextMessage用于处理mongo的消息,HttpContext用于处理http消息,
MostCommonMessage用于处理大多数消息,InputResponse用于处理redis消息
具体的处理是交给InputMessageHandler来处理,其定义如下
struct InputMessageHandler {
typedef ParseResult (*Parse)(butil::IOBuf* source, Socket *socket, bool read_eof, const void *arg);
Parse parse;
typedef void (*Process)(InputMessageBase* msg);
Process process;
typedef bool (*Verify)(const InputMessageBase* msg);
Verify verify;
// An argument associated with the handler.
const void* arg;
// Name of this handler, must be string constant.
const char* name;
};
parse:用于解析响应
process:解析后作具体的处理
verify:主要用于process前的校验
初始化
客户端初始化
InputMessenger的创建是通过get_or_new_client_side_messenger
InputMessenger* g_messenger = NULL;
static pthread_once_t g_messenger_init = PTHREAD_ONCE_INIT;
static void InitClientSideMessenger() {
g_messenger = new InputMessenger;
}
InputMessenger* get_or_new_client_side_messenger() {
pthread_once(&g_messenger_init, InitClientSideMessenger);
return g_messenger;
}
在注册完所有的Protocol后,对于协议支持处理process_response方法的,会创建对应的InputMessageHandler,将Protocol的parse和process_response添加到InputMessageHandler,最后通过AddHandler添加到InputMessenger的_handlers中
for (size_t i = 0; i < protocols.size(); ++i) {
if (protocols[i].process_response) {
InputMessageHandler handler;
// `process_response' is required at client side
handler.parse = protocols[i].parse;
handler.process = protocols[i].process_response;
// No need to verify at client side
handler.verify = NULL;
handler.arg = NULL;
handler.name = protocols[i].name;
if (get_or_new_client_side_messenger()->AddHandler(handler) != 0) {
exit(1);
}
}
}
服务端初始化
是通过Server::BuildAcceptor()来创建的
InputMessageHandler handler;
std::vector<Protocol> protocols;
ListProtocols(&protocols);
for (size_t i = 0; i < protocols.size(); ++i) {
if (protocols[i].process_request == NULL) {
// The protocol does not support server-side.
continue;
}
if (has_whitelist &&
!is_http_protocol(protocols[i].name) &&
!whitelist.erase(protocols[i].name)) {
// the protocol is not allowed to serve.
RPC_VLOG << "Skip protocol=" << protocols[i].name;
continue;
}
// `process_request' is required at server side
handler.parse = protocols[i].parse;
handler.process = protocols[i].process_request;
handler.verify = protocols[i].verify;
handler.arg = this;
handler.name = protocols[i].name;
if (acceptor->AddHandler(handler) != 0) {
LOG(ERROR) << "Fail to add handler into Acceptor("
<< acceptor << ')';
delete acceptor;
return NULL;
}
}
列出所有的协议,看协议是否有实现process_request ,有将协议中的parse,process_request,verify赋值给InputMessageHandler添加到Acceptor中
消息处理
brpc使用的边缘触发,触发处理函数是InputMessenger的静态方法OnNewMessages
- 调用Socket的DoRead从网络上读取数据
- 调用InputMessenger的ProcessNewMessage来处理消息
- 调用CutInputMessage选择正确的Prototol来解析接收到的数据
- 创建InputMessageBase,将协议对应的process函数指针和arg赋值给_process和_arg
- 如果对应的协议指定的verify方法则作校验操作
- 调用QueueMessage让任务放到线程池队列中来执行处理,如果失败,则本线程来执行处理
- 唤醒线程执行
static void QueueMessage(InputMessageBase* to_run_msg,
int* num_bthread_created,
bthread_keytable_pool_t* keytable_pool) {
if (!to_run_msg) {
return;
}
// Create bthread for last_msg. The bthread is not scheduled
// until bthread_flush() is called (in the worse case).
// TODO(gejun): Join threads.
bthread_t th;
bthread_attr_t tmp = (FLAGS_usercode_in_pthread ?
BTHREAD_ATTR_PTHREAD :
BTHREAD_ATTR_NORMAL) | BTHREAD_NOSIGNAL;
tmp.keytable_pool = keytable_pool;
if (bthread_start_background(
&th, &tmp, ProcessInputMessage, to_run_msg) == 0) {
++*num_bthread_created;
} else {
ProcessInputMessage(to_run_msg);
}
}
启动协程即bthread运行ProcessInputMessage,调用InputMessageBase的方法_process
void* ProcessInputMessage(void* void_arg) {
InputMessageBase* msg = static_cast<InputMessageBase*>(void_arg);
msg->_process(msg);
return NULL;
}