• 第十一章 GetAway服务网关详解


    目录

    一、服务网关使用背景

    二、服务网关的种类和区别

    三、Gateway 简介

    优点

    缺点

    Gateway组成

    三、快速入门案例

    1、创建网关服务,引入 GetAway 依赖

    2、创建主类

    3、配置GetAway网关服务

    4、创建 订单服务模块 及创建 商品服务模块

    5、进行测试

    使用网关之前

    使用网关之后


    一、服务网关使用背景

            如下图所示,订单服务 调用 商品服务 的 流程的变化从1-4。

    • 1、最初:订单服务使用 restTemplate 调用商品服务,订单服务自己维护ip地址。
    • 2、然后:订单服务使用 restTemplate 调用商品服务,都使用注册中心。
    • 3、然后:订单服务使用 新的负载均衡 调用商品服务,使用ribbon。
    • 4、最后:订单服务使用 优雅的方式去 调用商品服务,使用openfeign。

            存在问题:此时,如果有新的客户端分别调用 订单服务 和 商品服务,那么这个客户端需要维护新的ip和port。而新客户端调用这些微服务时候,微服务又需要解决进行认证鉴权、安全校验、跨域问题。如果微服务 订单服务 和 商品服务 可能有成百上千个。此时存在的问题是: 

    • 新客户端要维护成千上万个ip和port,维护困难。
    • 新客户端需要进行认证鉴权、安全校验、跨域,那么认证鉴权、安全校验、跨域等问题比较复杂,若在每个微服务都进行解决认证鉴权、安全校验、跨域问题等问题,又会造成代码重复问题。

           解决方案:使用服务网关。而服务网关也是一个微服务,也可从注册中心获取ip。因此,所谓的API网关,就是指系统的统一入口,它封装了应用程序的内部结构,为客户端提供统一服务,一些与业务本身功能无关的公共逻辑可以在这里实现,诸如认证、鉴权、监控、路由转发等等。添加上API网关之后,系统的架构图变成了如下所示:

    二、服务网关的种类和区别

    • 服务网关种类
    名称作用问题
    Ngnix+lua使用nginx的反向代理和负载均衡可实现对api服务器的负载均衡及高可用。lua是一种脚本语言,可以来编写一些简单的逻辑,nginx支持lua脚本。
    Kong基于Nginx+Lua开发,性能高,稳定,有多个可用的插件(限流、鉴权等等)可以开箱即用。

    1、只支持Http协议

    2、二次开发,自由扩展困难

    3、提供管理API,缺乏更易用的管控、配置方式。

    zuulNetflix开源的网关,功能丰富,使用JANA开发,易于二次开发zuul1.0 缺乏管控,无法动态配置;依颡组件较多;处理Http请求依赖的是Web容器,性能不如Nginx
    Spring cloud GatewaySpring cloud Gateway Spring公司为了替换Zuul而开发的网关服务
    • zuul 和 Spring cloud Gateway 区别
    zuulSpring cloud Gateway
    Zuul 1.x,是基于阻塞V/O的API网关Spring Cloud Gateway基于异步非阻塞模型,建立在Spring Framework5、Project Reactor和Spring Boot 2之上
    Zuul 1.x,是基于Servlet 2.5,使用阻塞架构和传统的IO处理模型(高并发线程数量上涨,严重影响请求处理时间),它不支持任何长连接(如WebSocket)Spring Cloud Gateway基于webplus(webplus基于Servlet 3.x异步非阻塞的模型,核心是Reactor响应式编程),支持WebSocket

    Zuul 1.x,设计模式和Nginx较像,每次V/О操作都是从工作线程中选择一个执行,请求线程被阻塞到工作线程完成。

    但是差别是Nginx用C++实现,Zuul用Java实现,故而JVM本身会有第—次加载较慢的情况,使得Zuul的性能相对较差。

    根据官方提供的基准测试,Spring Cloud Gateway的RPS(每秒请求数)是Zuul的1.6倍。
    Zuul 2.x  理念更先进,想基于Netty非阻塞和支持长连接,性能较Zuul 1.x有较大提升,但SpringCloud目前还没有整合。与Spring紧密集成拥有更好的开发体验

    三、Gateway 简介

           Spring Cloud Gateway是Spring公司基于Spring 5.0,Spring Boot 2.0和Project Reactor等技术开发的网关,它旨在为微服务架构提供一种简单有效的统一的API路由管理方式。它的目标是替代 Netilx Zuul,其不仅提供统一的路由方式,并且基于Filter链的方式提供了网关基本的功能,例如:安全,监控/指标和限流。

    优点

    • 性能强劲:是第一代网关Zuul的1.6倍
    • 功能强大:内置了很多实用的功能,例救转发、监控、限流等
    • 设计优雅,容易扩展

    缺点

    • 其实现依赖Netty与WebFlux,不是传统的Servlet编程模型,学习成本高
    • 不能将其部署在Tomcat、Jetty等Servlet容器里,只能打成jar包执行
    • 需要Spring Boot 2.0及以上的版本,才支持

    Gateway组成

           Gateway核心是:route、Predicate、Filter。

    • route:动态路由,能够匹配任何请求属性;
    • Predicate:断言,如果请求与断言相匹配则进行路由;
    • Filter:过滤器,可以在请求被路由前或者之后对请求进行修改。

    三、快速入门案例

         流程:通过网关服务,对访问路径进行请求,如果请求符合断言,则调用订单服务模块。

    1、创建网关服务,引入 GetAway 依赖

    完整pom如下:

    1. "1.0" encoding="UTF-8"?>
    2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    3. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    4. <parent>
    5. <artifactId>springcloudbaseartifactId>
    6. <groupId>com.hwadee.springcloud2022groupId>
    7. <version>0.0.1-SNAPSHOTversion>
    8. parent>
    9. <modelVersion>4.0.0modelVersion>
    10. <groupId>com.hwadee.springcloudgroupId>
    11. <artifactId>routeServer7000artifactId>
    12. <version>0.0.1-SNAPSHOTversion>
    13. <dependencies>
    14. <dependency>
    15. <groupId>org.springframework.cloudgroupId>
    16. <artifactId>spring-cloud-starter-gatewayartifactId>
    17. dependency>
    18. <dependency>
    19. <groupId>org.springframework.cloudgroupId>
    20. <artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
    21. dependency>
    22. dependencies>
    23. project>

    注意:如果GetAway网关服务模块中引入GetAway依赖,则不能引入 starter-web, 如果引入 starter-web 则会引入tomcat,与 GetAway 底层的webFlux冲突,如下图:

    2、创建主类

    1. import org.springframework.boot.SpringApplication;
    2. import org.springframework.boot.autoconfigure.SpringBootApplication;
    3. import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
    4. @SpringBootApplication
    5. @EnableEurekaClient// 启动 eureka 客户端
    6. public class RouteServerApplication {
    7. public static void main(String[] args) {
    8. SpringApplication.run(RouteServerApplication.class, args);
    9. }
    10. }

    3、配置GetAway网关服务

           添加配置文件,配置文件中配置GetAway网关服务。

    1. server:
    2. port: 7000
    3. spring:
    4. application:
    5. name: route-service # 为当前商品服务命名
    6. cloud:
    7. gateway:
    8. routes: #路由数组[路由就是指定当请求满足什么条件的时候转到哪个微服务〕
    9. - id: order_route #当前路由的标识,要求唯一,默认uuid。自定义命名:一般是 要转发的服务名_route
    10. uri: http://localhost:9000 #请求最终要被转发到的 订单服务 的地址
    11. order: 1 #路由的优先级,数字越小级别越高
    12. predicates: #断言(条件判断返回值类型是boolean,就是路由转发要满足的条件)
    13. - Path=/order-serv/** #当请求路径满足Path指定的规则时,才进行路由转发,如/order-serv/order/select/22
    14. filters: #过滤器,请求在传递过程中可以通过过滤器对请求进行一定的修改
    15. - StripPrefix=1 #使用 StripPrefix= x 是指在转发前去掉几层路径。见下面属性说明案例。
    16. - id: order_route #当前路由的标识,要求唯一
    17. uri: http://localhost:9001 #请求最终要被转发到的 产品服务 的地址
    18. order: 1 #路由的优先级,数字越小级别越高
    19. predicates: #断言(条件判断返回值类型是boolean,就是路由转发要满足的条件)
    20. - Path=/product-serv/** #当请求路径满足Path指定的规则时,才进行路由转发
    21. filters: #过滤器,请求在传递过程中可以通过过滤器对请求进行一定的修改
    22. - StripPrefix=1 #使用 StripPrefix= 1 在转发前去掉1层路径。
    23. eureka:
    24. client:
    25. service-url: # 配置服务注册地址,与 eureka-server 中暴露地址保持一致
    26. defaultZone: http://localhost:8000/eureka
    27. instance:
    28. prefer-ip-address: true # 是否使用 IP 地址注册,默认 false
    29. # instance-id: product-service # 实例 id,服务的唯一标识
    30. instance-id: ${spring.cloud.client.ip-address}:${server.port} # 如果想在控制页面看到服务地址与端口,可以将 instance-id 这样配置
    31. lease-renewal-interval-in-seconds: 5 # 发送心跳的间隔,单位秒,默认 30
    32. lease-expiration-duration-in-seconds: 10 # 续约到期时间,单位秒,默认90

        属性介绍说明:

    routes#路由数组[路由就是指定当请求满足什么条件的时候转到哪个微服务]
    id

    id: order_route  # 表示当前路由的标识,要求唯一,默认是uuid。

    一般是转发到哪个服务就在哪个服务名后加route

    uri#请求最终要被转发到的哪个服务的地址,如:http://localhost:8081
    orderorder:1 #路由的优先级,数字越小级别越高
    predicates#断言(条件判断返回值类型是boolean,就是路由转发要满足的条件)
    Path# - Path=/product-serv/**,当请求路径满足Path指定的规则时,才进行路由转发,如:/product-serv/order/buy/22 满足条件,会进行路由转发。
    filters#过滤器,请求在传递过程中可以通过过滤器对请求进行一定的修改
    StripPrefix  

    # -StripPrefix = 1 是指转发之前去掉1层路径,例如:

    我们的需求是 当浏览器访问路径是http://localhost:8081/order-serv/order/buy/22时候,
    希望访问微服务的真是路径是:http://localhost:8081/order/buy/22,
    但是如果不使用过滤器,访问order服务的路径会变为变为:http://localhost:8081/order-serv/order/buy/22,
    与我们实际希望访问的路径http://localhost:8081/order/buy/22不符,访问不到实际的真实路径。
    使用StripPrefix=1是指在转发前去掉几层路径。如果StripPrefix=1,则将请求
    那么访问http://localhost:8081/order-serv/order/buy/22时候,会去掉第一层“/order-serv”,
    此时路径变为我们希望的真实路径http://localhost:8081/order/buy/22 

    4、创建 订单服务模块 及创建 商品服务模块

         创建 订单服务模块 及创建 商品服务模块 见第十章 

         删除 商品服务 模块中的 controller 内 selectHystrixBreaker方法里的超时代码,修改如下:

    1. import com.hwadee.springcloud.entity.Product;
    2. import com.netflix.hystrix.contrib.javanica.annotation.DefaultProperties;
    3. import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
    4. import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
    5. import org.springframework.beans.factory.annotation.Value;
    6. import org.springframework.web.bind.annotation.PathVariable;
    7. import org.springframework.web.bind.annotation.RequestMapping;
    8. import org.springframework.web.bind.annotation.RestController;
    9. import java.math.BigDecimal;
    10. @RestController
    11. @RequestMapping("/product")
    12. public class ProductController {
    13. //方便后面讲负载均衡,查看ip,此处获取配置中的端口号和ip
    14. @Value("${server.port}")
    15. private String port;
    16. @Value("${spring.cloud.client.ip-address}")
    17. private String ip;
    18. @RequestMapping(value = "/select/{id}")
    19. @HystrixCommand(fallbackMethod = "selectHystrixBreakerFallback", commandProperties = {
    20. @HystrixProperty(name = "circuitBreaker.enabled", value = "true"),//是否开启断路器
    21. @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "20"),//请求次数
    22. @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "10000"),//时间窗口期
    23. @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "60"),//失败率达到多少后跳闸
    24. })
    25. public Product selectHystrixBreaker(@PathVariable Long id) {
    26. // 程序异常 测试异常熔断
    27. if (id<=0) {
    28. throw new RuntimeException("id无效");
    29. }
    30. // 程序正常执行
    31. Product product = new Product();
    32. product.setId(id);
    33. // 后面需要测试负载均衡,所以返回 ip 地址及端口号
    34. product.setName("当前访问服务地址:" + ip + ":" + port + " " + "从购物车删除订单,订单号:" + id);
    35. product.setPrice(new BigDecimal(10000.0));
    36. System.out.println(product);
    37. return product;
    38. }
    39. public Product selectHystrixBreakerFallback(Long id) {
    40. Product product = new Product();
    41. product.setId(id);
    42. product.setName("当前访问服务地址:" + ip + ":" + port + " " + "查询订单异常,通过注解 @HystrixCommand()指定的备选方案进行服务熔断");
    43. product.setPrice(new BigDecimal(10000.0));
    44. return product;
    45. }
    46. }

    5、进行测试

         分别启动 注册中心、订单服务、商品服务、和网关服务

         分别访问以下地址查看使用网关之前和使用网关之后的效果。

    • 使用网关之前

           访问商品服务:http://localhost:9001/product/select/2
           访问订单服务:http://localhost:9000/order/select/22

    • 使用网关之后

          访问商品服务:http://localhost:7000/product-serv/product/select/22
          访问订单服务:http://localhost:7000/order-serv/order/select/22

    第十章:Hystrix断路器详解+服务熔断

    第十二章:Spring Cloud Config 统一配置中心详解

  • 相关阅读:
    C 语言程序的执行流程
    2.安装conda python库
    手把手教你搭建SpringCloudAlibaba之Nacos服务注册中心
    PHP+AJAX实现异步上传文件
    最新版 Let’s Encrypt免费证书申请步骤,保姆级教程
    unity - Blend Shape - 变形器 - 实践
    【leetcode】获取生成数组中的最大值 c++
    微信小程序 checkbox 实现双向绑定以及特殊交互处理
    转转图书对基于Drools引擎的DMN实践
    < Python全景系列-6 > 掌握Python面向对象编程的关键:深度探索类与对象
  • 原文地址:https://blog.csdn.net/qq_41946216/article/details/127401374