反向代理學習筆記(一) Nginx與反向代理緒論

北冥有隻魚發表於2023-03-26
本來是隻想學習Nginx的,但是想來只學Nginx學過來有些狹窄,因為現在反向代理伺服器

什麼是代理?

作為一個滬漂程式設計師,聽到代理這個詞,我下意識的想到了中介,現在在上海已經很少能找到房東看房子了,基本上都是從中介那裡看房,從這個角度來說中介代理了房東的部分職責,帶你看房。在漢語詞典中也是這麼闡釋的,待他人處理事務。那我們給代理前面加上正向這個詞呢,這也就成為了計算機領域內的專有名詞,正向代理。

什麼是正向代理?

那什麼是正向代理呢,我想起大學的上機課,為了讓我們好好學習,上機課的電腦是無法看到一些娛樂網站的, 比如知乎、騰訊遊戲。因為有同學確實在課上打遊戲,絲毫不聽課。學校好像意識到了問題的不對,加上了限制,再一次上課的我們,就發現一些娛樂網站上不了了。是透過網路白名單來進行的限制,那有什麼方法能夠繞開這個限制呢,答案就是代理,上網的時候,流量先到達我們的代理伺服器,獲取到內容之後,再給我們。像下面這樣:

iDXFGH.jpeg

這是代理伺服器的第一個用處,繞開瀏覽限制,一些學校和其他組織使用防火牆來使使用者訪問受限制的網際網路。 代理伺服器可以用於繞開這些限制,因為它們使使用者可以連線到代理伺服器,而不是直接連線到它們正在訪問的沾點。與之相對,我們也可以使用代理伺服器來組織特定使用者群訪問某些站點,比如學校網路可能配置為透過啟動內容篩選規則的代理連線到Web,不在白名單的,拒絕轉發響應。某些場景下,網際網路使用者也希望保護自己的線上身份,在一些情況下,網際網路使用者希望增強其線上匿名性,比如不想顯示自己的真實ip,如果我們用代理伺服器來訪問網際網路,發表評論的時候就更難追溯到真實ip。這是正向代理,我們可以認為正向代理,代理的是人。

什麼是反向代理?

那反向代理呢,反向代理代理的則是伺服器,有的時候我們並不願意將我們的服務端應用完整的暴露出去,這會增大服務端被攻擊的風險,這也就是反向代理伺服器,如下圖所示:

No alt text provided for this image

圖片來自ByteByteGo。反向代理伺服器可以幫助我們保護服務端,同時也可以幫我們做負載均衡,快取靜態資源,加密和解密SSL請求。本篇我們的重頭戲就是反向代理伺服器。

反向代理伺服器

想我剛實習的時候,因為會的比較少,覺得自己用的技術比較沒有逼格,聽到Nginx、Redis這些名詞的時候,心裡總是有幾分敬畏,覺得很有感覺。那反向代理伺服器有哪些呢? 比較知名的是Nginx,網站用的什麼伺服器處理請求,有些網站可以在響應中看到,我們首先看下掘金有沒有宣告自己用的是什麼伺服器處理的請求:

i4x85F.jpeg

是Nginx,本來我以為反向代理伺服器會使用一個,我扒了扒其他請求,發現不是:

i4xgDJ.jpeg

這個Tengine是啥,我們搜尋一下:

i4xx3c.jpeg

原來是基於Nginx的HTTP伺服器,我們進他的官網看看:

i4x66V.jpeg

在原來Nginx的基礎上,針對大訪問量網站的需求,新增了很多高階功能和特性。那可以理解為Nginx Plus嘛,那我們自然就會有一個問題,既然Tengine比Nginx更強大,為什麼沒有取代Nginx呢? 寫到這裡,突然想起一句話,物競天擇,適者生存。不是更強大的完全就能完全取代弱的,合適的,適合環境的,自然能夠生存下來。 bing還貼心的搜出了下面這個問題:

既然 Tengine 比 Nginx 更強大,為什麼沒有取代 Nginx 呢?

這個問題來自於知乎,下面節選一下我認為比較不錯的回答:

開源軟體的模式從來不是誰取代誰,而是百花齊放,博採眾長。若意見不合,也歡迎自立門戶。

寫到這裡,想起知乎之前看到的一個問題:

Cloudflare棄用NGINX,改用Rust編寫的Pingora,你怎麼看?

還真是白花齊放哈,又來了一個Pingora,對於Pingora,我們目前就姑且理解到另一個反向代理伺服器吧,關於Cloudflare為什麼用Pingora取代Rust,參看下面這篇文章: https://blog.cloudflare.com/zh-cn/how-we-built-pingora-the-pr...

在上面的知乎問答中,我又看到了其他方向代理伺服器:

  • BFE
BFE (Beyond Front End) 是百度開源的現代化、企業級的七層負載均衡系統。 使用Go編寫。

對應的文章參看: 為什麼BFE可以取代Nginx:十問十答 https://zhuanlan.zhihu.com/p/533272410

  • Higress
Higress 是基於阿里內部兩年多的 Envoy Gateway 實踐沉澱,以開源 Istio 與 Envoy 為核心構建的下一代雲原生閘道器。Higress 實現了安全防護閘道器、流量閘道器、微服務閘道器三層閘道器合一,可以顯著降低閘道器的部署和運維成本。

這些只做瞭解,我們的重頭戲還在Nginx上。

Nginx 入門

本篇的定位是入門,會簡單使用即可。上面的的瞭解是從宏觀上認識的Nginx,現在讓我們走進Nginx官網,去看看Nginx。

nginx [engine x] is an HTTP and reverse proxy server, a mail proxy server, and a generic TCP/UDP proxy server, originally written by Igor Sysoev. For a long time, it has been running on many heavily loaded Russian sites including Yandex Mail.Ru , VK , and Rambler . According to Netcraft, nginx served or proxied 21.23% busiest sites in February 2023 . Here are some of the success stories: Dropbox , Netflix, Wordpress.com, FastMail.FM

nginx(engine x的縮寫)是一個HTTP代理伺服器,郵箱代理伺服器,通用的TCP/UDP代理伺服器。原作者為Igor Sysoev。長期以來,工作在一些負載很重的俄羅斯網站,包括Yandex 、Mail.Ru、VK 、Rambler 。根據Netcraft的調研報告顯示,2023年2月,最繁忙的網站中,21.23%都由Nginx提供服務或進行代理。

這裡做到對Nginx有個基本印象,其他特性我們放到後面來講,我們現在首先將Nginx裝起來,我們依然在官網尋找,看看有沒有寫好的命令,讓我們複製一下就可以讓Nginx跑起來的命令。

i4d8Hc.jpeg

i4dIeA.jpeg

很全面,我們就跟著文件走就行了:

# 安裝Nginx
sudo yum install yum-utils
cd /etc/yum.repos.d
# 建立Nginx.repo
touch nginx.repo
# 然後在Nginx.repo裡面新增配置
[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true

[nginx-mainline]
name=nginx mainline repo
baseurl=http://nginx.org/packages/mainline/centos/$releasever/$basearch/
gpgcheck=1
enabled=0
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true
# 然後執行下面命令
yum install nginx

執行完上面的命令,我發現我把Nginx安裝到了etc目錄下,那如何確定安裝檔案的位置呢:

# 執行下面命令,會找到安裝的檔名
rpm -qa|grep nginx
rpm -ql  上一步找到的檔名

一般在Linux上安裝第三方軟體,我們推薦安裝在/opt下面,現在讓我們給Nginx挪一挪窩:

mv /etc/nginx  /opt/nginx

挪過去之後發現,啟動不行,我又挪回去了。這裡先不深究了。

我們現在來簡單的看下Nginx的目錄結構:

i4sifd.jpeg

貌似唯一認識的就是nginx.conf,反向代理和負載均衡應該就是在這裡配置的,要不,我們先讓Nginx啟動下,給自己一點成就感:

nginx 

預設配置中,Nginx會自動在80埠(HTTP)上提供一個歡迎頁面,如果能夠成功訪問該頁面,則表示Nginx已經成功啟動。像下面這樣:

i4soEw.jpeg

接著我們來配置反向代理和負載均衡,首先我是一名Java程式設計師,我有一個服務端專案,我現在做了叢集,一共是兩個節點,我希望為這兩個節點提供負載均衡和反向代理, 那應該怎麼配置呢?這也就是反向代理。我們開啟nginx下面的nginx.conf配置檔案

events {
    worker_connections  1024;
}
http {
    include       /etc/nginx/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  /var/log/nginx/access.log  main;
    sendfile        on;
    #tcp_nopush     on;
    keepalive_timeout  65;
    #gzip  on;
    #包含/etc/nginx/conf.d/路徑下所有字尾為.conf的配置檔案 
    include /etc/nginx/conf.d/*.conf;
}        

在/etc/nginx/conf.d有一個配置檔案叫default.conf,裡面是一個server{}格式的程式碼塊,所以在Nginx的基本配置格式:

http{
    server { 

    }
}

處理請求首先要宣告你要處理什麼請求,比如我們有個應用駐留在8080埠,根路徑是test,所以所有請求根路徑的最字首是test,都轉發到這個應用。

反向代理

那我們應該在這個配置檔案的http語法塊下寫一個server語法塊:

server{
        listen  8080;
        location /test{
              proxy_pass  http://192.168.2.2:8080/test;
        }
}        

nginx暫時監聽的是本機,那麼所有本機ip,埠8080,根路徑是test的請求都會被轉發到http://192.168.2.2:8080/test。然後nginx -s reload 重新載入配置檔案即可。反向代理好了,現在我們來做負載均衡。

負載均衡

Nginx支援的負載均衡策略:

  • round-robin — requests to the application servers are distributed in a round-robin fashion,
請求被被應用迴圈接受
  • least-connected — next request is assigned to the server with the least number of active connections,
當一個新的請求與需要被處理時,系統會查詢所有的伺服器,並且選擇當前連線數量最少的伺服器來處理這個請求。
  • ip-hash — a hash-function is used to determine what server should be selected for the next request (based on the client’s IP address).
根據客戶端的ip地址,透過hash演算法來決定應該有哪個伺服器處理請求。

基本語法:

 upstream myapp1 {
       # ip_hash;這裡宣告負載均衡演算法,候選值有:ip_hash、least_conn
       # 預設是輪詢    
       server 192.168.2.2:8080;
       server 192.168.2.2:8081;
}
    server{
        listen  8080;
        location /test{            
              proxy_pass  http://myapp1/test;
        }
 }

之間的對映關係如下圖所示:

iDmzfo.jpeg

nginx 支援熱載入,語法如下:

nginx -s signal
signal 的取值為: stop、quit、reload、reopen。 
stop — fast shutdown 快速停止
quit — graceful shutdown 優雅的停止
reload — reloading the configuration file 再次載入配置檔案
reopen — reopening the log files 再次開啟日誌檔案

總結一下

到現在為止,我們對正向代理、反向代理已經有了一個大致的印象,並且我們能夠使用Nginx來搭建負載均衡和反向代理。本來還打算介紹一下Nginx作為靜態資源的伺服器,發現對映過去老是403,折騰良久,遂放棄。

參考資料