問題
k8s
中ingress
使用的是ingress-nginx
.
項目中用到了spring cloud gateway
做API
網關,部署環境有docker
、k8s
等. 測試出現一個問題:
請求的URL
路徑中如果出現了中文
參數,如http://localhost:8080/test?param=你好
,如果部署在docker
或者裸機
上,後臺
服務接收到的參數param
是你好
,但是如果部署在k8s
上,後臺接收到的參數可能是UrlEncode
之後的%E4%BD%A0%E5%A5%BD
,這不是後臺需要的. 雖然可以在後臺通過URLDecoder.decode(name, "UTF-8")
強制解碼,不過比較麻煩.
分析
測試中發現,
- 如果直接將
後臺
服務部署到k8s
上,通過service -> ingress
暴露出來,不管是通過k8s
中ClusterIP
,如http://10.96.240.18:8080/test?param=你好
, 還是通過ingress
域名http://local.com/test?param=你好
請求後臺服務,後臺能夠正確接收到參數爲你好
,證明問題可能不是因爲部署在k8s
上造成的,只可能是spring cloud gateway
做API
網關原因; - 但是部署在
docker
或者裸機
上,通過spring cloud gateway
網關請求後臺
服務,後臺能夠正確接收到參數爲你好
,證明網關也是沒有問題的,問題只可能是部署環境k8s
的原因; - 如果將網關服務部署到
k8s
上,又有兩種情況:- 通過
ingress
域名請求網關 -> 後臺
,後臺接收到的參數是%E4%BD%A0%E5%A5%BD
,看似是網關的問題; - 通過
ClusterIP
請求網關 -> 後臺
,後臺接收到的參數是你好
,這又證明網關沒問題,看似是ingress
的問題,但前面也證明了ingress
可以正確傳遞中文
字符,非常的奇怪!
- 通過
- 將
spring cloud gateway
中所有的Filter
全部註釋掉,發現通過ingress
域名請求網關 -> 後臺
,後臺也能正確的接收到中文
參數,證明還是網關
的問題,而且這個問題只有部署在k8s
中搭配ingress-nginx
使用時纔會暴露.
解決
依次將註釋掉的Filter
加回去,證明問題出現在class XXXX extends ForwardedHeaderFilter
這個類上.這個類用於設置網關跨域訪問
和網關本身接口權限驗證
.
測試發現,即使只註釋成下面這樣,還是會有問題,但是註釋掉@Component
,就沒有問題.應該是super.filter(exchange, chain)
父類這個方法有問題.
@Component
@Slf4j
public class AuthTokenFilter extends ForwardedHeaderFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
//跨域問題 接口權限驗證 TODO
return super.filter(exchange, chain);
}
}
改成下面這樣測試可以解決問題.
@Component
@Slf4j
public class AuthTokenFilter extends ForwardedHeaderFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
//跨域問題 接口權限驗證 TODO
return chain.filter(exchange);
}
}