検索
ホームページバックエンド開発PHPチュートリアル4: Nginx の詳細なイベントと接続 (パート 1)

Nginx は本質的にイベント駆動型の Web サーバーです。イベント処理フレームワークが解決する必要がある問題は、イベントを収集、管理、配布する方法です。
イベントは主に

  • ネットワーク イベント (主に TCP ネットワーク イベント)
  • タイマー イベント

Nginx はコア モジュール ngx_event_module を定義しています。Nginx のモジュール化の詳細と全体像を理解するには、ブログを参照してください。Nginx は、開始時に呼び出します ngx_init_cycle メソッドが設定ファイルを解析するときに、対象の「events {}」設定項目が nginx.conf で見つかると、ngx_event_module モジュールが動作を開始します。コア モジュール ngx_event_module 内の ngx_event_core_module モジュールは、このモジュールが使用するイベント駆動型メカニズムとイベントの管理方法を定義します。

イベントモジュールは新しいモジュールタイプです。nginx_module_tは、異なるタイプのモジュールごとに、このタイプのモジュールの共通インターフェースを記述する構造体があります。このインターフェースは、ngx_module_t構造体に保存されます。 ctxのメンバー。コア モジュールの一般インターフェイスは ngx_core_module_t で、イベントの一般インターフェイスは ngx_event_module_t 構造体です。

<code><span>typedef</span><span>struct</span> {
<span>//位于文件 ngx_event.h</span><span>//事件模块 的名字</span>
    ngx_str_t              *name;
    <span>//在解析 配置前,这个回调 方法用于创建存储配置选项参数的结构体</span><span>void</span>                 *(*create_conf)(ngx_cycle_t *cycle);
    <span>// 在解析配置项完成 之后,init_conf方法会被调用,用以综合处理当前事件模块感兴趣的全部配置项</span><span>char</span>                 *(*init_conf)(ngx_cycle_t *cycle, <span>void</span> *conf);
    <span>// 对于事件驱动机制,每个事件模块需要实现10个抽象方法 </span>
    ngx_event_actions_t     actions;
} ngx_event_module_t;</code>

ngx_event_module_tactions メンバーは、イベント駆動型モジュールの定義。 ngx_event_module_t中的actions成员是定义事件驱动模块的核心方法。

<code><span>typedef</span><span>struct</span> {
    <span>/* 添加事件方法,它将负责把1个感兴趣 事件添加到操作 系统提供的事件驱动机制 */</span>
    ngx_int_t  (*add)(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags);
    <span>/*删除事件方法,它将1个已经存在于事件驱动机制中的事件移除 */</span>
    ngx_int_t  (*del)(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags);
    <span>/*启用 1个 事件,目前事件框架不会调用 这个 方法,大部分事件驱动模块对于该方法的实现都是与上面的add方法完全一致的*/</span>
    ngx_int_t  (*enable)(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags);
    <span>/*禁用1个事件,目前事件框架不会 调用这个方法 ,大部分事件驱动器对于这个方法的实现与上面的del方法完全一致*/</span>
    ngx_int_t  (*disable)(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags);
    <span>/*向事件驱动机制中添加一个新的连接,这意味着连接上的读写事件都添加到事件驱动机制中*/</span>
    ngx_int_t  (*add_conn)(ngx_connection_t *c);
    <span>/*从事件驱动机制中移除一个连接的读写事件*/</span>
    ngx_int_t  (*del_conn)(ngx_connection_t *c, ngx_uint_t flags);
    <span>/*仅在多线程环境下会被调用,目前Nginx在产品环境下还不会以多线程方式运行*/</span>
    ngx_int_t  (*notify)(ngx_event_handler_pt handler);
    <span>/*在正常的工作循环中,将调用process_events方法来 处理事件*/</span>
    ngx_int_t  (*process_events)(ngx_cycle_t *cycle, ngx_msec_t timer,
                                 ngx_uint_t flags);
   <span>/*初始化事件驱动模块的方法*/</span>
    ngx_int_t  (*init)(ngx_cycle_t *cycle, ngx_msec_t timer);
    <span>// 退出事件驱动模块前调用的方法</span><span>void</span>       (*done)(ngx_cycle_t *cycle);
} ngx_event_actions_t;</code>

ngx_event_core_module 和9个事件驱动模块都必须ngx_module_t结构体的ctx成员 实现ngx_event_module_t 接口

<code><span>struct</span> ngx_event_s {
    <span>/*事件相关的对象,通常data指向ngx_connection_t连接对象。开启文件异步I/O 时,它可能会指向*/</span><span>void</span>            *data;
     <span>/* 标志位,标识事件可写,意味着对应的TCP连接可写,也即连接处于发送网络包状态 */</span><span>unsigned</span>         write:<span>1</span>;
     <span>/* 标志位,标识可建立新的连接,一般是在ngx_listening_t对应的读事件中标记 */</span><span>unsigned</span>         accept:<span>1</span>;
     <span>/*检测当前事件是否是过期的,它仅仅是给驱动模块使用的,而事件消费模块可以不用关心 */</span><span>/* used to detect the stale events in kqueue and epoll */</span><span>unsigned</span>         instance:<span>1</span>;

    <span>/*
     * the event was passed or would be passed to a kernel;
     * in aio mode - operation was posted.
     */</span><span>unsigned</span>         active:<span>1</span>;

    <span>unsigned</span>         disabled:<span>1</span>;

    <span>/* the ready event; in aio mode 0 means that no operation can be posted */</span><span>unsigned</span>         ready:<span>1</span>;

    <span>unsigned</span>         oneshot:<span>1</span>;

    <span>/* aio operation is complete */</span><span>unsigned</span>         complete:<span>1</span>;

    <span>unsigned</span>         eof:<span>1</span>;
    <span>unsigned</span>         error:<span>1</span>;

    <span>unsigned</span>         timedout:<span>1</span>;
    <span>unsigned</span>         timer_set:<span>1</span>;

    <span>unsigned</span>         delayed:<span>1</span>;

    <span>unsigned</span>         deferred_accept:<span>1</span>;

    <span>/* the pending eof reported by kqueue, epoll or in aio chain operation */</span><span>unsigned</span>         pending_eof:<span>1</span>;

    <span>unsigned</span>         posted:<span>1</span>;

    <span>unsigned</span>         closed:<span>1</span>;

    <span>/* to test on worker exit */</span><span>unsigned</span>         channel:<span>1</span>;
    <span>unsigned</span>         resolver:<span>1</span>;

    <span>unsigned</span>         cancelable:<span>1</span>;

<span>#if (NGX_WIN32)</span><span>/* setsockopt(SO_UPDATE_ACCEPT_CONTEXT) was successful */</span><span>unsigned</span>         accept_context_updated:<span>1</span>;
<span>#endif</span><span>#if (NGX_HAVE_KQUEUE)</span><span>unsigned</span>         kq_vnode:<span>1</span>;

    <span>/* the pending errno reported by kqueue */</span><span>int</span>              kq_errno;
<span>#endif</span><span>/*
     * kqueue only:
     *   accept:     number of sockets that wait to be accepted
     *   read:       bytes to read when event is ready
     *               or lowat when event is set with NGX_LOWAT_EVENT flag
     *   write:      available space in buffer when event is ready
     *               or lowat when event is set with NGX_LOWAT_EVENT flag
     *
     * epoll with EPOLLRDHUP:
     *   accept:     1 if accept many, 0 otherwise
     *   read:       1 if there can be data to read, 0 otherwise
     *
     * iocp: TODO
     *
     * otherwise:
     *   accept:     1 if accept many, 0 otherwise
     */</span><span>#if (NGX_HAVE_KQUEUE) || (NGX_HAVE_IOCP)</span><span>int</span>              available;
<span>#else</span><span>unsigned</span>         available:<span>1</span>;
<span>#endif</span>    ngx_event_handler_pt  handler;


<span>#if (NGX_HAVE_IOCP)</span>
    ngx_event_ovlp_t ovlp;
<span>#endif</span>    ngx_uint_t       index;

    ngx_log_t       *<span>log</span>;

    ngx_rbtree_node_t   timer;

    <span>/* the posted queue */</span>
    ngx_queue_t      <span>queue</span>;

<span>#if 0</span><span>/* the threads support */</span><span>/*
     * the event thread context, we store it here
     * if $(CC) does not understand __thread declaration
     * and pthread_getspecific() is too costly
     */</span><span>void</span>            *thr_ctx;

<span>#if (NGX_EVENT_T_PADDING)</span><span>/* event should not cross cache line in SMP */</span>    uint32_t         padding[NGX_EVENT_T_PADDING];
<span>#endif</span><span>#endif</span>
};


<span>#if (NGX_HAVE_FILE_AIO)</span><span>struct</span> ngx_event_aio_s {
    <span>void</span>                      *data;
    ngx_event_handler_pt       handler;
    ngx_file_t                *file;

<span>#if (NGX_HAVE_AIO_SENDFILE)</span>
    ssize_t                  (*preload_handler)(ngx_buf_t *file);
<span>#endif</span>    ngx_fd_t                   fd;

<span>#if (NGX_HAVE_EVENTFD)</span>
    int64_t                    res;
<span>#endif</span><span>#if !(NGX_HAVE_EVENTFD) || (NGX_TEST_BUILD_EPOLL)</span>
    ngx_err_t                  err;
    size_t                     nbytes;
<span>#endif</span>    ngx_aiocb_t                aiocb;
    ngx_event_t                event;
};

<span>#endif</span></code>

Nginx的连接

 被动连接

这种连接是指 客户端发起的,服务器被动接受的连接

<code><span>//在 文件ngx_connection.h中</span><span>struct</span> ngx_connection_s {
  <span>/*  连接未使用时,data成员用于充当连接池中空闲链表中的next指针。当连接被使用时,data的意义由使用它的Nginx模块而定。在HTTP模块中,data指向ngx_http_request_t请求*/</span><span>void</span>               *data;
    <span>// 连接对应的读事件 </span>
    ngx_event_t        *read;
    <span>// 连接对应的写事件 </span>
    ngx_event_t        *write;
    <span>// 套接字句柄 </span>
    ngx_socket_t        fd;
    <span>//直接接收网络字符流的方法</span>
    ngx_recv_pt         recv;
    <span>// 直接发送网络字符流的办法</span>
    ngx_send_pt         send;
    <span>// 以ngx_chain_t链表为 参数来 接收 网络 字符流的方法 </span>
    ngx_recv_chain_pt   recv_chain;
    <span>// 以ngx_chain_t链表为 参数来 发送 网络 字符流的方法 </span>
    ngx_send_chain_pt   send_chain;
    <span>/*这个连接对应的ngx_listening_t监听对象,此连接由listening监听端口的事件建立*/</span>
    ngx_listening_t    *listening;
    <span>//这个连接上已经发送出去的字节数</span>
    off_t               sent;
    <span>// 可以记录日志的ngx_log_t对象</span>
    ngx_log_t          *<span>log</span>;
    <span>/* 内存池。一般在accept一个新连接时,会创建一个 内存池,而在这个 连接结束时会销毁内存池。所有的ngx_connectionn_t结构 体都是预分配,这个内存池的大小将由上面的listening 监听对象中的 pool_size成员决定*/</span>
    ngx_pool_t         *pool;

    <span>int</span>                 type;
    <span>// 连接客户端的sockaddr结构体</span><span>struct</span> sockaddr    *sockaddr;
    <span>// 连接 sockaddr结构体的 长度</span>
    socklen_t           socklen;
    <span>// 连接客户端字符串形式的IP地址</span>
    ngx_str_t           addr_text;

    ngx_str_t           proxy_protocol_addr;

    in_port_t           proxy_protocol_port;

<span>#if (NGX_SSL)</span>
    ngx_ssl_connection_t  *ssl;
<span>#endif</span><span>/*本机监听端口 对应 的sockaddr结构 体 ,也就是listening监听对象中的sock
    addr成员*/</span><span>struct</span> sockaddr    *local_sockaddr;
    socklen_t           local_socklen;
     <span>/*用于接收、缓存客户端 发来的字节流,每个事件消费模块可自由决定从连接池中分配多大空间给 buffer这个 缓存字段*/</span>
    ngx_buf_t          *buffer;

    ngx_queue_t         <span>queue</span>;
    <span>// 连接使用次数。ngx_connection_t结构体每次建立一条来自客户端的连接,或者主动向后端服务器发起连接时,number都会加1*/</span>
    ngx_atomic_uint_t   number;
    <span>// 处理 请求次数</span>
    ngx_uint_t          requests;

    <span>unsigned</span>            buffered:<span>8</span>;

    <span>unsigned</span>            log_error:<span>3</span>;     <span>/* ngx_connection_log_error_e */</span><span>unsigned</span>            timedout:<span>1</span>;
    <span>unsigned</span>            error:<span>1</span>;
    <span>unsigned</span>            destroyed:<span>1</span>;

    <span>unsigned</span>            idle:<span>1</span>;
    <span>unsigned</span>            reusable:<span>1</span>;
    <span>unsigned</span>            close:<span>1</span>;
    <span>unsigned</span>            shared:<span>1</span>;

    <span>unsigned</span>            sendfile:<span>1</span>;
    <span>unsigned</span>            sndlowat:<span>1</span>;
    <span>unsigned</span>            tcp_nodelay:<span>2</span>;   <span>/* ngx_connection_tcp_nodelay_e */</span><span>unsigned</span>            tcp_nopush:<span>2</span>;    <span>/* ngx_connection_tcp_nopush_e */</span><span>unsigned</span>            need_last_buf:<span>1</span>;

<span>#if (NGX_HAVE_IOCP)</span><span>unsigned</span>            accept_context_updated:<span>1</span>;
<span>#endif</span><span>#if (NGX_HAVE_AIO_SENDFILE)</span><span>unsigned</span>            busy_count:<span>2</span>;
<span>#endif</span><span>#if (NGX_THREADS)</span>
    ngx_thread_task_t  *sendfile_task;
<span>#endif</span>
};</code>

主动连接

作为Web服务器,Nginx也需要向其他服务器发起连接,使用ngx_peer_connection_t

<code><span>// 当使用长连接与上游服务器通信时,可通过该方法由连接池获取 一个新的连接</span><span>typedef</span> ngx_int_t (*ngx_event_get_peer_pt)(ngx_peer_connection_t *pc,
    <span>void</span> *data);
<span>// 当 使用长连接与上游服务器通信时,通过该方法 将使用完毕 的连接释放给连接池</span><span>typedef</span><span>void</span> (*ngx_event_free_peer_pt)(ngx_peer_connection_t *pc, <span>void</span> *data,
    ngx_uint_t state);
<span>struct</span> ngx_peer_connection_s {
    <span>/*一个主动连接实际 上也需要ngx_connection_t结构体的大部分成员,并且处于重用的考虑 而定义 了connecion*/</span>
    ngx_connection_t                *connection;
    <span>// 远端服务器的socketaddr</span><span>struct</span> sockaddr                 *sockaddr;
    <span>// sockaddr地址长度</span>
    socklen_t                        socklen;
    <span>// 远端服务器的名称 </span>
    ngx_str_t                       *name;
    <span>// 表示在连接 一个 远端服务器,当前连接出现 异常失败后可以重试的次数,也就是允许的最多失败的次数</span>
    ngx_uint_t                       tries;
    ngx_msec_t                       start_time;

    ngx_event_get_peer_pt            get;
    ngx_event_free_peer_pt           <span>free</span>;
    <span>void</span>                            *data;

<span>#if (NGX_SSL)</span>
    ngx_event_set_peer_session_pt    set_session;
    ngx_event_save_peer_session_pt   save_session;
<span>#endif</span><span>// 本机地址信息 </span>
    ngx_addr_t                      *local;

    <span>int</span>                              type;
    <span>// 套接字的接收缓冲区大小</span><span>int</span>                              rcvbuf;
    <span>// 记录日志的ngx_log_t对象</span>
    ngx_log_t                       *<span>log</span>;

    <span>unsigned</span>                         cached:<span>1</span>;
<span>#if (NGX_HAVE_TRANSPARENT_PROXY)</span><span>unsigned</span>                         transparent:<span>1</span>;
<span>#endif</span><span>/* ngx_connection_log_error_e */</span><span>unsigned</span>                         log_error:<span>2</span>;
};</code>
ngx_event_core_module と 9 つのイベント駆動型モジュールは、ngx_module_t 構造体の ctx メンバーに ngx_event_module_t インターフェイスを実装する必要がありますrrreee

Nginx 接続

パッシブ接続

🎜🎜この種類の接続は、クライアントサーバーによって受動的に受け入れられます。 接続🎜🎜rrreee🎜アクティブ接続🎜🎜 Web サーバーとして、Nginx は、アクティブな接続の多くの特性を表すために ngx_peer_connection_t 構造体を使用する必要もあります。保留中の接続はパッシブ接続 ngx_connection_t に定義されているため、ngx_connection_t 構造体は ngx_peer_connection_t 構造体で参照されます。 🎜rrreee🎜').addClass('事前番号付け').hide(); $(this).addClass('has-numbering').parent().append($numbering); for (i = 1; i 🎜').text(i)); }; $numbering.fadeIn(1700); }); }); 🎜 🎜 以上、パート 4: Nginx の詳細なイベントと接続 (パート 1) を紹介しました。内容の側面も含めて、PHP チュートリアルに興味のある友人に役立つことを願っています。 🎜 🎜 🎜
声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
誇大広告を超えて:今日のPHPの役割の評価誇大広告を超えて:今日のPHPの役割の評価Apr 12, 2025 am 12:17 AM

PHPは、特にWeb開発の分野で、最新のプログラミングで強力で広く使用されているツールのままです。 1)PHPは使いやすく、データベースとシームレスに統合されており、多くの開発者にとって最初の選択肢です。 2)動的コンテンツ生成とオブジェクト指向プログラミングをサポートし、Webサイトを迅速に作成および保守するのに適しています。 3)PHPのパフォーマンスは、データベースクエリをキャッシュおよび最適化することで改善でき、その広範なコミュニティと豊富なエコシステムにより、今日のテクノロジースタックでは依然として重要になります。

PHPの弱い参照は何ですか、そしていつ有用ですか?PHPの弱い参照は何ですか、そしていつ有用ですか?Apr 12, 2025 am 12:13 AM

PHPでは、弱い参照クラスを通じて弱い参照が実装され、ガベージコレクターがオブジェクトの回収を妨げません。弱い参照は、キャッシュシステムやイベントリスナーなどのシナリオに適しています。オブジェクトの生存を保証することはできず、ごみ収集が遅れる可能性があることに注意する必要があります。

PHPで__invoke Magicメソッドを説明してください。PHPで__invoke Magicメソッドを説明してください。Apr 12, 2025 am 12:07 AM

\ _ \ _ Invokeメソッドを使用すると、オブジェクトを関数のように呼び出すことができます。 1。オブジェクトを呼び出すことができるように\ _ \ _呼び出しメソッドを定義します。 2。$ obj(...)構文を使用すると、PHPは\ _ \ _ Invokeメソッドを実行します。 3。ロギングや計算機、コードの柔軟性の向上、読みやすさなどのシナリオに適しています。

同時性については、PHP 8.1の繊維を説明します。同時性については、PHP 8.1の繊維を説明します。Apr 12, 2025 am 12:05 AM

繊維はPhp8.1で導入され、同時処理機能が改善されました。 1)繊維は、コルーチンと同様の軽量の並行性モデルです。 2)開発者がタスクの実行フローを手動で制御できるようにし、I/O集約型タスクの処理に適しています。 3)繊維を使用すると、より効率的で応答性の高いコードを書き込むことができます。

PHPコミュニティ:リソース、サポート、開発PHPコミュニティ:リソース、サポート、開発Apr 12, 2025 am 12:04 AM

PHPコミュニティは、開発者の成長を支援するための豊富なリソースとサポートを提供します。 1)リソースには、公式のドキュメント、チュートリアル、ブログ、LaravelやSymfonyなどのオープンソースプロジェクトが含まれます。 2)StackOverFlow、Reddit、およびSlackチャネルを通じてサポートを取得できます。 3)開発動向は、RFCに従うことで学ぶことができます。 4)コミュニティへの統合は、積極的な参加、コード共有への貢献、および学習共有への貢献を通じて達成できます。

PHP対Python:違いを理解しますPHP対Python:違いを理解しますApr 11, 2025 am 12:15 AM

PHP and Python each have their own advantages, and the choice should be based on project requirements. 1.PHPは、シンプルな構文と高い実行効率を備えたWeb開発に適しています。 2。Pythonは、簡潔な構文とリッチライブラリを備えたデータサイエンスと機械学習に適しています。

PHP:それは死にかけていますか、それとも単に適応していますか?PHP:それは死にかけていますか、それとも単に適応していますか?Apr 11, 2025 am 12:13 AM

PHPは死にかけていませんが、常に適応して進化しています。 1)PHPは、1994年以来、新しいテクノロジーの傾向に適応するために複数のバージョンの反復を受けています。 2)現在、電子商取引、コンテンツ管理システム、その他の分野で広く使用されています。 3)PHP8は、パフォーマンスと近代化を改善するために、JITコンパイラおよびその他の機能を導入します。 4)Opcacheを使用してPSR-12標準に従って、パフォーマンスとコードの品質を最適化します。

PHPの未来:適応と革新PHPの未来:適応と革新Apr 11, 2025 am 12:01 AM

PHPの将来は、新しいテクノロジーの傾向に適応し、革新的な機能を導入することで達成されます。1)クラウドコンピューティング、コンテナ化、マイクロサービスアーキテクチャに適応し、DockerとKubernetesをサポートします。 2)パフォーマンスとデータ処理の効率を改善するために、JITコンパイラと列挙タイプを導入します。 3)パフォーマンスを継続的に最適化し、ベストプラクティスを促進します。

See all articles

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

SublimeText3 Linux 新バージョン

SublimeText3 Linux 新バージョン

SublimeText3 Linux 最新バージョン

mPDF

mPDF

mPDF は、UTF-8 でエンコードされた HTML から PDF ファイルを生成できる PHP ライブラリです。オリジナルの作者である Ian Back は、Web サイトから「オンザフライ」で PDF ファイルを出力し、さまざまな言語を処理するために mPDF を作成しました。 HTML2FPDF などのオリジナルのスクリプトよりも遅く、Unicode フォントを使用すると生成されるファイルが大きくなりますが、CSS スタイルなどをサポートし、多くの機能強化が施されています。 RTL (アラビア語とヘブライ語) や CJK (中国語、日本語、韓国語) を含むほぼすべての言語をサポートします。ネストされたブロックレベル要素 (P、DIV など) をサポートします。

AtomエディタMac版ダウンロード

AtomエディタMac版ダウンロード

最も人気のあるオープンソースエディター

DVWA

DVWA

Damn Vulnerable Web App (DVWA) は、非常に脆弱な PHP/MySQL Web アプリケーションです。その主な目的は、セキュリティ専門家が法的環境でスキルとツールをテストするのに役立ち、Web 開発者が Web アプリケーションを保護するプロセスをより深く理解できるようにし、教師/生徒が教室環境で Web アプリケーションを教え/学習できるようにすることです。安全。 DVWA の目標は、シンプルでわかりやすいインターフェイスを通じて、さまざまな難易度で最も一般的な Web 脆弱性のいくつかを実践することです。このソフトウェアは、

VSCode Windows 64 ビットのダウンロード

VSCode Windows 64 ビットのダウンロード

Microsoft によって発売された無料で強力な IDE エディター