前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >SpringCloud Alibaba学习笔记 ——(五、新一代服务网关 Gateway)

SpringCloud Alibaba学习笔记 ——(五、新一代服务网关 Gateway)

作者头像
Gorit
发布2021-12-30 17:30:45
6330
发布2021-12-30 17:30:45
举报
文章被收录于专栏:Gorit 带你学全栈系列

SpringCloudAlibaba —— 新一代服务网关 Gateway

Author: Gorit

Date:2021年1月

Refer:阿里云大学

2021年发表博文: 10/30

五、新一代服务网关 Gateway

SpringCloud Gateway 2.2.6 版本 doc

5.1 SpringCloud Gateway

5.1.1 什么是微服务网关?

微服务网关是整个微服务 api 接口的入口,可以实现很多功能。 作用:可以实现用户的验证登录、解决跨域,日志拦截,权限控制,限流、熔断、负载均衡、黑名单和白名单机制

5.1.2 微服务的架构模式?

前后端分离,前端调用地址都能够被抓包分析到

传统方式我们可以使用 过滤器拦截用户会话信息,这个过程所有的服务都必须写入该验证会话登录的代码。

5.1.3 过滤器与网关的区别

过滤器:适合单个服务实现过滤请求

网关拦截:整个微服务实现过滤请求 能够解决整个微服务中冗余代码。

5.2 Zuul 与 Gateway 有哪些区别

  1. Zuul 网关属于 NetFix 公司开源框架,属于第一代微服务网关
  2. Gateway 属于 SpringCloud 自己研发的网关框架,属于第二代微服务网关
  3. 相比来说,Gateway 比 Zuul 网关性能要好很多

主要:

  • Zuul 网关底层基于 Servlet 实现,阻塞式 api
  • SpringCloud Gateway 基于 Spring5 构建,能够实现响应式非阻塞 api,支持长连接,能够更好的支持 Spring 体系产品,依赖 SpringBoot-WebFlux

5.3 Gateway 整合 Nacos 实现服务转发

网关的服务端口号一般为:80 或者 443

开启 nacos,开启 8080 的 memeber 服务进行测试

  1. 创建一个 Maven 项目,并命名为 Gateway
  2. 导入 Maven 依赖
代码语言:javascript
复制
<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.0modelVersion>

    <groupId>cn.goritgroupId>
    <artifactId>GatewayartifactId>
    <version>1.0-SNAPSHOTversion>

    <parent>
        <artifactId>spring-boot-starter-parentartifactId>
        <groupId>org.springframework.bootgroupId>
        <version>2.3.4.RELEASEversion>
    parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-starter-gatewayartifactId>
            <version>2.2.4.RELEASEversion>
        dependency>
        
        
        <dependency>
            <groupId>com.alibaba.cloudgroupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
            <version>2.2.4.RELEASEversion>
        dependency>
    dependencies>
project>

编写 application.yml

这里是作为测试用,后期会编写配置类,来实现路由的跳转

代码语言:javascript
复制
server:
  port: 80

# 服务网关名称
spring:
  application:
    name: gorit-gateway
  cloud:
    gateway:
      discovery:
        locator:
          # 开启服务 id 去注册中心上获取转发地址
          enabled: true
      routes:
        # 路由 id,就是前面的服务 name
        - id: gorit-member
          ## 基于 lb 负载均衡形式转发
          uri: lb://gorit-member/
          filters:
            - StripPrefix=1
          # 匹配规则  127.0.0.1/memeber/xxxx
          predicates:
            - Path=/member/**
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848

编写 app 运行

PS:确保 nacos 和 8080 端口的 member 启动了

然后我们访问 127.0.0.1/member/user 就能访问到 127.0.0.1:8080/user 的服务

5.3.1 网关与 Nginx 的区别

微服务网关能做的事情,Nginx 也可以实现

相同点:

  • 都可以实现 API 的拦截、反向代理、请求过滤、复杂均衡、可以完全和网关实现一样的效果

不同点

  • Nginx 采用 C 语言编写的
  • 在微服务领域中,都是自己语言去编写
  • 在微服务领域中每个编程语言都有,比如我们使用 Java 构建微服务项目,Gateway 也是 java 语言编写的。能够更好的对我们的微服务实现扩展功能
  • 相比 Nginx 扩展功能的化,我们必须要学习 lua 或者 c 语言。那么学习成本就会非常高

5.4 基于 Gateway拦截请求参数

官方文档:链接

实现案例:

没有传递 token 参数的话,就不会转发

  1. 在 Gateway 项目中创建一个包 filter,创建一个类 GlobalTokenFilter
代码语言:javascript
复制
package cn.gorit.filter;

import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
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;

/**
 * @Classname GlobalTokenFilter
 * @Description 全局过滤使用
 * @Date 2021/1/20 20:14
 * @Created by CodingGorit
 * @Version 1.0
 */
@Component
public class GlobalTokenFilter implements GlobalFilter {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 获取参数
        String token = exchange.getRequest().getQueryParams().getFirst("token");
        if (StringUtils.isEmpty(token)) {
            ServerHttpResponse response = exchange.getResponse();
            response.setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR);
            String msg = "token null is not allowed";
            DataBuffer buffer = response.bufferFactory().wrap(msg.getBytes());
            return response.writeWith(Mono.just(buffer));
        }
        return chain.filter(exchange);
    }

}
  1. 再次请求http://127.0.0.1/member/user 接口,我们发现,如果没有 token 就会返回错误i信息

token null is not allowed

  1. 携带 token,请求 http://127.0.0.1/member/user?token=xasdawdwa 接口(token 可以为任意值)。可以看到正常返回

user+ 8080

5.5 Gateway 集群原理分析

5.5.1 网关集群部署原理

网关一旦宕机,整个微服务无法通信

如何解决? 网关实现集群 基于 Nginx 实现即可

网关实现了集群如何访问?

  1. 使用 nginx
  2. lvs 虚拟 vip

环境配置

  1. 网关1 127.0.0.1:81
  2. 网关2 127.0.0.1:82

Nginx 服务器 127.0.0.1:80, 使用 Nginx 对 网关进行负载均衡的配置

5.5.2 动态网关配置

动态网关:任何配置都实现不用重启网关服务器都可以及时刷新网关配置

实现思路:

  1. 分布式配置中心 不建议使用 阅读性差 需要定义 json 格式的配置
代码语言:javascript
复制
{
	"路由的id": '',
	"路由的名称": '',
	"路由的规则": ''
}
  1. 基于数据表结构设计 特别建议
代码语言:javascript
复制
id	route_id	route_name		route_pattern	route_type	route_url
1	member		gorit-member	/member/**		0		   gorit-member

网关已经提供了 api 接口

  1. 直接新增
  2. 直接修改

思路:

默认加载的时候

  1. 当我们的网关你服务启动的时候,从数据库查询网关配置
  2. 将数据库的内容读取到网关内存

5.6 Gateway 源码

SpringBoot 项目源码入口

  1. GatewayClassPathWarningAutoConfiguration作用检查是否配置我们webfux依赖。
  2. GatewayAutoConfiguration加载了我们Gateway需要的注入的类。
  3. GatewayLoadBa|ancerClientAutoConfiguration网关需要使用的负载均衡。 Lb//mayikt-member//根据服务名称查找真实地址.
  4. GatewayRedisAutoConfiguration网关 整合Redis整合Lua实现限流。
  5. GatewayDiscoveryClientAutoConfiguration服务注册与发现功能。

5.7 Gateway 如何解决网关跨域问题

微服务跨域问题解决,在后端解决

使用 jsonp 只能用 GET 请求

解决:

  1. 使用 SpringBoot 注解 @CrossOrigin
  2. HttpClient 转发
  3. Jsonp 不支持 post,属于前端解决
  4. Nginx 解决跨域问题保证我们的域名和端口的一致性
  5. Nginx 也可以通过配置文件解决跨域问题
  6. 使用过滤器允许接口可以跨域,响应头设置
  7. 使用网关能带吗允许你所有服务可以跨域问题

跨域解决方案 1,配置文件方式

代码语言:javascript
复制
server:
  port: 80

# 服务网关名称
spring:
  application:
    name: gorit-gateway
  cloud:
    gateway:
      discovery:
        locator:
          # 开启服务 id 去注册中心上获取转发地址
          enabled: true
      # 跨域配置
      globalcors:
        corsConfigurations:
          '[/**]':
            allowCredentials: true
            allowedOrigins: "*"
            allowedHeaders: "*"
            allowedMethods: "*"
            maxAge: 3628800
      routes:
        # 路由 id
        - id: member
          ## 基于 lb 负载均衡形式转发
          uri: lb://gorit-member/
          filters:
            - StripPrefix=1
          # 匹配规则
          predicates:
            - Path=/member/**
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848

跨域解决方案2:Java 配置类

代码语言:javascript
复制
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.reactive.CorsWebFilter;
import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;
import org.springframework.web.util.pattern.PathPatternParser;

/**
 * @Classname CrossConfig
 * @Description 配置类解决跨域
 * @Date 2021/1/22 18:14
 * @Created by CodingGorit
 * @Version 1.0
 */
@Configuration
public class CrossConfig {

    @Bean
    public CorsWebFilter corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(new PathPatternParser());
        source.registerCorsConfiguration("/**", buildConfig());
        return new CorsWebFilter(source);
    }

    private CorsConfiguration buildConfig() {
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.addAllowedOrigin("*");
        corsConfiguration.addAllowedHeader("*"); // 请求头
        corsConfiguration.addAllowedMethod("*"); // 所有方法
        corsConfiguration.setMaxAge(3628800L);
        return corsConfiguration;
    }
}

下一节

Sentinel 服务保护框架

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021/02/04 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • SpringCloudAlibaba —— 新一代服务网关 Gateway
  • 五、新一代服务网关 Gateway
    • 5.1 SpringCloud Gateway
      • 5.1.1 什么是微服务网关?
      • 5.1.2 微服务的架构模式?
      • 5.1.3 过滤器与网关的区别
    • 5.2 Zuul 与 Gateway 有哪些区别
      • 5.3 Gateway 整合 Nacos 实现服务转发
        • 5.3.1 网关与 Nginx 的区别
      • 5.4 基于 Gateway拦截请求参数
        • 5.5 Gateway 集群原理分析
          • 5.5.1 网关集群部署原理
          • 5.5.2 动态网关配置
        • 5.6 Gateway 源码
          • 5.7 Gateway 如何解决网关跨域问题
            • 下一节
        相关产品与服务
        负载均衡
        负载均衡(Cloud Load Balancer,CLB)提供安全快捷的四七层流量分发服务,访问流量经由 CLB 可以自动分配到多台后端服务器上,扩展系统的服务能力并消除单点故障。轻松应对大流量访问场景。 网关负载均衡(Gateway Load Balancer,GWLB)是运行在网络层的负载均衡。通过 GWLB 可以帮助客户部署、扩展和管理第三方虚拟设备,操作简单,安全性强。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档