sách gpt4 ăn đã đi

Hãy để tôi cùng nhau phân tích ngắn gọn về kiến ​​trúc Nginx

In lại Tác giả: qq735679552 Thời gian cập nhật: 27-09-2022 22:32:09 30 4
mua khóa gpt4 giày nike

CFSDN nhấn mạnh vào giá trị tạo ra nguồn mở và chúng tôi cam kết xây dựng nền tảng chia sẻ tài nguyên để mọi nhân viên CNTT có thể tìm thấy thế giới tuyệt vời của bạn tại đây.

Bài viết blog CFSDN này cho phép mình phân tích sơ lược về kiến ​​trúc Nginx. Nó được tác giả sưu tầm và biên soạn. Nếu các bạn quan tâm đến bài viết này thì nhớ like nhé.

Hãy để tôi cùng nhau phân tích ngắn gọn về kiến ​​trúc Nginx

1. Cơ sở hạ tầng Nginx

  。

Sau khi nginx được khởi động, nó chạy ở chế độ nền dưới dạng daemon. Quá trình nền bao gồm một quy trình chính và nhiều quy trình công nhân. Như được hiển thị bên dưới:

Hãy để tôi cùng nhau phân tích ngắn gọn về kiến ​​trúc Nginx

chủ nhân。

nginx là một mô hình đa quy trình trong đó một quy trình chính quản lý quy trình và nhiều quy trình công nhân xử lý công việc. Thiết kế cơ sở hạ tầng, như thể hiện trong hình dưới đây:

Hãy để tôi cùng nhau phân tích ngắn gọn về kiến ​​trúc Nginx

Thiết kế cơ sở hạ tầng.

Master chịu trách nhiệm quản lý quy trình công nhân và quy trình công nhân chịu trách nhiệm xử lý các sự kiện mạng. Toàn bộ khung được thiết kế theo hướng sự kiện, không đồng bộ và không chặn.

Ưu điểm của thiết kế này:

  • 1. Có thể tận dụng tối đa các máy đa lõi và nâng cao khả năng xử lý đồng thời.
  • 2. Cân bằng tải có thể đạt được giữa nhiều công nhân.
  • 3.Master giám sát và quản lý thống nhất hành vi của người lao động. Sau khi ngoại lệ công nhân xảy ra, quy trình công nhân có thể được bắt đầu tích cực, từ đó cải thiện độ tin cậy của hệ thống. Ngoài ra, quy trình Chính kiểm soát việc nâng cấp chương trình, sửa đổi mục cấu hình và các hoạt động khác trong khi dịch vụ đang chạy, từ đó nâng cao khả năng mở rộng động tổng thể và khả năng cập nhật nóng.

2.Quy trình chính

  。

2.1 Logic cốt lõi.

Logic chính của quy trình chính là trong ngx_master_process_cycle và trọng tâm cốt lõi là mã nguồn:

  1. ngx_master_process_cycle(ngx_cycle_t *chu kỳ) 
  2.     ... 
  3.     ngx_start_worker_processes(chu kỳ, ccf->worker_processes, 
  4.                                         (Xử lý lỗi). 
  5.     ... 
  6.  
  7.  
  8.      ( ;; ) { 
  9.         nếu (trì hoãn) {...} 
  10.  
  11.         ngx_log_debug0(NGX_LOG_DEBUG_EVENT, chu kỳ->nhật ký, 0, "ngưng hoạt động"); 
  12.  
  13.         sigsuspend(&bộ); 
  14.  
  15.         ngx_time_update(); 
  16.  
  17.         ngx_log_debug1(NGX_LOG_DEBUG_EVENT, chu kỳ->nhật ký, 0, 
  18.                              "dậy đi, sigio %i", sigio); 
  19.  
  20.         nếu (ngx_reap) { 
  21.             ngx_reap = 0; 
  22.             ngx_log_debug0(NGX_LOG_DEBUG_EVENT, chu kỳ->nhật ký, 0, "gặt hái trẻ em"); 
  23.             live = ngx_reap_children(chu kỳ); 
  24.         } 
  25.  
  26.         nếu (!live && (ngx_terminate || ngx_quit)) {...} 
  27.  
  28.         nếu (ngx_terminate) {...} 
  29.  
  30.         nếu (ngx_quit) {...} 
  31.  
  32.         nếu (ngx_reconfigure) {...} 
  33.  
  34.         nếu (ngx_restart) {...} 
  35.  
  36.         nếu (ngx_reopen) {...} 
  37.  
  38.         nếu (ngx_change_binary) {...} 
  39.  
  40.         nếu (ngx_noaccept) { 
  41.             ngx_noaccept = 0; 
  42.             ngx_noaccepting = 1; 
  43.             ngx_signal_worker_processes(chu kỳ, 
  44.                                                   ngx_signal_value(NGX_SHUTDOWN_SIGNAL)); 
  45.         } 
  46.     } 
  47.  } 

Từ đoạn code trên có thể hiểu master tiến trình chủ yếu được sử dụng để quản lý tiến trình worker, bao gồm 4 chức năng chính sau:

1. Chấp nhận tín hiệu từ thế giới bên ngoài. Các bit cờ khác nhau trong vòng lặp chính tương ứng với các tín hiệu khác nhau. Ví dụ: ngx_quit đại diện cho tín hiệu QUIT, có nghĩa là tắt toàn bộ dịch vụ một cách nhẹ nhàng.

2. Gửi thư đến từng quy trình công nhân. Ví dụ: ngx_noaccept đại diện cho tín hiệu WINCH, có nghĩa là tất cả các tiến trình con không còn chấp nhận kết nối mới và chủ sẽ gửi các ngữ nghĩa QUIT tới tất cả các tiến trình con.

3. Theo dõi trạng thái chạy của quy trình công nhân. Ví dụ: ngx_reap đại diện cho tín hiệu CHILD, cho biết rằng một tiến trình con kết thúc bất ngờ. Tại thời điểm này, trạng thái chạy của tất cả các tiến trình con cần được theo dõi, việc này chủ yếu được thực hiện bởi ngx_reap_children.

4. Khi quá trình đánh thức thoát ra (trong những trường hợp bất thường), một quy trình đánh thức mới sẽ tự động được khởi động lại. Chủ yếu là trong ngx_reap_children.

2.2 Cập nhật nóng.

2.2.1 Cập nhật nóng cấu hình tải lại nóng.

Hãy để tôi cùng nhau phân tích ngắn gọn về kiến ​​trúc Nginx

Tải lại nóng.

Khi nginx hot-update cấu hình, cấu hình có thể được cập nhật mượt mà trong khi chạy. Quá trình cụ thể như sau:

  • 1. Cập nhật tệp cấu hình nginx.conf, gửi tín hiệu SIGHUP đến master hoặc thực thi nginx -s tải lại
  • 2. Quy trình chính sử dụng cấu hình mới và bắt đầu quy trình công nhân mới.
  • 3. Sử dụng quy trình Worker đã định cấu hình cũ, không còn chấp nhận các yêu cầu kết nối mới và thoát sau khi hoàn thành kết nối hiện có.

2.2.2 Hot nâng cấp - chương trình cập nhật nóng.

Hãy để tôi cùng nhau phân tích ngắn gọn về kiến ​​trúc Nginx

Nâng cấp nóng.

Quá trình nâng cấp nóng nginx như sau:

1. Thay thế file Nginx cũ bằng file Nginx mới (lưu ý sao lưu).

2. Gửi tín hiệu USR2 đến quy trình chính (nâng cấp dễ dàng lên phiên bản mới của chương trình Nginx).

3. Quy trình chính sửa đổi số tệp pid và thêm hậu tố .oldbin.

4. Quy trình chính bắt đầu quy trình chính mới với tệp Nginx mới. Tại thời điểm này, quy trình chính/công nhân cũ và mới tồn tại cùng một lúc.

5. Gửi tín hiệu WINCH đến chủ cũ, đóng quy trình công nhân cũ và quan sát điều kiện làm việc của quy trình công nhân mới. Nếu nâng cấp thành công, tín hiệu QUIT được gửi đến quy trình chính cũ và quy trình chính cũ sẽ bị đóng; nếu nâng cấp không thành công, nó cần được khôi phục, gửi tín hiệu HUP đến quy trình chính cũ (đọc lại tệp cấu hình) , gửi tín hiệu QUIT đến máy chủ mới và tắt máy chủ và máy chủ mới.

3.Quy trình công nhân

  。

3.1 Logic cốt lõi.

Logic chính của quy trình công nhân là trong ngx_worker_process_cycle và trọng tâm cốt lõi là mã nguồn:

  1. ngx_worker_process_cycle(ngx_cycle_t *chu kỳ, void *dữ liệu) 
  2.     ngx_int_t công nhân = (intptr_t) dữ liệu; 
  3.  
  4.     ngx_process = NGX_PROCESS_WORKER; 
  5.     ngx_worker = công nhân; 
  6.  
  7.     ngx_worker_process_init(chu kỳ, công nhân); 
  8.  
  9.     ngx_setproctitle("quy trình công nhân"); 
  10.  
  11.      ( ;; ) { 
  12.  
  13.         nếu (ngx_exiting) {...} 
  14.  
  15.         ngx_log_debug0(NGX_LOG_DEBUG_EVENT, chu kỳ->nhật ký, 0, "chu kỳ công nhân"); 
  16.  
  17.         ngx_process_events_and_timers(chu kỳ); 
  18.  
  19.         nếu (ngx_terminate) {...} 
  20.  
  21.         nếu (ngx_quit) {...} 
  22.  
  23.         nếu (ngx_reopen) {...} 
  24.     } 

Từ đoạn mã trên, có thể hiểu rằng quy trình worker chủ yếu xử lý các sự kiện mạng, được triển khai thông qua phương thức ngx_process_events_and_timers. Các sự kiện chủ yếu bao gồm: sự kiện mạng và sự kiện hẹn giờ.

3.2 epoll hướng sự kiện.

Khi quy trình công nhân xử lý các sự kiện mạng, nó dựa vào mô hình epoll để quản lý các kết nối đồng thời, đạt được các tính năng hướng sự kiện, không đồng bộ, không chặn và các tính năng khác. Như được hiển thị bên dưới:

Hãy để tôi cùng nhau phân tích ngắn gọn về kiến ​​trúc Nginx

infographic-Bên trong-NGINX_nonblocking 。

Thông thường, trong quá trình kết nối đồng thời lớn, tại mỗi thời điểm (một khoảng thời gian tương đối ngắn), chỉ một phần nhỏ kết nối với các sự kiện, tức là các kết nối đang hoạt động, cần được xử lý. Dựa trên hiện tượng trên, epoll đạt được khả năng xử lý IO mạng hiệu quả và ổn định bằng cách tách biệt quản lý kết nối và quản lý kết nối chủ động.

Hãy để tôi cùng nhau phân tích ngắn gọn về kiến ​​trúc Nginx

So sánh mô hình mạng

Trong số đó, epoll sử dụng hiệu quả bổ sung, xóa và truy vấn hiệu quả của cây đỏ đen để quản lý kết nối và sử dụng danh sách liên kết hai chiều để duy trì các kết nối hoạt động.

Hãy để tôi cùng nhau phân tích ngắn gọn về kiến ​​trúc Nginx

cấu trúc dữ liệu epoll

3.3 Sự việc.

Vì tất cả các công nhân đều được phân nhánh từ quy trình chính nên tất cả họ đều nghe cùng một cổng. Bằng cách này, nhiều tiến trình con sẽ cạnh tranh khi chấp nhận thiết lập kết nối, gây ra vấn đề "sấm sét bầy đàn" nổi tiếng. Mã lõi của logic xử lý lõi công nhân ngx_process_events_and_timers như sau:

  1. void ngx_process_events_and_timers(ngx_cycle_t *cycle){ 
  2.     // Ổ cắm nghe sẽ được xử lý ở đây. 
  3.     ... 
  4.  
  5.     nếu (ngx_accept_disabled > 0) { 
  6.             ngx_accept_disabled--; 
  7.     } khác { 
  8.         // Lấy khóa và tham gia bộ sưu tập chờ, 
  9.         nếu (ngx_trylock_accept_mutex(chu kỳ) == NGX_ERROR) { 
  10.             trở lại
  11.         } 
  12.         ... 
  13.         // Đặt cờ xử lý trì hoãn sự kiện đọc và ghi mạng, nghĩa là xử lý nó sau khi khóa được giải phóng 
  14.         nếu (ngx_accept_mutex_held) { 
  15.             cờ |= NGX_POST_EVENTS; 
  16.         } 
  17.     } 
  18.     ... 
  19.     // Ở đây epollwait chờ các sự kiện mạng 
  20.     //Sự kiện kết nối mạng, đưa vào hàng đợi ngx_posted_accept_events 
  21.     // Sự kiện đọc và ghi mạng, đưa vào hàng đợi ngx_posted_events 
  22.     (void) ngx_process_events(chu kỳ, bộ đếm thời gian, cờ); 
  23.     ... 
  24.     // Xử lý các sự kiện kết nối mạng trước tiên. Chỉ khi có được khóa thì mới có các sự kiện kết nối ở đây. 
  25.     ngx_event_process_posted(chu kỳ, &ngx_posted_accept_events); 
  26.     // Nhả khóa để các tiến trình khác có thể lấy được 
  27.     nếu (ngx_accept_mutex_held) { 
  28.         ngx_shmtx_unlock(&ngx_accept_mutex); 
  29.     } 
  30.     // Xử lý các sự kiện đọc và ghi mạng 
  31.     ngx_event_process_posted(chu kỳ, &ngx_posted_events); 

Từ đoạn mã trên, chúng ta có thể thấy rằng Nginx giải quyết được vấn đề về đàn sấm sét:

1. Tách biệt các sự kiện kết nối khỏi các sự kiện đọc và ghi. Các sự kiện kết nối được lưu trữ dưới dạng ngx_posted_accept_events và các sự kiện đọc và ghi được lưu trữ dưới dạng ngx_posted_events.

2. Đặt khóa ngx_accept_mutex. Chỉ quá trình lấy được khóa mới có thể xử lý các sự kiện kết nối.

3.4 Cân bằng tải.

Chìa khóa của tải giữa các công nhân nằm ở số lượng kết nối mà mỗi người có quyền truy cập. Điều kiện tiên quyết để lấy khóa kết nối truy cập là ngx_accept_disabled > 0, vì vậy ngx_accept_disabled là ngưỡng chính để triển khai cơ chế cân bằng tải.

  1. ngx_int_t ngx_accept_disabled; 
  2. ngx_accept_disabled = ngx_cycle->connection_n / 8 - ngx_cycle->free_connection_n; 

Do đó, khi nginx khởi động, giá trị của ngx_accept_disabled là số âm và giá trị của nó là 7/8 tổng số kết nối. Khi số lượng kết nối của tiến trình đạt 7/8 tổng số kết nối, tiến trình sẽ không còn xử lý các kết nối mới. Đồng thời, mỗi lần 'ngx_process_events_and_timers' được gọi, ngx_accept_disabled sẽ bị giảm đi 1 cho đến khi giá trị của nó. thấp hơn ngưỡng trước khi thử xử lý lại kết nối mới. Do đó, cân bằng tải giữa các quy trình con nginx worker sẽ chỉ được kích hoạt khi số lượng kết nối được xử lý bởi một quy trình worker đạt 7/8 trên tổng số quy trình tối đa của nó không được thỏa mãn khi bất kỳ điều kiện nào được đáp ứng. Như được hiển thị bên dưới:

Hãy để tôi cùng nhau phân tích ngắn gọn về kiến ​​trúc Nginx

Điều kiện làm việc thực tế.

Quy trình có 'pid' 1211 là quy trình chính và phần còn lại là quy trình công nhân.

4.Suy nghĩ

  。

4.1 Tại sao không sử dụng mô hình đa luồng để quản lý kết nối?

1. Dịch vụ không trạng thái, không cần chia sẻ bộ nhớ tiến trình.

2. Sử dụng các quy trình độc lập để chúng không ảnh hưởng lẫn nhau. Nếu một quy trình gặp sự cố bất thường, dịch vụ của các quy trình khác sẽ không bị gián đoạn, điều này giúp cải thiện độ tin cậy của kiến ​​trúc.

3. Tài nguyên không được chia sẻ giữa các quy trình và không yêu cầu khóa, do đó chi phí do khóa gây ra sẽ được loại bỏ.

4.2 Tại sao không sử dụng đa luồng để xử lý nghiệp vụ hợp lý?

1. Số lượng quy trình đã bằng số lượng lõi. Việc tạo các luồng mới để xử lý các tác vụ sẽ chỉ làm mất đi các quy trình hiện có và làm tăng chi phí chuyển đổi.

2. Là lớp truy cập, về cơ bản nó là công việc chuyển tiếp dữ liệu. Phần tốn thời gian chờ đợi của các tác vụ IO mạng đã được xử lý sang chế độ không chặn/hoàn toàn không đồng bộ/theo hướng sự kiện. có rất ít ý nghĩa. Và nếu có logic xử lý chặn trong quy trình thì mỗi doanh nghiệp nên giải quyết vấn đề này. Ví dụ: openResty sử dụng Lua coroutine để tối ưu hóa các dịch vụ chặn.

Địa chỉ gốc: https://zhuanlan.51cto.com/art/202104/656922.htm.

Cuối cùng, bài viết Hãy cùng tôi phân tích kiến ​​trúc Nginx kết thúc tại đây. Nếu bạn muốn biết thêm về Hãy để tôi cùng nhau phân tích kiến ​​trúc Nginx, vui lòng tìm kiếm các bài viết về CFSDN hoặc tiếp tục duyệt các bài viết liên quan. tương lai blog của tôi! .

30 4 0
qq735679552
Hồ sơ

Tôi là một lập trình viên xuất sắc, rất giỏi!

Nhận phiếu giảm giá taxi Didi miễn phí
Phiếu giảm giá taxi Didi
Chứng chỉ ICP Bắc Kinh số 000000
Hợp tác quảng cáo: 1813099741@qq.com 6ren.com
Xem sitemap của VNExpress