java—Spring Cloud Gateway微服务网关「建议收藏」

java—Spring Cloud Gateway微服务网关「建议收藏」网关是加在整个微服务最前沿的防火墙和代理器,隐藏微服务结点 IP 端口信息, 从而加强对服务端口的安全保护。

Spring Cloud Gateway

1、简介

  • Spring Cloud Gateway 是 Spring 官网基于 Spring 5.0Spring Boot 2.0Project Reactor 等技术开发的网关服务

  • Spring Cloud Gateway 基于Filter链提供网关基本功能:安全、监控/埋点、限流等。

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

  • Spring Cloud Gateway 是替代 Netflix Zuul 的一套解决方案。

 1.1、名词概念

  • 路由(route): 路由信息由 一个ID一个目的URL一组断言工厂一组Filter 组成。如果路由断言为 真,说明请求URL和配置路由匹配,就可以通过路由去匹配对应的服务,否则不允通过。

  • 断言(Predicate):断言函数输入类型是 Spring 5.0框架 中的 ServerWebExchange,允许开发者去定义匹配来自于HTTP Request中的任何信息比如请求头和参数。

  • 过滤器(Filter): Spring Cloud Gateway中的 Filter 分为两种类型,分别是Gateway Filter和Global Filter,过滤器将会对匹配到的 请求响应 进行修改处理 。

 1.2、服务核心

  • 网关的核心功能是:过滤器链路由转发

  • Spring Cloud Gateway 组件的 核心 是一系列的 过滤器,通过过滤器链可以将客户端发送的请求转发(路由)到对应的微服务。 网关是加在整个微服务最前沿的防火墙和代理器,隐藏微服务 结点 IP 端口信息, 从而加强对服务端口的安全保护。

  • 网关本身也是一个微服务,也需要将其注册到服务注册中心。

 1.3、服务架构

 不管是来自于客户端(PC或移动端)的请求,还是服务内部调用。一切对服务的请求都可经过网关,然后再由网关来实现 鉴权、动态路由 等等操作。

 网关就是整个服务的统一入口,来自各个地方请求通过网关之后在进行下一步的调度转发。

c49.png

2、部署

 在配置好 服务中心具体服务提供 之后,重新添加一个项目模块,项目名自定义。

 2.1、依赖管理

 网关只需要在服务中心进行注册,然后通过网关服务调取其他的服务接口,完成请求的转发即可。

<?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>bill-manager-springCloud</artifactId>
        <groupId>com.beordie</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>gateway</artifactId>

    <dependencies>
        <!--网关依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
        
		<!--中心服务-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
    </dependencies>

</project>

 2.2、启动类

 通过 springboot 注解启动,添加服务中心的扫描注解。

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

 2.3、配置文件

 主要配置相应的 服务中心地址路由规则 ,以及涉及 跨域资源请求 的配置。

# 配置端口信息
server:
  port: 8086
  tomcat:
    uri-encoding: UTF-8

spring:
  application:
    name: gateway
  cloud:
    gateway:
      routes:
        - id: bill-service-route
          # 代理的服务地址
          uri: lb://bill-service
          # 路由断言,可以配置映射路径
          predicates:
            - Path=/api/**
          filters:
          # 添加请求路径的前缀
            - StripPrefix=1
      globalcors:
        corsConfigurations:
          '[/**]':
            allowedOrigins: "*"
            allowedMethods:
              - GET
              
eureka:
  client:
    service-url:
      defaultZone: HTTP://127.0.0.1:10086/eureka
  instance:
    prefer-ip-address: true

3、路由

 3.1、id

- id: bill-service-route

 表示当前设置路由的标识,可以随便进行定义。

 3.2、uri

uri: HTTP://127.0.0.1:9091
uri: lb://bill-service

  将符合 Path 规则的一切请求,都代理到 uri 参数指定的地址,也就是代理到 http://127.0.0.1:9091 的服务。

  在刚才的路由规则中,把路径对应的服务地址写死了!如果同一服务有多个实例的话,这样做显然不合理。

  使用 lb://bill-service 这样的形式,通过 lb: 加上服务的名字,也就是在对应服务配置文件中指定的 application-name,也可以从服务中心注册的服务名找。

  • 路由配置中 uri 所用的协议为 lb 时(以 uri: lb://bill-service 为例),gateway 将使用 LoadBalancerClient 把 bill-service 通过 eureka 解析为实际的主机和端口,并进行 ribbon 负载均衡。

 3.3、predicates

- Path=/api/**

 定义请求当前路由的 url格式,也就是说 HTTP://127.0.0.1:8086/api/ 下面的所有请求都会朱发到当前路由进行处理。

 3.4、filters

 功能和名字意义相同,就是配置路由的过滤器的一些功能。

  • 添加前缀:对请求地址添加前缀路径之后再作为代理的服务地址。
- PrefixPath=/bill
  • 去除前缀:将请求地址中路径去除一些前缀路径之后再作为代理的服务地址,数字表示去除几个前缀。
- StripPrefix=1 

4、跨域

  在 js 请求访问中,如果访问的地址与当前服务器的 域名ip 或者 端口号 不一致则称为跨域请求。若不解决则不能获取到对应地址的返回结果(能够请求,但是结果会被浏览器所拦截)。

 一般网关都是所有微服务的统一入口,必然在被调用的时候会出现跨域问题。

  表示对所有访问到网关服务器的请求地址都进行跨域设置。

globalcors:
  corsConfigurations:
    '[/**]':

 4.1、源地址

 指定允许访问的服务器地址,如:http://localhost:10000 也是可以的, 如果使用 *** **就表示所有的访问都可以。

allowedOrigins: "*"

 4.2、请求方式

 指定可以访问的请求方式,可以指定多种。

allowedMethods:
  - GET
  - POST
  - HEAD

5、过滤器

 5.1、简介

 Gateway 作为网关的其中一个重要功能,就是实现请求的鉴权。而这个动作往往是通过网关提供的过滤器来实现的。前面的 路由功能 也是使用过滤器实现的。

Gateway自带过滤器有几十个,常见自带过滤器有:

过滤器名称 功能
AddRequestHeader 对匹配上的请求加上Header
AddRequestParameters 对匹配上的请求路由添加参数
AddResponseHeader 对从网关返回的响应添加Header
StripPrefix 对匹配上的请求路径去除前缀

过滤器.png

 5.2、 配置全局默认过滤器

  这些自带的过滤器的使用和路由配置时的方法一致,也可以将这些过滤器配置成不只是针对某个路由,而是可以对所有路由生效,也就是配置默认过滤器。

# 默认过滤器,对所有路由都生效
default-filters:
  - AddResponseHeader=X-Response-Foo, Bar
  - AddResponseHeader=name, beordie

  和上面一样的配置完成之后,每次的请求响应都会携带两个请求头信息,对应的名称和参数和配置的一致,可以在浏览器中对 Response Header 进行查看。

 5.3、自定义局部过滤器

  • 编写过滤器,需要继承 AbstractGatewayFilterFactory 并且需要定义内部类来完成参数的赋值。
  • 过滤器名需要以 GatewayFilterFactory 结尾。
package com.beordie.filters;

import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.http.server.reactive.*;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.List;

@Component
public class MyParamGatewayFilterFactory extends
        AbstractGatewayFilterFactory<MyParamGatewayFilterFactory.Config> {
    static final String PARAM_NAME = "param";
    public MyParamGatewayFilterFactory() {
        super(Config.class);
    }
    public List<String> shortcutFieldOrder() {
        return Arrays.asList(PARAM_NAME);
    }

    @Override
    public GatewayFilter apply(Config config) {
        return (exchange, chain) -> {
            //获取请求参数中param对应的参数名 的参数值
            ServerHttpRequest request = exchange.getRequest();
            if(request.getQueryParams().containsKey(config.param)){
                request.getQueryParams().get(config.param).
                        forEach(value -> System.out.printf("------------局部过滤器--------%s = %s------",
                                config.param, value));
            }
            return chain.filter(exchange);
        };
    }

    public static class Config{
        //对应在配置过滤器的时候指定的参数名
        private String param;
        public String getParam() {
            return param;
        }
        public void setParam(String param) {
            this.param = param;
        }
    }
}

 然后就可以在配置文件对拦截器进行使用。

- MyParam=name

 请求在通过时,过滤去就会试图去查找参数名叫做 name 的携带参数,并且进行控制台的打印操作。

 5.4、 自定义全局过滤器

  • 全局过滤器不需要在配置文件中进行配置,直接定义将会配置在程序中

  • 需要实现 GlobalFilter, Ordered 两个接口。

    package com.beordie.filters;
    
    import org.apache.commons.lang.StringUtils;
    import org.springframework.boot.web.servlet.filter.OrderedFilter;
    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.web.server.ServerWebExchange;
    import reactor.core.publisher.Mono;
    
    /** * @Description * @Date 2021/8/22 17:21 * @Created 30500 */
    public class MyGlobalFilter implements GlobalFilter, Ordered {
        @Override
        public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
            System.out.println("--------------全局过滤器MyGlobalFilter------------------");
            String token = exchange.getRequest().getHeaders().getFirst("token");
            if(StringUtils.isBlank(token)){
                //设置响应状态码为未授权
                exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
                return exchange.getResponse().setComplete();
            }
            return chain.filter(exchange);
        }
    
        @Override
        public int getOrder() {
            // 值越小,全局控制器的执行就越靠前
            return 1;
        }
    }
    

6、扩展知识

 6.1、负载均衡和熔断

 Gateway中默认就已经集成了 Ribbon 负载均衡和 Hystrix 熔断机制。但是所有的超时策略都是走的默认值,比如熔断超时时间只有1S,很容易就触发了。因此建议手动进行配置.

hystrix:
  command:
    default:
      execution:
        isolation:
          thread:
			timeoutInMilliseconds: 6000 #服务降级超时时间,默认1S
ribbon:
  ConnectTimeout: 1000 # 连接超时时长
  ReadTimeout: 2000 # 数据通信超时时长
  MaxAutoRetries: 0 # 当前服务器的重试次数
  MaxAutoRetriesNextServer: 0 # 重试多少次服务

 6.2、Gateway的高可用

  • 启动多个 Gateway 服务,自动注册到Eureka,形成集群。如果是服务内部访问,访问Gateway,自动负载均衡,没问题。

  • 但是,Gateway更多是外部访问,PC端、移动端等。它们无法通过Eureka进行负载均衡,那么该怎么办? 此时, 可以使用其它的服务网关,来对Gateway进行代理。比如:Nginx 。

 6.3、Gateway与Feign的区别

  • Gateway 作为整个应用的流量入口,接收所有的请求,如PC、移动端等,并且将不同的请求转发至不同的处理微服务模块,其作用可视为nginx;大部分情况下用作权限鉴定、服务端流量控制。
  • Feign 则是将当前微服务的部分服务接口暴露出来,并且主要用于各个微服务之间的服务调用 。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
转载请注明出处: https://daima100.com/13800.html

(0)

相关推荐

  • mysql 为什么 SQL 语句不要过多的 join?「建议收藏」

    mysql 为什么 SQL 语句不要过多的 join?「建议收藏」第一部分 Linux上查看内存的使用情况该用什么命令 free -mh 可以看到内存或者缓存情况 total 总内存 used 已用内存 free 空闲内存 buff/cache 已使用的缓存 av…

    2023-03-18
    96
  • 长沙坍塌_最新楼房倒塌事件

    长沙坍塌_最新楼房倒塌事件国务院事故调查报告已公布,干货很多,但最让我震惊的还是报告中提到的那份不合格的“合格房屋安全检测报告”,以及他背后的故事,因为实在是太雷人,也非

    2023-07-05
    86
  • Python中if和elif的区别是什么?

    Python中if和elif的区别是什么?在Python中,if和elif都是条件语句,用于控制程序的执行流程。if语句表示如果条件成立,执行if下面的代码块;而elif则是else if的缩写,表示如果if条件不成立,那么判断elif条件是否成立,如果成立,执行elif下面的代码块。最后,如果所有条件都不成立,可以使用else语句。

    2024-02-09
    42
  • 数据结构第九章查找自测题答案_自考数据结构

    数据结构第九章查找自测题答案_自考数据结构查找的一些基本概念 查找表 是由同一类型的 数据元素 构成的集合,它是一种以查找为“核心”,同时包括其他运算的非常灵活的数据结构。 上面概念中的集合和数学上的定义是一致的,简单地说就是由任意一些可分辨

    2023-01-22
    101
  • python的len函数探究(Python len函数)

    python的len函数探究(Python len函数)python中len()的用法:

    2023-11-22
    79
  • “票房”英语怎么说?「建议收藏」

    “票房”英语怎么说?「建议收藏」2021年春节档以超78亿元的票房成绩收官,创下影史同期最高纪录。贾玲也凭借电影《你好,李焕英》,成为了中国影史上票房最高的女导演。A scen

    2023-07-05
    83
  • 企业数据库选型规则有哪些_企业数据库

    企业数据库选型规则有哪些_企业数据库背景 企业数据库选型规则。 一、数据库部署形式 随着硬件发展,指标上会有变化。 部署形式决定了容量上限,计算能力上限,读写带宽上限,RPO,RTO指标,适应场景。 1、分布式部署(例如pg+citus

    2023-06-11
    77
  • 用Python提高你的编程技能

    用Python提高你的编程技能Python是一种功能强大的高级编程语言,拥有简单易学、开发速度快、代码精简等特点,因此被广泛用于人工智能、科学计算、Web开发等领域。

    2024-04-18
    17

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注