memcached的学习(9)

2018.6.14
之前学习了memcached的网络模型,主要是服务于多个客户端TCP连接的网络模型创建,也是CS架构上我们值得学习的一个模型,在设计网络模型的时候可以学习这种框架。今天来学习memcached的命令解析,也就是接收到了网络传来的数据包,按照不同的命令解析,并调用不同的功能模块。

————————————————————————————————————————————
我们回顾上一章发现Memcached会分成主线程和N个工作线程。主线程主要用于监听accpet客户端的Socket连接,而工作线程主要用于接管具体的客户端连接。

主线程和工作线程之间主要通过基于Libevent的pipe的读写事件来监听,当有连接练上来的时候,主线程会将连接交个某一个工作线程去接管,后期客户端和服务端的读写工作都会在这个工作线程中进行。

工作线程也是基于Libevent的事件的,当有读或者写的事件进来的时候,就会触发事件的回调函数。那么Memcached是如何来解析客户端上传的命令数据报文的呢?这一章我们详细讲解命令的解析过程?

Memcached的命令解析源码分析

conn数据结构

每一个连接都会有自己的一个conn数据结构。这个结构主要存储每个连接的基本信息。
这一章中用到的几个比较重要的参数:

char * rbuf:用于存储客户端数据报文中的命令。
int rsize:rbuf的大小。
char * rcurr:未解析的命令的字符指针。
int rbytes:未解析的命令的长度。

数据结构含义如下:
在这里插入图片描述

整体流程

  1. 当客户端和Memcached建立TCP连接后,Memcached会基于Libevent的event事件来监听客户端是否有可以读取的数据。
  2. 当客户端有命令数据报文上报的时候,就会触发drive_machine方法中的conn_read这个Case。
  3. memcached通过try_read_network方法读取客户端的报文。如果读取失败,则返回conn_closing,去关闭客户端的连接;如果没有读取到任何数据,则会返回conn_waiting,继续等待客户端的事件到来,并且退出drive_machine的循环;如果数据读取成功,则会将状态转交给conn_parse_cmd处理,读取到的数据会存储在c->rbuf容器中。
  4. conn_parse_cmd主要的工作就是用来解析命令。主要通过try_read_command这个方法来读取c->rbuf中的命令数据,通过\n来分隔数据报文的命令。如果c->buf内存块中的数据匹配不到\n,则返回继续等待客户端的命令数据报文到来conn_waiting;否则就会转交给process_command方法,来处理具体的命令(命令解析会通过\0符号来分隔)。
  5. process_command主要用来处理具体的命令。其中tokenize_command这个方法非常重要,将命令拆解成多个元素(KEY的最大长度250)。例如我们以get命令为例,最终会跳转到process_get_command这个命令 process_*_command这一系列就是处理具体的命令逻辑的。
  6. 我们进入process_get_command,当获取数据处理完毕之后,会转交到conn_mwrite这个状态。如果获取数据失败,则关闭连接。
  7. 进入conn_mwrite后,主要是通过transmit方法来向客户端提交数据。如果写数据失败,则关闭连接或退出drive_machine循环;如果写入成功,则又转交到conn_new_cmd这个状态。
  8. conn_new_cmd这个状态主要是处理c->rbuf中剩余的命令。主要看一下reset_cmd_handler这个方法,这个方法回去判断c->rbytes中是否还有剩余的报文没处理,如果未处理,则转交到conn_parse_cmd(第四步)继续解析剩余命令;如果已经处理了,则转交到conn_waiting,等待新的事件到来。在转交之前,每次都会执行一次conn_shrink方法。
  9. conn_shrink方法主要用来处理命令报文容器c->rbuf和输出内容的容器是否数据满了?是否需要扩大buffer的大小,是否需要移动内存块。接受命令报文的初始化内存块大小2048,最大8192。

状态机的整理变换过程如下:
在这里插入图片描述

命令rbuf数据结构变化图:

1.读取客户端的数据
在这里插入图片描述
2.解析buf中的命令。如果遇到\n,则表明是一个命令语句的结尾标识符。
在这里插入图片描述
3.命令拆分。命令解析出来之后,对命令进行分解,分解是通过空格来分离的。第一个参数一般为操作方法,第二个参数一般为KEY。
在这里插入图片描述

4.内存块重设置。如果rbuf内存块使用空间不足,或者大于8k,则需要进行重新分配内存块。
在这里插入图片描述
————————————————————————————————————————————

具体分析:

从上面的分析流程来看,通过event记录的回调函数来捕捉读写事件的触发,下面就以一个get命令,分析,是如何接收到命令,解析,执行,并返回给客户端的过程。
在这里插入图片描述
这里只是分析了从客户端发送的命令,进行取命令,解析命令,执行命令,打包返回结果,再次取新命令的执行过程,而打包返回结果在发送给客户端是memcached的回应消息的过程,这一过程也比较复杂,我们在之后在分析。

思考与分析:

这里我们可以学习到的是,memcached的解析命令并处理的过程,以及对于不合适命令,不符合格式命令的处理,对于多客户端连接、缓冲大小限制的处理。涉及到命令处理的过程,都可以很好的借鉴memcached的处理方式。

猜你喜欢

转载自blog.csdn.net/u012414189/article/details/84317267
今日推荐