0 | 前言
最近,大模型很火,国内国外都在争相推出自己的大语言模型(LLM),有些可以公开调用 API,有些只能面向 B 端用户,各家 API 调用范式还不一致,如果单个去接的话,会花费大量的时间和经历去阅读API文档和配置 token。
由于业务需要,我们需要提供一个统一的大模型 API 聚合入口服务,对使用者屏蔽底层接入细节,统一接口规范,以及配置对应大模型的 token。
然而,大模型的提供方既有国内的(minimax,spark,文心一言等等),也有国外的(openai,claude,google-palm等等),如果将我们的聚合服务放到一个地方部署,就会有一个问题:如果部署在国内,那么很多大模型API调用的连通性就有障碍;如果部署在国外,那访问国内大模型API接口就会很慢。
本文,针对这个痛点,提出了统一域名下的跨地域联合部署方案。
1 | 方案
在最初的版本,是一套代码分别在A地和B地同时部署,通过在接口文档里,显式规定用不同的域名来区分调用A地的模型还是B地的模型API。能解决问题,但是往往使用者有概率会忽略这部分内容,导致沟通成本的提升;同时,这种方式也不利于后续的扩展(如果有C地部署,那就需要新增一个新的域名访问)。
因此,在升级方案里,通过 nginx配置转发 + header自定义字段 的形式,来实现统一域名下的跨地域服务调用。 基本原理是:统一域名指向特定的 nginx 服务器,通过在请求的 header 里的自定义字段,将请求转发到不同地域。

2 | 实操
从上面的方案原理,可以看到,关键点就在 nginx 的配置:如何配置 nginx.conf 文件,来实现根据 header 里的特定 kv,来实现请求的转发。 这里直接上 nginx.conf 上的相关配置(提供了开箱即用的全量配置文件,但是重点在最后十几行,可以直接看最后的说明):
dart
worker_processes 4;
error_log /error.log info;
events {
accept_mutex on;
multi_accept on;
use epoll;
worker_connections 4096;
}
http {
include mime.types;
default_type application/octet-stream;
log_format main '$time_local $remote_user $remote_addr $host $request_uri $request_method $http_cookie '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" '
'$request_time $upstream_response_time "$upstream_cache_status"';
log_format browser '$time_iso8601 $cookie_km_uid $remote_addr $host $request_uri $request_method '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" '
'$request_time $upstream_response_time "$upstream_cache_status" $http_x_requested_with $http_x_real_ip $upstream_addr $request_body';
log_format client '{"@timestamp":"$time_iso8601",'
'"time_local":"$time_local",'
'"remote_user":"$remote_user",'
'"http_x_forwarded_for":"$http_x_forwarded_for",'
'"host":"$server_addr",'
'"remote_addr":"$remote_addr",'
'"http_x_real_ip":"$http_x_real_ip",'
'"body_bytes_sent":$body_bytes_sent,'
'"request_time":$request_time,'
'"status":$status,'
'"upstream_response_time":"$upstream_response_time",'
'"upstream_response_status":"$upstream_status",'
'"request":"$request",'
'"http_referer":"$http_referer",'
'"http_user_agent":"$http_user_agent"}';
access_log /access.log main;
sendfile on;
keepalive_timeout 120s 100s;
keepalive_requests 500;
send_timeout 60000s;
client_header_buffer_size 4k;
proxy_ignore_client_abort on;
proxy_buffers 16 32k;
proxy_buffer_size 64k;
proxy_busy_buffers_size 64k;
proxy_send_timeout 60000;
proxy_read_timeout 60000;
proxy_connect_timeout 60000;
proxy_cache_valid 200 304 2h;
proxy_cache_valid 500 404 2s;
proxy_cache_key $host$request_uri$cookie_user;
proxy_cache_methods GET HEAD POST;
proxy_redirect off;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Frame-Options SAMEORIGIN;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
server_tokens off;
client_max_body_size 50G;
add_header X-Cache $upstream_cache_status;
autoindex off;
resolver 127.0.0.1:53 ipv6=off;
map $http_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;
location / {
proxy_pass http://$proxy_upstream;
}
}
}
说明:
proxy_set_header Connection "upgrade";
如果需要支持 websocket 链接,需要配置此项;http_region
表示 http 请求的 header 里的 key=region 的值;map $http_region $proxy_upstream
表示是一个映射(可以理解成if else),即当 region=cn1 的时候, 转向 upstream=server_cn_1 所对应的 server=server_cn_1.com;当region=us1 的时候,转向 upstream=server_us_1 所对应的 server=server_us_1.com。
因此,以上 nginx 配置表示:监听80端口,通过判断 header 里的 region 值,将请求转发给不同的后端服务。
3 | 一些感触
- nginx 真的很强大,越了解它,越觉得强大
- 所有做工程的都应该要了解/熟悉/掌握/精通 nginx(前端/devops/后端/架构)
- 老毛子是真厉害
- 晚饭不吃真的会饿