一、前言

随着业务的扩展,微服务会不对增加,相应的其对外开放的 API 接口也势必增多,这不利于前端的调用以及不同场景下数据的返回,因此,我们通常都需要设计一个 API 网关作为一个统一的 API 入口,来组合一个或多个内部 API。

二、简单介绍

# 2.1 API 网关使用场景

黑白名单: 实现通过 IP 地址控制请求的访问日志:实现访问日志的记录,进而实现日志分析,处理性能指标等协议适配:实现通信协议的校验、适配转换的功能身份认证:对请求进行身份认证计流限流:可以设计限流规则,记录访问流量路由:将请求进行内部(服务)转发

# 2.2 API 网关的实现

业界常用的 API 网关有很多方式,如:Spring Cloud Zuul、 Nginx、Tyk、Kong。本篇介绍的对象正是 Spring Cloud Zuul

Zuul 是 Netflix 公司开源的一个 API 网关组件,提供了认证、鉴权、限流、动态路由、监控、弹性、安全、负载均衡、协助单点压测等边缘服务的框架。

Spring Cloud Zuul 是基于 Netflix Zuul 的微服务路由和过滤器的解决方案,也用于实现 API 网关。其中,路由功能负责将外部请求转发到具体的微服务实例上,是实现外部访问统一入门的基础。而过滤功能是负责对请求的处理过程进行干预,是实现请求校验、服务聚合等功能的基础。

Spring Cloud Zuul 和 Eureka 进行整合时,Zuul 将自身注册到 Eureka 服务中,同时从 Eureka 中获取其他微服务信息,以便请求可以准确的通过 Zuul 转发到具体微服务上。

三、实战演练

本次测试案例基于之前发表的文章中介绍的案例进行演示,不清楚的读者请先转移至 《Spring Cloud 入门 之 Hystrix 篇(四)》 进行浏览。

当前的项目列表如下:

服务实例 端口 描述
common-api - 公用的 api,如:实体类
eureka-server 9000 注册中心(Eureka 服务端)
goods-server 8081 商品服务(Eureka 客户端)
goods-server-02 8082 商品服务(Eureka 客户端)
goods-server-03 8083 商品服务(Eureka 客户端)
order-server 8100 订单服务(Eureka 客户端)

创建一个为名 gateway-server 的 Spring Boot 项目。

# 3.1 添加依赖

<!-- eureka 客户端 -->
<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>

# 3.2 配置文件

server:
port: 9600spring:
application:
name: gatewayeureka:
instance:
instance-id: gateway-9600
prefer-ip-address: true
client:
service-url:
defaultZone: http://localhost:9000/eureka/ # 注册中心访问地址

# 3.3 启动 Zuul

在启动类上添加 @EnableZuulProxy 注解:

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

启动上边的所有项目,打开 Postman 请求订单下单接口,如下图:

图中,我们首先不经过网关直接访问 order-server 项目请求地址:http://localhost:8100/order/place

之后再修改成访问 gateway-server 项目的请求地址:http://localhost:9600/order/order/place

最终,响应结果都一样。

提示:http://localhost:9600/order/order/place 中第一个 order 表示的是注册在 Eureka 上的订单服务名称。

# 3.4 zuul 常用配置

修改路由:

zuul:
sensitive-headers: # 全局忽略敏感头,即允许接收 cookie 等请求头信息
routes:
extlight: # 任意名字,保证唯一即可
path: /extlight/** # 自定义,真正用到的请求地址
service-id: ORDER # 路由到的目标服务名称

将订单服务的路由名称改成 extlight。

使用 Postman 请求下单接口,运行结果:

请求成功。

禁用路由:

zuul:
ignored-patterns:
- /order/order/**

http://localhost:9600/order/order/place 无法被正常路由到订单服务,响应返回 404。

路由加前缀:

zuul:
prefix: /api

所有请求中的 path 需要添加 api 前缀。如: http://localhost:9600/extlight/order/place 需要改成 http://localhost:9600/api/extlight/order/place。

设置敏感头:

zuul:
sensitive-headers: # 设置全局敏感头,如果为空,表示接收所有敏感头信息

zuul:
routes:
extlight: # 任意名字,保证唯一即可
path: /extlight/** # 自定义,真正用到的请求地址
service-id: ORDER # 路由到的目标服务名称
sensitive-headers: # 针对 /extlight/ 的请求设置敏感头信息

四、Zuul 自定义过滤器

Zuul 的核心技术就是过滤器,该框架提供了 ZuulFilter 接口让开发者可以自定义过滤规则。

我们以身份检验为例,自定义 ZuulFilter 过滤器实现该功能。

# 4.1 创建用户服务

新建名为 user-server 的项目。

添加依赖:

<!-- common api -->
<dependency>
<groupId>com.extlight.springcloud</groupId>
<artifactId>common-api</artifactId>
<version>${parent-version}</version>
</dependency><!-- springmvc -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency><!-- eureka 客户端 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

application.yml:

server:
port: 8200spring:
application:
name: USEReureka:
instance:
instance-id: user-api-8200
prefer-ip-address: true # 访问路径可以显示 IP
client:
service-url:
defaultZone: http://localhost:9000/eureka/ # 注册中心访问地址

登录接口:

@RestController
@RequestMapping("/user")
public class LoginController {@PostMapping("/login")
public Result login(String username, String password, HttpServletResponse response) {if ("admin".equals(username) && "admin".equals(password)) {
// 模拟生成 token,实际开发中 token 应存放在数据库或缓存中
String token = "123456";
Cookie cookie = new Cookie("token", token);
cookie.setPath("/");
cookie.setMaxAge(60 * 10);
response.addCookie(cookie);return Result.success();
}return Result.fail(401, "账号或密码错误");
}
}

user-server 启动类:

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

# 4.2 创建 ZuulFilter 过滤器

在 gateway-server 项目中,新建一个过滤器,需要继承 ZuulFilter 类

@Component
public class AuthenticationFilter extends ZuulFilter {/**
* 是否开启过滤
*/
@Override
public boolean shouldFilter() {
RequestContext context = RequestContext.getCurrentContext();
HttpServletRequest request = context.getRequest();boolean flag = request.getRequestURI().contains("/login");
// 如果是登录请求不进行过滤
if (flag) {
System.out.println("========不执行 zuul 过滤方法=======");
} else {
System.out.println("========执行 zuul 过滤方法=======");
}
return !flag;
}/**
* 过滤器执行内容
*/
@Override
public Object run() throws ZuulException {RequestContext context = RequestContext.getCurrentContext();
HttpServletRequest request = context.getRequest();
String token = request.getParameter("token");
// 此处模拟获取数据库或缓存中的 token
String dbToken = "123456";
// 此处简单检验 token
if (token == null || "".equals(token) || !dbToken.equals(token)) {
context.setSendZuulResponse(false);
context.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value());
}return null;
}/**
* 过滤器类型
*/
@Override
public String filterType() {
return "pre";
}/**
* 过滤器执行顺序
*/
@Override
public int filterOrder() {
return 0;
}}

其中,filterType 有 4 种类型:

pre: 这种过滤器在请求被路由之前调用。我们可利用这种过滤器实现身份验证、在集群中选择请求的微服务、记录调试信息等。routing:这种过滤器将请求路由到微服务。这种过滤器用于构建发送给微服务的请求,并使用 Apache HttpClient 或 Netfilx Ribbon 请求微服务。post:这种过滤器在路由到微服务以后执行。这种过滤器可用来为响应添加标准的 HTTP Header、收集统计信息和指标、将响应从微服务发送给客户端等。error:在其他阶段发生错误时执行该过滤器。

其过滤顺序如下图:

# 4.3 测试过滤器

运行所有项目,测试操作步骤如下:

请求用户服务的登录接口(http://localhost:9600/user/user/login),请求不执行 zuul 过滤方法,并且请求响应返回的 cookie 包含 token请求订单服务的下单接口(http://localhost:9600/extlight/order/place),但不携带 token,请求需要执行 zuul 过滤方法,请求响应 401 权限不足请求订单服务的下单接口(http://localhost:9600/extlight/order/place),携带之前登录接口返回的 token,请求需要执行 zuul 过滤方法,校验通过后路由到订单服务执行之后的操作

测试效果图如下:

五、案例源码

Zuul demo 源码

六、参考资料

Announcing Zuul: Edge Service in the Cloud

Spring Cloud 入门 之 Zuul 篇(五)相关推荐

  1. Spring Cloud 入门 之 Config 篇(六)

    一.前言 随着业务的扩展,为了方便开发和维护项目,我们通常会将大项目拆分成多个小项目做成微服务,每个微服务都会有各自配置文件,管理和修改文件起来也会变得繁琐.而且,当我们需要修改正在运行的项目的配置时 ...

  2. Spring Cloud 入门 之 Hystrix 篇(四)

    一.前言 在微服务应用中,服务存在一定的依赖关系,如果某个目标服务调用慢或者有大量超时造成服务不可用,间接导致其他的依赖服务不可用,最严重的可能会阻塞整条依赖链,最终导致业务系统崩溃(又称雪崩效应). ...

  3. Spring Cloud 入门 之 Ribbon 篇(二)

    一.前言 上一篇<Spring Cloud 入门 之 Eureka 篇(一)> 介绍了微服务的搭建,服务注册与发现.但在文章中留了一个小尾巴--如何正确使用 Eureka 进行服务发现并调 ...

  4. Spring Cloud 入门 之 Feign 篇(三)

    一.前言 在上一篇文章<Spring Cloud 入门 之 Ribbon 篇(二)> 中介绍了 Ribbon 使用负载均衡调用微服务,但存在一个问题:消费端每个请求方法中都需要拼接请求服务 ...

  5. Spring Cloud 入门 之 Eureka 篇(一)

    一.前言 Spring Cloud 是一系列框架的有序集合.它利用 Spring Boot 的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册.配置中心.消息总线.负载均衡.断路器.数据 ...

  6. Spring Cloud入门教程 - Zuul实现API网关和请求过滤

    简介 Zuul是Spring Cloud提供的api网关和过滤组件,它提供如下功能: 认证 过滤 压力测试 Canary测试 动态路由 服务迁移 负载均衡 安全 静态请求处理 动态流量管理 在本教程中 ...

  7. Spring Cloud入门,看这篇就够了!

    点击▲关注 "中生代技术"   给公众号标星置顶 更多精彩 第一时间直达 概述 首先我给大家看一张图,如果大家对这张图有些地方不太理解的话,我希望你们看完我这篇文章会恍然大悟. 什 ...

  8. eureka集群只注册一个_Spring cloud系列教程第十篇- Spring cloud整合Eureka总结篇

    Spring cloud系列教程第十篇- Spring cloud整合Eureka总结篇 本文主要内容: 1:spring cloud整合Eureka总结 本文是由凯哥(凯哥Java:kagejava ...

  9. Spring Cloud入门-Admin服务监控中心(Hoxton版本)

    文章目录 Spring Cloud入门系列汇总 摘要 Spring Boot Admin 简介 创建admin-server模块 创建admin-client模块 监控信息演示 结合注册中心使用 修改 ...

最新文章

  1. Nginx 虚拟主机配置及负载均衡
  2. codeforces193B
  3. CTF web题总结--SSRF
  4. 丰农控股 CIO 王轶枭:万亿级农资市场,神策数据助力大丰收筑就数据驱动核心竞争力...
  5. linux下简单限制网卡速度
  6. 迫不及待,英特尔推特“官宣”GPU发布时间
  7. 关于MVC打印问题,打印指定的内容
  8. OpenCV探索之路(五):图像变换——边缘检测(canny、sobel、laplacian)
  9. 学python有前途吗-python有前景吗
  10. php与plc,plc编程语言有哪几种
  11. 计算机二级ppt没弄内容,计算机二级office考试中PPT母版知识考察点有哪些
  12. editplus编辑器使用-快速开始(editplus通过sftp协议远程编辑文件)
  13. MySQL从入门到精通之sql语言---(9月2日更新)
  14. 强化学习经典算法笔记(六):深度Q值网络 Deep Q Network
  15. GetLastError() 返回值对照表
  16. Typora导入CSDN
  17. 怎么做新闻软文推广?故事性新闻稿写作技巧_云媒易
  18. 化金或沉金工艺简要总结
  19. 怎样在iPhone、iPad上的Safari浏览器中快速关闭所有标签页?
  20. 服务过美国总统竞选的非传统投票UI [解析及DEMO]

热门文章

  1. 题目1001:A+B for Matrices
  2. Android开发之高德API篇:2、高德API线路规划
  3. poj3279 反转 挑战程序设计竞赛
  4. SQLAlchemy 多条件查询
  5. 操作系统实践(四/五)
  6. Qt:Windows编程—Qt实现本地服务管理
  7. 学习笔记:首次进行JUnit+Ant构建自动的单元测试(一)
  8. netty 发送 http请求
  9. 20155207实验2 Windows口令破解
  10. java解析xml实例——获取天气信息