4: 심층적인 Nginx 이벤트 및 연결(1부)
Nginx는 본질적으로 이벤트 중심 웹 서버입니다. 이벤트 처리 프레임워크가 해결해야 할 문제는 이벤트를 수집, 관리 및 배포하는 방법입니다.
이벤트는 주로
- 네트워크 이벤트(주로 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는 Nginx 모듈 인터페이스를 나타냅니다. 각 유형의 모듈에 대해 이 인터페이스는 ctx 멤버에 저장됩니다. ngx_module_t 구조의 핵심 모듈의 일반 인터페이스는 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_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_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>
웹 서버로서 Nginx는 활성 연결을 나타내기 위해
구조를 사용하여 다른 서버에 대한 연결도 시작해야 합니다. 대기 중인 연결의 많은 특성은 수동 연결 ngx_connection_t에 정의되어 있으므로 ngx_peer_connection_t 구조는 ngx_connection_t를 참조합니다. 구조. 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>

핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

Video Face Swap
완전히 무료인 AI 얼굴 교환 도구를 사용하여 모든 비디오의 얼굴을 쉽게 바꾸세요!

인기 기사

뜨거운 도구

메모장++7.3.1
사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전
중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기
강력한 PHP 통합 개발 환경

드림위버 CS6
시각적 웹 개발 도구

SublimeText3 Mac 버전
신 수준의 코드 편집 소프트웨어(SublimeText3)

뜨거운 주제











CONNECTION_REFUSED는 일반적으로 원격 서버에 연결을 시도할 때 발생하는 네트워크 연결 오류입니다. 클라이언트 장치가 서버와의 네트워크 연결 설정을 시도하고 서버가 연결 요청을 거부하면 CONNECTION_REFUSED 오류가 반환됩니다. 일반적인 이유는 다음과 같습니다: 서버가 시작되지 않음, 서버가 추가 연결 요청을 수락할 수 없음, 서버 방화벽이 연결을 차단함 등.

해결 방법: 1. 네트워크 연결을 확인합니다. 2. 서버 상태를 확인합니다. 3. 캐시와 쿠키를 삭제합니다. 4. 방화벽 및 보안 소프트웨어 설정을 확인합니다.

PHP를 사용하여 MySQL 데이터베이스에 연결할 때 PHPWarning:mysqli_connect():(HY000/2002):Connectionrefused 오류 메시지가 표시되는 경우 아래 단계에 따라 이 문제를 해결할 수 있습니다. MySQL 서비스가 정상적으로 실행되고 있는지 확인하려면 먼저 MySQL 서비스가 정상적으로 실행되고 있는지 확인해야 합니다. 서비스가 실행되지 않거나 시작되지 않는 경우 연결 거부 오류가 발생할 수 있습니다. 당신은 할 수

PHP8.0의 이벤트 처리 라이브러리: 이벤트 인터넷의 지속적인 발전과 함께 널리 사용되는 백엔드 프로그래밍 언어인 PHP는 다양한 웹 애플리케이션 개발에 널리 사용됩니다. 이 과정에서 이벤트 중심 메커니즘은 매우 중요한 부분이 되었습니다. PHP8.0의 이벤트 처리 라이브러리 Event는 보다 효율적이고 유연한 이벤트 처리 방법을 제공합니다. 이벤트 처리란 무엇입니까? 이벤트 처리는 웹 애플리케이션 개발에 있어 매우 중요한 개념입니다. 이벤트는 모든 종류의 사용자 행일 수 있습니다.

Steam의 여름 세일은 이전에 최고의 게임 할인 행사를 주최했으며 올해는 Valve가 또 다른 홈런을 치는 것으로 보입니다. Steam 여름 할인 할인 게임 중 일부를 소개하는 예고편(아래 보기)이 방금 출시되었습니다.

PHP에서 endif 키워드의 사용 시나리오 및 예 PHP 언어에서 endif 키워드는 조건문에서 코드의 가독성을 향상시키는 데 사용됩니다. 일반 if 문과 달리 endif 키워드를 사용하면 조건문의 끝을 더 명확하게 하여 코드를 더 간결하고 이해하기 쉽게 만들 수 있습니다. 이 기사에서는 endif 키워드의 사용 시나리오와 예를 소개합니다. 조건문에서 endif 키워드를 사용하는 시나리오 (1) 다수의 중첩 조건문 실제 개발에서는 다음과 같이 다층 중첩 조건문을 자주 접하게 됩니다.

Pygame의 이벤트 모듈 Event(Event)는 Pygame의 중요한 모듈 중 하나이며 일반적으로 사용되는 마우스 클릭, 키보드 탭, 게임 창 이동, 창 크기 조정, 특정 플롯 트리거 및 종료 등 전체 게임 프로그램을 구성하는 핵심입니다. .게임 등은 "이벤트"로 간주될 수 있습니다. 이벤트 유형 파이게임은 이벤트를 처리하는 데 특별히 사용되는 구조, 즉 이벤트 큐를 정의하는데, 이 구조는 큐에서 "선착순 처리"라는 기본 원칙을 따르며, 이벤트 큐를 통해 사용자 작업을 순차적으로 처리할 수 있습니다. -by-one 방식(트리거 이벤트). 다음 표에는 파이게임에서 일반적으로 사용되는 게임 이벤트가 나열되어 있습니다. 이름 설명 QUIT 사용자가 창의 닫기 버튼을 누릅니다. ATIVEEVENTPy

브라우저 크기가 조정될 때 JavaScript에서 창 크기를 가져오려면 window.outerWidth 및 window.outerHeight 이벤트를 사용하세요. 예제 다음 코드를 실행하여 이벤트 −<!DOCTYPEhtml><html> <script>&am을 사용하여 브라우저 창 크기를 확인할 수 있습니다.
