PHP非同期プログラミング、非同期の本質


非同期を実現する方法はどれらがありますか?swooleはいくつかの非同期方法を提供していますが、それらの下位層はどのような方法で実現されていますか?
非同期化を実現する方法は次のとおりです.
  • スレッド方式
  • プロセス方式
  • IO多重
  • スレッド方式はプロセス方式と同様で、非同期要求がある場合、1つのスレッドまたはプロセスを開き、データを取得すると、スレッド間で直接データを共有することができる.プロセス間では、共有メモリ、パイプなどのプロセス通信機構によりデータ転送を行うことができる.考え方は簡単で、この記事を参考にしてswooleを利用することができます.プロセスとeventloopはphp非同期プログラミングを実現するが、欠点は非常に明らかで、オーバーヘッドが大きすぎて、1つの非同期要求は、1つのスレッドまたはプロセスを開く.
    IO多重方式は、通常select,poll,epollといういくつかの方式があり、現在最も流行しているのは当然epollであり、性能がよく、理論的には接続制限がなく、単一プロセス内で数十万の接続を維持することができる.この方式を用いると、非同期要求がある場合、現在のプロセス内で、もう一つの接続を非同期要求とすることができ、オーバーヘッドが少なく、性能がよく、主流の非同期実現はこの方式である.swooleはいくつかの非同期http client,mysql clientを提供し、http servermysql 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 fdreactorに入れて傍受することであり、本質的にはepollであり、IO多重技術である.