构建微服务时,常见的问题是为系统的客户端应用程序提供唯一的网关。
事实上,您的服务被拆分为小型微服务应用程序,这些应用程序应该对用户不可见,否则可能会导致大量的开发/维护工作。还有一些情况,整个生态系统网络流量可能会通过一个可能影响群集性能的点。
为了解决这个问题,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主要有四种类型的过滤器,使我们能够在任何特定事务的请求处理的不同时间线中拦截流量。我们可以为特定的url模式添加任意数量的过滤器。
使用不同的过滤器在Zuul内部请求处理流程
关键词 | 备注 |
---|---|
类型Type | 定义在路由过程中,过滤器被应用的阶段 |
执行顺序Execution Order | 在同一个Type中,定义过滤器执行的顺序 |
条件Criteria | 过滤器被执行必须满足的条件 |
动作Action | 如果条件满足,过滤器中将被执行的动作 |
在请求被路由到源服务器前要执行的过滤器
认证
选路由
请求日志
处理将请求发送到源服务器的过滤器
在响应从源服务器返回时要被执行的过滤器
对响应增加HTTP 头
收集统计和度量
将响应以流的方式发送回客户端
上述阶段中出现错误要执行的过滤器
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; } }
现在让我们通过使用Zuul创建一个简单而有意义的生态系统来尝试一下。我们将创建下面的组件来演示整个事物:
学生微服务 - 基于spring boot启动的微服务,它只是暴露单个URL以启用一些搜索功能。为简单起见,我们将返回硬编码值,但在现实世界中,我们可以让此服务连接数据库以获取数据。
Zuul网关服务
它基于spring boot启动,它将基本上拦截学生服务的所有流量并应用一系列请求过滤器然后路由到底层服务,并在响应服务时再次,它将应用一些响应过滤。由于它是一个网关,我们可以使用过滤器有效地采取许多有趣和有用的操作。
网关服务的一些共同责任是 -
按照以下步骤开发学生微服务,稍后将通过zuul代理访问的几个REST端点。稍后我们将研究zuul部分,现在让我们先创建学生服务。
创建一个Spring boot项目从 spring初始化 网站,依赖于 Web 。
将项目解压缩并导入到IDEA中。在此步骤中,使用命令执行maven构建, mvn clean install
以便正确下载所有maven依赖项。
我们现在只需向此服务添加一些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控制器 @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创建实际的网关服务。
这将是一个基于 Spring boot 的微服务,但它有一个特殊的功能。它将使用zuul创建一个代表学生服务的API网关。稍后我们可以添加任意数量的微服务,如学生服务,学校服务并能够创建一个强大的微服务生态系统。
从 spring初始化网站 创建一个具有 Zuul
依赖关系的Spring boot项目。
将项目作为现有maven项目解压缩并导入IDEA。在此步骤中,使用命令执行maven构建, mvn clean install
以便正确下载所有maven依赖项。
现在 @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(); } }
打开application.yml并在下面添加条目
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支持4种类型的过滤器,即 pre
, post
, route
和 error
。在这里,我们将创建每种类型的过滤器。
要编写过滤器,我们基本上需要执行以下步骤:
com.netflix.zuul.ZuulFilter
filterType
, filterOrder
, shouldFilter
和 run
方法。这里的 filterType
方法只能返回四个String中的任何一个 - pre/post/route/error
。降低此值后,过滤器将像特定过滤器一样运行。 run
method是根据我们的要求放置滤波器逻辑的地方。 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; } }
创建要自动注册和启用的这些过滤器的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(); }
所以我们启用了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
请在评论部分将您的问题提交给我。
快乐学习!!