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"
//處理方法1void test_func(int data){int sec = (data % 3) 1;printf("tid:%p -- get data:%d, sleep:%d\n", pthread_self, data, sec);sleep(sec);}
//處理方法2void 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,嵌入式 等。
,