SpringBoot部署于Istio时,getRequestURL()丢失请求端口问题排查
Istio转发请求丢失端口问题排查与解决
问题原因
当请求通过Istio Ingress Gateway的9091端口进入集群后,Istio的Envoy代理默认会重写请求的Host头:要么替换为后端服务的集群内部地址(不带端口),要么使用网关内部的默认端口(如80)。而SpringBoot的httpServletRequest.getRequestURL()方法依赖请求的Host头或监听端口构建URL,因此会错误显示为80端口,而非原始请求的9091端口。
同时,Istio默认不会自动传递X-Forwarded-Port这类转发头,SpringBoot也不会默认优先使用转发头构建请求URL,进一步导致端口信息丢失。
解决方案
方案1:在VirtualService中强制保留原始Host头
修改VirtualService配置,添加请求头设置,让Istio转发时保留原始请求的Host头(包含端口):
apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: neo-dms-service-frontend spec: hosts: - "*" gateways: - gateway http: - route: - destination: host: neo-dms-service.default.svc.cluster.local port: number: 9091 headers: request: set: Host: "%REQ(Host)%"
应用配置后,SpringBoot即可通过getRequestURL()获取到包含9091端口的正确URL。
方案2:开启Istio转发头传递并配置SpringBoot识别
步骤1:配置Istio传递X-Forwarded-Port头
修改gateway-ports.yml中的meshConfig,添加代理元数据配置以开启转发头传递:
apiVersion: install.istio.io/v1alpha1 kind: IstioOperator metadata: name: istio-with-extra-ports spec: profile: default meshConfig: enableTracing: true defaultConfig: tracing: sampling: 100 proxyMetadata: # 开启X-Forwarded-Port等转发头的传递 ISTIO_META_X_FORWARDED_PORT: "true" components: ingressGateways: - namespace: istio-system name: istio-ingressgateway enabled: true k8s: service: ports: # 原有端口配置保持不变 - port: 15021 targetPort: 15021 name: status-port protocol: TCP - port: 80 targetPort: 8080 name: http2 protocol: TCP - port: 443 targetPort: 8443 name: https protocol: TCP - port: 15012 targetPort: 15012 name: tcp-istiod protocol: TCP - port: 15443 targetPort: 15443 name: tls protocol: TCP - port: 9091 targetPort: 9091 name: http-neo-dms-service protocol: TCP
重新安装或升级Istio使配置生效:
istioctl install -y -f gateway-ports.yml
步骤2:配置SpringBoot识别转发头
在SpringBoot应用的application.properties中添加以下配置,让应用优先使用转发头构建请求URL:
# 启用原生转发头处理策略 server.forward-headers-strategy=NATIVE # 配置Tomcat识别X-Forwarded系列头 server.tomcat.remoteip.port-header=x-forwarded-port server.tomcat.remoteip.host-header=x-forwarded-host server.tomcat.remoteip.protocol-header=x-forwarded-proto
重启SpringBoot应用后,即可通过getRequestURL()获取到原始请求的9091端口。
验证
应用所有修改后,调用服务端点,检查httpServletRequest.getRequestURL()返回的URL端口是否为9091。
内容的提问来源于stack exchange,提问作者Tomáš Přitrský
相关产品推荐
相关产品推荐

