一、工作原理
nginx的高效能主要是因為
1、事件驅動架構
Nginx採用事件驅動的非阻塞方式處理請求,主要利用了作業系統提供的多路複用機制,透過非同步非阻塞的方式處理大量併發請求,減少了執行緒切換和資源消耗,提高了併發處理能力和系統的穩定性。
2、事件迴圈
事件迴圈機制是核心的工作模式之一。它透過單執行緒的方式處理事件,包括等待事件、處理事件和繼續迴圈。在等待事件時,Nginx並不會像傳統多執行緒模型那樣阻塞等待,而是透過事件通知機制在有事件發生時再進行處理,這樣可以充分利用CPU資源,提升系統的效率和效能。
3、多程序
Nginx可以透過配置檔案中的worker_processes
選項來啟動多個程序來處理請求。每個程序都有自己獨立的事件迴圈和資源管理,程序之間沒有共享狀態,這種設計可以避免單點故障,提高系統的可靠性和穩定性。並且Nginx的多程序模型使得它能夠更好地利用多核CPU,透過並行處理請求來提高整體的處理能力。
二、反向代理
server {
listen 80;
server_name example.com;
root /root/build/;#靜態資源地址
index index.html;
location /api/server/ {
proxy_pass http://localhost:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For
}
}
例如在這個例子中,設定了index目錄和靜態資源目錄。並且設定了域名訪問。很大了保證了伺服器的安全性。在下面的反向代理配置中,透過正規表示式將/api/server/開頭的對映到http://localhost:8080這個地址。
三、負載均衡
負載均衡也就是透過反向代理到不同的服務,保證服務的可用性。多用於在分散式系統中。例如某個系統分佈在100個伺服器上,當某幾臺伺服器崩潰時,會代理到其他伺服器,不會影響系統的執行。更好的實現橫向擴充套件。
例如一個簡單的get請求程式碼
import tornado.ioloop
import tornado.web
class MainHandler(tornado.web.RequestHandler):
def get(self):
self.write("Hello, Tornado!")
def make_app():
return tornado.web.Application([
(r"/", MainHandler),
])
if __name__ == "__main__":
app = make_app()
app.listen(8888)
print("Server running on http://localhost:8888")
tornado.ioloop.IOLoop.current().start()
具體的負載均衡演算法
1、輪詢
nginx的均衡預設演算法:直接基於事件迴圈。類似於排隊,一個一個來,例如第一個請求分發給第一個服務,第二個就分發給第二個服務,以此類推。缺點:沒有具體情況具體分析,某些情況下的請求會導致負載很高。
upstream tornado_servers {
server 192.168.31.158:8888;
server localhost:8888;
}
server {
listen 80;
server_name 192.168.62.132;
location / {
proxy_pass http://tornado_servers;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
location /nginx_status {
stub_status on;
access_log off;
allow 192.168.62.0/24; # 允許訪問的IP地址,根據需要調整
deny all; # 禁止其他IP地址訪問
}
}
將上述訪問執行在兩個不同的伺服器上,預設的輪詢會每個伺服器都請求一次,除非有一臺掉線,否則nginx會均分請求。
下面行的localhost塊b表示新的匹配規則,用於檢視nginx當前的連線數和請求統計資訊。
server accepts handled requests
Active connections: 1
表示當前活躍的連線數,即正在與Nginx伺服器建立通訊的客戶端連線數量。
server accepts handled requests
accepts: 表示Nginx已經接受的連線總數。
handled: 表示Nginx已經處理的連線總數。
requests: 表示Nginx已經處理的請求總數。
Reading: 0 Writing: 1 Waiting: 0
Reading: 正在讀取客戶端請求的數量。
Writing: 正在向客戶端傳送響應的數量。
Waiting: 當前空閒的客戶端連線數,等待處理請求
2、最少連線
會將請求分配給連線最少的服務,保證系統的整體效能。缺點是沒有具體情況具體分析,沒有考慮負載情況,不是請求越多負載越大。
upstream tornado_servers {
least_conn; # 使用最少連線數演算法
server 192.168.31.158:8888;
server localhost:8888;
}
server {
listen 80;
server_name 192.168.62.132;
location / {
proxy_pass http://tornado_servers;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
least_conn
欄位表示使用最少連線演算法。
3、IP雜湊
透過客戶端的IP地址的雜湊值分配給特定的伺服器,如果下一次請求的IP雜湊值與之前一樣,那麼依然會請求到之前的伺服器。如果不一樣那麼為新的伺服器建立新的雜湊值。這樣避免了伺服器的切換開銷,保持了會話的一致性。但是這樣的缺點是同一個客戶端的請求無法做到負載均衡。
upstream tornado_servers {
ip_hash; # 使用IP雜湊演算法
server 192.168.31.158:8888;
server localhost:8888;
}
server {
listen 80;
server_name 192.168.62.132;
location / {
proxy_pass http://tornado_servers;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
location /nginx_status {
stub_status on;
access_log off;
allow 192.168.62.0/24; # 允許訪問的IP地址,根據需要調整
deny all; # 禁止其他IP地址訪問
}
}
4、加權輪詢
在輪詢的基礎上為每個伺服器加上一個權重值,每個伺服器的承受連線數量。在輪詢的情況下再次考慮權重值。例如兩臺伺服器,伺服器A、B的權重分別為5,3輪詢流程為:
第一次請求:伺服器A處理請求
第二次請求:伺服器B處理請求
第三次請求:伺服器A處理請求
第四次請求:伺服器A處理請求
第五次請求:伺服器A處理請求
第六次請求:伺服器B處理請求
upstream tornado_servers {
server 192.168.31.158:8888 weight=5;
server localhost:8888 weight=3;
}
server {
listen 80;
server_name 192.168.62.132;
location / {
proxy_pass http://tornado_servers;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
location /nginx_status {
stub_status on;
access_log off;
allow 192.168.62.0/24; # 允許訪問的IP地址,根據需要調整
deny all; # 禁止其他IP地址訪問
}
}
5、加權最小連線
在最小連線的演算法基礎上,加上權重值。這時候需要根據連線數量和權重值來評估目標伺服器。
例如伺服器A、B、C。權重值分別為5、3、2。連線數分別為10、5、3.
計算加權連線數:
伺服器A:10/5=2
伺服器B:5/3=1.67
伺服器C:3/2=1.5
那麼根據加權連線數,最小加權連線數為1.5。那麼會代理到伺服器C
upstream tornado_servers {
least_conn; # 使用最少連線數演算法
server 192.168.31.158:8888 weight=5;
server localhost:8888 weight=3;
}
server {
listen 80;
server_name 192.168.62.132;
location / {
proxy_pass http://tornado_servers;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
location /nginx_status {
stub_status on;
access_log off;
allow 192.168.62.0/24; # 允許訪問的IP地址,根據需要調整
deny all; # 禁止其他IP地址訪問
}
}
四、總結
反向代理就像是位於使用者和真實伺服器之間的一座橋樑,它接收使用者的請求並將其轉發到後端的多臺伺服器上。這種配置不僅隱藏了真實伺服器的資訊,還能提供安全性和負載均衡功能。負載均衡透過智慧地分發請求到不同的伺服器,確保每臺伺服器的負載相對平衡,從而提高整體效能和可靠性。這種結合能夠有效地處理高併發請求,保證系統在壓力下仍能保持穩定執行。