ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

SpringCloudGateway网关 学习记录

2022-04-20 10:01:44  阅读:185  来源: 互联网

标签:网关 服务 service 记录 SpringCloudGateway product Gateway 路由


 

微服务网关的概念:

  什么是微服务网关:        现在流行的微服务架构中,对大多数的服务进行指量上的拓展增多以应对服务的工作量需求。对此每个微服务都会有对应的ip端口。 在大型的项目中可能这种对外的访问ip端口是成百上千的。对访问与管理是很不方便的。对这种情况应对的方案就是配置一个微服务 网关。让所有的请求访问到微服务网关中再由网关进行同一的管理(权监、负载均衡、日志等等..)。这样对我们的维护与使用也是 极大的遍历。   作用和应用场景:        网关的作业:负载均衡、监控、用户权限鉴定、缓存等等...   其中最主要的就是与外界取得联系对服务暴露进行统一管理   常见的API网关实现方式:        SpringCloudGateway: SpringCloud提供的网关服务        Nginx:使用Nginx的反向代理和负载均衡可实现对api服务器的负载均衡及高可用                     问题:自注册的问题和网关本身的扩展性        Zuul:Netflflix开源,功能丰富,使用JAVA开发,易于二次开发;需要运行在web容器中,如Tomcat。                     问题:缺乏管控,无法动态配置;依赖组件较多;处理Http请求依赖的是Web容器,性能不如Nginx;

 

 

 

微服务网关GateWay

ZUUL是一个基于阻塞IO的微服务网关。其内在原理也依赖Servlet。所以其整体的性能并不是很良好。

对于JAVA项目来说SpringCloudGateWay是主场作战。在Spring大家庭中融入的比较好。所以使用起来相对方便。

 

在SpringCloudGateWay中有三个比较核心的概念:

 

 

 

 

1. 路由(route) 路由是网关最基础的部分,路由信息由一个ID、一个目的URL、一组断言工厂和一 组Filter组成。如果断言为真,则说明请求URL和配置的路由匹配。 2. 断言(predicates) Java8中的断言函数,Spring Cloud Gateway中的断言函数输入类型是 Spring5.0框架中的ServerWebExchange。Spring Cloud Gateway中的断言函数允许开发者去定 义匹配来自Http Request中的任何信息,比如请求头和参数等。 3. 过滤器(fifilter) 一个标准的Spring webFilter,Spring Cloud Gateway中的Filter分为两种类型, 分别是Gateway Filter和Global Filter。过滤器Filter可以对请求和响应进行处理

 


 

SpringCloud Gateway的使用:

(1)导入依赖

  <!-- 网关依赖 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>

(2)配置启动类

package com.kerry.gateway;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

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

(3)编写application.yml配置文件

server:
  port: 8001

spring:
  application:
    name: server-gateway #服务名称
  cloud:
    gateway:
      routes:
      - id: category-service   #自定义的路由id,保持唯一
        uri: http://127.0.0.1:9001  #目标服务地址
        predicates:  #路由条件 可于网上搜索更多
        - Path=/category/**,/admin/category/**
      - id: headline-service
        uri: http://127.0.0.1:9002
        predicates:
        - Path=/headline/**,/admin/headline/**

到此简简单单的路由功能已经实现了,但是我们可以注意到在目标服务地址上我们填写的对应的ip端口,这样写死的话

明显是不够完善的。对此我们可以引入动态路由

 

动态路由

(1)添加注册中心依赖
        <!-- eureka网关-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

(2)修改application.yml配置文件

server:
  port: 8001

spring:
  application:
    name: server-gateway #服务名称
  cloud:
    gateway:
      routes:
      - id: category-service
        uri: lb://service-category
        predicates:
        - Path=/category/**,/admin/category/**
      - id: headline-service
        uri:  lb://service-headline
        predicates:
        - Path=/headline/**,/admin/headline/**

eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:8000/eureka #,http://127.0.0.1:8999/eureka/
      registry-fetch-interval-seconds: 5 # 获取服务列表的周期:5s
  instance:
    prefer-ip-address: true #使用ip注册
    ip-address: 127.0.0.1
uri : uri以 lb: //开头(lb代表从注册中心获取服务),后面接的就是你需要转发到的服务名称 

 

 

重写转发路径

在SpringCloud Gateway中,路由转发是直接将匹配的路由path直接拼接到映射路径(URI)之后,那么在微服务开发中往往没有那么便利。 这里就可以通过RewritePath机制来进行路径重写。    (1)案例改造  修改 application.yml ,将匹配路径改为 /product-service/**  重新启动网关,我们在浏览器访问http://127.0.0.1:8080/product-service/product/1,会抛出404。这是由于路由转发规则默认转发到商品微服务 ( http://127.0.0.1:9002/product-service/product/1 )路径上,而商品微服务又没有 product-service 对应的映射配置。  (2)添加RewritePath重写转发路径 
spring:
  application:
    name: api-gateway #指定服务名
  cloud:
    gateway:
      routes:
      - id: product-service
        uri: lb://shop-service-product
        predicates:
        - Path=/product-service/**
        filters:
        - RewritePath=/product-service/(?<segment>.*), /$\{segment}
通过RewritePath配置重写转发的url,将/product-service/(?.*),重写为{segment},然后转发到订单 微服务。比如在网页上请求http://localhost:8080/product-service/product,此时会将请求转发到 http://127.0.0.1:9002/product/1( 值得注意的是在yml文档中 $ 要写成 $\ )      

过滤器

SpringCloudGateway中不仅有路由功能还支持对请求的过滤。相比Zuul网关,SpringCloudGateway的过滤器功能就相对较少 只有:"pre"和"post"两个。     pre:这种过滤器在请求被路由之前调用。我们可利用这种过滤器实现身份验证、在集群中选择请求的微服务、记录调试信息等。   post:这种过滤器在路由到微服务以后执行。这种过滤器可用来为响应添加标准的 HTTPHeader、收集统计信息和指标、将响应从微服务发送给客户端等。   SpringCloudGateway的过滤器类型有两种:
  GatewayFilter:应用到单个路由或者一个分组的路由上   GlobalFilter:应用到所有的路由上。

 

我们可以通过GlobalFilter类来实现统一鉴权:

开发中的鉴权逻辑:     1.当客户端第一次请求服务时,服务端对用户进行信息认证(登录)     2.认证通过,将用户信息进行加密形成token,返回给客户端,作为登录凭证     3.以后每次请求,客户端都携带认证的token     4.服务端对token进行解密,判断是否有效。

 

 

 

代码实现:

package com.kerry.gateway.filter;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.cloud.gateway.filter.GatewayFilter;
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;


/*
* 该类为用户登录权监过滤器  todo:后期将token参数改到session或者是redis中。
* 目前的代码效果为:当请求链接来到网关的时候会判断请求参数中是否有token参数,如果无的话则视为没有权限,如果有则视为有权限
* 例子:
*    http://localhost:8001/admin/category/demo.do/1            效果:访问失败
*    http://localhost:8001/admin/category/demo.do/1?token=1    效果:访问成功
* */
@Slf4j
@Component
public class LoginFilter implements GlobalFilter, Ordered {



    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        log.info("执行了自定义的登录权监全局过滤器");
        //String url = exchange.getRequest().getURI().getPath();
        // 忽略以下url请求
        // if(url.indexOf("/login") >= 0){
          // return chain.filter(exchange);
        // }
        String token = exchange.getRequest().getQueryParams().getFirst("token");
        if (StringUtils.isBlank(token)) {
            log.info( "token is empty ..." );
            exchange.getResponse().setStatusCode( HttpStatus.UNAUTHORIZED );
            return exchange.getResponse().setComplete();
        }
        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        return 0;
    }
}

 


学习小记:

 
SpringCloud Gateway底层使用的web框架是webflux和SpringMVC不兼容引入的限流组件是hystrix。redis底层不再使用jedis,而是lettuce。

由于SpringCloud Gateway在SpringCloud上是主场作战,所以在进行网关上的使用上相对于ZUUL等其他技术上更为简单有效。它是基于Nttey的响应式开发模式

 

SpringCloud Gateway的核心概念有路由(route)断言(predicates)过滤器(filter)

 

Gateway的路由功能上很强大,支持各种各样的条件匹配同时也支持动态路由【动态路由需引入Eureka服务】。

 

Gateway在过滤器的功能上比不上ZUUL那么丰富,只要'pre'和'post'。一个是请求被路由之前调用,一个是路由到微服务之后调用。

过滤器的类型有GatewayFilter(局部)和 GlobalFilter(全局)。全局过滤器较为常用,可作用于用户信息认证校验token。

 

SpringCloud Gateway过滤器不止可以用作用户信息校验,还可以作为网关限流

限流算法:计数器、漏桶算法、令牌桶算法
      计算器算法:规定时间内只能访问到最大阈值,到时间会重置累计数重新增加
      漏桶算法:这个算法跟线程池隔离类似,规定一个容量池的大小,限制住访问量
      令牌桶算法:是漏桶算法的一种改进更好的控制访问量的灵活度。

网关限流中
   1.基于Filter的限流,是Gateway官方提供的基于令牌桶的限流法,需要引入
      redis依赖,在配置中可以调整令牌桶的容量与数度还有对象来源
   2.基于Sentinel的限流,也是需要引入依赖,编写配置类,网关配置。基于Sentinel
      的Gateway限流底层也是依靠Filter功能,只需要在配置类中注入实例定义好限流方法
      即可实习限流功能。

在分布式架构体系中,高可用是非常关键的存在。网关统一了服务的对外访问。那如
果说是单一的网关服务万一宕机,那对整个项目的影响是巨大的。所以我们应该
对网关也进行高可用的部署。然后将网关交给nginx进行统一管理,还能进行负载均衡
这样就可以大大的降低网关服务层的错误率。

 

 

标签:网关,服务,service,记录,SpringCloudGateway,product,Gateway,路由
来源: https://www.cnblogs.com/zcl1116/p/16168594.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有