如果用过微服务项目,那么一定知道网关服务,而微服务的网关服务,就一定离不开Spring Cloud Zuul,那他做网关有什么优势呢,项目没有网关也能访问,为什么要用网关呢?
今天就来说说Spring Cloud Zuul
优势
1 面向服务路由(集合Eruka的serverId)
2 可以统一微服务的权限过滤
3 拥有负载均衡,熔断的能力
上面就大概说了下,下面具体剖析
1 面向服务路由,是怎么回事,和其他的路由有什么区别?
上代码,我们先建立一个springCloudZull
看下他的配置文件
spring.application.name=api-gateway
server.port=5555
# eureka
eureka.client.serviceUrl.defaultZone=http://localhost:1111/eureka/
# routes to url
zuul.routes.api-a-url.path=/api-a-url/**
zuul.routes.api-a-url.url=http://localhost:8001/
在配置文件中我们看到 # routes to url 这个就是他的路由配置 当访问http://localhost:5555/api-a-url/hello 时,就会被路由到http://localhost:8001/hello 这就是传统的路由方式,我们看到这样配置对运维人员来说,就比较麻烦。 所以,zuul与eruka合作,搞出来了一个面向服务的路由,他的配置是这样的
zuul.routes.api-a.path=/api-a-url/**
zuul.routes.api-a.serviceId=hello-service
这个serviceId,就是eruka中注册的serviceId,使用service就可以直接访问对应的服务,是不是简洁了很多,我们来一个栗子
我们启动一个Eruka,然后在他上面注册三个服务,一个我们的网关服务,另外两个是用来路由的服务,启动后是这样的
然后访问http://localhost:5555/api-a-url/hello 返回的就是路由后的结果
因为是通过服务的id来路由,所以是面向服务的路由。
接下来说说,他的权限过滤,其实没有他来做权限过滤各个子服务也可以,但是这样的话就要写很多的过滤器,重复代码,不符合don’t repeat yourself思想,所以使用zuul来统一过滤,下面说说他的实现
public class AccessFilter extends ZuulFilter {
private static Logger log = LoggerFactory.getLogger(AccessFilter.class);
@Override
public String filterType() {
return "pre";
}
@Override
public int filterOrder() {
return 0;
}
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() {
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
log.info("send {} request to {}", request.getMethod(), request.getRequestURL().toString());
Object accessToken = request.getParameter("accessToken");
if(accessToken == null) {
log.warn("access token is empty");
ctx.setSendZuulResponse(false);
ctx.setResponseStatusCode(401);
return null;
}
log.info("access token ok");
return null;
}
}
以上就是他的实现代码,首先要实现ZuulFilter接口,接口中有几个方法
filterType 这里是定义使用哪个类型的过滤器,有四种类型,分别对应不同的生命周期,pre是在请求服务前过滤
filterOrder 过滤器执行顺序,过个过滤器,要哪个先执行就是通过他来定义
shouldFilter 判断过滤器是否要被执行
第四个方法就是 执行过滤器的内容了,这里面是判断请求中有没有token,如果有那么就允许访问,如果没有就拦截
写完之后,还要将他放到容器里,这样才能生效
@EnableZuulProxy
@SpringCloudApplication
public class Application {
public static void main(String[] args) {
new SpringApplicationBuilder(Application.class).web(true).run(args);
}
@Bean
public AccessFilter accessFilter() {
return new AccessFilter();
}
这里要说说@Bean这个注解,之前我们说过@Bean只能放在方法上,有点鸡肋,其实不然,通过这个使用,就能发现@Bean还是可以灵活的加载一些我们想要的内容
这样我们就实现了统一的过滤。
接下来说说负载均衡和熔断的实现方式,也是通过配置
zuul.routes.api-d.path=/ddd/**
zuul.routes.api-d.serviceId=hello
ribbon.eureka.enabled=true
hello.ribbon.listOfServers=http://localhost:8001/,http://localhost:8002/
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=60000
#ribbon.ConnectTimeout=3000
#ribbon.ReadTimeout=60000
因为zuul的pom中本身就集成了ribbon和hystrix所以只需要配置就可以了,我们可以通过配置超时时间和熔断时间来处理,负载均衡通过ribbon.eureka.enabled=true开启。