首页 > 其他分享 >第五章 Gateway--服务网关

第五章 Gateway--服务网关

时间:2023-08-14 22:45:37浏览次数:53  
标签:网关 断言 -- gateway 转发 Gateway 路由 请求

5.1 网关简介

大家都都知道在微服务架构中,一个系统会被拆分为很多个微服务。那么作为客户端要如何去调用这么多的微服务呢?如果没有网关的存在,我们只能在客户端记录每个微服务的地址,然后分别去调用。

 

这样的架构,会存在着诸多的问题:

客户端多次请求不同的微服务,增加客户端代码或配置编写的复杂性

认证复杂,每个服务都需要独立认证。 存在跨域请求,在一定场景下处理相对复杂。

上面的这些问题可以借助API网关来解决。 所谓的API网关,就是指系统的统一入口,它封装了应用程序的内部结构,为客户端提供统一服

务,一些与业务本身功能无关的公共逻辑可以在这里实现,诸如认证、鉴权、监控、路由转发等等。

添加上API网关之后,系统的架构图变成了如下所示:

我们也可以观察下,我们现在的整体架构图:

在业界比较流行的网关,有下面这些:

Ngnix+lua

使用nginx的反向代理和负载均衡可实现对api服务器的负载均衡及高可用 lua是一种脚本语言,可以来编写一些简单的逻辑,  nginx支持lua脚本

Kong

基于Nginx+Lua开发,性能高,稳定,有多个可用的插件(限流、鉴权等等)可以开箱即用。 问题: 只支持Http协议;二次开发,自由扩展困难;提供管理API,缺乏更易用的管控、配置方式。

Zuul  Netflix开源的网关,功能丰富,使用JAVA开发,易于二次开发  问题:缺乏管控,无法动态配

置;依赖组件较多;处理Http请求依赖的是Web容器,性能不如Nginx

Spring Cloud Gateway

Spring公司为了替换Zuul而开发的网关服务,将在下面具体介绍。

注意:SpringCloud  alibaba技术栈中并没有提供自己的网关,我们可以采用Spring  Cloud   Gateway来做网关

5.2   Gateway简介

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

优点: 

性能强劲:是第一代网关Zuul的1.6倍

功能强大:内置了很多实用的功能,例如转发、监控、限流等 设计优雅,容易扩展

缺点:

其实现依赖Netty与WebFlux,不是传统的Servlet编程模型,学习成本高

不能将其部署在Tomcat、Jetty等Servlet容器里,只能打成jar包执行 需要Spring  Boot  2.0及以上的版本,才支持

5.3  Gateway快速入门

要求:      通过浏览器访问api网关,然后通过网关将请求转发到商品微服务

 第1步:创建一个 api-gateway的模块,导入相关依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>shop-parent</artifactId>
        <groupId>com.shop</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>api-gateway</artifactId>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
    </dependencies>
</project>

第2步: 创建主类

package com.shop.api.gateway;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication(exclude= DataSourceAutoConfiguration.class )//排除数据库连接
public class ApiGatewayApplication {
    public static void main(String[] args) {
        SpringApplication.run(ApiGatewayApplication.class,args);
    }
}

第3步: 添加配置文件

server:
  port: 7000
spring:
  application:
    name: api-gateway
  cloud:
    gateway:
      routes:  # 路由数组[路由 就是指定当请求满足什么条件的时候转到哪个微服务]
        - id: product_route # 当前路由的标识, 要求唯一
          uri: http://localhost:8081 # 请求要转发到的地址
          order: 1 # 路由的优先级,数字越小级别越高
          predicates: # 断言(就是路由转发要满足的条件)
            - Path=/product-serv/** # 当请求路径满足Path指定的规则时,才进行路由转发
          filters: # 过滤器,请求在传递过程中可以通过过滤器对其进行一定的修改
            - StripPrefix=1

第4步: 启动项目, 并通过网关去访问微服务

 

5.3.2 增强版

现在在配置文件中写死了转发路径的地址, 前面我们已经分析过地址写死带来的问题, 接下来我们从 注册中心获取此地址。

第1步:加入nacos依赖

<!--nacos客户端-->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

第2步:在主类上添加注解

@SpringBootApplication(exclude= DataSourceAutoConfiguration.class )
@EnableDiscoveryClient
public class ApiGatewayApplication {
    public static void main(String[] args) {
        SpringApplication.run(ApiGatewayApplication.class,args);
    }
}

第3步:修改配置文件

server:
  port: 7000
spring:
  application:
    name: api-gateway
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
    gateway:
      discovery:
        locator:
          enabled: true
      routes:  # 路由数组[路由 就是指定当请求满足什么条件的时候转到哪个微服务]
        - id: product_route # 当前路由的标识, 要求唯一
          #uri: http://localhost:8081 # 请求要转发到的地址
          uri: lb://service-product # lb指的是从nacos中按照名称获取微服务,并遵循负载均衡策略
          order: 1 # 路由的优先级,数字越小级别越高
          predicates: # 断言(就是路由转发要满足的条件)
            - Path=/product-serv/** # 当请求路径满足Path指定的规则时,才进行路由转发
          filters: # 过滤器,请求在传递过程中可以通过过滤器对其进行一定的修改
            - StripPrefix=1

第4步:测试

5.3.3 简写版

第1步:  去掉关于路由的配置

server:
  port: 7000
spring:
  application:
    name: api-gateway
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
    gateway:
      discovery:
        locator:
          enabled: true

第2步: 启动项目,并通过网关去访问微服务

这时候,就发现只要按照网关地址/微服务/接口的格式去访问,就可以得到成功响应。

5.4   Gateway核心架构

5.4.1 基本概念

路由(Route) 是 gateway 中最基本的组件之一,表示一个具体的路由信息载体。主要定义了下面的几个 信息:

id,路由标识符,区别于其他 Route。

uri,路由指向的目的地    uri,即客户端请求最终被转发到的微服务。

order,用于多个 Route 之间的排序,数值越小排序越靠前,匹配优先级越高。

predicate,断言的作用是进行条件判断,只有断言都返回真,才会真正的执行路由。

filter,过滤器用于修改请求和响应信息。

5.4.2 执行流程

执行流程大体如下:

1.    Gateway Client向Gateway Server发送请求
2.    请求首先会被HttpWebHandlerAdapter进行提取组装成网关上下文
3.    然后网关的上下文会传递到DispatcherHandler,它负责将请求分发给RoutePredicateHandlerMapping
4.    RoutePredicateHandlerMapping负责路由查找,并根据路由断言判断路由是否可用
5.    如果过断言成功,由FilteringWebHandler创建过滤器链并调用

6. 请求会一次经过PreFilter--微服务--PostFilter的方法,最终返回响应

5.5 断言

Predicate(断言, 谓词) 用于进行条件判断,只有断言都返回真,才会真正的执行路由。 断言就是说: 在 什么条件下 才能进行路由转发

5.5.1 内置路由断言工厂

SpringCloud Gateway包括许多内置的断言工厂,所有这些断言都与HTTP请求的不同属性匹配。具体 如下:

基于Datetime类型的断言工厂

此类型的断言根据时间做判断,主要有三个:

AfterRoutePredicateFactory: 接收一个日期参数,判断请求日期是否晚于指定日期 BeforeRoutePredicateFactory: 接收一个日期参数,判断请求日期是否早于指定日期 BetweenRoutePredicateFactory:   接收两个日期参数,判断请求日期是否在指定时间段内

-After=2019-12-31T23:59:59.789+08:00[Asia/Shanghai]

基于远程地址的断言工厂     RemoteAddrRoutePredicateFactory:接收一个IP地址段,判断请求主

机地址是否在地址段中

-RemoteAddr=192.168.1.1/24

基于Cookie的断言工厂

CookieRoutePredicateFactory:接收两个参数,cookie    名字和一个正则表达式。   判断请求

cookie是否具有给定名称且值与正则表达式匹配。

-Cookie=chocolate, ch.

基于Header的断言工厂

HeaderRoutePredicateFactory:接收两个参数,标题名称和正则表达式。 判断请求Header是否 具有给定名称且值与正则表达式匹配。

-Header=X-Request-Id, \d+

基于Host的断言工厂

HostRoutePredicateFactory:接收一个参数,主机名模式。判断请求的Host是否满足匹配规则。

-Host=**.testhost.org

基于Method请求方法的断言工厂

MethodRoutePredicateFactory:接收一个参数,判断请求类型是否跟指定的类型匹配。

-Method=GET

基于Path请求路径的断言工厂

PathRoutePredicateFactory:接收一个参数,判断请求的URI部分是否满足路径规则。

-Path=/foo/{segment}

基于Query请求参数的断言工厂

QueryRoutePredicateFactory :接收两个参数,请求param和正则表达式, 判断请求参数是否具 有给定名称且值与正则表达式匹配。

-Query=baz, ba.

基于路由权重的断言工厂

WeightRoutePredicateFactory:接收一个[组名,权重],    然后对于同一个组内的路由按照权重转发

routes:

-id: weight_route1 uri: host1 predicates:

-Path=/product/**

-Weight=group3, 1

-id: weight_route2 uri: host2 predicates:

-Path=/product/**

-Weight= group3, 9

内置路由断言工厂的使用

接下来我们验证几个内置断言的使用:

server:
  port: 7000
spring:
  application:
    name: api-gateway
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
    gateway:
      discovery:
        locator:
          enabled: true
      routes:  # 路由数组[路由 就是指定当请求满足什么条件的时候转到哪个微服务]
        - id: product_route # 当前路由的标识, 要求唯一
          #uri: http://localhost:8081 # 请求要转发到的地址
          uri: lb://service-product # lb指的是从nacos中按照名称获取微服务,并遵循负载均衡策略
          order: 1 # 路由的优先级,数字越小级别越高
          predicates: # 断言(就是路由转发要满足的条件)
            - Path=/product-serv/** # 当请求路径满足Path指定的规则时,才进行路由转发
            - Before=2023-08-14T00:00:00.000+08:00 #限制请求时间在2023-08-14之前
            - Method=POST #限制请求方式为POST
          filters: # 过滤器,请求在传递过程中可以通过过滤器对其进行一定的修改
            - StripPrefix=1

 

标签:网关,断言,--,gateway,转发,Gateway,路由,请求
From: https://www.cnblogs.com/eagle888/p/17629984.html

相关文章

  • QT画图
    重点:每个QWidget都自带的功能,继承了QPainteDevice都可以使用QPainter来进行绘图。我们需要调用paintEvent绘制事件,这个事件QWidget这个类自带的事件。重写这个事件:如果父类有某个办法,此时这个子类需要有一个更跟父类同样方法名称的。实例化对象写法:QQPainterpainter(this);//......
  • 20230813 arm64 汇编学习 helloworld.s
    Programming with64-Bit ARMAssembly Language SingleBoardComputerDevelopment forRaspberryPiandMobileDevices —StephenSmith 32bitsARM64指令:////Assemblyprogramtoprint"helloworld"tostdout////x0-x2parameterstolinuxfunct......
  • nacos集群部署
    准备nacos一般集群需要至少3个节点。我们先准备3台机器: 192.168.11.200、192.168.11.196、192.168.11.126nacos的默认服务端口是8848,但是由于我们的机器上还有其他nacos服务正在作用,所以,我们这里把端口改为8748,如下:192.168.11.200:8748192.168.11.196:8748192.168.11.......
  • javaagent
    1、模式一:-javaaent1.1、编写MyAgent.javaimportjava.lang.instrument.Instrumentation;publicclassMyAgent{publicstaticvoidpremain(StringagentArg,Instrumentationinstrumentation){System.out.println("premain");}}1.2、在ME......
  • 字节码角度看synchronized和反射的实现原理
    前几天,关于字节码技术,我们讲了字节码的基础,常见的字节码框架以及在软件破解和APM链路监控方面的一些应用.今天我们回到Java本身,看下我们常用的synchronized关键字和反射在字节码层面是如何实现的.synchronized代码块级别的synchronized如下方法的内部使用了synchronized......
  • 苍穹外卖
     POJO:又分为了 Entity DTO VO 1、GIT 在idea创建git  再点击对勾,再点击绿色指向的,传到gitee 2、进行MD5加密   DigestUtils.md5DigestAsHex    getBytes()是将password输出为编码格式iso-8859-1password=DigestUtils.md5DigestAsHex(password......
  • CentOS7 安装
    1、下载ElasticSearch8.9并安装https://www.elastic.co/guide/en/elasticsearch/reference/8.9/rpm.html#rpm-repowgethttps://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-8.9.0-x86_64.rpmwgethttps://artifacts.elastic.co/downloads/elasticsearch/ela......
  • C# 获取网页上指定的元素
    直接上代码//usingSystem;//usingSystem.Net.Http;//usingSystem.Threading.Tasks;//usingHtmlAgilityPack;//usingNewtonsoft.Json;//classProgram//{//staticasyncTaskMain(string[]args)//{//usingvarhttpClient=newHttpClient();......
  • 关于Vue的就地更新策略的解析
    在Vue中使用v-for渲染列表时,默认使用就地更新策略。该策略默认是基于索引的,规定在列表绑定的数据元素顺序变化时,不会重新创建整个列表,而只是更新对应DOM元素上的数据。以下代码实现了一个TODO列表的勾选、添加和删除功能:<!DOCTYPEhtml><html><head><title>In-PlaceUpd......
  • 线性泛基因组和图形泛基因组
     001、线性泛基因组仅仅包含序列信息。迭代组装、map-to-pan、个体denovo组装的泛基因组均是线性泛基因组。 002、图形泛基因组图结构泛基因组是一个二维序列图谱,它以参考基因组为框架,以单个碱基作为图的节点,碱基间的前后关系作为图的边,存在序列差异的地方会自然形成不同......