实现异步的方式有哪些?swoole提供了一些异步的方法,那么底层是怎么实现的呢?实现异步的方式有:线程模式进程模式IO多路复用线程模式类似于进程模式,当有异步请求时,开启一个线程或进程,线程获取到数据后可以直接共享数据。进程之间可以通过共享内存、管道等进程通信机制来传输数据,思路很简单,可以参考这篇文章使用swoole_process和eventloop实现php异步编程,但是缺点非常明显,开销太大,一个异步请求需要开一个线程或者进程。IO多路复用方式通常有select、poll、epoll,当然目前最流行的是epoll,性能好,理论上没有连接数限制,单个进程可以维持几十万个连接数。使用这种方式,当有异步请求时,可以在当前进程中再开启一个连接进行异步请求,开销很小,性能非常好,主流的异步实现都是这种方式。swoole提供了一些异步的http客户端,mysql客户端,可以让你异步访问http服务器和mysql服务器,通过回调处理返回的数据。使用方式是IO多路复用。看一段swoole的源码:asynchronoustcprequeststaticintswClient_tcp_connect_async(swClient*cli,char*host,intport,doubletimeout,intnonblock){intret;cli->超时=超时;//分配输入内存缓冲区cli->buffer=swString_new(cli->buffer_input_size);如果(!cli->缓冲区){返回SW_ERR;}if(!(cli->onConnect&&cli->onError&&cli->onClose)){swWarn("onConnect/onError/onClose回调没有set.");returnSW_ERR;}if(swClient_inet_addr(cli,host,port)<0){returnSW_ERR;}while(1){ret=connect(cli->socket->fd,(structsockaddr*)&cli->server_addr.addr,cli->server_addr.len);if(ret<0){if(errno==EINTR){continue;}SwooleG.error=errno;}break;}if((ret<0&&errno==EINPROGRESS)||ret==0){if(SwooleG.main_reactor->add(SwooleG.main_reactor,cli->socket->fd,cli->reactor_fdtype|SW_EVENT_WRITE)<0){returnSW_ERR;}returnSW_OK;}returnret;}关键看这段:if(SwooleG.main_reactor->add(SwooleG.main_reactor,cli->socket->fd,cli->reactor_fdtype|SW_EVENT_WRITE)<0){returnSW_ERR;}returnSW_OK;就是把socketfd放到reactor里面去监听,本质上就是epoll,也就是IO多路复用技术。
