最近在使用spring cloud zuul进行一些服务网关的搭建和改造,由于一些原因,所以没有使用config server和eureka做统一的配置管理和服务发现注册,而是直接在zuul server上配置了db进行routes的配置,因此使用的是static routing的模式,即直接指定一个route的url而不是serviceId。而我们url指向的地址,是一个nginx地址,相当于通过nginx来做的一个service的负载均衡。
但在实际使用过程中我们发现一些问题,当下游服务返回的消息大小超过下游nginx设置的gzip阈值的时候,会触发响应报文的压缩,而zuul所接收到的报文,竟然是没有解压缩的!如果这时候我们需要对响应报文进行一些解析甚至是加密处理的话,会发现我们拿到的报文是二进制码,无法进行下一步操作。而我们知道在我们平时使用的一些HttpClient工具的时候,这些工具能够自动帮我们处理响应的解压。那zuul这一块是怎么处理的呢?我们有什么办法去配置自动解压呢?
首先我在github上找到了这个issue:
https://github.com/spring-cloud/spring-cloud-netflix/issues/2363
里面这一段话引起了我的注意:
纳尼?RibbonRoutingFilter是自动解压的?SimpleHostRoutingFilter默认不解压?其实也想得通。你就把zuul当做一个nginx嘛。但是我们本身的业务流程怎么办呀?那我们就深入到代码里面去看看这个disableContentCompression是怎么调用的。
在SimpleHostRoutingFilter中我们看到了创建HttpClient的过程,看到没有调用我们要找的disableContentCompression方法。那我就放心了,这个方法肯定是在httpClientFactory中创建的,那我们再去找这个httpClientFactory在哪里创建的?这里可以告诉大家一个小技巧。先直接对这个httpClientFactory对应的ApacheHttpClientFactory来find usage,如果发现不是很好找的话,可以先找ApacheHttpClientFactory这个接口的实现,你spring容器要注入,总的有个实现吧。我们查找实现,找到了这么个类:
金灿灿的disableContentCompression有木有啊。我们大致确定了这个类就是我们要找的factory,那这个类在哪里用到呢?我们对这个类find usage,就到了这里。
而这个configuration是被ZuulProxyAutoConfiguration所引入的,一切都联系起来了
到这儿,我们知道了为什么SimpleHostRoutingFilter是默认不执行解压的,那对于我们需要解压的逻辑我们应该怎么处理呢?不知道大家有没有注意apacheHttpClientFactory这个方法上面,有个ConditionalOnMissingBean注解?有这个注解一切都好办了,你只需要在你的scan path下加上一个configuration,并且定义自己的一个ApacheHttpClientFactory的bean方法就行了,代码如下:
亲测可用。
以上是目前使用到zuul的一个问题小结,如果大家有什么问题欢迎留言和讨论。