概述
本文讲述了twemproxy0.4的消息处理流程。通过本文可以了解到twemproxy0.4的消息处理全流程。
流程总体描述
作为一个代理服务器twemproxy0.4,首先要接收来自client的了解,和client端建立好连接;然后,需要后后端的服务器建立连接,并把从client端接收到的连接发送给后端服务器,然后把服务器端的返回信息通过和client的连接发送给client。最后完成整个流程。
本章我们来具体分析一下twemproxy0.4是如何处理这些消息的。
处理客户端的连接请求
如上图所示,客户端向配置好的twemproxy的监听地址发送连接请求,twemproxy接收连接请求,完成tcp三次握手后(调用accept函数)会创建一个新的已连接文件描述符newfd,twemproxy把该newfd添加到事件处理框架中,若客户端有消息到来,就会产生读事件,进入消息处理流程。
消息处理初始化
启动时的初始化
twemproxy0.4启动时的初始化代码相对简单,启动代码在文件src/nc.c中,main作为软件入口,其函数调用关系如下:
main()
-> nc_pre_run(&nci)
-> nc_run(&nci)
-> core_start(nci) //这里进行软件的初始化
-> core_loop(ctx) // 这里进入事件处理循环
-> core_stop(ctx) //若软件停止运行,执行这里
-> nc_post_run(&nci) //软件退出,需要做一些清理工作
而在core_start会完成整个软件的初始化,在该函数中的函数调用关系如下:
core_start(struct instance *nci)
->mbuf_init(nci); // mbuf管理机制初始化
->msg_init(); // msg处理机制初始化
->conn_init(); // conn结构管理初始化
->core_ctx_create(nci); //进入核心事件处理循环
->conn_deinit();
->msg_deinit();
->mbuf_deinit();
消息处理初始化,从上面的调用关系我们可以看到,消息处理机制的初始化在函数core_ctx_create中完成,该函数的函数调用关系如下:
core_ctx_create(struct instance *nci)
-> conf_create()
-> server_pool_init()
-> core_calc_connections()
-> stats_create()
-> event_base_create() // 设置事件处理函数
-> server_pool_preconnect() // 预先和后台的redis或memcached server建立连接
-> proxy_init() // 创建连接监听socket,监听来自客户端的连接请求
最终完成和client端的连接后,会把recv函数设置成:msg_recv。正式进入client的消息处理循环。
消息处理流程概览
说明:
(1) 正常的完整的消息处理流程是:
过程a->过程b->过程c->过程d
(2) 处理客户端(client)端请求的流程是:
过程a->过程b
(3) 处理后端服务器返回数据的流程是:
过程c->过程d
消息处理流程详解
消息从客户端到后端redis/memcached服务器需要经历以下几步:
- (1) 接收client端的消息
- (2) 把client端的消息转发给后端redis/memcached服务器
- (3) 接收后端redis/memcached服务器的返回消息
- (4) 把后端redis/memcached服务器的返回消息转发送给client端
下面分别介绍这几步的实现原理:
twemproxy和client 及其 server端的连接示意
假设twemproxy和client端建立的连接名称为:client_conn,和后端的redis/memcached建立的连接是:server_conn。
接收client端的消息
twemproxy接收客户端的请求流程如下:
twemproxy接收客户端的请求是基于client_conn连接进行的,基于该连接在事件处理框架中注册的读事件(read event)来监听和触发客户端的发送的消息。
注意:该流程中有一个环节是处理fragment消息,对于fragment的处理会在后面的文章中进行分析。
转发client端的消息给后端redis/memcached服务器
twemproxy从client接受完消息后,会放到和客户端连接的输出队里中,在转发client端消息时,只需要从该队列中获取消息即可。处理过程如下:
完成转发消息是通过在server_conn连接的fd上注册写事件来触发的。
接收后端redis/memcached服务器的返回消息
通过上面的两个流程已经把客户端的消息发送给后端redis/memached服务器了,该流程从redis/memached服务器读取返回消息,具体流程如下图所示:
基于server_conn注册读事件,触发读取redis/memcached服务器的返回消息。
转发从后端redis/memcached服务器接收到的消息给client端
把redis/memcached的返回消息返回给client端是通过在client_conn的fd上注册写事件来完成的。具体流程如下图所示:
总结
本文分析了twemproxy的消息处理流程,可以看出twemproxy通过事件处理框架和两个消息队列来完成整个消息传递过程。