現(xiàn)在很多公司都是區(qū)分內(nèi)外網(wǎng)的,而從外網(wǎng)是無法直接訪問內(nèi)網(wǎng)部署的站點與API的,當一個部署在內(nèi)網(wǎng)的站點(比如官網(wǎng))需要向外部開放的時候就需要利用Nginx來進行代理轉(zhuǎn)發(fā)。
以一個vue+springboot項目為例
【注】:本文假定前端以IP的形式訪問后端api,例如:172.16.2.2:8081/a/b
外網(wǎng)(云)服務(wù)器IP:114.251.x.x
站點域名:a.aaa.com.cn(當前映射到172.16.2.1)
內(nèi)網(wǎng)前端服務(wù)器IP:172.16.2.1
內(nèi)網(wǎng)后端服務(wù)器IP:172.16.2.2
該項目的前后端都是部署在內(nèi)網(wǎng)的,所以在內(nèi)網(wǎng)直接訪問不會有問題,而從外網(wǎng)訪問當然也就訪問不到。
步驟一:將域名在DNS上的IP映射由內(nèi)網(wǎng)IP改為外網(wǎng)服務(wù)器IP,然后配置Nginx
將 a.aaa.com.cn 在DNS上的映射由內(nèi)網(wǎng)IP(172.16.2.1)更改為外網(wǎng)服務(wù)器的IP(114.251.x.x),這樣外網(wǎng)客戶對 a.aaa.com.cn 的訪問請求會被映射到 114.251.x.x 的80端口(域名映射到IP而不是端口,http默認訪問80端口),而該服務(wù)器上的nginx會將打到80端口上的請求轉(zhuǎn)發(fā)(配置監(jiān)聽轉(zhuǎn)發(fā)即可)到內(nèi)網(wǎng)前端服務(wù)器約定好的端口,比如 172.16.2.1:8080 ,這種方式可以通過80端口這一個外網(wǎng)端口用nginx把外網(wǎng)流量打到多個端口。
如果內(nèi)網(wǎng)前端服務(wù)器上vue部署的tomcat/nginx監(jiān)聽的是8080端口,那這時已經(jīng)可以通過域名訪問到頁面并看到頁面的靜態(tài)內(nèi)容了。
但是請注意,當前是無法在前端直接以IP的形式(172.16.2.2:8081/a/b)調(diào)用api的,因為提供api的后端服務(wù)器是內(nèi)網(wǎng)服務(wù)器,而此時在前端向后端發(fā)起的請求的host是a.aaa.com.cn(解析到外網(wǎng)IP),也就無法訪問到后端服務(wù)器。
步驟二:更改vue中api請求形式,然后配置nginx
這一步的根本目的是改變請求的host。
假定原先vue中某個api的請求方式是 172.16.2.2:8081/a/b ,現(xiàn)在把它替換為 a.aaa.com.cn/a/b 。
const ipAddr = '172.16.2.2', domainAddr = 'a.aaa.com.cn';
export var demo = `${ipAddr}:8081/a/b` ===> export var demo = `${domainAddr}/a/b`
用這種域名的形式替換掉ip形式,把前端發(fā)出的請求打到前端172.16.2.1上唯一的公網(wǎng)端口,然后配置nginx,將路徑為 /a/b 的請求轉(zhuǎn)發(fā)到 172.16.2.2:8081/a/b 。這樣,請求的host就從172.16.2.1變成了a.aaa.com.cn,這也就避免了內(nèi)外網(wǎng)不通或是跨域的問題。
所以,整個過程的公網(wǎng)數(shù)據(jù)流向是:
外網(wǎng)域名 -> 外網(wǎng)服務(wù)器:80 -> 內(nèi)網(wǎng)前端:8080(前端顯示) -> (發(fā)出請求) -> 外網(wǎng)域名 -> 外網(wǎng)服務(wù)器:80 -> 內(nèi)網(wǎng)前端:8080 -> nginx分發(fā) -> 內(nèi)網(wǎng)后端
(圖片下面還有一種方案,也可以看一下)

補充另外一種類似的思路(未驗證):
這種方案的根本目的也是通過代理的方式更改host
基于webpack的vue自帶代理,可以直接用,就不需要額外配置代理了,否則用node.js寫一個簡單的express也可以。webpack的代理配置在/config/index.js中,示例配置如下:
assetsSubDirectory: 'static',
assetsPublicPath: '/',
proxyTable: {
'/a': {
target: 'http://172.16.2.2:8081',//目標接口地址
changeOrigin: true,//是否跨域
pathRewrite: {
'/a': '/a'//重寫接口
}
}
}
這種方案理論上是可行的,而且更簡單一些。然而手里暫時沒有可以做驗證的資源,后續(xù)驗證了再來更新吧。