0 | 前言
在上篇文章《一个入口通全球 | 如何使用同一个域名访问多地部署的同一个服务》中,介绍了如何通过一个域名访问部署在不同地域的同一个服务:
在上面方案中,是通过用户在header里指定自定义字段region来实现请求的转发。这个方案有个比较大的痛点是:用户需要清楚调用的API和服务部署地域的mapping关系,然后设定region值。对用户来说,用不同的域名访问不同地域的同一个服务没有本质区别,依旧需要用户自己去决定如何调用。
1 | 方案升级
所以,为了解决这个问题,我们对旧方案再做一次升级,目标是:用户无需自定义region字段,也无需掌握API和地域的mapping关系,只需要调用同一个域名,服务端自动去判断和转发请求。
这个可以通过请求的subpath来做判断:
2 | 实操
这里,还是借助nginx来转发请求。那么,问题就聚焦成了:
如何配置nginx.conf,来实现:同一个域名,根据不同的subpath来访问不同的服务地址?
这里还是需要借助lua脚本来实现这个业务逻辑,nginx.conf配置如下:
http {
...
map $the_region $proxy_upstream {
cn1 server_cn_1;
us1 server_us_1;
default server_us_1;
}
upstream server_us_1 {
server server_us_1.com;
}
upstream server_cn_1 {
server server_cn_1.com;
}
server {
listen 80;
server_name server.com;
location / {
set $the_region '';
access_by_lua_block {
local subpath = ngx.var.uri
ngx.log(ngx.ERR, "subpath=", subpath)
local cn_vendors = {"minimax", "xunfei"}
local us_vendors = {"openai", "claude", "google"}
for i, vendor in ipairs(cn_vendors) do
if string.find(subpath, vendor) then
ngx.var.the_region = 'cn1'
break
end
end
ngx.log(ngx.ERR, "the_region=",ngx.var.the_region)
}
proxy_pass http://$proxy_upstream;
}
}
}
代码逻辑解释:
server模块监听来自 server.com:80 的所有请求;
设置一个nginx的环境变量 the_region;
在lua脚本里,首先获得请求的subpath;
指定不同api供应商所在的区域,如minimax在cn,openai在us
- local cn_vendors = {"minimax", "xunfei"}
- local us_vendors = {"openai", "claude", "google"}
根据请求的subpath,循环遍历区域cn下的所有供应商,如果有包含关系,则设置 the_region = cn;(这里只有两个区域cn和us,所以只需要遍历一个区域即可)
然后通过proxy_pass转发请求,通过map方法选择对应的后端服务:
map $the_region $proxy_upstream {
cn1 server_cn_1;
us1 server_us_1;
default server_us_1; #兜底方案: 如果the_region字段为空,则默认走某一个后端服务
}
upstream server_us_1 {
server server_us_1.com;
}
upstream server_cn_1 {
server server_cn_1.com;
}
3 | 一些感触
最近看了华为心声社区的一篇文章《在华为做硬件22年,一个农村草根的逆袭之路》,里面有一句话,特别触动:
那时候心里充满了激情,感觉每天都有进展,自发自驱地拼命往前赶,好像除了工作没有其他,单纯地快乐着。
如果工作不能让自己快乐,工作又是为何?