webservice 具有特殊性,因为wsdl 文件是服务器端生成的(大部分,而且是动态的),所以我们直接使用nginx 进行proxy 会有问题
实际上此问题比较常见,而且网上也有人碰到,可能因为时间比较长了,技术变动,不见得就能解决问题,以下是自己在实践中一些整理
主要的问题
- 对于soap 的地址是不对
- 如果基于动态代码生成调用,会有问题(比如基于cfx 动态执行webservice),造成代码无法生成(还是上边soap地址不对引起的)
解决方法
原则是替换,只要保障wsdl 的schema 文件符合要求,而且关联地址可以访问就行了,最简单的方法就是基于nginx 的sub_filter 模块
- 参考配置
location / {
sub_filter http://xxxx 'https://yxxxxxx';
sub_filter_types text/xml;
sub_filter_once off;
proxy_set_header Accept-Encoding '';
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
client_body_buffer_size 10M;
proxy_set_header X-Forwarded-Proto $scheme;
client_max_body_size 10G;
proxy_buffers 1024 4k;
proxy_read_timeout 300;
proxy_pass http://xxxxx;
}
- 几个核心参数说明
sub_filter_types 指定替换的类型,可以指定为*
sub_filter_once 表示我们要进行多次替换
sub_filter 进行替换的指定,比较简单
一些坑
默认sub_filter 对于gzip 似乎是不处理的,会造成大家发现没有生效,此时大家可能会怀疑是指令没生效,实际是没问题的,只是gzip 的问题
解决方法:我们在proxy 的时候不进行gzip 的处理(通过Accept-Encoding 请求头),比如上边的我使用了'' 也可以使用identity,但是大家需要
注意的是对于有些服务尽管我们配置了不使用gzip 处理,但是服务开发者或者服务器管理员,强制使用了gzip(节省带宽),可能就不生效了
解决方法是有的,比如如下图
合理处理机制是先通过nginx proxy 一次(不实用gzip 了),然后在proxy 处理,这样就可以规避gzip 问题了,当然也有社区开发了gunzip_filter 模块可以使用
也是不错的,但是很多时候我们生产环境是没有打包的,而且有时比较难打包,所以基于多次proxy 是一个不错的选择
参考资料
https://forum.nginx.org/read.php?11,271185
https://httpwg.org/specs/rfc7231.html#header.accept-encoding
https://nginx.org/en/docs/http/ngx_http_proxy_module.html
https://cxf.apache.org/docs/dynamic-clients.html
https://github.com/catap/ngx_http_gunzip_filter_module