Zuul 网关和基本应用场景
构建微服务时, 常见的问题是为系统的客户端应用程序提供唯一的网关.
事实上, 您的服务被拆分为小型微服务应用程序, 这些应用程序应该对用户不可见, 否则可能会导致大量的开发 / 维护工作. 还有一些情况, 整个生态系统网络流量可能会通过一个可能影响群集性能的点.
为了解决这个问题, Netflix(微服务的一个主要采用者)创建并开源了它的 Zuul,Zuul 是 Netflix 的基于 JVM 的路由器和服务器端负载均衡器. 后来 Spring 在 Pivotal 下已经在其 Spring Cloud 中对其进行了调整, 使我们能够通过简单的步骤轻松有效地使用 zuul.
Zuul 是一种边缘服务, 它支持对多个服务请求的代理. 它为您的生态系统提供统一的 "前门", 允许任何浏览器, 移动应用程序或其他用户界面使用来自多个主机的服务. 您可以将 Zuul 与其他 Netflix 堆栈组件 (如 Hystrix) 集成以实现容错, 使用 Eureka 进行服务发现, 或者使用它来管理整个系统中的路由规则, 过滤器和负载平衡.
最重要的是, Spring 框架通过 Spring boot/cloud 很好地适应了所有这些组件.
路由器和过滤器
路由是微服务架构不可或缺的一部分. 例如,/ 可以映射到您的 Web 应用程序,/API/users 映射到用户服务并 / API/shop 映射到商店服务.
Netflix 使用 Zuul 进行以下操作:
认证
洞察
压力测试
金丝雀测试
动态路由
服务迁移
负载脱落
安全
静态响应处理
主动 / 主动流量管理
Zuul 的规则引擎允许规则和过滤器基本上以任何 JVM 语言编写, 内置支持 Java 和 Groovy.
Zuul 组件
Zuul 主要有四种类型的过滤器, 使我们能够在任何特定事务的请求处理的不同时间线中拦截流量. 我们可以为特定的 url 模式添加任意数量的过滤器.
前置过滤器 - 在路由请求之前调用.
后置过滤器 - 在路由请求后调用.
路由过滤器 - 用于路由请求.
错误过滤器 - 在处理请求时发生错误时调用.
使用不同的过滤器在 Zuul 内部请求处理流程
过滤器关键概念
关键词 | 备注 |
---|---|
类型 Type | 定义在路由过程中,过滤器被应用的阶段 |
执行顺序 Execution Order | 在同一个 Type 中,定义过滤器执行的顺序 |
条件 Criteria | 过滤器被执行必须满足的条件 |
动作 Action | 如果条件满足,过滤器中将被执行的动作 |
标准过滤器类型
PRE
在请求被路由到源服务器前要执行的过滤器
适用业务场景:
认证
选路由
请求日志
ROUTING
处理将请求发送到源服务器的过滤器
POST
在响应从源服务器返回时要被执行的过滤器
对响应增加 HTTP 头
收集统计和度量
将响应以流的方式发送回客户端
ERROR
上述阶段中出现错误要执行的过滤器
过滤器样例
- public class PreFilter extends ZuulFilter {
- // 过滤器类型
- @Override
- public String filterType() {
- return "pre";
- }
- // 过滤器顺序
- @Override
- public int filterOrder() {
- return 1;
- }
- // 是否加入过滤器流程中
- @Override
- public boolean shouldFilter() {
- return true;
- }
- // 过滤器运行代码
- @Override
- public Object run() {
- RequestContext ctx = RequestContext.getCurrentContext();
- HttpServletRequest request = ctx.getRequest();
- System.out.println("Request Method :" + request.getMethod() + "Request URL :" + request.getRequestURL().toString());
- return null;
- }
- }
netflix zuul 实例概述
现在让我们通过使用 Zuul 创建一个简单而有意义的生态系统来尝试一下. 我们将创建下面的组件来演示整个事物:
学生微服务 - 基于 spring boot 启动的微服务, 它只是暴露单个 URL 以启用一些搜索功能. 为简单起见, 我们将返回硬编码值, 但在现实世界中, 我们可以让此服务连接数据库以获取数据.
Zuul 网关服务
它基于 spring boot 启动, 它将基本上拦截学生服务的所有流量并应用一系列请求过滤器然后路由到底层服务, 并在响应服务时再次, 它将应用一些响应过滤. 由于它是一个网关, 我们可以使用过滤器有效地采取许多有趣和有用的操作.
网关服务的一些共同责任是 -
在网关层应用微服务身份验证和安全性以保护实际服务
我们可以通过使一些日志记录在边缘获取有意义的数据和统计数据来实现微服务洞察和监控进入生态系统的所有流量, 从而为我们提供准确的生产视图.
动态路由可以根据需要将请求路由到不同的后端群集.
我们可以通过逐渐增加到新集群的流量来进行运行时压力测试, 以便在许多情况下衡量性能, 例如集群有新的 H / W 和网络设置, 或者部署了新版本的生产代码.
我们可以进行动态负载, 即为每种类型的请求分配容量, 并删除超出限制的请求.
我们可以应用静态响应处理, 即直接在边缘构建一些响应, 而不是将它们转发到内部集群进行处理.
技术栈和运行环境
Java 1.8 和 IntelliJIDEA 作为开发环境
Spring cloud Zuul 作为网关代理提供商
Spring boot 作为应用程序框架
Spring REST 用于将微服务暴露为 REST
Maven 作为构建工具
创建学生微服务
按照以下步骤开发学生微服务, 稍后将通过 zuul 代理访问的几个 REST 端点. 稍后我们将研究 zuul 部分, 现在让我们先创建学生服务.
创建 Spring Boot 项目
创建一个 Spring boot 项目从 spring 初始化网站, 依赖于 Web.
将项目解压缩并导入到 IDEA 中. 在此步骤中, 使用命令执行 maven 构建, mvn clean install 以便正确下载所有 maven 依赖项.
添加几个 REST 端点
我们现在只需向此服务添加一些 REST 端点, 以便稍后测试网关. 为此, 我们需要通过添加注释添加一个 REST 控制器 @RestController. 为简单起见, 我们将添加一个模型类 Student.
完成所有更改后, 该类将如下所示.
- package com.example.springboostudentservice;
- import java.util.Date;
- import org.springframework.boot.SpringApplication;
- import org.springframework.boot.autoconfigure.SpringBootApplication;
- import org.springframework.Web.bind.annotation.PathVariable;
- import org.springframework.Web.bind.annotation.RequestMapping;
- import org.springframework.Web.bind.annotation.RestController;
- @RestController
- @SpringBootApplication
- public class SpringBootStudentServiceApplication
- {
- @RequestMapping(value = "/echoStudentName/{name}")
- public String echoStudentName(@PathVariable(name = "name") String name)
- {
- return "hello <strong style=\"color: red;\">" + name + "</strong> Responsed on :" + new Date();
- }
- @RequestMapping(value = "/getStudentDetails/{name}")
- public Student getStudentDetails(@PathVariable(name = "name") String name)
- {
- return new Student(name, "Pune", "MCA");
- }
- public static void main(String[] args)
- {
- SpringApplication.run(SpringBootStudentServiceApplication.class, args);
- }
- }
- class Student
- {
- String name;
- String address;
- String cls;
- public Student(String name, String address, String cls) {
- super();
- this.name = name;
- this.address = address;
- this.cls = cls;
- }
- public String getName() {
- return name;
- }
- public String getAddress() {
- return address;
- }
- public String getCls() {
- return cls;
- }
- }
应用程序配置
- spring:
- application:
- name: student
- server:
- port: 8090
这里我们按属性给这个服务命名, spring.application.name=student 我们也定义了默认端口 server.port=8090. 我们需要覆盖默认端口, 因为我们将在 localhost 中运行不同微服务的多个实例.
验证学生服务
最后使用命令执行 maven 构建, mvn clean install 并通过运行命令将此项目作为 spring boot 应用程序启动 java -jar target\spring-boot-zuulgatway-student-service-0.0.1-SNAPSHOT.jar. 现在, 一旦服务器启动, 转到浏览器并测试端点是否正常工作.
http://localhost:8090/echoStudentName/james
http://localhost:8090/getStudentDetails/james
创建学校微服务
创建过程和学生微服务一样, 但是由于服务之间的功能和差异性, 我们需要对接口进行简单的修改
添加几个 REST 断点
我们现在只需向此服务添加一些 REST 端点, 为此, 我们需要通过添加注释添加一个 REST 控制器 @RestController. 为简单起见, 我们将添加一个模型类 School.
完成所有更改后, 该类将如下所示.
- @SpringBootApplication
- @RestController
- public class SpringBootZuulgatewaySchoolServiceApplication {
- @RequestMapping(value = "/echoSchoolName/{name}")
- public String echoSchoolName(@PathVariable(name = "name") String name)
- {
- return "hello <strong style=\"color: green;\">" + name + "</strong> Responsed on :" + new Date();
- }
- @RequestMapping(value = "/getSchoolDetails/{name}")
- public School getSchoolDetails(@PathVariable(name = "name") String name)
- {
- return new School(name, "China", "ZheJiang");
- }
- public static void main(String[] args) {
- SpringApplication.run(SpringBootZuulgatewaySchoolServiceApplication.class, args);
- }
- }
- class School
- {
- String name;
- String address;
- String cls;
- public School(String name, String address, String cls) {
- super();
- this.name = name;
- this.address = address;
- this.cls = cls;
- }
- public String getName() {
- return name;
- }
- public String getAddress() {
- return address;
- }
- public String getCls() {
- return cls;
- }
- }
应用程序配置
现在打开 application.properties 文件并添加这些条目.
- spring:
- application:
- name: school
- server:
- port: 8100
这里我们按属性给这个服务命名, spring.application.name=school 我们也定义了默认端口 server.port=8100`. 我们需要覆盖默认端口, 因为我们将在 localhost 中运行不同微服务的多个实例.
验证学校服务
最后使用命令执行 maven 构建, mvn clean install 并通过运行命令将此项目作为 spring boot 应用程序启动 java -jar target\spring-boot-zuulgatway-school-service-0.0.1-SNAPSHOT.jar. 现在, 一旦服务器启动, 转到浏览器并测试端点是否正常工作.
http://localhost:8100/echoSchoolName / 学军中学
http://localhost:8100/getSchoolDetails / 学军中学
现在我们将使用 Zuul 创建实际的网关服务.
创建 Zuul 网关服务
这将是一个基于 Spring boot 的微服务, 但它有一个特殊的功能. 它将使用 zuul 创建一个代表学生服务的 API 网关. 稍后我们可以添加任意数量的微服务, 如学生服务, 学校服务并能够创建一个强大的微服务生态系统.
创建 String Boot 项目
从 spring 初始化网站创建一个具有 Zuul 依赖关系的 Spring boot 项目.
将项目作为现有 maven 项目解压缩并导入 IDEA. 在此步骤中, 使用命令执行 maven 构建, mvn clean install 以便正确下载所有 maven 依赖项.
启用 Zuul 服务
现在 @EnableZuulProxy 在 src 文件夹中的 Spring 启动应用程序类中添加注释. 使用此批注, 此工件将像 Zuul 服务代理一样运行, 并将启用 API 网关层的所有功能, 如前所述. 然后我们将添加一些过滤器和路由配置.
- import com.example.zuuldemo.filters.ErrorFilter;
- import com.example.zuuldemo.filters.PostFilter;
- import com.example.zuuldemo.filters.PreFilter;
- import com.example.zuuldemo.filters.RouteFilter;
- import org.springframework.boot.SpringApplication;
- import org.springframework.boot.autoconfigure.SpringBootApplication;
- import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
- import org.springframework.context.annotation.Bean;
- @SpringBootApplication
- @EnableZuulProxy
- public class ZuuldemoApplication {
- public static void main(String[] args) {
- SpringApplication.run(ZuuldemoApplication.class, args);
- }
- @Bean
- public PreFilter preFilter() {
- return new PreFilter();
- }
- @Bean
- public PostFilter postFilter() {
- return new PostFilter();
- }
- @Bean
- public ErrorFilter errorFilter() {
- return new ErrorFilter();
- }
- @Bean
- public RouteFilter routeFilter() {
- return new RouteFilter();
- }
- }
Zuul 应用配置
打开 application.YAML 并在下面添加条目
- zuul:
- routes:
- student:
- url: http://localhost:8090
- school:
- url: http://localhost:8100
- server:
- port: 8080
这里 zuul.routes.student.url 将路由所有流量以请求 / student 到实际的学生服务服务器. zuul.routes.school.url 将路由所有流量以请求 / school 到实际的学校服务服务器 server.port- 需要覆盖默认端口, 因为我们将在 localhost 中运行不同微服务的多个实例.
添加 Zuul 过滤器
正如我们已经描述了 zuul 组件, 我们将添加一些过滤器, Zuul 支持 4 种类型的过滤器, 即 pre,post,route 和 error. 在这里, 我们将创建每种类型的过滤器.
要编写过滤器, 我们基本上需要执行以下步骤:
需要扩展 com.netflix.zuul.ZuulFilter
需要重写 filterType,filterOrder,shouldFilter 和 run 方法. 这里的 filterType 方法只能返回四个 String 中的任何一个 - pre/post/route/error. 降低此值后, 过滤器将像特定过滤器一样运行.
runmethod 是根据我们的要求放置滤波器逻辑的地方.
此外, 我们可以根据需要添加任意数量的任何特定过滤器, 这种情况 filterOrder 将用于确定该过滤器执行阶段该文件管理器的顺序.
前置过滤器代码 - 我们将添加以下预过滤器. 目前, 过滤器除了 println 用于测试目的之外什么都不做. 但实际上那些功能足以完成前面提到的许多重要方面.
- package com.example.springbootzuulgateway.filters;
- import javax.servlet.http.HttpServletRequest;
- import com.netflix.zuul.ZuulFilter;
- import com.netflix.zuul.context.RequestContext;
- public class PreFilter extends ZuulFilter {
- @Override
- public String filterType() {
- return "pre";
- }
- @Override
- public int filterOrder() {
- return 1;
- }
- @Override
- public boolean shouldFilter() {
- return true;
- }
- @Override
- public Object run() {
- RequestContext ctx = RequestContext.getCurrentContext();
- HttpServletRequest request = ctx.getRequest();
- System.out.println("Request Method :" + request.getMethod() + "Request URL :" + request.getRequestURL().toString());
- return null;
- }
- }
后置过滤器
- package com.example.springbootzuulgateway.filters;
- import com.netflix.zuul.ZuulFilter;
- public class PostFilter extends ZuulFilter {
- @Override
- public String filterType() {
- return "post";
- }
- @Override
- public int filterOrder() {
- return 1;
- }
- @Override
- public boolean shouldFilter() {
- return true;
- }
- @Override
- public Object run() {
- System.out.println("Inside Response Filter");
- return null;
- }
- }
路由过滤器
- package com.example.springbootzuulgateway.filters;
- import com.netflix.zuul.ZuulFilter;
- public class RouteFilter extends ZuulFilter {
- @Override
- public String filterType() {
- return "route";
- }
- @Override
- public int filterOrder() {
- return 1;
- }
- @Override
- public boolean shouldFilter() {
- return true;
- }
- @Override
- public Object run() {
- System.out.println("Inside Route Filter");
- return null;
- }
- }
错误过滤器
- package com.example.springbootzuulgateway.filters;
- import com.netflix.zuul.ZuulFilter;
- public class ErrorFilter extends ZuulFilter {
- @Override
- public String filterType() {
- return "error";
- }
- @Override
- public int filterOrder() {
- return 1;
- }
- @Override
- public boolean shouldFilter() {
- return true;
- }
- @Override
- public Object run() {
- System.out.println("Inside Route Filter");
- return null;
- }
- }
5.5. 注册 zuul 过滤器
创建要自动注册和启用的这些过滤器的 bean 定义.
- @Bean
- public PreFilter preFilter() {
- return new PreFilter();
- }
- @Bean
- public PostFilter postFilter() {
- return new PostFilter();
- }
- @Bean
- public ErrorFilter errorFilter() {
- return new ErrorFilter();
- }
- @Bean
- public RouteFilter routeFilter() {
- return new RouteFilter();
- }
Netflix zuul 示例演示
所以我们启用了 Zuul, 添加了所需的配置并开发了过滤器. 所以我们可以做基本的测试来理解整个事情.
使用命令执行 maven 构建, mvn clean install 并通过运行命令将此项目作为 spring boot 应用程序启动 java -jar target\spring-boot-zuulgateway-0.0.1-SNAPSHOT.jar.
现在, 一旦服务器启动, 转到浏览器并通过访问学生服务名称和学校服务来测试端点是否正常工作, 即 / student 和 / school.
http://localhost:8080/student/echoStudentName/james
http://localhost:8080/school/echoSchoolName / 学军学校
总结
这就是 netflix zuul 过滤器示例. 我建议你自己做, 通过代理添加一些更多的底层服务和路由请求, 应用不同类型的过滤器并在过滤器中添加真正的逻辑.
链接: https://pan.baidu.com/s/1zpUBTCDNVHO4s8TAIOxKVA 提取码: 8v7w
请在评论部分将您的问题提交给我.
快乐学习!!
来源: https://www.cnblogs.com/sanshengshui/p/10954796.html