简单的来说,我们把zuul这个项目启动起来,注册到eurake上,那么他就可以代理eurake上面的服务(默认),各种玩法听我细细道来。
源码下载路径在:https://download.csdn.net/download/qq_22075041/10869452,代码参考microservice-gateway-zuul模块。
首先加入zuul的依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zuul</artifactId>
</dependency>
<!--需要eurake的client依赖,因为要注册到eurake上-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
启动类上加一个注解@EnableZuulProxy,配置文件只需要把注册到eurake的配置做一下就可以了:
server:
port: 8040
spring:
application:
name: microservice-gateway-zuul
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
instance:
prefer-ip-address: true
以上配置zuul默认代理eurake的所有服务,调用的时候以注册到eurake上的服务名。
但是我觉得服务名太长了不好记,我要自定义,配置如下:
zuul:
routes:
# 服务名 访问路径 注意/*和/**的区别:适配一层和适配多层
microservice-provider-user: /user/**
如果我要忽略某几个微服务的代理呢?这样配(多个用逗号分开):
zuul:
ignored-services: microservice-provider-user,microservice-consumer-movie
如果我只想代理指定的微服务呢?
zuul:
ignored-services: '*' # 使用'*'可忽略所有微服务
routes:
microservice-provider-user: /user/**
还可以这样玩:同时指定微服务的serviceId和对应路径path:
zuul:
routes:
abc: # 该配置方式中,abc只是给路由一个名称,可以任意起名。
service-id: microservice-provider-user
path: /user/** # service-id对应的路径
玩法2:同时指定path和url
zuul:
routes:
user-route: # 该配置方式中,user-route只是给路由一个名称,可以任意起名。
url: http://localhost:8000/ # 指定的url
path: /user/** # url对应的路径。
玩法2升级:同时指定path和URL,并且不破坏Zuul的Hystrix、Ribbon特性
zuul:
routes:
user-route:
path: /user/**
service-id: microservice-provider-user
ribbon:
eureka:
enabled: false # 禁用掉ribbon的eureka使用。详见:http://cloud.spring.io/spring-cloud-static/Camden.SR3/#_example_disable_eureka_use_in_ribbon
microservice-provider-user:
ribbon:
listOfServers: localhost:8000,localhost:8001
为Zuul添加全局映射前缀: 应用场景比如项目根目录不是/ 而是/abc之类的
zuul:
prefix: /api
strip-prefix: false # 默认为ture
routes:
microservice-provider-user: /user/**
logging:
level:
com.netflix: DEBUG
# 访问Zuul的/api/microservice-provider-user/1路径,请求将会被转发到microservice-provider-user的/api/1,,可以查看日志打印,有助于理解。
为Zuul添加局部映射前缀,就是给某个服务添加:
zuul:
routes:
microservice-provider-user:
path: /user/**
strip-prefix: false
logging:
level:
com.netflix: DEBUG
# 这样访问Zuul的/user/1路径,请求将会被转发到microservice-provider-user的/user/1,可以查看日志打印,有助于理解。
我要忽略某些敏感路径,这样配:
zuul:
ignoredPatterns: /**/admin/** # 忽略所有包括/admin/的路径
routes:
microservice-provider-user: /user/**
还有基于正则的玩法,削微有点不同,代码参考microservice-gateway-zuul-reg-exp模块:
@SpringBootApplication
@EnableZuulProxy
public class ZuulApplication {
@Bean
public PatternServiceRouteMapper serviceRouteMapper() {
// 调用构造函数PatternServiceRouteMapper(String servicePattern, String routePattern)
// servicePattern指定微服务的正则
// routePattern指定路由正则
return new PatternServiceRouteMapper("(?<name>^.+)-(?<version>v.+$)", "${version}/${name}");
}
public static void main(String[] args) {
SpringApplication.run(ZuulApplication.class, args);
}
}
====================================
1.zuul现在使用的是HttpClient,可以使用其他的
2.zuul还支持把一些敏感请求头文件不传到代理的服务上
3.zuul服务自身转发,也可以配置。
4.访问zuul的/route,可以看到zuul所有代理的情况
5.@EnableZuulServer是一个zuul的轻量级自由注解,不带有负载,断路等功能
=========================================
接下里聊一下大文件上传,参考代码microservice-gateway-zuul-file-upload模块:
# 上传大文件得将超时时间设置长一些,否则会报超时异常。以下几行超时设置来自http://cloud.spring.io/spring-cloud-static/Camden.SR3/#_uploading_files_through_zuul
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds: 60000
ribbon:
ConnectTimeout: 3000
ReadTimeout: 60000
还有一个小技巧,我们上传一般使用的是springMVC,当我们使用zuul代理的时候,可以在代理路径前加上/zuul/*,则不会被springMVC上传的时候限制大小。
=============================================
zuul的fallback,参考代码microservice-gateway-zuul-fallback模块,其实就是自定义一个response
package com.itmuch.cloud.study.fallback;
import org.springframework.cloud.netflix.zuul.filters.route.ZuulFallbackProvider;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.stereotype.Component;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
@Component
public class UserFallbackProvider implements ZuulFallbackProvider {
@Override
public String getRoute() {
// 表明是为哪个微服务提供回退
return "microservice-provider-user";
}
@Override
public ClientHttpResponse fallbackResponse() {
return new ClientHttpResponse() {
@Override
public HttpStatus getStatusCode() throws IOException {
// fallback时的状态码
return HttpStatus.OK;
}
@Override
public int getRawStatusCode() throws IOException {
// 数字类型的状态码,本例返回的其实就是200,详见HttpStatus
return this.getStatusCode().value();
}
@Override
public String getStatusText() throws IOException {
// 状态文本,本例返回的其实就是OK,详见HttpStatus
return this.getStatusCode().getReasonPhrase();
}
@Override
public void close() {
}
@Override
public InputStream getBody() throws IOException {
// 响应体
return new ByteArrayInputStream("用户微服务不可用,请稍后再试。".getBytes());
}
@Override
public HttpHeaders getHeaders() {
// headers设定
HttpHeaders headers = new HttpHeaders();
MediaType mt = new MediaType("application","json", Charset.forName("UTF-8"));
headers.setContentType(mt);
return headers;
}
};
}
}
==================================
定义zuul的过滤器:
package com.itmuch.cloud.study.filters.pre;
import javax.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
public class PreRequestLogFilter extends ZuulFilter {
private static final Logger LOGGER = LoggerFactory.getLogger(PreRequestLogFilter.class);
@Override
public String filterType() {
return "pre";
}
@Override
public int filterOrder() {
return 1;
}
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() {
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
PreRequestLogFilter.LOGGER.info(String.format("send %s request to %s", request.getMethod(), request.getRequestURL().toString()));
return null;
}
}
然后注入这个bean
package com.itmuch.cloud.study;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
import org.springframework.context.annotation.Bean;
import com.itmuch.cloud.study.filters.pre.PreRequestLogFilter;
@SpringBootApplication
@EnableZuulProxy
public class ZuulApplication {
public static void main(String[] args) {
SpringApplication.run(ZuulApplication.class, args);
}
@Bean
public PreRequestLogFilter preRequestLogFilter() {
return new PreRequestLogFilter();
}
}
zuul支持自定义Fifter,也有很多实现好的Fifter(在org.springframework.cloud.netflix.zuul.filters包下)。
如果想禁用某一个Fifter,只需设置zuul.<SimpleClassName>.<filterType> .disable = true。例如,要禁用org.springframework.cloud.netflix.zuul.filters.post.SendResponseFilter 需设置 zuul.SendResponseFilter.post.disable = true。