博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Zuul案例、常见使用方式
阅读量:2442 次
发布时间:2019-05-10

本文共 6685 字,大约阅读时间需要 22 分钟。

搭建Zuul服务

依赖:

org.springframework.cloud
spring-cloud-starter-eureka
org.springframework.cloud
spring-cloud-starter-zuul
org.springframework.boot
spring-boot-starter-web

在程序的启动类EurekaZuulClientApplication 加上@EnableEurekaClient注解,开启EurekaClient的功能;加上@SpringBootApplication注解,表明自己是一一个Spring Boot工程;加上@EnableZuulProxy注解,开启Zuul的功能。代码如下:

@SpringBootApplication@EnableEurekaClient@EnableZuulProxypublic class EurekaZuulClientApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaZuulClientApplication.class, args); }}

配置:

server:  port: 5000spring:  application:    name: service-zuuleureka:  client:    service-url:      defaultZone: http://localhost:8761/eureka/zuul:  routes:    hiapi:      path: /hiapi/**      serviceId: eureka-client    ribbonapi:      path: /ribbonapi/**      serviceId: eureka-ribbon-client    feignapi:      path: /feignapi/**      serviceId: eureka-feign-client

在本案例中,zuul.routes.hiapi.path为"/hiapi/**",zuul.routes.hiapi.serviceId为"eureka-client",这两个配置就可以将以"/hiapi"开头的Url路由到eureka-client服务。其中,zuul.routes.hiapi 中的“hiapi" 是自己定义的,需要指定它的path 和serviceld, 两者配合使用,就可以将指定类型的请求Url 路由到指定的ServiceId。

同理,满足以“/ribbonapi" 开头的请求Url都会被分发到eureka-ibbon- client, 满足以“/feignapi/"开头的请求Url都会被分发到eureka-feign-client服务。如果某服务存在多个实例,Zuul结合Ribbon会做负载均衡,将请求均分的部分路由到不同的服务实例。

依次启动工程eureka-server、 eureka-client、 eureka-ribbon-client、 eureka-feign-client和eureka-zuul-client,其中eureka-client启动两个实例,端口为8762和8763。在浏览器上多次访问htp:/:ocalhost:000hipihinamn= forezp,浏览器会交替显示以下内容:

hi forezp, i am from port:8762hi forezp, i am from port:8763

可见Zuul在路由转发做了负载均衡。同理,多次访问htpt:ocalhost:5000/ei/gnapi/jin hi?name-forezp和ht://ocahtosto000/rbbonapihi? name=forezp,也可以看到相似的内容。

如果不需要用Ribbon做负载均衡,可以指定服务实例的Url,用zuul.routes.hiapi.url配置指定,这时就不需要配置zuul.routes.hiapi.serviceld了。一旦指定了 Url, Zuul 就不能做负载均衡了,而是直接访问指定的Url, 在实际的开发中这种做法是不可取的。修改配置的代码如下:

zuul:	routes:		hiapi:			path: /hiapi/**			url: http://localhost:8762

如果你想指定Url,并且想做负载均衡,那么就需要自己维护负载均衡的服务注册列表。首先,将ribbon.eureka.enabled改为false,即Ribbon负载均衡客户端不向Eureka Client获取服务注册列表信息。然后需要自己维护一份注册列表, 该注册列表对应的服务名为hiapi-v1(这个名字可自定义),通过配置hiapi-v1.ribbon.listOfServers来配置多个负载均衡的Url。代码如下:

zuul:	routes:		path: /hiapi/**		srerviceId: hiapi-v1ribbon:	eureka:		enabled: falsehiapi-v1:	ribbon:		listOfServers: http://localhost:8762,http://localhost:8763

在Zuul上配置API接口的版本号

如果想给每一个服务的 API接口加前缀,例如ht://oclthost:50000 /v1/hiapihi?name=forezp/,即在所有的API接口上加一一个v1作为版本号。这时需要用到zul.prefix的配置,配置示例代码如下:

zuul:  routes:    hiapi:      path: /hiapi/**      serviceId: eureka-client    ribbonapi:      path: /ribbonapi/**      serviceId: eureka-ribbon-client    feignapi:      path: /feignapi/**      serviceId: eureka-feign-client  prefix: /v1

重新启动eureka- zuul-service服务,在浏览器上访问http://localhost:5000/v1/hiapi/hi?name=test,浏览器会显示:

在这里插入图片描述

在Zuul上配置熔断器

Zuul作为Netflix组件,可以与Ribbon、Eureka和Hystrix等组件相结合,实现负载均衡、熔断器的功能。

在默认情况下,Zuul 和Ribbon相结合,实现了负载均衡的功能

在Zuul中实现熔断功能需要实现ZzulFallbackProvider的接口。实现该接口有两个方法,

  • 一个是getRoute()方法,用于指定熔断功能应用于哪些路由的服务;
  • 另一个方法fallbackResponse()为进入熔断功能时执行的逻辑。

ZuulFallbackProvider 的源码如下:

在这里插入图片描述

实现一个针对eureka-client服务的熔断器,当eureka-client的服务出现故障时,进入熔断逻辑,向浏览器输入一句错误提示,代码如下:

@Componentpublic class MyFallbackProvider implements ZuulFallbackProvider {
@Override public String getRoute() {
return "eureka-client"; } @Override public ClientHttpResponse fallbackResponse() {
return new ClientHttpResponse() {
@Override public HttpStatus getStatusCode() throws IOException {
return HttpStatus.OK; } @Override public int getRawStatusCode() throws IOException {
return 200; } @Override public String getStatusText() throws IOException {
return "OK"; } @Override public void close() {
} @Override public InputStream getBody() throws IOException {
return new ByteArrayInputStream("oooops!error,i'm the fallback.".getBytes()); } @Override public HttpHeaders getHeaders() {
HttpHeaders httpHeaders = new HttpHeaders(); httpHeaders.setContentType(MediaType.APPLICATION_JSON); return httpHeaders; } }; }}

重新启动eureka-zuul-client 工程,并且关闭eureka-client 的所有实例,在浏览器上访问htp://ocalhost:5000 /hiapi/hi?name-forezp,浏览器显示:

在这里插入图片描述
如果需要所有的路由服务都加熔断功能,只需要在getRoute()方法上返回"*"的匹配符:

@Override	public String getRoute() {
return "*"; }

在Zuul中使用过滤器

实现过滤器很简单,只需要继承ZuulFiter,并实现ZuulFiter中的抽象方法,包括filterType()和filterOrder(),以及IZuulFilter的shouldFilter()和Object run()的两个方法

  • filterType()即过滤器的类型,它有4种类型,分别是“pre"“post”“routing"和error”。
  • filterOrder()是过滤顺序, 它为一个Int类型的值, 值越小,越早执行该过滤器。
  • shouldFilter()表示该过滤器是否过滤逻辑,如果为true,则执行run()方法;如果为false,则不执行run()方法。
  • run()方法写具体的过滤的逻辑。

在本例中,检查请求的参数中是否传了token这个参数,如果没有传,则请求不被路由到具体的服务实例,直接返回响应,状态码为401。

@Componentpublic class MyFilter extends ZuulFilter {
private static Logger log = LoggerFactory.getLogger(MyFilter.class); @Override public String filterType() {
return PRE_TYPE; } @Override public int filterOrder() {
return 0; } @Override public boolean shouldFilter() {
return true; } @Override public Object run() {
RequestContext ctx = RequestContext.getCurrentContext(); HttpServletRequest request = ctx.getRequest(); String accessToken = request.getParameter("token"); if (accessToken == null) {
log.warn("token is empty!"); ctx.setSendZuulResponse(false); ctx.setResponseStatusCode(401); try {
ctx.getResponse().getWriter().write("token is empty!"); } catch (IOException e) {
e.printStackTrace(); } } log.info("ok"); return null; }}

重新启动服务,打开浏览器,访问http://localhost:5000/hiapi/hi?name=forezp,浏览器显示:

在这里插入图片描述
再次输入http://localhost:5000/hiapi/hi?name=forezp&token=HJHKLL
在这里插入图片描述

可见,MyFilter 这个Bean注入IoC容器之后,对请求进行了过滤,并在请求路由转发之前进行了逻辑判断。在实际开发中,可以用此过滤器进行安全验证。本例的架构图如图:

在这里插入图片描述

Zuul的常见使用方式

Zuul是采用了类似于SpringMVC的DispatchServlet来实现的,采用的是异步阻塞模型,所以性能比Ngnix差。由于Zuul和其他Netflix组件可以相互配合、无缝集成,Zuul 很容易就能实现负载均衡、智能路由和熔断器等功能。在大多数情况下,Zuul都是以集群的形式存在的。由于Zuul的横向扩展能力非常好,所以当负载过高时,可以通过添加实例来解决性能瓶颈。

一种常见的使用方式是对不同的渠道使用不同的Zuul来进行路由,例如移动端共用一个Zuul网关实例,Web端用另一个Zuul网关实例,其他的客户端用另外一个Zuul实例进行路由。这种不同的渠道用不同Zul实例的架构如下图所示:

在这里插入图片描述

另外一种常见的集群是通过Ngnix和Zuul相互结合来做负载均衡。暴露在最外面的是Ngnix主从双热备进行Keepalive, Ngnix 经过某种路由策略,将请求路由转发到Zuul集群上,Zul最终将请求分发到具体的服务上。架构图如下图所示:
在这里插入图片描述

转载地址:http://zopqb.baihongyu.com/

你可能感兴趣的文章
[script]P_CHECK_BLACK.sql 检查当前用户下是否有varchar2字段的末尾包含空格
查看>>
实验-数据分布对执行计划的影响.txt
查看>>
实验-闪回数据库
查看>>
实验-闪回表
查看>>
oracle审计
查看>>
typeof运算符_JavaScript typeof运算子
查看>>
react 前端拆分_React中的代码拆分
查看>>
jsonp_JSONP指南
查看>>
如何禁用ESLint规则
查看>>
如何在macOS上安装PostgreSQL
查看>>
mysql用户权限_MySQL用户权限
查看>>
JavaScript切换条件
查看>>
在邮件标头中找到无效的字符_在Express中使用HTTP标头
查看>>
express 邮件发送_使用Express发送回复
查看>>
react生命周期_React生命周期事件
查看>>
叶节点到根节点的路径_节点路径模块
查看>>
前端测试简介
查看>>
如何查找公共子字符串长度_如何在C中查找字符串的长度
查看>>
javascript运算符_JavaScript比较运算符
查看>>
字符串tostring_字符串toString()方法
查看>>