关于协程栈。
原来的线程池模式,只有有限个线程,栈空间不是问题。
改成协程模式后,10000个客户端就是10000个协程,每个2M(实际上用过6M)栈的话就是20G。这对于转发器,一个小服务器来说,成本有点高。
我的解决方案如下:
连接到达时,也就是accept之后,分配了context,但是没有栈。直到它的呼叫请求被一个线程抓住,发现这个context没有栈,才给它分配一个栈(向下自增型)。这时,线程一个栈,context一个栈,共两个。
通过makecontext为协程设置一个入口点,swapcontext切换进入工作流程。
此时线程还在抓着这个协程,直到它进入IO,进行yield,才放手。
这个协程,几经转折,完成了任务,结束这次业务请求后,栈被收回。寄存在线程的工作空间。这个线程在接收到空栈的context时可以把这个栈空间转给新的context。线程只寄存一个栈空间。
分配和释放之间会有冲突,如果冲突了,就不分配。线程就直接以同步方式执行这个context。
它所调用的各种IO也都不会执行yield。这个线程就退化成接续模式。在压力测试中发现了这种退化。
【 在 wallyz 的大作中提到:
: 如果说"密钥协商,和登录认证"造成了“IO长时间占用线程”的话,那应该说明的是,之前“接续模式”的程序本身的IO方式有些问题
: 因为SSL_do_handshake本身支持以非阻塞方式进行,主要是适当的处理SL_ERROR_WANT_READ和SSL_ERROR_WANT_WRITE;
: 登录认证就更不用说了,肯定只是一些应用层的消息交互,如果设计没问题,这必然不可能造成IO长时间占用线程
: ...................
--
修改:ylh0315 FROM 221.218.61.*
FROM 221.218.61.*