澳门金沙vip 3

twemproxy代码框架概述——剖析twemproxy代码前编

这么大家经过上述的图贰,图3以及图四,将图第11中学10、1壹以及第88中学要马到功成的根本流程张开了深入分析,营造了她们之间的中坚关系,对于阅读代码有了3个龙骨,相信以后经过对于那3个流程和五个模块的严重性代码解析,大家就足以“会当凌绝顶,一览众山小”。

接下去我们来看msg_recv函数中的msg_recv_chain,一样也是一个框架

4.终极将每1个conn请求对应的每3个conn响应发给客户端。

 1 struct conn {
 2    /*
 3     ...
 4    */
 5    int                 sd;              /* socket descriptor 套接字描述符*/    
 6    /*
 7     ...
 8    */
 9     conn_recv_t         recv;            /* recv (read) handler 接收msg函数指针*/
10     conn_recv_next_t    recv_next;       /* recv next message handler 接收下一个msg的函数指针*/
11     conn_recv_done_t    recv_done;       /* read done handler 接收完成的函数指针*/
12    /*
13     ...
14    */
15     size_t              recv_bytes;      /* received (read) bytes 接收数据的字节数*/
16     size_t              send_bytes;      /* sent (written) bytes 发送数据的字节数*/
17    /*
18     ...
19    */
20     err_t               err;             /* connection errno 接受数据错误*/
21     unsigned            recv_active:1;   /* recv active? 是否在接收数据*/
22     unsigned            recv_ready:1;    /* recv ready? 是否准备接收数据*/
23    /*
24     ...
25    */
26     unsigned            eof:1;           /* eof? aka passive close? 数据读到尾部*/
27     unsigned            done:1;          /* done? aka close? 完成数据接收*/
28     unsigned            redis:1;         /* redis?           网络协议是不是redis*/
29    /*
30     ...
31    */
32 };

 

 

继之,大家将服务层和客户层细分成五个模块,大家能够以为一是客户层接收,2是服务层发送,3是服务层接收,4是客户层发送。那样确实一,二步骤构成了图第11中学1一的nc_request.c的机要内容,而三,四整合了图1中11的nc_response.c的关键内容,如图4所示。

mbuf

 

在connection.h中

twemproxy的主干流程概述

别的,对于博文有题目标请大家在评价中留言与博主研商,博主会及时过来的!!!!

澳门金沙vip 1

在nc_message.h里

一.先是以十,1一为主线来观望整个程序的收发流程,因为大家驾驭作为1个缓存中间件代理,最关键的唯有是与客户端以及服务器的互相流程。

1 struct mbuf {
2     uint32_t           magic;   /* mbuf magic (const) 这个值不是很理解是什么意思,一般是0xdeadbeef*/
3     STAILQ_ENTRY(mbuf) next;    /* next mbuf 下一块mbuf,代码里所有的mbuf几乎都是以单向链表的形式存储的*/
4     uint8_t            *pos;    /* read marker 表示这块mbuf已经读到那个字节了*/
5     uint8_t            *last;   /* write marker 表示这块mbuf已经写到哪个字节*/
6     uint8_t            *start;  /* start of buffer (const) 表示这块mbuf的起始位置*/
7     uint8_t            *end;    /* end of buffer (const) 表示这块mbuf的结束位置*/
8 };
9 STAILQ_HEAD(mhdr, mbuf);    /*mhdr是mbuf单向队列的队列头部*/

那般我们得以将数据收发进度分成以下肆步:

在那个代码中大家又会发觉二个conn->recv_done,方今大家只要知道它是吸收停止的函数,一样不需求了然她的切实可行落到实处,因为它也是在《twemproxy代码框架概述——分析twemproxy代码前编》提到的客户层服务层扮演的剧中人物是例外的,为此,达成也是分裂的,这里根本指的是《twemproxy代码框架概述——剖判twemproxy代码前编》提到的澳门金沙vip,模块1模块3

三.接着等待接受来自服务端——redis服务集群的s_conn响应,通过那在此之前的照射关系将其和conn请求关联起来。

在redis包中大概会存在多key的景况,2个msg中的mbuf具体是怎么存的,还须要达成对于redis协议的解读,大家本事精通为啥须要msg_repair,,在此间稍稍挖个坑。近来我们得以通晓为它产生了四个新的nbuf去读下一轮的网络数据。

实则贰和肆是服从同3个出殡和埋葬流程msg_send,而一和3是根据同四个收到流程msg_recv。

在后面大家看到在代码中山高校量应用了断言**ASSERT**,如ASSERT(mbuf->end – mbuf->last >
0),就象征该内部存款和储蓄器还并未有被写满,查看这一个断言会使大家对代码有更加好的认知。同时,它也是四个很好的代码习于旧贯

如图1所示,src下的是大家最珍视的业务代码,这里有多少个重要的文件夹,一文本夹里的是网络编制程序模型,里面包括epoll,kqueue以及evport多少个常用的模型。二文书夹里的是哈希算法,其主要来哈希redis协议或许memcache协议的key,包蕴crc16,crc3二,MD5等哈希算法。三是相比较首要的文书,它是在这里不光成功了深入分析redis协议只怕memcache协议,还成功了那四个切磋的分片职业。

正文目的在于支持我们研商出twemproxy接收流程的代码逻辑框架,有个别具体的落到实处内需大家在今后抽空去查究依旧大家自行索求。在那篇小说开首前,我们要搞好二个相当的小的心情准备,由于twemproxy代码是一份精美的c语言代码,为此,在twemproxy的代码中会大篇幅使用c指针。不过不论是习感到常品种的指针依然函数指针,都能够让我们这么些c语言使用者大饱眼福,生出一种“原来还是能如此写!!!”的快感。

 除此以外,对于博文万分的请大家在商酌中留言与博主切磋,博主会及时复苏的!!!!

接着就是在connection.c中的接受函数conn_recv,比较轻松,一些对此收发网络数据蒙受的状态的拍卖值得学习

 

 

此地能够初阶窥视到twemproxy精致的代码结议和高可读性,通过查阅文件的名字,大家竟然能够大约YY出这些文件下的代码的意义,而且是八玖不离10。

本文实现了对于twemproxy整个接收流程的探求,首先介绍了相关的数据结构——mbuf、msg以及conn,在底下的光景里大家会越来越多地去询问它们,在以后的深入分析中它们是中流砥柱,接着深入分析了接受流程中的各种函数msg_repair、msg_parse、msg_parsed、msg_recv_chain、msg_recv以及conn_recv,最终较为介绍了它们在吸收中的功能,当然稍稍挖了多少个坑,表示之后再填。下面我们会入眼研究twemproxy的redis协议深入分析和twemproxy发送流程,敬请期待!!

然后,在图1中10的nc_message代码阅读中大家会发觉有四个非常重要流程:一个是发送流程msg_send和一个收受流程msg_recv

在研商twemproxy接收流程此前,大家亟须对部分我们会用到的数据结构举行验证,以便我们更加好地去商讨,这边在教师结构时,仅仅批注与twemproxy接收流程相关的代码,其余代码暂且不开始展览剖判。

二.再通过哈希conn请求的key值将其切分成具备一样key哈希值的呼吁——s_conn请求发给服务端——redis服务集群

先是看下重要流程,很轻巧的代码在nc_message.c中的msg_recv

本篇将去探究twemproxy源码的主干流程,想来对于想要开首啃那份不错源码生肉的童鞋会有相当的大的支援。这里大家首先要找到 twemproxy正确的张开药方式——twemproxy的文书结构,接着介绍twemproxy程序代码框架,最终介绍twemproxy程序的主干流程。主干流程是本章节的首要。本次注重是为了能将那份代码较为复杂的流水生产线实香港行政局地简约的模块分解和流程分解,以利于我们后边的开卷。

 

图叁. twemproxy流程细化图

如此那般我们完结了百分百接收流程的斟酌,至于发送流程须要在下多少个篇章中做到。

因此对源码文件结构的查究,大家明白了twemproxy的着力内容和关键点,分明了翻阅twemproxy代码的流程,接着深入分析twemproxy的大旨内容,我们综合出了大家前途读书代码的多个基本点流程即发送流程msg_send和收受流程msg_recv,还有五个关键模块即:客户层接收、服务层发送、服务层接收以及客户层发送,分明了逐一模块的功能、三个流程与种种模块的联络。下一章将第3达成四个重要流程代码的讲课。

上边正是剖判分包框架msg_parse

 

 1 static rstatus_t
 2 msg_parsed(struct context *ctx, struct conn *conn, struct msg *msg)
 3 {
 4     struct msg *nmsg;
 5     struct mbuf *mbuf, *nbuf;
 6 
 7     mbuf = STAILQ_LAST(&msg->mhdr, mbuf, next);
 8     if (msg->pos == mbuf->last) {//正好结束分包
 9         /* no more data to parse */
10         conn->recv_done(ctx, conn, msg, NULL);
11         return NC_OK;
12     }
13 
14     /*
15      * Input mbuf has un-parsed data. Split mbuf of the current message msg
16      * into (mbuf, nbuf), where mbuf is the portion of the message that has
17      * been parsed and nbuf is the portion of the message that is un-parsed.
18      * Parse nbuf as a new message nmsg in the next iteration.
19      */
20     //下面的所有工作就是把mbuf收到的网络数据,将不属于这个包msg的而属于下个包nmsg的内容分割出去放到下一个包nmsg
21     nbuf = mbuf_split(&msg->mhdr, msg->pos, NULL, NULL);
22     if (nbuf == NULL) {
23         return NC_ENOMEM;
24     }
25 
26     nmsg = msg_get(msg->owner, msg->request, conn->redis);
27     if (nmsg == NULL) {
28         mbuf_put(nbuf);
29         return NC_ENOMEM;
30     }
31     mbuf_insert(&nmsg->mhdr, nbuf);
32     nmsg->pos = nbuf->pos;
33 
34     /* update length of current (msg) and new message (nmsg)*/
35     nmsg->mlen = mbuf_length(nbuf);
36     msg->mlen -= nmsg->mlen;
37 
38     conn->recv_done(ctx, conn, msg, nmsg);
39 
40     return NC_OK;
41 }

一.twemproxy首先接受客户端发起的conn请求。

总结

此地还有几个第1的文件组,4是先后的进口,如图所示,main函数就在内部,伍是治本与客户端的接连,陆是用来分析配置文件的,7是达成了晶莹剔透连接池的,8是能够看出首要的程序流程,九是兑现了内存管理的内部存储器池,十是数额收发的主干流程,1壹是多少请求和响应,是多少收发流程10的具体贯彻,1二是用来管理与服务器的总是。

 1 static rstatus_t
 2 msg_parse(struct context *ctx, struct conn *conn, struct msg *msg)
 3 {
 4     rstatus_t status;
 5 
 6     if (msg_empty(msg)) {
 7         /* no data to parse */
 8         conn->recv_done(ctx, conn, msg, NULL);
 9         return NC_OK;
10     }
11 
12     msg->parser(msg);//解析函数器,这个我们会在后续的文章中提到,即完整的redis协议解析流程
13 
14     switch (msg->result) {
15     case MSG_PARSE_OK:
16         status = msg_parsed(ctx, conn, msg);//解析一个包完成,进行分包
17         break;
18 
19     case MSG_PARSE_REPAIR:
20         status = msg_repair(ctx, conn, msg);//将受到的网络数据分到不同的buffer中
21         break;
22 
23     case MSG_PARSE_AGAIN:
24         status = NC_OK;
25         break;
26 
27     default:
28         status = NC_ERROR;
29         conn->err = errno;
30         break;
31     }
32 
33     return conn->err != 0 ? NC_ERROR : status;
34 }

澳门金沙vip 2

 

本来接下去首先要上一幅图,便是twemproxy的公文结构图

澳门金沙vip 3

图4. twemproxy模块图

 1 rstatus_t
 2 msg_recv(struct context *ctx, struct conn *conn)
 3 {
 4     rstatus_t status;
 5     struct msg *msg;
 6 
 7     ASSERT(conn->recv_active);
 8 
 9     conn->recv_ready = 1;//表示准备接收网络数据
10     do {
11         msg = conn->recv_next(ctx, conn, true);
12         if (msg == NULL) {
13             return NC_OK;
14         }
15 
16         status = msg_recv_chain(ctx, conn, msg);//接收函数链,在这个流程中会改变conn->recv_ready的值,表示本次接收流程终止
17         if (status != NC_OK) {
18             return status;
19         }
20     } while (conn->recv_ready);//一旦不准备接收网络数据,就停止
21 
22     return NC_OK;
23 }

图一 文件结构图

上边正是msg_parsed,用于深入分析二个包完结后含有