Zuul 是 Netflix 开源的微服务网关,它可以和 Eureka、Ribbon、Hystrix 等组件配合使用。Zuul 的核心就是一系列过滤器,这些过滤器可以完成以下功能:
目前,Zuul 使用默认 HTTP 客户端是 Apache HTTP Client。
下面介绍编写一个 Zuul 微服务网关和基本的配置。
Eureka 注册中心,启动在 8761 端口
一个或多个服务,注册在 Eureka 中
比如我目前 Eureka 上已经注册了两个服务
分别是用户中心的服务提供者(8080端口)和服务消费者(8081端口)
通过地址栏访问 http://localhost:8080/user/1 和 http://localhost:8081/hello 均能访问到两个服务
其中后者访问效果如下,下面以这个为示例,介绍网关的使用
下面我们来介绍 zuul,通过网关来访问这两个服务(通常我只暴露服务消费者,即 web 那个服务,服务提供者我们通常不暴露出去)
1.创建一个 SpringBoot 项目
注意:目前我使用都是最新版本, SpringBoot 版本是 2.1.7.RELEASE,SpringCloud 版本是 Greenwich.RELEASE
pom.xml 添加依赖
2.启动类添加 @EnableZuulProxy 注解
3.添加配置
application.yml
启动在 9000 端口,注册服务到 Eureka
4.运行启动类,启动 Zuul 在 9000 端口
可以看到网关注册到了 Eureka
通过地址栏访问
http://localhost:9000/服务名/请求路径,就可以访问到其他服务的路径
如我的用户中心服务消费者服务名为 sens-user-web (上图左侧的 Application 名称是全部大写,实际我的服务名是全小写的)
即下面两个请求结果是一样的
http://localhost:9000/sens-user-web/hello
http://localhost:8081/hello
可见,网关帮我们转发了这个请求
如果想访问另一个服务,一样的方法
http://localhost:9000/sens-user-core/user/1 也能访问到 http://localhost:8080/user/1
可见,目前我们几乎没有任何其他的配置,就能实现通过网关访问到所有的请求
但是这还不够,下面我们会介绍自定义路由和容错回退的一些配置
目前通过网关访问其他服务的路径,示例如下
http://localhost:9000/sens-user-web/hello
http://localhost:9000/sens-user-core/user/1
现在我有两个需求
解决办法很简单,只需要几行配置
在 application.yml 添加配置
上面几行配置,分别是设置统一的前缀,单条路由重写,排除自定义路由(排除后,访问404),排除服务(该服务所有请求404)
这样一来
配置前是 http://localhost:9000/sens-user-web/hello
配置后是 http://localhost:9000/api/user/hello
注意:因为我没有排除 sens-user-web,所有之前的 http://localhost:9000/sens-user-web/hello 也可以访问
通常我们通过网关访问一个路径,如 http://localhost:9000/sens-user-web/hello,
网关会自己转发到 sens-user-web 服务中的 /hello 路径,
因为 Zuul 内部使用了 Ribbon 做负载均衡,那么对于一些时间比较长的请求,可能会被作为超时处理。
默认时间是 1 秒
示例
访问 http://localhost:9000/sens-user-web/hello
我在 sens-user-web 服务 /hello 方法里写一个 sleep,睡眠5s,看会不会超时(也可以通过打断点暂停的方法测试)
效果如下
解决办法
在 pom.xml 中设置超时时间
当服务不可用的时候,网关会响应 50X 之类的错
比如超时是这样的
这是系统默认的界面,很不友好
我们可以重写回归响应的方法,给用户一个比较好的提示
解决办法如下
在网关项目中新建一个类
重启网关服务
当 @EnableZuulProxy 和 Spring Boot Actuator配合使用时,Zuul 会暴露两个端点:/actuator/routes, /actuator/filters 。借助这两个端点,我们可以方便地、直观地查看级管理 Zuul。
通常,我们直接访问是会报 404,如下配置可以解决
在 application.yml 添加
这个配置在 springboot 1.x 版本是 management.security.enabled=false,端点路径是 /routes和 /filters
该端点主要是查看路由列表
http://localhost:9000/actuator/routes
GET 是获取路由列表,POST请求是立即刷新路由列表
该端点可以查看所有的过滤器,了解 error、post、pre、route 四种过滤器有哪些,是否启动,执行顺序(order) 是多少。
http://localhost:9000/actuator/filters
源码地址:https://github.com/saysky/sens-web/tree/master/sens-api-gateway
- 身份认证和安全
- 审查和监控
- 动态路由
- 压力测试
- 负载均衡
- 等待
目前,Zuul 使用默认 HTTP 客户端是 Apache HTTP Client。
下面介绍编写一个 Zuul 微服务网关和基本的配置。
准备
Eureka 注册中心,启动在 8761 端口
一个或多个服务,注册在 Eureka 中
比如我目前 Eureka 上已经注册了两个服务
分别是用户中心的服务提供者(8080端口)和服务消费者(8081端口)
通过地址栏访问 http://localhost:8080/user/1 和 http://localhost:8081/hello 均能访问到两个服务
其中后者访问效果如下,下面以这个为示例,介绍网关的使用
下面我们来介绍 zuul,通过网关来访问这两个服务(通常我只暴露服务消费者,即 web 那个服务,服务提供者我们通常不暴露出去)
一、编写 Zuul 微服务网关
1.创建一个 SpringBoot 项目
注意:目前我使用都是最新版本, SpringBoot 版本是 2.1.7.RELEASE,SpringCloud 版本是 Greenwich.RELEASE
pom.xml 添加依赖
- <!-- Eureka client -->
- <dependency>
- <groupId>org.springframework.cloud</groupId>
- <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
- </dependency>
- <!-- zuul -->
- <dependency>
- <groupId>org.springframework.cloud</groupId>
- <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
- </dependency>
2.启动类添加 @EnableZuulProxy 注解
- @SpringBootApplication
- @EnableZuulProxy
- public class SensApiGatewayApplication {
- public static void main(String[] args) {
- SpringApplication.run(SensApiGatewayApplication.class, args);
- }
- }
3.添加配置
application.yml
- server:
- port: 9000
- spring:
- application:
- name: sens-api-gateway
- eureka:
- client:
- serviceUrl:
- defaultZone: http://localhost:8761/eureka/
启动在 9000 端口,注册服务到 Eureka
4.运行启动类,启动 Zuul 在 9000 端口
可以看到网关注册到了 Eureka
通过地址栏访问
http://localhost:9000/服务名/请求路径,就可以访问到其他服务的路径
如我的用户中心服务消费者服务名为 sens-user-web (上图左侧的 Application 名称是全部大写,实际我的服务名是全小写的)
即下面两个请求结果是一样的
http://localhost:9000/sens-user-web/hello
http://localhost:8081/hello
可见,网关帮我们转发了这个请求
如果想访问另一个服务,一样的方法
http://localhost:9000/sens-user-core/user/1 也能访问到 http://localhost:8080/user/1
可见,目前我们几乎没有任何其他的配置,就能实现通过网关访问到所有的请求
但是这还不够,下面我们会介绍自定义路由和容错回退的一些配置
二、自定义路由
目前通过网关访问其他服务的路径,示例如下
http://localhost:9000/sens-user-web/hello
http://localhost:9000/sens-user-core/user/1
现在我有两个需求
- 首先我觉得 sens-user-web 太长,我想改成 user
- sens-user-core 这个服务我不想暴露,我只想暴露服务消费者。访问生产者的话让网关响应404比较好
解决办法很简单,只需要几行配置
在 application.yml 添加配置
- zuul:
- # 前缀,所有服务里的路径前加 /api
- prefix: /api
- routes:
- sens-user-web: /user/**
- # 排除某些路由, 支持正则表达式
- ignored-patterns:
- - /**/abc/efg
- # 排除服务
- ignored-services: sens-user-core
上面几行配置,分别是设置统一的前缀,单条路由重写,排除自定义路由(排除后,访问404),排除服务(该服务所有请求404)
这样一来
配置前是 http://localhost:9000/sens-user-web/hello
配置后是 http://localhost:9000/api/user/hello
注意:因为我没有排除 sens-user-web,所有之前的 http://localhost:9000/sens-user-web/hello 也可以访问
三、设置超时时间
通常我们通过网关访问一个路径,如 http://localhost:9000/sens-user-web/hello,
网关会自己转发到 sens-user-web 服务中的 /hello 路径,
因为 Zuul 内部使用了 Ribbon 做负载均衡,那么对于一些时间比较长的请求,可能会被作为超时处理。
默认时间是 1 秒
示例
访问 http://localhost:9000/sens-user-web/hello
我在 sens-user-web 服务 /hello 方法里写一个 sleep,睡眠5s,看会不会超时(也可以通过打断点暂停的方法测试)
- @GetMapping("/hello")
- public String index() throws InterruptedException {
- System.out.println("进来了");
- //主线程暂停5s
- Thread.sleep(5000);
- return "Hello, this is user web page.";
- }
效果如下
解决办法
在 pom.xml 中设置超时时间
- # 超时时间,ribbon和hystrix是同时生效的,哪个值小哪个生效
- hystrix:
- command:
- default:
- execution:
- isolation:
- thread:
- timeoutInMilliseconds: 60000
- ribbon:
- ReadTimeout: 60000
- ConnectTimeout: 3000
四、Zuul 的容错和回归
当服务不可用的时候,网关会响应 50X 之类的错
比如超时是这样的
这是系统默认的界面,很不友好
我们可以重写回归响应的方法,给用户一个比较好的提示
解决办法如下
在网关项目中新建一个类
- package com.liuyanzhao.sens.api.gateway.config;
- import com.netflix.hystrix.exception.HystrixTimeoutException;
- import org.springframework.cloud.netflix.zuul.filters.route.FallbackProvider;
- 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;
- /**
- * @author 言曌
- * @date 2019-08-08 10:34
- */
- @Component
- public class MyFallbackProvider implements FallbackProvider {
- @Override
- public String getRoute() {
- //表明是为哪个微服务提供回退,*表示所有微服务
- return "*";
- }
- @Override
- public ClientHttpResponse fallbackResponse(String route, Throwable cause) {
- if(cause instanceof HystrixTimeoutException) {
- return response(HttpStatus.GATEWAY_TIMEOUT);
- }
- return this.fallbackResponse();
- }
- public ClientHttpResponse fallbackResponse() {
- return this.response(HttpStatus.INTERNAL_SERVER_ERROR);
- }
- private ClientHttpResponse response(final HttpStatus status) {
- return new ClientHttpResponse() {
- @Override
- public HttpStatus getStatusCode() throws IOException {
- return status;
- }
- @Override
- public int getRawStatusCode() throws IOException {
- return status.value();
- }
- @Override
- public String getStatusText() throws IOException {
- return status.getReasonPhrase();
- }
- @Override
- public void close() {
- }
- @Override
- public InputStream getBody() throws IOException {
- return new ByteArrayInputStream("服务不可用,请稍后再试。Service is not available, please try again later.".getBytes());
- }
- @Override
- public HttpHeaders getHeaders() {
- //headers设定
- HttpHeaders headers = new HttpHeaders();
- MediaType mediaType = new MediaType("application", "json", Charset.forName("UTF-8"));
- headers.setContentType(mediaType);
- return headers;
- }
- };
- }
- }
重启网关服务
五、管理端点
当 @EnableZuulProxy 和 Spring Boot Actuator配合使用时,Zuul 会暴露两个端点:/actuator/routes, /actuator/filters 。借助这两个端点,我们可以方便地、直观地查看级管理 Zuul。
通常,我们直接访问是会报 404,如下配置可以解决
在 application.yml 添加
- # 开启权限访问端点,如 /actuator/routes, /actuator/filters
- management:
- endpoints:
- web:
- exposure:
- include: '*'
这个配置在 springboot 1.x 版本是 management.security.enabled=false,端点路径是 /routes和 /filters
- 路由端点
该端点主要是查看路由列表
http://localhost:9000/actuator/routes
GET 是获取路由列表,POST请求是立即刷新路由列表
- 过滤器路由路径
该端点可以查看所有的过滤器,了解 error、post、pre、route 四种过滤器有哪些,是否启动,执行顺序(order) 是多少。
http://localhost:9000/actuator/filters
源码地址:https://github.com/saysky/sens-web/tree/master/sens-api-gateway
您可以选择一种方式赞助本站
支付宝扫一扫赞助
微信钱包扫描赞助
赏