摘要:目前最常用的軟件反向代理服務(wù)器有和。基于實(shí)現(xiàn)動(dòng)態(tài)代理為了實(shí)現(xiàn)動(dòng)態(tài)代理方案,需要在反向代理服務(wù)器中增加定制的功能。同時(shí),由于反向代理服務(wù)器需要處理大量的代理請(qǐng)求,因此會(huì)頻繁的讀取反向代理配置數(shù)據(jù)。
基于 Nginx 的動(dòng)態(tài)代理
作者:趙波
日期:2016 年 8 月 4 日
在實(shí)際應(yīng)用中,遇到了這樣一個(gè)場(chǎng)景:
已有一個(gè)手機(jī) APP 客戶端,需要在該 APP 客戶端中實(shí)現(xiàn)通過(guò) Web 的形式接入其他的應(yīng)用頁(yè)面。按照常規(guī)的流程,在 APP 中為應(yīng)用設(shè)置入口鏈接按鈕,當(dāng)用戶點(diǎn)擊應(yīng)用入口按鈕時(shí),APP 啟動(dòng) WebView 并打開(kāi)設(shè)置的應(yīng)用鏈接即可。
但在該場(chǎng)景中,接入 APP 的應(yīng)用均部署在內(nèi)網(wǎng)服務(wù)器,外網(wǎng)無(wú)法直接訪問(wèn),因此在 APP 中配置的鏈接是內(nèi)網(wǎng)地址,當(dāng)用戶通過(guò)外網(wǎng)使用 APP 時(shí),將無(wú)法訪問(wèn)接入的 Web 應(yīng)用。
針對(duì)如上場(chǎng)景中遇到的問(wèn)題,本文中提出了基于 Nginx 實(shí)現(xiàn)動(dòng)態(tài)代理的解決方案。
使用代理在前面的場(chǎng)景中,要實(shí)現(xiàn)內(nèi)網(wǎng)應(yīng)用能夠被外網(wǎng)訪問(wèn),一般有兩種方式:
將應(yīng)用部署到可被外網(wǎng)訪問(wèn)的服務(wù)器,通常為 DMZ 區(qū)服務(wù)器
使用反向代理服務(wù)器,將外網(wǎng)請(qǐng)求代理轉(zhuǎn)發(fā)到內(nèi)網(wǎng)的應(yīng)用服務(wù)器
其中,將內(nèi)網(wǎng)應(yīng)用部署到可被外網(wǎng)訪問(wèn)的服務(wù)器上的方法,通常受限于可提供的硬件環(huán)境、安全控制等方面的問(wèn)題,并不是解決該類問(wèn)題的首選方案。因此,通常會(huì)在可被外網(wǎng)訪問(wèn)的服務(wù)器上部署反向代理服務(wù)器,使用代理轉(zhuǎn)發(fā)來(lái)解決。
目前最常用的軟件反向代理服務(wù)器有 Apache 和 Nginx 。通過(guò)配置文件設(shè)置,就可以將特定的鏈接向應(yīng)用服務(wù)器轉(zhuǎn)發(fā)。例如 Nginx 可通過(guò)以下簡(jiǎn)單的配置,即可實(shí)現(xiàn)代理轉(zhuǎn)發(fā):
server { listen 80; server_name domain.com; location /app1 { proxy_redirect off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_pass http://192.168.10.38:3000/app1; } access_log logs/domain.com.access.log; }
在以上實(shí)例中,Nginx 配置完成后,即可將 http://domain.com/app 的所有請(qǐng)求代理轉(zhuǎn)發(fā)到 http://192.168.10.38:3000/app1 地址,這樣就可以實(shí)現(xiàn)針對(duì) app1 的從外網(wǎng)訪問(wèn)內(nèi)網(wǎng)應(yīng)用的代理轉(zhuǎn)發(fā)功能。此時(shí) app1 對(duì)于外網(wǎng)的訪問(wèn)地址就變成了 http://domain.com/app 。
通過(guò)使用代理服務(wù)器, 所有的應(yīng)用將擁有統(tǒng)一域名 ,而通過(guò) 二級(jí)目錄區(qū)分 不同的應(yīng)用。
在 Apache 中同樣可以采用類似的策略進(jìn)行代理轉(zhuǎn)發(fā),本文中主要以 Nginx 作為實(shí)例。
在多個(gè)接入多個(gè)應(yīng)用的情況下,只要按照上述實(shí)例中的配置,為不同的應(yīng)用分配不同的二級(jí)目錄,即可實(shí)現(xiàn)向不同應(yīng)用進(jìn)行代理轉(zhuǎn)發(fā)。這樣就可以解決文章開(kāi)始提出的問(wèn)題。
但是這一解決方案也存在問(wèn)題:
當(dāng)需要新增/修改/刪除應(yīng)用的代理轉(zhuǎn)發(fā)配置時(shí),需要人工修改配置文件,并重啟代理轉(zhuǎn)發(fā)服務(wù)器,這將導(dǎo)致服務(wù)的暫時(shí)不可用。
當(dāng)接入應(yīng)用較多時(shí),配置文件將越來(lái)越大,對(duì)用人工維護(hù)造成極大的不便。
當(dāng)代理轉(zhuǎn)發(fā)服務(wù)器進(jìn)行集群化部署時(shí),每次對(duì)配置文件的更新,都需要更新所有代理轉(zhuǎn)發(fā)服務(wù)器,并進(jìn)行重啟,這將增大維護(hù)的風(fēng)險(xiǎn)。
針對(duì)以上的問(wèn)題,需要對(duì)該訪問(wèn)進(jìn)行進(jìn)一步改進(jìn)。
使用動(dòng)態(tài)代理如果能夠使反向代理服務(wù)器動(dòng)態(tài)的通過(guò)集中的配置數(shù)據(jù)更新針對(duì)應(yīng)用的代理配置,就可以解決上述方案中存在的問(wèn)題。
經(jīng)過(guò)研究分析,本文中提出 動(dòng)態(tài)代理 方案,流程如下:
當(dāng)請(qǐng)求進(jìn)入反向代理服務(wù)器時(shí),反向代理服務(wù)器將分析進(jìn)入的請(qǐng)求 URL ,識(shí)別 URL 中的二級(jí)目錄(用于區(qū)分不同的應(yīng)用),然后使用該二級(jí)目錄作為應(yīng)用標(biāo)識(shí),到代理配置數(shù)據(jù)數(shù)據(jù)中進(jìn)行查詢,獲得代理地址的返回結(jié)果,然后將該請(qǐng)求轉(zhuǎn)發(fā)到對(duì)應(yīng)的應(yīng)用服務(wù)器。
同時(shí),管理人員可以通過(guò)特定的管理端,對(duì)代理配置數(shù)據(jù)進(jìn)行 CRUD 操作,方便管理人員對(duì)代理應(yīng)用配置的實(shí)時(shí)管理。
通過(guò)以上流程,即可實(shí)現(xiàn)在不中斷服務(wù)的情況下,動(dòng)態(tài)修改代理配置。同時(shí)也可以確保集群化的反向代理服務(wù)器同步更新,都可以獲得最新的配置數(shù)據(jù)。
使用動(dòng)態(tài)代理方案,即可以解決在文章開(kāi)頭提出的問(wèn)題。
基于 Nginx 實(shí)現(xiàn)動(dòng)態(tài)代理為了實(shí)現(xiàn)動(dòng)態(tài)代理方案,需要在反向代理服務(wù)器中增加定制的功能。針對(duì)這一目的,研究了目前主流的反向代理服務(wù)器 Apache 和 Nginx ,結(jié)論如下:
Apache 和 Nginx 均可以增加定制的模塊以實(shí)現(xiàn)定制的功能。但是 Apache 目前必須使用 C 語(yǔ)言按照 Apache 的要求編寫(xiě)模塊,這對(duì)于開(kāi)發(fā)者要求相對(duì)較高。而 Nginx 同樣可以使用 C 語(yǔ)言開(kāi)發(fā)擴(kuò)展模塊,但除此之外,目前已有針對(duì) Nginx 開(kāi)發(fā)的 Lua 語(yǔ)言解釋器模塊,即可以在 Nginx 的配置文件中直接調(diào)用 Lua 語(yǔ)言開(kāi)發(fā)的腳本程序,這種方式極大的降低了定制功能開(kāi)發(fā)的難度。因此,采用 Nginx 作為反向代理服務(wù)器,使用 Lua 語(yǔ)言作為定制功能開(kāi)發(fā)語(yǔ)言,進(jìn)行動(dòng)態(tài)代理功能實(shí)現(xiàn)。
同時(shí),由于反向代理服務(wù)器需要處理大量的代理請(qǐng)求,因此會(huì)頻繁的讀取反向代理配置數(shù)據(jù)。基于這一情況,選用 Redis 作為數(shù)據(jù)庫(kù),利用其高性能的數(shù)據(jù)讀寫(xiě),支撐代理配置數(shù)據(jù)的頻繁訪問(wèn)。
根據(jù)以上的技術(shù)選型,設(shè)計(jì)流程圖如下:
在 Nginx 的配置文件中通過(guò) Lua 解釋器模塊,調(diào)用 Lua 腳本。請(qǐng)求進(jìn)入 Nginx 后,通過(guò) Lua 腳本處理請(qǐng)求,并連接 Redis 獲取當(dāng)前 URL 對(duì)應(yīng)的應(yīng)用的代理地址,處理完成后,將代理地址回寫(xiě)到 Nginx 的配置塊,由 Nginx 完成后續(xù)的代理轉(zhuǎn)發(fā)工作。
在運(yùn)行期間,管理人員可以使用代理管理端,對(duì) Redis 中的代理配置數(shù)據(jù)進(jìn)行操作,操作完成后,Nginx 代理服務(wù)器將及時(shí)讀取到最新的配置數(shù)據(jù)進(jìn)行轉(zhuǎn)發(fā)。
Nginx 動(dòng)態(tài)代理優(yōu)化 代理配置數(shù)據(jù)緩存經(jīng)過(guò)調(diào)研,在具體開(kāi)發(fā)過(guò)程中,采用了基于 Nginx 進(jìn)行了模塊擴(kuò)展的 OpenResty。OpenResty 基于 Nginx 擴(kuò)展了大量的模塊,其中非常核心的特點(diǎn)就是在 Nginx 中集成了 Lua 解釋器,實(shí)現(xiàn)了 Nginx 調(diào)用 Lua 腳本。同時(shí) OpenResty 還提供了 Lua 語(yǔ)言實(shí)現(xiàn)的訪問(wèn) Redis 的代碼模塊。
在實(shí)際測(cè)試過(guò)程中,當(dāng)訪問(wèn)量較大時(shí),由于 Nginx 服務(wù)器每次代理都會(huì)查詢 Redis ,可能是導(dǎo)致 Redis 壓力過(guò)大而無(wú)法響應(yīng),導(dǎo)致請(qǐng)求被阻塞。
為了應(yīng)對(duì)這一問(wèn)題,在 Nginx 中,使用 Lua 腳本設(shè)置內(nèi)存緩存,從 Redis 獲取的代理數(shù)據(jù)將在一定時(shí)間內(nèi)保留在 Nginx 服務(wù)器的內(nèi)存中,在內(nèi)存緩存數(shù)據(jù)有效期內(nèi),將不會(huì)再重復(fù)向 Redis 請(qǐng)求數(shù)據(jù)。
經(jīng)過(guò)測(cè)試,在進(jìn)行數(shù)據(jù)緩存優(yōu)化后,極大的提高了 Redis 訪問(wèn)的穩(wěn)定性。
Redis 集群化由于單點(diǎn) Redis 一旦無(wú)法提供服務(wù),將導(dǎo)致 Nginx 代理服務(wù)無(wú)法正常使用。針對(duì)這一問(wèn)題,需要對(duì) Redis 進(jìn)行集群化。
目前比較成熟的解決方案是對(duì) Redis 進(jìn)行主從備份,一個(gè)主節(jié)點(diǎn)提供對(duì)外服務(wù),多個(gè)從節(jié)點(diǎn)進(jìn)行數(shù)據(jù)備份,并在主節(jié)點(diǎn)停止服務(wù)后產(chǎn)生新的主節(jié)點(diǎn)繼續(xù)提供服務(wù)。使用 Redis 提供的 Redis Sentinel 進(jìn)行主從節(jié)點(diǎn)監(jiān)控,并向 Nginx 提供最新的主節(jié)點(diǎn)信息。
Nginx 集群化隨著訪問(wèn)量逐漸增大,單機(jī)的 Nginx 將無(wú)法再支持過(guò)大的訪問(wèn)量,同時(shí)單機(jī) Nginx 一旦停止服務(wù),將影響整個(gè)系統(tǒng)的正常運(yùn)行。因此需要將 Nginx 進(jìn)行集群化,部署多個(gè) Nginx 反向代理服務(wù)器,提供同樣的服務(wù)。
基于 Nginx 的動(dòng)態(tài)代理方案,提供的代理服務(wù)為無(wú)狀態(tài)服務(wù),因此可以直接復(fù)制 Nginx 以實(shí)現(xiàn)集群化。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/39359.html
摘要:客戶收益與展望利用的云網(wǎng)基礎(chǔ)架構(gòu),該公司通過(guò)較低的成本,在不到一周的時(shí)間內(nèi),快速搭建一套高速穩(wěn)定的加速平臺(tái)方案。背景Git是目前世界上最流行的分布式版本控制系統(tǒng),GitHub是一個(gè)基于Git的代碼托管平臺(tái),一個(gè)擁有143萬(wàn)開(kāi)發(fā)者的社區(qū),是一個(gè)巨大的開(kāi)源寶庫(kù)。作為全球程序員和編程愛(ài)好者的聚集地,諸多優(yōu)秀的開(kāi)源項(xiàng)目代碼都托管于GitHub上。UCloud深圳某初創(chuàng)客戶,正在開(kāi)發(fā)運(yùn)營(yíng)一款海外社交A...
摘要:背景最近在做一個(gè)基于的微信公眾平臺(tái)腳手架,由于我只有一個(gè)域名,現(xiàn)在同時(shí)有好幾個(gè)應(yīng)用在上面掛載著,所以只能做一下反向代理,可是反向代理只能代理動(dòng)態(tài)文件,對(duì)于靜態(tài)資源貌似沒(méi)有什么好的解決方法本文針對(duì)以上問(wèn)題進(jìn)行逐步解決,通過(guò)修改相關(guān)配置,并結(jié)合 背景 最近在做一個(gè)基于koa的微信公眾平臺(tái)腳手架,由于我只有一個(gè)域名demozhan.com,現(xiàn)在同時(shí)有好幾個(gè)web應(yīng)用在上面掛載著,所以只能做一...
摘要:背景最近在做一個(gè)基于的微信公眾平臺(tái)腳手架,由于我只有一個(gè)域名,現(xiàn)在同時(shí)有好幾個(gè)應(yīng)用在上面掛載著,所以只能做一下反向代理,可是反向代理只能代理動(dòng)態(tài)文件,對(duì)于靜態(tài)資源貌似沒(méi)有什么好的解決方法本文針對(duì)以上問(wèn)題進(jìn)行逐步解決,通過(guò)修改相關(guān)配置,并結(jié)合 背景 最近在做一個(gè)基于koa的微信公眾平臺(tái)腳手架,由于我只有一個(gè)域名demozhan.com,現(xiàn)在同時(shí)有好幾個(gè)web應(yīng)用在上面掛載著,所以只能做一...
摘要:目前在和平臺(tái)下使用最廣泛的免費(fèi)服務(wù)器有和。涉及到普通用戶執(zhí)行命令時(shí)權(quán)限不足的問(wèn)題,可在命令前增加指令解決。是基于二進(jìn)制的線路協(xié)議,與協(xié)議作用相同,但屬于服務(wù)器自有協(xié)議是服務(wù)器,它實(shí)現(xiàn)了協(xié)議等協(xié)議安裝。 前言 瀏覽器上網(wǎng)的過(guò)程簡(jiǎn)單來(lái)說(shuō)即是瀏覽器從服務(wù)器中獲取網(wǎng)站信息,經(jīng)過(guò)渲染后將效果呈現(xiàn)給用戶。這里側(cè)重介紹下在幕后默默工作著的服務(wù)器。Web服務(wù)器是運(yùn)行在物理服務(wù)器上的一個(gè)程序,永久地等待...
閱讀 1526·2023-04-26 00:20
閱讀 1121·2023-04-25 21:49
閱讀 803·2021-09-22 15:52
閱讀 577·2021-09-07 10:16
閱讀 972·2021-08-18 10:22
閱讀 2664·2019-08-30 14:07
閱讀 2237·2019-08-30 14:00
閱讀 2651·2019-08-30 13:00