這是當時兵將稀缺時開發過程的分享,建立proxy是開發中期時決定使用,但還要符合目前各個已開發並經過SIT測試過關的模組所定義的URI,這時不借助AI協助不行了。
需求是:
/a2a-api/v1/token這個URI及token後的延伸, pass_proxy給http://a2a-auth:8083/
/a2a-api/v1/非token的URI及其延伸則pass_proxy給http://a2a-biz:8084/,例:/a2a-api/v1/products/{pNo}, /a2a-api/v1/products:item, /a2a-api/v1/products/pi_orders等,
在nginx.conf設定分流方式如下:
server {
listen 80;
# /a2a-api/v1/token
# /a2a-api/v1/token/xxx
# /a2a-api/v1/token?xxx
location = /a2a-api/v1/token {
proxy_pass http://a2a-auth:8083;
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_set_header X-Forwarded-Proto $scheme;
}
location ^~ /a2a-api/v1/token/ {
proxy_pass http://a2a-auth:8083;
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_set_header X-Forwarded-Proto $scheme;
}
# 其他 /a2a-api/v1/ 開頭的 API
# 例如:
# /a2a-api/v1/products/123
# /a2a-api/v1/products:item
# /a2a-api/v1/products/pi_orders
location ^~ /a2a-api/v1/ {
proxy_pass http://a2a-biz:8084;
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_set_header X-Forwarded-Proto $scheme;
}
}
這樣會有以下的效果:
/a2a-api/v1/token -> http://a2a-auth:8083
/a2a-api/v1/token/refresh -> http://a2a-auth:8083
/a2a-api/v1/token/abc/def -> http://a2a-auth:8083
/a2a-api/v1/products/123 -> http://a2a-biz:8084
/a2a-api/v1/products:item -> http://a2a-biz:8084
/a2a-api/v1/products/pi_orders -> http://a2a-biz:8084
然而,已開發好並經過SIT的Spring Boot程式像:a2a-biz的@PostMapping("/v1/pi-orders/{txnNo}"),在/v1後沒接products;而a2a-auth的@PostMapping("/v1/token")設定,已經有塞入v1了,那nginx.conf該怎麼修正?
Nginx要做的是:外部URI保留/a2a-api,轉給後端時移除/a2a-api。用到rewrite機制。
server {
listen 80;
# a2a-auth:
# 外部 /a2a-api/v1/token
# 後端 /v1/token
location = /a2a-api/v1/token {
rewrite ^/a2a-api(/.*)$ $1 break; # 剔掉/v1/token
proxy_pass http://a2a-auth:8083;
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_set_header X-Forwarded-Proto $scheme;
}
# a2a-auth:
# 外部 /a2a-api/v1/token/xxx
# 後端 /v1/token/xxx
location ^~ /a2a-api/v1/token/ {
rewrite ^/a2a-api(/.*)$ $1 break; # 剔掉/v1/toke
proxy_pass http://a2a-auth:8083;
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_set_header X-Forwarded-Proto $scheme;
}
# a2a-biz:
# 外部 /a2a-api/v1/pi-orders/123
# 後端 /v1/pi-orders/123
#
# 外部 /a2a-api/v1/products/xxx
# 後端 /v1/products/xxx
location ^~ /a2a-api/v1/ {
rewrite ^/a2a-api(/.*)$ $1 break; # 導向http://a2a-biz:8084/v1/...
proxy_pass http://a2a-biz:8084;
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_set_header X-Forwarded-Proto $scheme;
}
}
其中$1是正則表達式的用法,它記憶^/a2a-api(/.*)$的小括號內容存到$1變數,記憶範圍是從/a2a-api後的/開始到URI結束。
結果a2a-auth這個模組的Spring Boot竟直接設定context-path為/a2a-auth,而不是預設的/,其實這拿掉application.properties裡的server.servlet.context-path=/a2a-auth設定會比較好,但真的遇到開發人員以已經過SIT測試OK不想改怎麼辦?只好再調一次nginx.conf。
# 精準匹配 /a2a-api/v1/token
location = /a2a-api/v1/token {
rewrite ^/a2a-api(/.*)$ /a2a-auth$1 break; # 變成/a2a-auth/v1/token
proxy_pass http://a2a-auth:8083;
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_set_header X-Forwarded-Proto $scheme;
}
# 匹配 /a2a-api/v1/token/xxx
location ^~ /a2a-api/v1/token/ {
rewrite ^/a2a-api(/.*)$ /a2a-auth$1 break;
proxy_pass http://a2a-auth:8083;
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_set_header X-Forwarded-Proto $scheme;
}
轉送結果:
/a2a-api/v1/token
→ http://a2a-auth:8083/a2a-auth/v1/token
/a2a-api/v1/token/refresh
→ http://a2a-auth:8083/a2a-auth/v1/token/refresh
這篇內容分類上應該是要和Proxy放在一起,但因為是開發測試過程才知道事先規劃不足導致,更像人為的雷包,所以視為Trouble Shooting的一種。這也得益於Nginx的靈活配置及AI強大,但是但是,如有必要,系統如果有空能改寫能重測,最好不要用這種削足適履的設定,日後不好維護,但終究抵不過deadline的現實。