1. 程式人生 > >[nginx] upstream結束和keepalive實現

[nginx] upstream結束和keepalive實現

  • upstream請求結束:資料互動出錯、後端關閉socket時nginx接收到FIN、content-length資料已接收到
  • upstream結束的主函式ngx_http_upstream_finalize_request()
  • keepalive機制nginx長連線

一、upstream finalize

upstream請求結束分三種情況:

  1. read()、write()過程中出現NGX_ERROR/NGX_ABORT,表示請求過程中發生異常,設定p->upstream_error = 1
  2. read()函式時後端關閉socket,後端系統傳送FIN分節到nginx,接收到該訊號則設定rev->ready = 0
    p->upstream_eof = 1
  3. 正常情況下,upstream接收Header時會記錄content-length,然後接收body時減小p->length的值,當所有body接收完時p->length=0,並設定p->upstream_done = 1

分析ngx_http_upstream_finalize_request()

  • 清除cleanup指標,因為在upstream的前面階段:create、init、傳送請求、接收Headers時出現異常則會呼叫ngx_http_finalize_request(),並執行cleanup()的呼叫。所以這裡首先要清除cleanup指標;
  • u->finalize_request(),實際呼叫ngx_http_proxy_finalize_request,沒有任何操作;
  • u->peer.free(),實際呼叫’ngx_http_upstream_keepalive_close_handler()’進行peer的“關閉”操作;
  • 如果peer->connection不為空,則關閉connection,原因是上一步有可能是keepalive裡把connection放到cache裡後置為空,所以不用關閉connection;
  • ngx_http_send_special(),設定一個帶有last標誌的特殊buffer,告知資料傳送環節需要將之前快取而沒有傳送的buffer chain,傳送出去;
  • ngx_http_finalize_request(),結束請求
    • 如果還沒資料沒傳送完c->buffered不為0,則設定write控制代碼為ngx_http_write,表示要繼續傳送資料,在函式ngx_http_writengx_htt_finalize_request()是最後執行,形成遞迴;
    • 若資料傳送完了,則直接幹到這一行r->done = 1,標記結束,並把client的write控制代碼關閉
    • ngx_http_post_action(),若無後續操作,則無實際執行
    • 如果socket關閉了,會發送FIN分節,標記c->read->eof,執行ngx_http_close_request()關閉socket,????
    • ngx_http_finalize_connection(),關閉連結
      • 檢查請求的引用計數器,不等於1說明還有多個動作在操作著請求???(請求建立時ngx_http_create_request()該值賦為1);
      • 引用計數器為1時,檢查keepalive是否超時,接著結束keepalive請求返回;
      • 呼叫ngx_http_set_lingering_close(),預設lingering超時是5s
        • 設定ngx_http_lingering_close_handler()讀事件,意思客戶端在lingering_timeout時間內沒有進行任何操作,那麼就會關閉與客戶端的連線,如果有操作,也有總時間lingering_time超時,然後呼叫ngx_http_close_request()
        • ngx_shutdown_socket(fd, NGX_WRITE_SHUTDOWN)關閉socket寫端;
        • 呼叫ngx_http_lingering_close_handler(),進一步會ngx_http_free_request()列印請求日誌、釋放request,ngx_http_close_connection()中釋放connection,並ngx_close_socket(fd)回收描述符。lingering機制詳見nginx lingering_close,進一步也可以瞭解與之相關的case:nginx的延遲關閉

二、upstream keepalive

啟用nginx到upstream的keepalive,需要設定proxy http\1.1和覆蓋connection為空(nginx預設會置為close)。

2.1 資料傳送

  • ngx_http_proxy_create_request(),nginx首先準備好發向upstream的資料;
  • 呼叫uscf->peer.init(),實際呼叫ngx_http_upstream_init_keepalive_peer() ==> ngx_http_upstream_init_round_robin_peer(),通過負載均衡引擎獲取一個後端服務節點;
  • 是否連線該服務節點取決於keepalive queue中是否能從cache佇列線性查詢到該節點,若查詢到則從佇列中移出該節點,並將節點放到空閒佇列free;
  • ngx_http_upstream_send_request(),向該節點發送資料。

2.2 資料接收

  • 先接收upstream發來的Header,一邊接收一邊解析,直到完整接收到Header
  • nginx立即將Headers傳送給client,再接收Body,一邊從upstream接收一邊發往client,但這裡底層實際上是先buffer住,等所有資料接收完才發往client傳送資料;
  • 其中p->length記錄了待接收資料的長度(解析header時用content-length賦值給u->length然後呼叫ngx_http_proxy_input_filter_init()賦值給p->length),每次收到資料會減小,直到p->length為0時,會判斷connection_close(在http\1.0下預設為1否則為0),當upstream返回connection:close時設定為1,以決定是否keepalive;
  • 若遇到readv()返回0表示upstream傳送了FIN訊號而關閉的遠端socket,則nginx也後續相應關閉連結;
  • 最後若對方socket未關閉、socket未出錯、keepalive,則會把後端節點的連線物件存放到cache佇列頭部,如果佇列滿了,則釋放列隊尾部的一個元素,LRU淘汰策略。

相關推薦

[nginx] upstream結束keepalive實現

upstream請求結束:資料互動出錯、後端關閉socket時nginx接收到FIN、content-length資料已接收到 upstream結束的主函式:ngx_http_upstream_finalize_request() keepa

Nginx IIS 實現動靜分離(轉)

host rar web應用 localhost nginx服務器 .net 復雜 jpeg post 轉載地址:https://www.cnblogs.com/paul8339/p/5825201.html 動靜分離,說白了,就是將網站靜態資源(HTML,JavaScr

nginx+keepalive實現高可用負載均衡

keepalived+nginx高可實驗一:實驗環境 主nginx負載均衡器:192.168.10.63 (通過keepalived配置了VIP:192.168.10.188供外使用)副nginx負載均衡器:192.168.10.200(通過keepalived配置了VIP:192.168.10.188供外

memcached實現主主復制keepalive高可用方式

ali 上進 endif alived 函數 相同 pri face 軟件 實驗拓撲 實驗環境 服務器 IP地址 操作系統 主要軟件 memcached1 192.168.144.122 centos7.3 libevent2.1.8、memcached1.

專案部署、收集靜態檔案、nginxuwsgi實現負載均衡。

專案部署 1)靜態檔案伺服器 ​ 開發階段: live-server ​ 部署階段: nginx ​ 域名: www.meiduo.site Django專案靜態檔案收集: # 設定setting配置檔案 STATIC_ROOT = '指定收集靜態檔案的儲存目錄'

nginx upstream實現

很多其他模組會呼叫該模組完成對後端伺服器的訪問 upstream模組還是一個http模組,所有它自己必須要實現一些特定的介面: 1.static ngx_command_t ngx_http_upstream_commands[] = { { ngx_string("upstream

配置Keepalive實現nginx高可用

搭建環境 已關閉防火牆,關閉selinux; 所用伺服器IP地址如下: IP地址 伺服器 服務 192.168.91.129 master ke

Nginx + Tomcat基於HTTP協議實現反代、動靜分離、負載均衡session會話保持

1、演示環境: IP 作業系統 部署程式 192.168.1.143 CentOS 7.5 Nginx 192.168.1.144 CentOS 7.5 Tomcat

c++用cingetline實現輸入回車結束輸入

今天做一道測試題遇到了一個麻煩,我想要先讀入一個字串,再讀入一個整數,迴圈往復,直到字串是空,也就是說回車鍵結束迴圈。 最開始的想法是: string s;int d; while(cin>>s){ cin>>d; // prece

nginx工作原理實現高併發請求的原因

一、程序、執行緒?程序是具有一定獨立功能的,在計算機中已經執行的程式的實體。在早期系統中(如linux 2.4以前),程序是基本運作單位,在支援執行緒的系統中(如windows,linux2.6)中,執行緒才是基本的運作單位,而程序只是執行緒的容器。程式 本身只是指令、資料及

iOS直播--Nginx伺服器搭建RTMP,HLS推流實現

Nginx介紹Nginx ("engine x") 是一個高效能的HTTP和反向代理伺服器,也是一個IMAP/POP3/SMTP伺服器。Nginx是由Igor Sysoev為俄羅斯訪問量第二的Rambler.ru站點開發的,第一個公開版本0.1.0釋出於2004年10月

nginx upstream 配置實現多伺服器無感知切換

 在開發過程中,開發完成,完成測試階段,修復bug後都要重啟後臺服務,測試又在測試,每次重啟都要一兩分鐘,平凡的重啟,測試不幹了;所以想到就是部署兩臺伺服器;用nginx upstream 模組實現 無感知部署,發現一個bug,修復;直接部署不會打斷測試; 原來的測試環境部

Android自動接聽結束通話電話實現原理

轉自:http://bbs.51cto.com/thread-1078059-1.html 一  前言 這兩天要研究類似白名單黑名單以及手勢自動接聽的一些功能,所以呢,自然而然的涉及到怎麼自動接聽/結束通話電話的功能了。 對於自動接聽這一塊,android4.1

nginx反向代理負載均衡以及故障移除的實現

本次教程採用兩臺伺服器,每臺伺服器上安裝一個Nginx和一個Tomcat 兩臺伺服器地址如下: 192.168.211.131 43.226.35.137 首先在兩臺伺服器分別安裝Tomcat 安裝了兩臺不同版本的Tomcat用來區分 接下

keepalive高可用nginxnginx動靜分離)的實現

clust 修改配置 lin F12 ice ifconfig img 修改配置文件 51cto HA Cluster的配置前提: 1、各節點時間要同步; 2、確保iptables及selinux不會成為障礙; 3、(可選)各

lvs的natdr實現nginx反向代理,虛擬主機

html servers 參數 網絡拓撲 nag sysctl version conn keepal 1.LVS的基本用法 1.管理工具:ipvsadm2.基本概念 VS:Virtual Server,調度器 RS:Real Server(lvs), upstream

Nginx總結(五)如何配置nginxtomcat實現反向代理

前面講了如何配置Nginx虛擬主機,大家可以去這裡看看nginx系列文章:https://www.cnblogs.com/zhangweizhong/category/1529997.html 今天要說的是如何配置nginx和tomcat實現反向代理。   什麼是反向代理   &

通過Nginx、Consul、Upsync實現動態負載均衡服務平滑釋出

## 前提 前段時間順利地把整個服務叢集和中介軟體全部從`UCloud`遷移到阿里雲,筆者擔任了架構和半個運維的角色。這裡詳細記錄一下通過`Nginx`、`Consul`、`Upsync`實現動態負載均衡和服務平滑釋出的核心知識點和操作步驟,整個體系已經在生產環境中平穩執行。編寫本文使用的虛擬機器系統為`C

jsjquery實現回到頂層

left ret poi add 寬度 fadein soft 距離 jquery實現 js <!DOCTYPE html> <html> <head> <title>返回頂部</title> <styl

使用GridViewSimpleAdapter實現手機界面常見的九宮格

adapt height lns androi code 兩個 sha itme find 首先是兩個XML界面: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:androi