当前位置: 代码迷 >> 综合 >> Zuul 的使用
  详细解决方案

Zuul 的使用

热度:97   发布时间:2023-09-27 16:11:37.0

Zuul 是 Netflix 开源的微服务网关。自身还整合了 Ribbon、Hystrix 和 Actuator。

前言

  • 本文中涉及到的 Spring Cloud 内容,可以查看我的相关博客
  • 使用的 Zuul 版本为 2.0.0M8
  • 服务端指 Eureka Server 所在微服务,客户端指提供数据的微服务,消费端指获取数据的微服务

1、写 Zuul 网关

创建新项目,导入 Zuul 和 Eureka 依赖

compile('org.springframework.cloud:spring-cloud-starter-netflix-eureka-client')
compile('org.springframework.cloud:spring-cloud-starter-netflix-zuul')

启动类添加以下注解

@EnableZuulProxy

写下配置文件 application.yml

server:port: 8040
spring:application:name: Geteway_Zuul
eureka:client:service-url:defaultZone: http://localhost:8761/eureka/

酱,这个 Zuul 微服务网关就写好了。从配置可知,它可以注册到 Eureka Server 上。

启动服务端、客户端(服务名:Port),启动本 Zuul 网关,访问 http://localhost:8040/port/ (port 为服务的全小写拼写,不能有大写字母。其后为微服务的服务路径)。结果请自行测试。

默认 Zuul 会代理所有注册到 Eureka Server 上的微服务。路由规则为 http://ZUUL_HOST:ZUUL_PORT/ 微服务 serviceId/**,具体如上所述。

2、负载均衡和 Hystrix 容错、监控

如开篇所说,Zuul 集成了 Ribbon 和 Hystrix 。可自行检测,此处跳过。

3、路由

据书上说,Zuul 会暴露管理端点 routes,博主测试没有。这不重要,跳过。

接下来,是路由的一些配置

我写的微服务名为 Port ,以下配置中 port 即为此服务名,特此提醒

i、指定微服务的访问路径,相当于给服务起了个昵称

zuul:routes:# serviceId: 路径port: /p/**     # 映射 port 微服务到路径 /p/

ii、另一种方式指定微服务访问路径

zuul:routes:user-route:         # 这是路由名字,可以任意起service-id: port  # 这是服务名port: /p/**       # 映射 port 微服务到路径 /p/

iii、忽略微服务、路径以及指定微服务

zuul:
# 忽略 port 微服务
# ignored-services: port ignored-services: '*'             # 忽略所有微服务ignored-patterns: /**/admin/**    # 忽略所有包含 /admin/ 的路径routes:port: /p/**                     # 指定微服务

iv、正则表达式指定 Zuul 的路由配置规则

public PatternServiceRouteMapper serviceRouteMapper(){return new PatternServiceRouteMapper("(?<name>^.+)-(?<version>v.+$)","${version}/${name}");
}

例如微服务名为 provider-v1 ,通过这段代码,可以映射到 /v1/provider/** 这个路径

v、前缀

  • 示例 A
zuul:prefix: /user     # 前缀strip-prefix: true   routes:port:path: /p/**
  • 示例 B
zuul:routes:port:               # <-- 服务名path: /user/**    # 此时 /user 就是前缀strip-prifix: true
  • strip-prefix=false 时, /user/a/b/c —> /a/b/user/c

  • strip-prefix=true 时, /user/a/b/c —> /user/a/b/c,即原地址

vi、Zuul 的安全和 Header

  • 敏感 Header 的设置
zuul:routes:port:path: /user/**senstive-headers: Cookie,Set-Cookie,Authorization

若 senstive-headers 在 zuul 配置子目录下,即为全局配置:

zuul:senstive-headers: Cookie,Set-Cookie,Authorization # 这几项其实也是默认值
  • 忽略Header
zuul:ignored-headers: HeaderA,HeaderB

4、Zuul 过滤器

首先,来编写一个 Zuul 过滤器

public class PreRequestLogFilter extends ZuulFilter{
    private static final Logger LOGGER= LoggerFactory.getLogger(PreRequestLogFilter.class);@Overridepublic String filterType() {//指定过滤器类型,有 pre、route、post、error 等几种取值return "pre";}@Overridepublic int filterOrder() {//指定过滤器执行顺序,数字越大,越早执行return 0;}@Overridepublic boolean shouldFilter() {//决定是否要执行此过滤器return true;}@Overridepublic Object run() throws ZuulException {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;}
}

启动类中增加:

@Beanpublic PreRequestLogFilter preRequestLogFilter(){return new PreRequestLogFilter();}

控制台输出类似以下信息即表示过滤器已经被执行了

[nio-8040-exec-3] c.i.zuul.filter.PreRequestLogFilter      : send GET request to http://localhost:8040/user/p/user/1

如下配置可以禁用过滤器

zuul:PreRequestLogFilter:  # 类名pre:                # 类型disable: true

5 、Zuul 容错和回退

Zuul 默认整合了 Hystrix,但和之前监控方法级别的粒度不同,Zuul 的 Hystrix 监控数据的粒度是微服务
Zuul 的使用
所以回退方法也一定会有大不同,下面为 Zuul 添加回退

@Component
public class PortFallbackProvider implements FallbackProvider {
    @Overridepublic String getRoute() {// 指定为哪个微服务提供回退return "port";}@Overridepublic ClientHttpResponse fallbackResponse(String route, Throwable cause) {return new ClientHttpResponse() {@Overridepublic HttpStatus getStatusCode() throws IOException {return HttpStatus.OK;}@Overridepublic int getRawStatusCode() throws IOException {return this.getStatusCode().value();}@Overridepublic String getStatusText() throws IOException {return this.getStatusCode().getReasonPhrase();}@Overridepublic void close() {}@Overridepublic InputStream getBody() throws IOException {return new ByteArrayInputStream("微服务不可用!".getBytes());}@Overridepublic HttpHeaders getHeaders() {HttpHeaders headers=new HttpHeaders();MediaType mt=new MediaType("application","json", Charset.forName("UTF-8"));headers.setContentType(mt);return headers;}};}
}

若 Port 无法响应。浏览器会接收并显示“微服务不可用”

6、Sidecar 整合非 JVM 微服务

使用的 Sidecar 版本为 2.0.0.M8

首先,写一个非 JVM 的微服务。如下是一个名为 node-service.js 的文件

var http=require('http');
var url=require('url');
var path=require('path');
// 创建 Server
var server=http.createServer(function(req,res){
    // 获取路径var pathname=url.parse(req.url).pathname;res.writeHead(200,{
   'Content-Type':'application/json; charset=utf-8'});// 首页if(pathname==='/'){res.end(JSON.stringify({
   'index':'Welcome to the welcome page'}));}// health页else if(pathname==='/health.json'){res.end(JSON.stringify({
   'status':'UP'}));}// 404页else{res.end('404')}
});
// 监听并打印日志
server.listen(8060,function(){
    console.log('listening on localhost:8060');
});

在 Node.js 命令行中进入文件所在目录,然后执行以下命令来执行这个服务

$ node node-service.js

分别访问 localhost:8060、localhost:8060/health.json 测试服务

然后,在 Zuul 项目中加入 Sidecar 依赖

compile('org.springframework.cloud:spring-cloud-netflix-sidecar')

启动类上添加以下注解

@EnableSidecar
// @EnableSidecar 整合了 @EnableCircuitBreaker@EnableDiscoveryClient@EnableZuulProxy

配置文件添加如下内容

server:port: 8070
spring:application:name: Zuul_Sidecareureka:client:service-url:defaultZone: http://localhost:8761/eurekainstance:prefer-ip-address: true
sidecar:port: 8060                                    # Node.js 微服务的端口health-uri: http://localhost:8060/health.json # Node.js 微服务的健康检查 URL

启动服务端、客户端、node-service,然后启动 Sidecar,访问http://localhost:8070/zuul_sidecar/

首页显示“{‘index’:’Welcome to the welcome page’}”,即表示已成功使用 Sidecar(摩托挎斗)带上了 node-service 服务


后记

以上的代码大多数经过我的测试

引用内容源自 《Spring Cloud与Docker微服务架构实战》/周立 著