六,微服务网关

六,微服务网关

6.1 微服务网关

6.1.1微服务网关介绍

不同的微服务一般会有不同的网络地址,而外部客户端可能需要调用多个服务的接口才能完成一个业务需求,如果让客户端直接与各个微服务通信,会有以下的问题:
   客户端会多次请求不同的微服务,增加了客户端的复杂性
   存在跨域请求,在一定场景下处理相对复杂
   认证复杂,每个服务都需要独立认证
   难以重构,随着项目的迭代,可能需要重新划分微服务。例如,可能将多个服务合并成一个或者将一个服务拆分成多个。如果客户端直接与微服务通信,那么重构将会很难实施
   某些微服务可能使用了防火墙 / 浏览器不友好的协议,直接访问会有一定的困难
以上这些问题可以借助网关解决。
网关是介于客户端和服务器端之间的中间层,所有的外部请求都会先经过 网关这一层。也就是说,API的实现方面更多的考虑业务逻辑,而安全、性能、监控可以交由 网关来做,这样既提高业务灵活性又不缺安全性,典型的架构图如图所示:
六,微服务网关_第1张图片
优点如下:
   安全 ,只有网关系统对外进行暴露,微服务可以隐藏在内网,通过防火墙保护。
   易于监控。可以在网关收集监控数据并将其推送到外部系统进行分析。
   易于认证。可以在网关上进行认证,然后再将请求转发到后端的微服务,而无须在每个微服务中进行认证。
   减少了客户端与各个微服务之间的交互次数
   易于统一授权。
总结:微服务网关就是一个系统,通过暴露该微服务网关系统,方便我们进行相关的鉴权,安全控制,日志统一处理,易于监控的相关功能。
放两视频的图,感觉基本见图知意:
微服务网关的优点
六,微服务网关_第2张图片
微服务网关的作用
六,微服务网关_第3张图片
真实架构
六,微服务网关_第4张图片

6.1.2 微服务网关技术

实现微服务网关的技术有很多:
nginx Nginx (tengine x) 是一个高性能的HTTP和反向代理web服务器,同时也提供了IMAP/POP3/SMTP服务
zuul ,Zuul 是 Netflix 出品的一个基于 JVM 路由和服务端的负载均衡器。
spring-cloud-gateway, 是spring 出品的 基于spring 的网关项目,集成断路器,路径重写,性能比Zuul好。
我们使用gateway这个网关技术,无缝衔接到基于spring cloud的微服务开发中来。gateway官网:https://spring.io/projects/spring-cloud-gateway

6.2网关系统使用

6.2.1 需求分析

由于我们开发的系统 有包括前台系统和后台系统,后台的系统 给管理员使用。那么也需要调用各种微服务,所以我们针对 系统管理搭建一个网关系统。分析如下:
六,微服务网关_第5张图片

6.2.2 搭建后台网关系统

(1)搭建分析

创建网关微服务工程gateway,目录结构如下:
六,微服务网关_第6张图片

(2)工程搭建

(1)引入依赖
pom.xml如下:


<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>legou-parentartifactId>
        <groupId>com.lxsgroupId>
        <version>1.0-SNAPSHOTversion>
    parent>
    <modelVersion>4.0.0modelVersion>
    <artifactId>gatewayartifactId>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-starter-gatewayartifactId>
        dependency>
        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
        dependency>
        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-starter-openfeignartifactId>
        dependency>
        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-starter-netflix-hystrixartifactId>
        dependency>
        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-starter-configartifactId>
        dependency>
        <dependency>
            <groupId>org.springframework.retrygroupId>
            <artifactId>spring-retryartifactId>
        dependency>
    dependencies>
project>

(2)引导类
gateway/src/main/java/com/lxs/clound/GatewayApplication.java

package com.lxs.clound;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;

/**
 * @author
 * @version 1.0
 * @description 网关微服务
 * @createDate 2022/6/13 14:19
 **/
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
@EnableCircuitBreaker
public class GatewayApplication {
    public static void main(String[] args) {
        SpringApplication.run(GatewayApplication.class, args);
    }
}

(3)配置文件
gateway/src/main/resources/bootstrap.yml:

spring:
  application:
    name: gateway

config-repo/gateway.yml

server:
  port: 8062

ribbon:
  ConnectTimeout: 250 # 连接超时时间(ms)
  ReadTimeout: 2000 # 通信超时时间(ms)
  OkToRetryOnAllOperations: true # 是否对所有操作重试
  MaxAutoRetriesNextServer: 2 # 同一服务不同实例的重试次数
  MaxAutoRetries: 1 # 同一实例的重试次数

hystrix:
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutInMillisecond: 60000 # 熔断超时时长:6000ms

6.3 跨域配置

有时候,我们需要对所有微服务跨域请求进行处理,则可以在gateway中进行跨域支持。添加如下代码:

spring:
  cloud:
    gateway:
      globalcors:
        cors-configurations:
          '[/**]':
            allow-credentials: true
            allowed-origins: "*"
            allowed-headers: "*"
            allowed-methods: "*"
            max-age: 3600

6.4 网关过滤配置

六,微服务网关_第7张图片
路由过滤器允许以某种方式修改传入的HTTP请求或传出的HTTP响应。 如上图,根据请求路径路由到不同微服务去,这块可以使用Gateway的路由过滤功能实现。
内置的过滤器工厂有22个实现类,包括 头部过滤器、路径过滤器、Hystrix 过滤器 、请求URL 变更过滤器,还有参数和状态码等其他类型的过滤器。根据过滤器工厂的用途来划分,可以分为以下几种:Header、Parameter、Path、Body、Status、Session、Redirect、Retry、RateLimiter和Hystrix。

6.4.1 路径匹配过滤配置

我们还可以根据请求路径实现对应的路由过滤操作,例如请求中以 /brand/ 路径开始的请求,都直接交给 http://localhost:8062 服务处理,如下配置:
六,微服务网关_第8张图片
上图配置如下:

spring:
	cloud:
		gateway:
			routes:
				- id: item-service
					uri: http://localhost:9005
					predicates:
						- Path=/api/item/**

测试请求 http://localhost:8062/api/item/brand/list ,效果如下:
六,微服务网关_第9张图片

6.4.2 StripPrefix 过滤配置

很多时候也会有这么一种请求,用户请求路径是 /api/item/brand/list ,而真实路径
是 /brand/list ,这时候我们需要去掉 /api/item 才是真实路径,此时可以使用StripPrefix功能来实现路径的过滤操作,如下配置:
六,微服务网关_第10张图片
上图配置如下:

default-filters:
	- StripPrefix=2

测试请求 http://localhost:8001/api/item/brand/list ,效果如下:
六,微服务网关_第11张图片

6.4.3 LoadBalancerClient 路由过滤器(客户端负载均衡)

上面的路由配置每次都会将请求给指定的 URL 处理,但如果在以后生产环境,并发量较大的时候,我们需要根据服务的名称判断来做负载均衡操作,可以使用 LoadBalancerClientFilter 来实现负载均衡调用。 LoadBalancerClientFilter 会作用在url以lb开头的路由,然后利用 loadBalancer 来获取服务实例,构造目标 requestUrl ,设置到 GATEWAY_REQUEST_URL_ATTR 属性中,供NettyRoutingFilter 使用。
修改application.yml配置文件,代码如下:
在这里插入图片描述
上图配置如下:

- id: item-service
	uri: lb://item-service
	predicates:
		- Path=/api/item/**

测试请求路径 http://localhost:8001/api/item/brand/list
六,微服务网关_第12张图片

6.5 网关限流

网关可以做很多的事情,比如,限流,当我们的系统 被频繁的请求的时候,就有可能 将系统压垮,所以 为了解决这个问题,需要在每一个微服务中做限流操作,但是如果有了网关,那么就可以在网关系统做限流,因为所有的请求都需要先通过网关系统才能路由到微服务中。

6.5.1 思路分析

六,微服务网关_第13张图片

6.5.2 令牌桶算法

令牌桶算法是比较常见的限流算法之一,大概描述如下:
(1)所有的请求在处理之前都需要拿到一个可用的令牌才会被处理;
(2)根据限流大小,设置按照一定的速率往桶里添加令牌;
(3)桶设置最大的放置令牌限制,当桶满时、新添加的令牌就被丢弃或者拒绝; (4)请求达到后首先要获取令牌桶中的令牌,拿着令牌才可以进行其他的业务逻辑,处理完业务逻辑之后,将令牌直接删除;
(5)令牌桶有最低限额,当桶中的令牌达到最低限额的时候,请求处理完之后将不会删除令牌,以此保证足够的限流
如下图:
六,微服务网关_第14张图片
这个算法的实现,有很多技术,Guaua是其中之一,redis客户端也有其实现。

6.5.3 漏桶算法

六,微服务网关_第15张图片
算法思想是:
   水(请求)从上方倒入水桶,从水桶下方流出(被处理);
   来不及流出的水存在水桶中(缓冲),以固定速率流出;
   水桶满后水溢出(丢弃)。
   这个算法的核心是:缓存请求、匀速处理、多余的请求直接丢弃。

6.5.4 网关限流

spring cloud gateway 默认使用redis的RateLimter限流算法来实现。所以我们要使用首先需要引入redis的依赖
(1)引入redis依赖
在gateway的pom.xml中引入redis的依赖

<!--redis-->
>
	>org.springframework.boot>
	>spring-boot-starter-data-redis-reactive>
	>2.1.3.RELEASE>
>

(2)定义KeyResolver
在Applicatioin引导类中添加如下代码,KeyResolver用于计算某一个类型的限流的KEY也就是说,可以通过KeyResolver来指定限流的Key。
我们可以根据IP来限流,比如每个IP每秒钟只能请求一次,在GatewayWebApplication定义key的获取,获取客户端IP,将IP作为key,如下代码:

/***
 * IP限流
 * @return
 */
@Bean(name="ipKeyResolver")
public KeyResolver userKeyResolver() {
    return new KeyResolver() {
        @Override
        public Mono<String> resolve(ServerWebExchange exchange) {
            //获取远程客户端IP
            String hostName = exchange.getRequest().getRemoteAddress().getAddress().getHostAddress();
            System.out.println("hostName:"+hostName);
            return Mono.just(hostName);
        }
    };
}

(3)修改application.yml中配置项,指定限制流量的配置以及REDIS的配置,如图
修改如下图:
六,微服务网关_第16张图片
完成配置代码如下:
config-repo/gateway.yml

server:
  port: 8062

spring:
  redis:
    host: 192.168.220.110
    port: 6379
  cloud:
    gateway:
      globalcors:
        cors-configurations:
          '[/**]':
            allow-credentials: true
            allowed-origins: "*"
            allowed-headers: "*"
            allowed-methods: "*"
            max-age: 3600
      routes:
        - id: security-service
          uri: lb://security-service
          predicates:
            - Path=/api/security/**
        - id: admin-service
          uri: lb://admin-service
          predicates:
            - Path=/api/admin/**
        - id: route-service
          uri: lb://route-service
          predicates:
            - Path=/api/route/**
        - id: item-service
          uri: lb://item-service
          predicates:
            - Path=/api/item/**
          filters:
            - name: RequestRateLimiter
              args:
                key-resolver: "#{@ipKeyResolver}"
                redis-rate-limiter.replenishRate: 1
                redis-rate-limiter.burstCapacity: 4
        - id: search-service
          uri: lb://search-service
          predicates:
            - Path=/api/search/**
      default-filters:
        - StripPrefix=2

ribbon:
  ConnectTimeout: 250 # 连接超时时间(ms)
  ReadTimeout: 2000 # 通信超时时间(ms)
  OkToRetryOnAllOperations: true # 是否对所有操作重试
  MaxAutoRetriesNextServer: 2 # 同一服务不同实例的重试次数
  MaxAutoRetries: 1 # 同一实例的重试次数

hystrix:
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutInMillisecond: 60000 # 熔断超时时长:6000ms

解释:
redis-rate-limiter.replenishRate 是您希望允许用户每秒执行多少请求,而不会丢弃任何请求。这是令牌桶填充的速率
redis-rate-limiter.burstCapacity 是指令牌桶的容量,允许在一秒钟内完成的最大请求数,将此值设置为零将阻止所有请求。
key-resolver: “#{@ipKeyResolver}” 用于通过SPEL表达式来指定使用哪一个KeyResolver.
如上配置:
表示 一秒内,允许 一个请求通过,令牌桶的填充速率也是一秒钟添加一个令牌。
最大突发状况 也只允许 一秒内有一次请求,可以根据业务来调整 。
多次请求会发生如下情况:
六,微服务网关_第17张图片

你可能感兴趣的:(java知识体系,微服务,microservices,架构)