本文主要是介绍redis源码阅读3----客户端连接过程,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
本章主要讨论在client连接到server时。server在ae过程中是如何处理的。
主要讨论的是接口函数。
由于是初次debug。为了保险起见我还是把断点打在了aemain上。
然后在客户端执行redis-cli -p 7000
然后执行到
if (eventLoop->beforesleep != NULL && flags & AE_CALL_BEFORE_SLEEP)
eventLoop->beforesleep(eventLoop);
时,连接redis server成功。也就是说,客户端连接部分的代码全在beforesleep(eventLoop);里。
我们接着往下看。
进入函数,进一步分析得到,处理链接在这一步进行:networking.c下
handleClientsWithPendingWritesUsingThreads();
首先判断这个队列下有没有元素,如果没有的话,这个函数就直接return了,上一章也分析过。
int processed = listLength(server.clients_pending_write);
此段注释:如果I/O线程被禁用,或者我们需要服务的客户机很少,就不要使用I/O线程,而是使用同步代码(synchronous code)。
这里的I/O线程被禁用不能理解,然后的话,这里客户机很少,从代码中不难看出,很少就是1个线程。
if (server.io_threads_num == 1 || stopThreadedIOIfNeeded()) {
return handleClientsWithPendingWrites();
}
然后我们看一下handleClientsWithPendingWrites()函数:
这个函数在进入事件循环前调用,可以直接将replies写入client output buffer,而不用进行syscall去安装writable event handler。
int handleClientsWithPendingWrites(void) {
listIter li;
listNode *ln;
int processed = listLength(server.clients_pending_write);
listRewind(server.clients_pending_write,&li);
while((ln = listNext(&li))) {
client *c = listNodeValue(ln);
c->flags &= ~CLIENT_PENDING_WRITE;
listDelNode(server.clients_pending_write,ln);
/* If a client is protected, don't do anything,
* that may trigger write error or recreate handler. */ 客户端受保护是什么状态。先留下疑问。
if (c->flags & CLIENT_PROTECTED) continue;
/* Don't write to clients that are going to be closed anyway. */这个很正常。对要关闭的client就不写入了
if (c->flags & CLIENT_CLOSE_ASAP) continue;
/* Try to write buffers to the client socket. */对客户端写入。这也是客户端连接的主要函数。writeToClient(c,0)
if (writeToClient(c,0) == C_ERR) continue;
/* If after the synchronous writes above we still have data to
* output to the client, we need to install the writable handler. */
if (clientHasPendingReplies(c)) {
int ae_barrier = 0;
/* For the fsync=always policy, we want that a given FD is never
* served for reading and writing in the same event loop iteration,
* so that in the middle of receiving the query, and serving it
* to the client, we'll call beforeSleep() that will do the
* actual fsync of AOF to disk. the write barrier ensures that. */
if (server.aof_state == AOF_ON &&
server.aof_fsync == AOF_FSYNC_ALWAYS)
{
ae_barrier = 1;
}
if (connSetWriteHandlerWithBarrier(c->conn, sendReplyToClient, ae_barrier) == C_ERR) {
freeClientAsync(c);
}
}
}
return processed;
}
未完待续
这篇关于redis源码阅读3----客户端连接过程的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!