百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术资源 > 正文

微服务之服务网关介绍及(Spring Cloud Gateway搭建)

off999 2025-02-03 14:31 32 浏览 0 评论

0、前言


在微服务架构中,1个系统会被拆分为了很多个微服务。

如果每1个微服务都直接对外暴露出来,让用户直接访问这些微服务;

那么如何对用户的身份和权限进行鉴定?如何对微服务中的访问流量进行限流?

此时我们需要1个统一的入口(网关服务)以上问题将迎刃而解;



一、服务网关(Gateway)简介


微服务的网关=路由转发+过滤器


如果没有网关的存在,我们只能在客户端记录每个微服务的地址,然后分别去调用。



以上架构,会存在着诸多的问题:


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

认证复杂,每个服务都需要独立认证。

存在跨域请求,在一定场景下处理相对复杂。


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

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

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



Spring Cloud Gateway旨在为微服务架构提供一种简单有效的统一的 API路由管理方式。

它不仅提供统一的路由方式,并且基于Filter链的方式提供了网关基本的功能,例如:安全,监控和限流


微服务网关的作用


提供了统一访问入口,降低了服务受攻击面 提供了统一跨域解决方案 提供了统一日志记录操作,可以进行统一监控 提供了统一权限认证支持 提供了微服务限流功能,可以保护微服务,防止雪崩效应发生


二、Gateway搭建



1.创建1个api-gateway模块



2.pom依赖


我们使用的网关产品为spring-cloud框架提供的gateway;服务网关需要调用服务注册中心(Nacos)获取服务提供者的调用地址


<dependencies>
	<!--引入gateway网关-->
	<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-starter-gateway</artifactId>
	</dependency>
	
	<!--Nacos服务发现依赖-->
	<dependency>
		<groupId>com.alibaba.cloud</groupId>
		<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
	</dependency>
</dependencies>


3.创建启动类


package com.zhanggen.gateway;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

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


4.添加配置文件(application.yaml)


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


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

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

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

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


server:
  port: 7000
spring:
  application:
    name: api-gateway
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848 # nacos地址
    gateway:
      routes: # 路由数组[路由 就是指定当请求满足什么条件的时候转到哪个微服务]
        - id: user-service-route # 当前路由的标识, 要求唯一
          uri: lb://user-service # 请求要转发到的地址
          predicates: # 断言(就是路由转发要满足的条件)
            - Path=/user/** # 当请求路径满足Path指定的规则时,才进行路由转发


跨域配置


spring:
  cloud:
    gateway:
      globalcors:
        add-to-simple-url-handler-mapping: true
        corsConfigurations:
          '[/**]':
            allowedHeaders: "*"
            allowedOrigins: "*"
            allowedMethods:
              - GET
              - POST
              - DELETE
              - PUT
              - OPTION
      routes:
        # 平台管理
        - id: admin
          uri: lb://leadnews-admin
          predicates:
            - Path=/admin/**
          filters:
            - StripPrefix= 1
        - id: wemedia
          uri: lb://leadnews-wemedia
          predicates:
            - Path=/wemedia/**
          filters:
            - StripPrefix= 1


5.测试网关路由转发功能



启动项目,并通过网关去访问用户微服务,现请求流程如下


用户的请求http://127.0.0.1:7000/user/1到达GatWay GatWay摘取URL中的/user/1路径进行路由匹配 匹配成功之后URL变成http://user-service/user/1 GatWay调用客户端负载均衡器(Ribin)去服务注册中心(Nacos)拉取http://user-service/user/1对应的服务,进行负载均衡选择 选择出1个微服务之后http://user-service/user/1转换成http://127.0.0.1:8081/user/1 GatWay把用户请求转发到http://127.0.0.1:8081/user/1;


6.Nginx转发


使用Nginx转发用户请求到Gateway


worker_processes  1;

events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;
    gzip  on;

    upstream  heima-app-gateway{
        server localhost:51601;
    }

    server {
        listen 8801;
        location / {
            root html/app/;
            index index.html;
        }
        
        location ~/app/(.*) {
            proxy_pass http://heima-app-gateway/$1;
            proxy_set_header HOST $host;  # 不改变源请求头的值
            proxy_pass_request_body on;  #开启获取请求体
            proxy_pass_request_headers on;  #开启获取请求头
            proxy_set_header X-Real-IP $remote_addr;   # 记录真实发出请求的客户端IP
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;  #记录代理信息
        }
    }
    
    upstream  heima-wemedia-gateway{
        server localhost:51602;
    }

    server {
        listen 8802;
        location / {
            root html/wemedia-web/;
            index index.html;
        }
        
        location ~/wemedia/MEDIA/(.*) {
            proxy_pass http://heima-wemedia-gateway/$1;
            proxy_set_header HOST $host;  # 不改变源请求头的值
            proxy_pass_request_body on;  #开启获取请求体
            proxy_pass_request_headers on;  #开启获取请求头
            proxy_set_header X-Real-IP $remote_addr;   # 记录真实发出请求的客户端IP
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;  #记录代理信息
        }
    }
    
    upstream  heima-admin-gateway{
        server localhost:51603;
    }
    server {
        listen 8803;
        location / {
            root html/admin-web/;
            index index.html;
        }
        
        location ~/service_6001/(.*) {
            proxy_pass http://heima-admin-gateway/$1;
            proxy_set_header HOST $host;  # 不改变源请求头的值
            proxy_pass_request_body on;  #开启获取请求体
            proxy_pass_request_headers on;  #开启获取请求头
            proxy_set_header X-Real-IP $remote_addr;   # 记录真实发出请求的客户端IP
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;  #记录代理信息
        }
    }
}

nginx.conf


三、断言(理解)


断言就是1刀切,只有当前这1个条件判断成功才能进行路由转发,只有断言都返回真,才会真正的执行路由


1.基于Datetime类型的断言


# AfterRoutePredicateFactory:   接收一个日期参数,判断请求日期是否晚于指定日期
# BeforeRoutePredicateFactory:  接收一个日期参数,判断请求日期是否早于指定日期
# BetweenRoutePredicateFactory: 接收两个日期参数,判断请求日期是否在指定时间段内
- After=2019-12-31T23:59:59.789+08:00[Asia/Shanghai]


2.基于远程地址的断言


# RemoteAddrRoutePredicateFactory:接收一个IP地址段,判断请求主机地址是否在地址段中
- RemoteAddr=192.168.1.1/24


3.基于Cookie的断言


# CookieRoutePredicateFactory:接收两个参数,cookie 名字和一个正则表达式。 判断请求cookie是否具有给定名称且值与正则表达式匹配。
- Cookie=chocolate, ch. 


4.基于Header的断言


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


5.基于Host的断言


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


6.基于Path请求路径的断言


# PathRoutePredicateFactory:接收一个参数,判断请求的URI部分是否满足路径规则。
- Path=/foo/{segment}


7.基于Query请求参数的断言


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


8.使用


验证内置断言的使用:


server:
  port: 7000
spring:
  application:
    name: api-gateway
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848 # nacos地址
    gateway:
      routes: # 路由数组[路由 就是指定当请求满足什么条件的时候转到哪个微服务]
        - id: user-service-route # 当前路由的标识, 要求唯一
          uri: lb://user-service # 请求要转发到的地址
          predicates: # 断言(就是路由转发要满足的条件)
            - Path=/user/** # 当请求路径满足Path指定的规则时,才进行路由转发
            - Before=2019-11-28T00:00:00.000+08:00 # 限制请求时间在2019-11-28之前
            - Method=POST # 限制请求方式为POST


四、过滤器


Gateway也包含过滤器功能,网关服务的过滤器会对请求或响应进行拦截,完成一些通用操作。



1.过滤器执行时机


Gateway的过滤器中有2个执行时机:


PRE: 这种过滤器在请求被路由之前调用,可利用这种过滤器实现身份验证、在集群中选择请求的微服务、记录调试信息

POST:这种过滤器在路由到微服务以后执行,可用来为响应添加标准的HTTP Header、收集统计信息和指标、将响应从微服务发送给客户端


2.过滤器类型


Gateway的Filter从作用范围可分为2种


GatewayFilter:应用到单个路由或者一个分组的路由上

GlobalFilter:应用到所有的路由上


3.内置局部过滤器


局部过滤器是针对单个路由的过滤器。在SpringCloud Gateway中内置了很多不同类型的网关路由过滤器。具体如下:


过滤器工厂

作用

参数

AddRequestHeader

为原始请求添加Header

Header的名称及值

AddRequestParameter

为原始请求添加请求参数

参数名称及值

AddResponseHeader

为原始响应添加Header

Header的名称及值

DedupeResponseHeader

剔除响应头中重复的值

需要去重的Header名称及去重策略

Hystrix

为路由引入Hystrix的断路器保护

HystrixCommand的名称

FallbackHeaders

为fallbackUri的请求头中添加具体的异常信息

Header的名称

PrefixPath

为原始请求路径添加前缀

前缀路径

PreserveHostHeader

为请求添加一个preserveHostHeader=true的属性,路由过滤器会检查该属性以决定是否要发送原始的Host

RequestRateLimiter

用于对请求限流,限流算法为令牌桶

keyResolver、rateLimiter、statusCode、denyEmptyKey、emptyKeyStatus

RedirectTo

将原始请求重定向到指定的URL

http状态码及重定向的url

RemoveHopByHopHeadersFilter

为原始请求删除IETF组织规定的一系列Header

默认就会启用,可以通过配置指定仅删除哪些Header

RemoveRequestHeader

为原始请求删除某个Header

Header名称

RemoveResponseHeader

为原始响应删除某个Header

Header名称

RewritePath

重写原始的请求路径

原始路径正则表达式以及重写后路径的正则表达式

RewriteResponseHeader

重写原始响应中的某个Header

Header名称,值的正则表达式,重写后的值

SaveSession

在转发请求之前,强制执行WebSession::save操作

secureHeaders

为原始响应添加一系列起安全作用的响应头

无,支持修改这些安全响应头的值

SetPath

修改原始的请求路径

修改后的路径

SetResponseHeader

修改原始响应中某个Header的值

Header名称,修改后的值

SetStatus

修改原始响应的状态码

HTTP 状态码,可以是数字,也可以是字符串

StripPrefix

用于截断原始请求的路径

使用数字表示要截断的路径的数量

Retry

针对不同的响应进行重试

retries、statuses、methods、series

RequestSize

设置允许接收最大请求包的大小。如果请求包大小超过设置的值,则返回 413 Payload Too Large

请求包大小,单位为字节,默认值为5M

ModifyRequestBody

在转发请求之前修改原始请求体内容

修改后的请求体内容

ModifyResponseBody

修改原始响应体的内容

修改后的响应体内容


4.内置局部过滤器的使用


只需要把过滤器配置在微服务的配置文件中即可生效;


server:
  port: 7000
spring:
  application:
    name: api-gateway
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848 # nacos地址
    gateway:
      routes: # 路由数组[路由 就是指定当请求满足什么条件的时候转到哪个微服务]
        - id: user-service-route # 当前路由的标识, 要求唯一
          uri: lb://user-service # 请求要转发到的地址
          predicates: # 断言(就是路由转发要满足的条件)
            - Path=/user/** # 当请求路径满足Path指定的规则时,才进行路由转发
          filters:
            - SetStatus=2000 # 修改返回状态


5.内置全局过滤器


全局过滤器作用于所有路由无需配置。通过全局过滤器可以实现对权限的统一校验,安全性验证等功能。

SpringCloud Gateway内部也是通过一系列的内置全局过滤器对整个路由转发进行处理如下:



6.自定义全局过滤器(重点)


内置的过滤器已经可以完成大部分的功能,但是对于企业开发的一些业务功能处理,还是需要我们自己编写过滤器来实现的。


下面,我们一起通过代码的形式自定义一个过滤器,去完成统一的权限校验。


开发中的鉴权逻辑:


当客户端第一次请求服务时,服务端对用户进行信息认证(登录)

认证通过,将用户信息进行加密形成token,返回给客户端,作为登录凭证

以后每次请求,客户端都携带认证的token

服务端对token进行解密,判断是否有效。


下面的我们自定义一个GlobalFilter,去校验所有请求的请求参数中是否包含“token”,如何不包含请求参数“token”则不转发路由,否则执行正常的逻辑。


package com.zhanggen.gateway.auth;

import org.apache.commons.lang.StringUtils;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

//全局认证过滤器
@Component
public class AuthGlobalFilter implements GlobalFilter, Ordered {

    //认证逻辑
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

        //请求参数数,获取一个叫token的参数的值  String token =  request.getParamter("token")
        String token = exchange.getRequest().getQueryParams().getFirst("token");

        //判断是否请求参数中携带了token
        if (StringUtils.isBlank(token)) {
            System.out.println("鉴权失败");
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);//设置响应码 resp.setStatus(401)
            return exchange.getResponse().setComplete();//返回响应
        }

        //调用chain.filter继续向下游执行
        return chain.filter(exchange);
    }

    //决定当前过滤器的执行级别, 数组越小,优先级越高
    @Override
    public int getOrder() {
        return 0;
    }
}

com.zhanggen.gateway.auth.AuthGlobalFilter

相关推荐

如何确定电脑主板坏了(如何知道电脑主板坏了)
如何确定电脑主板坏了(如何知道电脑主板坏了)

1、如果主板坏了会不通电,这种情况下电脑的开关机键和重启键是没有任何作用的。如果是突然之间出现的情况,检查开关接线没有任何问题的情况下就是主板损坏。2、如果主板芯片损坏,则就是开机无反应或是各风扇都转,显示器无反应。另外,能开机的话,并不一...

2025-12-07 02:03 off999

路由器十大名牌排名榜(路由器排名前十的品牌)

从十大无线路由器排行榜来看,是这样的:1.网件无线路由器2.华硕无线路由器3.TP-LINK无线路由器4.华为无线路由器5.腾达无线路由器6.水星无线路由器7.磊科无线路由器8.小米无线路由器9.迅捷...

一台打印机如何多台电脑使用

(1)需要共享打印机的电脑必须在同一局域网下;(2)连接打印机的那台电脑和打印机必须保持开机状态。二、具体操作方法和步骤:(1)先点开始【再点设备和打印机】首先点击电脑左下角的开始按钮,在弹出的菜单上...

win10专业版下载软件(win 10专业版下载)
  • win10专业版下载软件(win 10专业版下载)
  • win10专业版下载软件(win 10专业版下载)
  • win10专业版下载软件(win 10专业版下载)
  • win10专业版下载软件(win 10专业版下载)
tplink路由器设置网址打不开
tplink路由器设置网址打不开

碰到这种情况可以尝试下面几种方法,还是无法打开TP-Link路由器的设置网址,则多半是这台TP-Link路由器本身问题。一、输入正确的设置网址TP-Link系列的无线路由器,不同的型号设置网址也不一样,192.168.1.1、192.168...

2025-12-07 00:03 off999

win7 纯净版ghost(win7纯净版ghost文件)

win7ghost备份系统的步骤:1、进入ghost界面,选择Local一Partition一ToImage;2、选择要操作的硬盘;3、选择要备份的分区;4、设置镜像文件的保存路径,点Save;5...

98版五笔字型字根表(五笔98版字根表高清)

五笔字型98版的字根表如下:一、1区横起笔11G王旁青头五夫一,12F土干十寸未甘雨,13D大犬戊其古石厂,14S木丁西甫一四里,15A工戈草头右框七。二、2区竖起笔21H目上卜止虎头具,...

电脑黑屏出现一堆字母(电脑屏幕黑屏突然又出现很多字母怎么办)

先尝试修复,不行就重装系统:第一、有可能是系统有问题了,可能的解决办法:1、开机不断点击F8键,进入系统操作选单,选“最后一次正确配置”,重启电脑,看能否解决。2、开机不断点击F8键,进入系统操作选单...

怎么清理系统数据(怎么清理系统数据安卓)

要清理系统占用的内存,可以尝试以下方法:1.关闭不必要的程序:打开任务管理器(在Windows中按Ctrl+Shift+Esc),查看运行中的程序和进程,关闭不必要的应用程序和任务,以释放内...

手机自动更新在哪里关闭(oppo软件自动更新怎么关闭)

1、首先要保证你的手机已经代开“开发者模式”,这样才能关闭或者打开系统自动更新;2、找到手机上的“设置”并点击;3、在设置页面找到“开发者选项”并点击;4、在开发者选项找到“系统自动更新”,因为系统默...

ae(aed是什么意思)

跨境电商里说的AE平台指的是AliExpress,也就是我们常说的四大平台之一的速卖通。速卖通是阿里巴巴旗下针对跨境出口,面向全球市场打造的跨境电商交易平台,被称为“国际版淘宝”,是全球第三大英文在线...

装系统进入bios(装系统进入不了PE界面)

在进入BIOS界面后,有两种方式可以重装系统,具体步骤如下:方式一:通过U盘重装系统将U盘插入电脑,重启电脑,在开机时按下F11、F12、ESC等热键,并选择USB启动项。进入安装界面后,选择“语言和...

怎么制作优盘安装系统(怎样制作优盘安装win10系统)

1.下载一键重装系统软件,打开后选择启动U盘界面,接着制作一个u盘启动盘来装系统。2.开机并不断按下U盘启动快捷键。3.U盘启动快捷键在U盘制作完成后软件界面中有提示。4.在进入系统启动菜单中选择带有...

镜像版和原版有啥区别(镜像版系统和原版)

镜像和原版不一个概念。镜像是指的一种文件格式。如ISO文件等。原版是指一个版本没有经过任何修改的系统。原版可以是形容一个镜像文件,如原版镜像。也可以形容一个系统,如原版系统。原版对应是非原版。如原...

中关村在线装机模拟器(中关村在线模拟装机平台)

有关装机模拟器自由装机最高配置取决于您的计算机配置和游戏需求。如果您想要在自由装机中的最高配置,建议您选择以下配置:CPU:AMDRyzen95900X或AM3IntelCor...

取消回复欢迎 发表评论: