微服务网关-Spring Cloud Gateway(上)

本文涉及的产品
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
注册配置 MSE Nacos/ZooKeeper,182元/月
MSE Nacos/ZooKeeper 企业版试用,1600元额度,限量50份
简介: 微服务网关-Spring Cloud Gateway(上)

正文


一、什么是网关?


       网关(Gateway)又称网间连接器、协议转换器。网关在网络层以上实现网络互连,是复杂的网络互连设备,仅用于两个高层协议不同的网络互连。网关既可以用于广域网互连,也可以用于局域网互连。 网关是一种充当转换重任的计算机系统或设备。使用在不同的通信协议、数据格式或语言,甚至体系结构完全不同的两种系统之间,网关是一个翻译器。与网桥只是简单地传达信息不同,网关对收到的信息要重新打包,以适应目的系统的需求。同层--应用层。-----摘自《百度百科》


二、Spring Cloud Gateway 原理


参考官网spring-cloud-gateway


三、构建简单的网关项目


pom文件如下


<?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">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.xiaojie</groupId>
    <artifactId>xiaojie-gateway</artifactId>
    <version>1.0-SNAPSHOT</version>
    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.4.2</version>
    </parent>
    <dependencies>
        <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-gateway -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
            <version>3.0.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
            <version>2021.1</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.alibaba.cloud/spring-cloud-starter-alibaba-nacos-discovery -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
            <version>2021.1</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-openfeign -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
            <version>3.0.2</version>
        </dependency>
        <!-- Feign Client for loadBalancing -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-loadbalancer</artifactId>
            <version>3.0.2</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-openfeign -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
            <version>3.0.2</version>
        </dependency>
        <!-- Feign Client for loadBalancing -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-loadbalancer</artifactId>
            <version>3.0.2</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.4</version>
        </dependency>
        <!-- mysql 依赖 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <!-- 阿里巴巴数据源 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.2.4</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis-reactive</artifactId>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.github.vladimir-bukhtoyarov/bucket4j-core -->
        <dependency>
            <groupId>com.github.vladimir-bukhtoyarov</groupId>
            <artifactId>bucket4j-core</artifactId>
            <version>6.0.1</version>
        </dependency>
    </dependencies>
</project>


启动类和简单api省略


四、路由谓词工厂


server:
  port: 80
spring:
  application:
    name: xiaojie-gateway
  cloud:
    gateway:
      routes:
#        - id: test_route
#          uri: https://www.baidu.com/
#          filters:
#            #这个意思是截取第一个前缀后访问 比如,请求/name/bar/foo,去除掉前面一个前缀之后,最后转发到目标服务的路径为/bar/foo
#            - StripPrefix=1
#          predicates:
#            - Path=/test #路径拦截
#             #ZonedDateTime dateTime = ZonedDateTime.now(); java8之后ZonedDateTime时间
#            - After=2021-07-14T09:51:55.052+08:00[Asia/Shanghai]
            #- Before=2021-07-15T09:51:55.052+08:00[Asia/Shanghai]
            #- Between=2021-07-14T09:51:55.052+08:00[Asia/Shanghai],2021-07-15T09:51:55.052+08:00[Asia/Shanghai]
            #- Cookie=xiaojie, [a-z]   #匹配cookie名字满足后面表达式的时候
            #- Header=X-Request-Id, \d+ # 匹配请求头中X-Request-Id 为数字的
            #- Host=**.xiaojie.com #匹配域名路由
            #- Method=GET,POST #拦截方法是get post 的请求
            #- Query=red, gree. #如果请求包含red其值与正则gree.表达式匹配的查询参数,则前面的路由匹配,因此green和greet将匹配
            #- RemoteAddr=192.168.1.1/24 #匹配ip
        #一下是权重路由匹配
        - id: weight_high
          uri: https://www.baidu.com
          predicates:
            - Weight=group1, 8
        - id: weight_low
          uri: https://www.sina.com
          predicates:
            - Weight=group1, 2


五、网关集群


555.jpg


通过Nginx转发到网关服务,网关经过轮训算法,或者其他的算法,转发到真实的服务器,进行服务的访问,下面开始配置。


网关端的配置文件


server:
  port: 82
####服务网关名称
spring:
  application:
    name: xiaojie-gateway
  cloud:
    gateway:
          ###路由策略
          routes:
            ###根据我们的服务名称查找地址实现调用
            - id: member
              #uri: http://127.0.0.1:8090
              uri: lb://xiaojie-member/ #服务的名称
              filters:
                - StripPrefix=1
              ###匹配规则
              predicates:
                - Path=/member/**
            #开启服务注册中心获取服务
          discovery:
            locator:
              enabled: true
    nacos:
      discovery:
        #注册地址
        server-addr: 127.0.0.1:8848,127.0.0.1:8849,127.0.0.1:8850
        #是否开启nacos注册
        enabled: true
        #账号
        username: xiaojie
        #密码
        password: nacos
        #命名空间 ,一定要对应上自己注册的服务的命名空间
        namespace: 28eb29ea-5a04-4714-8ae8-77d37c01166a
        #分组
        group: DEV_GROUP


会员服务端的配置文件


spring:
  application:
     name: xiaojie-member
  cloud:
    nacos:
      config:
        #前缀
        prefix: xiaojie-member
        #地址
        server-addr: 127.0.0.1:8848,127.0.0.1:8849,127.0.0.1:8850
        #扩展名
        file-extension: yaml
        #命名空间
        namespace: 28eb29ea-5a04-4714-8ae8-77d37c01166a
        #分组
        group: DEV_GROUP
        #开关
        enabled: true
        #动态刷新配置
        refresh-enabled: true
      discovery:
        #注册地址
        server-addr: 127.0.0.1:8848,127.0.0.1:8849,127.0.0.1:8850
        #是否开启nacos注册
        enabled: true
        #账号
        username: xiaojie
        #密码
        password: nacos
        #命名空间
        namespace: 28eb29ea-5a04-4714-8ae8-77d37c01166a
        #分组
        group: DEV_GROUP


Nginx添加如下配置


upstream xiaojie_gateway{
    server 127.0.0.1:81;
    server 127.0.0.1:82;
  }
  server {
        listen       80;
        server_name  gateway.xiaojie.com;
        #charset koi8-r;
        #access_log  logs/host.access.log  main;
        location / {
            proxy_pass http://xiaojie_gateway;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }       
    }


在网关中添加以下filter


package com.xiaojie.filter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
/**
 * @Description: 配置token过滤器
 * @author: xiaojie
 * @date: 2021.07.14
 */
@Component
@Slf4j
public class TokenFilter implements GlobalFilter {
    @Value("${server.port}")
    private String serverPort;
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        //获取参数
        String token = exchange.getRequest().getQueryParams().getFirst("token");
        if(!StringUtils.hasText(token)){
            //token为空转发到其他的地址
            ServerHttpResponse response = exchange.getResponse();
            //
            response.setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR);
            String msg = "token not is null ";
            DataBuffer buffer = response.bufferFactory().wrap(msg.getBytes());
            return response.writeWith(Mono.just(buffer));
        }
        // 在请求头中存放serverPort serverPort
        ServerHttpRequest request = exchange.getRequest().mutate().header("serverPort", serverPort)
                .build();
        log.info("端口号是...............{}"+serverPort);
        return chain.filter(exchange.mutate().request(request).build());
    }
}


访问http://gateway.xiaojie.com/member/getMember?token=456 可以看到实现了集群效果。

相关文章
|
16天前
|
存储 缓存 负载均衡
Gateway 网关坑我! 被这个404 问题折腾了一年?
小富分享了一个困扰团队一年多的 SpringCloud Gateway 路由 404 问题。通过日志追踪和源码分析,发现是网关在 Nacos 配置更新后未能正确清理旧的路由权重缓存,导致负载均衡时仍使用已删除的路由数据。最终通过监听路由刷新事件并手动更新缓存,成功解决了问题。
363 125
Gateway 网关坑我! 被这个404 问题折腾了一年?
|
17天前
|
数据可视化 Java BI
将 Spring 微服务与 BI 工具集成:最佳实践
本文探讨了 Spring 微服务与商业智能(BI)工具集成的潜力与实践。随着微服务架构和数据分析需求的增长,Spring Boot 和 Spring Cloud 提供了构建可扩展、弹性服务的框架,而 BI 工具则增强了数据可视化与实时分析能力。文章介绍了 Spring 微服务的核心概念、BI 工具在企业中的作用,并深入分析了两者集成带来的优势,如实时数据处理、个性化报告、数据聚合与安全保障。同时,文中还总结了集成过程中的最佳实践,包括事件驱动架构、集中配置管理、数据安全控制、模块化设计与持续优化策略,旨在帮助企业构建高效、智能的数据驱动系统。
将 Spring 微服务与 BI 工具集成:最佳实践
|
17天前
|
存储 安全 Java
管理 Spring 微服务中的分布式会话
在微服务架构中,管理分布式会话是确保用户体验一致性和系统可扩展性的关键挑战。本文探讨了在 Spring 框架下实现分布式会话管理的多种方法,包括集中式会话存储和客户端会话存储(如 Cookie),并分析了它们的优缺点。同时,文章还涵盖了与分布式会话相关的安全考虑,如数据加密、令牌验证、安全 Cookie 政策以及服务间身份验证。此外,文中强调了分布式会话在提升系统可扩展性、增强可用性、实现数据一致性及优化资源利用方面的显著优势。通过合理选择会话管理策略,结合 Spring 提供的强大工具,开发人员可以在保证系统鲁棒性的同时,提供无缝的用户体验。
|
17天前
|
消息中间件 Java 数据库
Spring 微服务中的数据一致性:最终一致性与强一致性
本文探讨了在Spring微服务中实现数据一致性的策略,重点分析了最终一致性和强一致性的定义、优缺点及适用场景。结合Spring Boot与Spring Cloud框架,介绍了如何根据业务需求选择合适的一致性模型,并提供了实现建议,帮助开发者在分布式系统中确保数据的可靠性与同步性。
|
18天前
|
消息中间件 Java Kafka
消息队列比较:Spring 微服务中的 Kafka 与 RabbitMQ
本文深入解析了 Kafka 和 RabbitMQ 两大主流消息队列在 Spring 微服务中的应用与对比。内容涵盖消息队列的基本原理、Kafka 与 RabbitMQ 的核心概念、各自优势及典型用例,并结合 Spring 生态的集成方式,帮助开发者根据实际需求选择合适的消息中间件,提升系统解耦、可扩展性与可靠性。
消息队列比较:Spring 微服务中的 Kafka 与 RabbitMQ
|
11天前
|
监控 安全 Java
Spring Cloud 微服务治理技术详解与实践指南
本文档全面介绍 Spring Cloud 微服务治理框架的核心组件、架构设计和实践应用。作为 Spring 生态系统中构建分布式系统的标准工具箱,Spring Cloud 提供了一套完整的微服务解决方案,涵盖服务发现、配置管理、负载均衡、熔断器等关键功能。本文将深入探讨其核心组件的工作原理、集成方式以及在实际项目中的最佳实践,帮助开发者构建高可用、可扩展的分布式系统。
48 1
|
18天前
|
jenkins Java 持续交付
使用 Jenkins 和 Spring Cloud 自动化微服务部署
随着单体应用逐渐被微服务架构取代,企业对快速发布、可扩展性和高可用性的需求日益增长。Jenkins 作为领先的持续集成与部署工具,结合 Spring Cloud 提供的云原生解决方案,能够有效简化微服务的开发、测试与部署流程。本文介绍了如何通过 Jenkins 实现微服务的自动化构建与部署,并结合 Spring Cloud 的配置管理、服务发现等功能,打造高效、稳定的微服务交付流程。
使用 Jenkins 和 Spring Cloud 自动化微服务部署
|
2月前
|
前端开发 Java API
Spring Cloud Gateway Server Web MVC报错“Unsupported transfer encoding: chunked”解决
本文解析了Spring Cloud Gateway中出现“Unsupported transfer encoding: chunked”错误的原因,指出该问题源于Feign依赖的HTTP客户端与服务端的`chunked`传输编码不兼容,并提供了具体的解决方案。通过规范Feign客户端接口的返回类型,可有效避免该异常,提升系统兼容性与稳定性。
189 0
|
3月前
|
缓存 监控 Java
说一说 SpringCloud Gateway 堆外内存溢出排查
我是小假 期待与你的下一次相遇 ~
515 5
|
3月前
|
Java API Nacos