iT邦幫忙

2026 iThome 鐵人賽

DAY 20
0
IT Operation

Podman Quadlet-容器服務化(在單體系統到微服務之間)系列 第 20

Proxy依不同URI分流到不同的Container

  • 分享至 

  • xImage
  •  

這是當時兵將稀缺時開發過程的分享,建立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的現實。


上一篇
Podman Quadlet的雷包
下一篇
不透過Quadlet把容器註冊成服務
系列文
Podman Quadlet-容器服務化(在單體系統到微服務之間)22
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言