新四季網

nginx如何同時配置反向與正向代理(反向代理及負載均衡)

2023-04-16 00:48:10

什麼是nginx?

總結送學習資料(包含視頻、技術學習路線圖譜、文檔等)

Nginx (engine x) 是一個高性能的HTTP和反向代理web伺服器…

除了反向代理,nginx還支持正向代理、負載均衡以及基於SSL安全證書的HTTPS訪問等功能特性~本文主要是介紹是如何配置nginx正向代理、反向代理及負載均衡,進入正文~

反向代理:看下面原理圖,就一目了然。其實客戶端對代理是無感知的,因為客戶端不需要任何配置就可以訪問,我們只需要將請求發送到反向代理伺服器,由反向代理伺服器去選擇目標伺服器獲取數據後,在返回給客戶端,此時反向代理伺服器和目標伺服器對外就是一個伺服器,暴露的是代理伺服器地址,隱藏了真實伺服器 IP位址。

一、代理服務

什麼是代理?來一張圖了解下

代理又分為正向代理和反向代理。

二、正向代理1.1 什麼是正向代理?

先來看張圖~

正向代理和反向代理的區別,一句話就是:如果我們客戶端自己用,就是正向代理。如果是在伺服器用,用戶無感知,就是反向代理。

2.Nginx配置文件

在學習 Nginx之前,要熟知它的配置文件,畢竟,下面需要做的所有配置(反向代理、負載均衡、動靜分離等),都是基於它的配置文件。

Nginx默認的配置文件是在安裝目錄下的 conf目錄下,後續對 Nginx的使用基本上都是對此配置文件進行相應的修改。完整的配置文件,可以看一下文章最後。修改過nginx.conf配置文件,記得要重啟Nginx服務(☆☆☆☆☆)

配置文件中有很多#號,該符號表示注釋內容,去掉所有以 #開頭的段落,精簡之後的配置文件內容如下(PS:其實注釋掉的地方,都是一些功能的使用代碼,需要用到的時候,取消注釋即可):

# 主進程叫master,負責管理子進程,子進程叫worker# worker_processes配置項表示開啟幾個業務進程,一般和cpu核數有關worker_processes 1;events { worker_connections 1024;}http { # include表示可以引入其他文件,此處表示引入http mime類型 include mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; # 虛擬主機,可以配置多個 server { listen 80; server_name localhost; location / { # 路徑匹配之後,哪個目錄下去匹配相應的網頁,html是相對路徑 root html; index index.html index.htm; } error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } }

去掉注釋信息後,可以將 nginx.conf 配置文件分為三部分:

2.1 第一部分:全局塊

worker_processes 1;

從配置文件開始到events塊之間的內容,主要會設置一些影響Nginx伺服器整體運行的配置指令,主要包括:配置運行Nginx伺服器的用戶(組)、允許生成的 worker process 數,進程PID存放路徑、日誌存放路徑和類型以及配置文件的引入等。

上面這行 worker_processes 配置,是 Nginx 伺服器是並發處理服務的關鍵配置,該值越大,可以支持的並發處理量也越多,但是會受到硬體、軟體等設備的約束。

2.2 第二部分:events 塊

events { worker_connections 1024;}

events 塊涉及的指令主要影響Nginx伺服器與用戶的網絡連接,常用的設置包括:是否開啟對多 work process下的網絡連接進行序列化,是否允許同時接收多個網絡連接,選取哪種事件驅動模型來處理連接請求,每個 work process 可以同時支持最大連接數等

上述例子就表示每個 work process 支持的最大連接數為 1024。這部分的配置對Nginx的性能影響較大,在實際中應該靈活配置。

2.3 第三部分:http 塊

http { include mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; server { listen 80; server_name localhost; location / { root html; index index.html index.htm; } error_page 500 502 503 504 /50x.html; location = /50x.html { root html; }}

這部分是 Nginx 伺服器配置中最頻繁的部分,代理、緩存和日誌定義等絕大多數功能和第三方模塊的配置都在這裡。需要注意的是:http 塊也可以包括 http 全局塊、server 塊。下面的反向代理、動靜分離、負載均衡都是在這部分中配置的

http 全局塊:http 全局塊配置的指令包括:文件引入、MIME-TYPE 定義、日誌自定義、連接超時時間、單連結請求數上限等。

server 塊:這塊和虛擬主機有密切關係,從用戶角度看,虛擬主機和一立的硬體主機是完全一樣的,該技術的產生是為了節省網際網路伺服器硬體成本。

每個http塊可以包括多個server塊,而每個server塊就相當於一個虛擬主機。而每個server塊也分為全局server塊,以及可以同時包含多個locaton塊。(☆☆☆☆☆)

2.3.1 全局 server 塊

最常見的配置是本虛擬機主機的監聽配置和本虛擬主機的名稱或IP配置。

2.3.2 location 塊

一個 server 塊可以配置多個 location 塊。

這塊的主要作用是:基於 Nginx 伺服器接收到的請求字符串(例如 server_name/uri-string),對虛擬主機名稱(也可以是 IP 別名)之外的字符串(例如 前面的 /uri-string)進行匹配,對特定的請求進行處理。地址定向、數據緩存和應答控制等功能,還有許多第三方模塊的配置也在這裡進行。

http { include mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; server { listen 80; server_name localhost; # 若請求路徑像這樣:www.xxxx/img/example.png # 則訪問/img/目錄下的文件時,nginx會去/var/www/image/img/目錄下找文件 location /img/ { root /var/www/image; } error_page 500 502 503 504 /50x.html; location = /50x.html { root html; }}

3. 反向代理如何配置3.1 反向代理實例一

實現效果:使用 Nginx 反向代理,訪問www.123.com直接跳轉到127.0.0.1:8080

注意:此處如果要想從www.123.com跳轉到本機指定的ip,需要修改本機的hosts文件。此處略過

配置代碼

如上配置,Nginx監聽 80埠,訪問域名為www.123.com(不加埠號時默認為 80埠),故訪問該域名時會跳轉到 127.0.0.1:8080 路徑上。

此處的意思為:nginx 反向代理服務監聽 192.168.17.129的80埠,如果有請求過來,則轉到proxy_pass配置的對應伺服器上,僅此而已。

在location下,同時配置root和proxy_pass選項時,兩個選項只會二選一執行

此處不能配置https反向代理

實驗結果:

3.2 反向代理實例二

實現效果:使用 Nginx 反向代理,根據訪問的路徑跳轉到不同埠的服務中,Nginx 監聽埠為 9001

訪問http://192.168.17.129/edu/直接跳轉到 127.0.0.1:8080

訪問http://192.168.17.129/vod/直接跳轉到 127.0.0.1:8081

第一步,需要準備兩個 tomcat,一個 8080 埠,一個 8081 埠,並準備好測試的頁面

第二步,修改 nginx 的配置文件,在 http 塊中配置 server

根據上面的配置,當請求到達 Nginx 反向代理伺服器時,會根據請求路徑不同進行分發到不同的服務上。

實驗結果:

補充:location 指令說明

該指令用於匹配 URL, 語法如下:

location [ = | ~ | ~* | ^~] uri {}

= :用於不含正則表達式的 uri 前,要求請求字符串與 uri 嚴格匹配,如果匹配成功,就停止繼續向下搜索並立即處理該請求

~:用於表示 uri 包含正則表達式,並且區分大小寫

~*:用於表示 uri 包含正則表達式,並且不區分大小寫

^~:用於不含正則表達式的 uri 前,要求 Nginx 伺服器找到標識 uri 和請求。字符串匹配度最高的 location 後,立即使用此 location 處理請求,而不再使用 location塊中的正則 uri 和請求字符串做匹配。

注意:如果 uri 包含正則表達式,則必須要有 ~ 或者 ~* 標識

Nginx完整配置文件

#user nobody;worker_processes 1;#error_log logs/error.log;#error_log logs/error.log notice;#error_log logs/error.log info;#pid logs/nginx.pid;events { worker_connections 1024;}http { include mime.types; default_type application/octet-stream; #log_format main '$remote_addr - $remote_user [$time_local] "$request" ' # '$status $body_bytes_sent "$http_referer" ' # '"$http_user_agent" "$http_x_forwarded_for"'; #access_log logs/access.log main; sendfile on; #tcp_nopush on; #keepalive_timeout 0; keepalive_timeout 65; #gzip on; server { listen 80; server_name localhost; #charset koi8-r; #access_log logs/host.access.log main; location / { root html; index index.html index.htm; } #error_page 404 /404.html; # redirect server error pages to the static page /50x.html # error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } # proxy the PHP scripts to Apache listening on 127.0.0.1:80 # #location ~ \.php$ { # proxy_pass http://127.0.0.1; #} # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 # #location ~ \.php$ { # root html; # fastcgi_pass 127.0.0.1:9000; # fastcgi_index index.php; # fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; # include fastcgi_params; #} # deny access to .htaccess files, if Apache's document root # concurs with nginx's one # #location ~ /\.ht { # deny all; #} } # another virtual host using mix of IP-, name-, and port-based configuration # #server { # listen 8000; # listen somename:8080; # server_name somename alias another.alias; # location / { # root html; # index index.html index.htm; # } #} # HTTPS server # #server { # listen 443 ssl; # server_name localhost; # ssl_certificate cert.pem; # ssl_certificate_key cert.key; # ssl_session_cache shared:SSL:1m; # ssl_session_timeout 5m; # ssl_ciphers HIGH:!aNULL:!MD5; # ssl_prefer_server_ciphers on; # location / { # root html; # index index.html index.htm; # } #}}

總結;

學習推薦;C/C Linux伺服器開發/後臺架構師【零聲教育】-學習視頻教程-騰訊課堂

Linux 線程池的概念與實現

2022-07-11 21:38·Linux特訓營

應用場景:

1、需要大量的線程來完成任務,且完成任務的時間比較短;

2、對性能要求苛刻的應用;

3、接受突發性的大量請求,但不至於使伺服器因此產生大量線程的應用

不使用線程池的情況:若是一個數據請求的到來伴隨一個線程去創建,就會產生一定的風險以及一些不必要的消耗。

1、線程若不限制數量的創建,在峰值壓力下,線程創建過多,資源耗盡,有程序崩潰的風險;

2、處理一個短時間任務時,會有大量的資源用於線程的創建與銷毀成本上。

功能:線程池是使用了已經創建好的線程進行循環處理任務,避免了大量線程的頻繁創建與銷毀的時間成本

如何實現一個線程池

線程池 = 大量線程 任務緩衝隊列

困難與解決方案:在創建線程時,都是伴隨創建線程的入口函數,一旦創建就無法改變,導致線程池進行任務處理的方式過於單一,靈活性太差。若任務隊列中的任務,不僅僅是單純的數據,而是包含處理任務方法在內的數據,這時候,線程池的線程是一條普通的執行流,只需要使用傳入的方法去處理數據即可。這樣子就可以提高線程池的靈活性

代碼實現流程:定義一個任務類Task,成員變量有要處理的數據_data和處理數據的方法_handler。成員函數有設置要處理數據和處理方式的函數setTask,還有一個處開始處理數據的函數run(創建線程時傳入的方法,由於創建線程必須有入口函數,這裡用run封裝所有的處理方式,讓所有線程都將run置為入口函數,就提高了線程池的靈活性)。再定義一個線程池類ThreadPool,成員變量有定義線程池中線程的最大數量thr_max,一個任務緩衝隊列_queue,一個互斥量_mutex,用於實現對緩衝隊列的安全性,一個條件變量_cond,用於實現線程池中線程的同步。

threadpool.hpp文件

//threadpool.hpp#include #include #include #include #include using namespace std;typedef void (*handler_t)(int);#define MAX_THREAD 5

//任務類

class ThreadTask{ public: ThreadTask { }、

//將數據與處理方式打包在一起

void setTask(int data, handler_t handler) { _data = data; _handler = handler; } //執行任務函數

void run { return _handler(_data); } private: int _data;

//任務中處理的數據

handler_t _handler;//

處理任務方式};//線程池類

class ThreadPool{ public: ThreadPool(int thr_max = MAX_THREAD) :_thr_max(thr_max) { pthread_mutex_init(&_mutex, NULL); pthread_cond_init(&_cond, NULL); for (int i = 0; i < _thr_max; i ) { pthread_t tid; int ret = pthread_create(&tid, NULL, thr_start, this); if (ret != 0) { printf("thread create error\n"); exit(-1); } } } ~ThreadPool { pthread_mutex_destroy(&_mutex); pthread_cond_destroy(&_cond); } bool taskPush(ThreadTask &task) { pthread_mutex_lock(&_mutex); _queue.push(task); pthread_mutex_unlock(&_mutex); pthread_cond_signal(&_cond); return true; } //

類的成員函數,有默認的隱藏參數this指針

//

置為static,沒有this指針,

static void *thr_start(void *arg) { ThreadPool *p = (ThreadPool*)arg; while (1) { pthread_mutex_lock(&p->_mutex); while (p->_queue.empty) { pthread_cond_wait(&p->_cond, &p->_mutex); } ThreadTask task; task =p-> _queue.front; p->_queue.pop; pthread_mutex_unlock(&p->_mutex); task.run;//

任務的處理要放在解鎖之外

} return NULL; } private: int _thr_max;//

線程池中線程的最大數量

queue _queue;//

任務緩衝隊列

pthread_mutex_t _mutex; //

保護隊列操作的互斥量

pthread_cond_t _cond; //

實現從隊列中獲取結點的同步條件變量

};

main.cpp

//main.cpp#include #include "threadpool.hpp"

//處理方法1

void test_func(int data){int sec = (data % 3) 1;printf("tid:%p -- get data:%d, sleep:%d\n", pthread_self, data, sec);sleep(sec);}

//處理方法2

void tmp_func(int data){printf("tid:%p -- tmp_func\n", pthread_self);sleep(1);}int main{ThreadPool pool;for (int i = 0; i < 10; i ){ThreadTask task;if (i % 2 == 0){task.setTask(i, test_func);}else{task.setTask(i, tmp_func);}pool.taskPush(task);}sleep(1000);return 0;}

運行結果:線程池最多有5個線程,標註的每種顏色對應的是同一個線程,這樣子就能完成通過幾個線程,完成多個任務,而不是多個線程完成多個任務。創建和銷毀的時間開銷也節省了不少

總結;

文章知識點與官方知識檔案匹配,可進一步學習相關知識

C/C Linux伺服器開發/後臺架構師【零聲教育】-學習視頻教程-騰訊課堂

學習路線圖;零聲教育 第11代 Linux C/C 後端伺服器架構開發 成長體系課程

更多視頻資料 課件 關注 後臺私信;資料;兩個字可以免費視頻領取 文檔 各大廠面試題 資料內容包括:C/C ,Linux,golang,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒體,CDN,P2P,K8S,Docker,TCP/IP,協程,DPDK,嵌入式 等。

,
同类文章
葬禮的夢想

葬禮的夢想

夢見葬禮,我得到了這個夢想,五個要素的五個要素,水火只好,主要名字在外面,職業生涯良好,一切都應該對待他人治療誠意,由於小,吉利的冬天夢想,秋天的夢是不吉利的
找到手機是什麼意思?

找到手機是什麼意思?

找到手機是什麼意思?五次選舉的五個要素是兩名士兵的跡象。與他溝通很好。這是非常財富,它擅長運作,職業是仙人的標誌。單身男人有這個夢想,主要生活可以有人幫忙
我不怎麼想?

我不怎麼想?

我做了什麼意味著看到米飯烹飪?我得到了這個夢想,五線的主要土壤,但是Tu Ke水是錢的跡象,職業生涯更加真誠。他真誠地誠實。這是豐富的,這是夏瑞的巨星
夢想你的意思是什麼?

夢想你的意思是什麼?

你是什​​麼意思夢想的夢想?夢想,主要木材的五個要素,水的跡象,主營業務,主營業務,案子應該抓住魅力,不能疏忽,春天夢想的吉利夢想夏天的夢想不幸。詢問學者夢想
拯救夢想

拯救夢想

拯救夢想什麼意思?你夢想著拯救人嗎?拯救人們的夢想有一個現實,也有夢想的主觀想像力,請參閱週宮官方網站拯救人民夢想的詳細解釋。夢想著敵人被拯救出來
2022愛方向和生日是在[質量個性]中

2022愛方向和生日是在[質量個性]中

[救生員]有人說,在出生88天之前,胎兒已經知道哪天的出生,如何有優質的個性,將走在什麼樣的愛情之旅,將與生活生活有什么生活。今天
夢想切割剪裁

夢想切割剪裁

夢想切割剪裁什麼意思?你夢想切你的手是好的嗎?夢想切割手工切割手有一個真正的影響和反應,也有夢想的主觀想像力。請參閱官方網站夢想的細節,以削減手
夢想著親人死了

夢想著親人死了

夢想著親人死了什麼意思?你夢想夢想你的親人死嗎?夢想有一個現實的影響和反應,還有夢想的主觀想像力,請參閱夢想世界夢想死亡的親屬的詳細解釋
夢想搶劫

夢想搶劫

夢想搶劫什麼意思?你夢想搶劫嗎?夢想著搶劫有一個現實的影響和反應,也有夢想的主觀想像力,請參閱週恭吉夢官方網站的詳細解釋。夢想搶劫
夢想缺乏缺乏紊亂

夢想缺乏缺乏紊亂

夢想缺乏缺乏紊亂什麼意思?你夢想缺乏異常藥物嗎?夢想缺乏現實世界的影響和現實,還有夢想的主觀想像,請看官方網站的夢想組織缺乏異常藥物。我覺得有些東西缺失了