PHP非同期プログラミング、非同期の本質
2465 ワード
非同期を実現する方法はどれらがありますか?
非同期化を実現する方法は次のとおりです.スレッド方式 プロセス方式 IO多重 スレッド方式はプロセス方式と同様で、非同期要求がある場合、1つのスレッドまたはプロセスを開き、データを取得すると、スレッド間で直接データを共有することができる.プロセス間では、共有メモリ、パイプなどのプロセス通信機構によりデータ転送を行うことができる.考え方は簡単で、この記事を参考にしてswooleを利用することができます.プロセスとeventloopはphp非同期プログラミングを実現するが、欠点は非常に明らかで、オーバーヘッドが大きすぎて、1つの非同期要求は、1つのスレッドまたはプロセスを開く.
IO多重方式は、通常
非同期
重要なのはこの部分です.
swoole
はいくつかの非同期方法を提供していますが、それらの下位層はどのような方法で実現されていますか?非同期化を実現する方法は次のとおりです.
IO多重方式は、通常
select
,poll
,epoll
といういくつかの方式があり、現在最も流行しているのは当然epoll
であり、性能がよく、理論的には接続制限がなく、単一プロセス内で数十万の接続を維持することができる.この方式を用いると、非同期要求がある場合、現在のプロセス内で、もう一つの接続を非同期要求とすることができ、オーバーヘッドが少なく、性能がよく、主流の非同期実現はこの方式である.swoole
はいくつかの非同期http client
,mysql client
を提供し、http server
とmysql server
に非同期でアクセスすることができ、コールバック方式で返されたデータを処理することができ、それらの使用方法はIO多重化である.swoole
のソースコードを見てみましょう.非同期
tcp
リクエストstatic int swClient_tcp_connect_async(swClient *cli, char *host, int port, double timeout, int nonblock)
{
int ret;
cli->timeout = timeout;
//alloc input memory buffer
cli->buffer = swString_new(cli->buffer_input_size);
if (!cli->buffer)
{
return SW_ERR;
}
if (!(cli->onConnect && cli->onError && cli->onClose))
{
swWarn("onConnect/onError/onClose callback have not set.");
return SW_ERR;
}
if (swClient_inet_addr(cli, host, port) < 0)
{
return SW_ERR;
}
while (1)
{
ret = connect(cli->socket->fd, (struct sockaddr *) &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)
{
return SW_ERR;
}
return SW_OK;
}
return ret;
}
重要なのはこの部分です.
if (SwooleG.main_reactor->add(SwooleG.main_reactor, cli->socket->fd, cli->reactor_fdtype | SW_EVENT_WRITE) < 0)
{
return SW_ERR;
}
return SW_OK;
socket fd
をreactor
に入れて傍受することであり、本質的にはepoll
であり、IO多重技術である.