SpringCloud 组件之 Gateway (微服务网关)
概述
不同的微服务会有不同的网络地址,客户端需要调用多个服务的接口才能完成一个业务需求。
网关的作用
1.整合各个微服务功能,形成一套系统 (最主要的作用) 2.在微服务网关中实现日志的统一记录 3.用户的操作跟踪 4.限流 5.用户权限认证
业务场景结构,不使用网关微服务系统
—> | 文件系统:1001
APP -> | 用户系统:1002 -> | 订单系统:1003
缺点
1.页面对接很多个域名(微服务),非常繁琐
2.安全隐患,微服务暴露的接口增加,增加服务器的受攻击面积
3.跨域问题
4.认证复杂,调用每个系统都要认证一次
######加入网关微服务系统
—> | 文件系统:1001
APP -> Gateway -> | 用户系统:1002
-> | 订单系统:1003
优点
1.安全,提供了统一的访问接口,减少了服务器的受攻击面积
2.提供了统一的跨域解决方案
3.提供了统一的认证服务,只需要在网关系统认证一次
4.提供了统一的日志记录操作
5.提供了限流功能,保护微服务防止雪崩效应发生
扩展 - 实现微服务网关的其他技术
nginx:高性能的HTTP和反向代理web服务器 和gateway不在一个比较体系里面,属于最外层流量的拦截,所处的位置不一样。 nginx抵御第一波并发流量,gateway主要是做路由功能 一般最外层的一定是nginx这种抗压能力很强的web服务器 Gateway分布式部署后,就可以加一个nginx服务器,客户端先进入nginx后,再由ng分发到Gateway上面去 zuul:用的很少,被淘汰了
spring-cloud-gateway:spring出品,基于spring的网关项目,集成断路器、路径重写,性能比Zuul好
- 构建Gateway工程
Maven依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring‐cloud‐starter‐gateway</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring‐cloud‐starter‐netflix‐hystrix</artifactId>
</dependency>
GatewayApplication.java
@SpringBootApplication
@EnableEurekaClient
public class GatewayApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayApplication.class, args);
}
}
application.yml
server:
port: 8001
spring:
application:
name: sysgateway
cloud:
gateway:
# 跨域设置
globalcors: # 全局配置
cors‐configurations:
'[/**]': # 匹配所有请求
allowedOrigins: "*" # 跨域处理 允许所有的域
allowedMethods: # 支持的方法
‐ GET
‐ POST
‐ PUT
‐ DELETE
# 路由
routes:
‐ id: goods # 唯一标识
# 直接路由到一个微服务地址,分布式的时候多个地址用lb
#uri: http://192.168.1.16:7001 # 用户请求需要路由到该服务的url
# lb方式,负载均衡,goods表示微服务的名称[集群环境]
uri: lb://goods
predicates: # 路由断言,路由配置规则
# 下面3中配置方式1.Host 2.-Path 3.filters
# 1. Host路由配置方式
#- Host=goods.abc.com** # 用户请求的域名配置规则,所有以goods.abc.com的请求都路由到http://192.168.1.16:7001
# 2. 路径匹配过滤配置方式
#- Path=/goods/** # 所有以/goods/开头的请求都路由到http://192.168.1.16:7001
# 3. filters
#filters:
# 自动去掉一个路径
# 将请求路径中的第一个路径去掉,路径以 / 区分
# 浏览器请求地址:http://goods.abc.com/api/goods/list,会自动去掉第一个路径变成了 http://goods.abc.com/goods/list
#- StripPrefix=1
#- Path=/api/goods/**
# 自动加上一个路径,所有请求
#- StripPrefix=1
#- Path=/**
# 浏览器请求地址:http://goods.abc.com/list,会自动加上/goods路径变成了 http://goods.abc.com/goods/list
#- PrefixPath=/goods
限流
限流位置: 网关 -> 限流操作 -> 微服务系统 限流怎么做? 1.令牌桶算法:Redis客户端有实现(RateLimter);google的Guava包中也有实现。 令牌的数量:最大限额、最小限额。 1)所有的请求在处理之前都需要拿到一个可用的令牌才会被处理; 2)根据限流大小,设置按照一定的速率往桶里添加令牌; 3)桶设置最大的放置令牌限制,当桶满时、新添加的令牌就被丢弃或者拒绝; 4)请求达到后首先要获取令牌桶中的令牌,拿着令牌才可以进行其他的业务逻辑,处理 完业务逻辑之后,将令牌直接删除; 5)令牌桶有最低限额,当桶中的令牌达到最低限额的时候,请求处理完之后将不会删除令牌,以此保证足够的限流 2.漏桶算法 3.计算算法 原理:未达到流量阈值:放行;达到流量阈值:返回249
Redis实现的限流
Maven依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring‐boot‐starter‐data‐redis‐reactive</artifactId>
<version>2.1.3.RELEASE</version>
</dependency>
GatewayApplicatioin.java
@Bean
public KeyResolver ipKeyResolver() {
return new KeyResolver() {
@Override
public Mono<String> resolve(ServerWebExchange exchange) {
String ip = exchange.getRequest().getRemoteAddress().getHostName();
return Mono.just(ip);
}
};
}
application.yml
spring.cloud.gateway.routes.filters:
‐ name: RequestRateLimiter # 局部限流过滤器,固定的不能改
args:
key‐resolver: "#{@ipKeyResolver}" # Bean 对象的名字,SpEL表达式根据#{@beanName}从Spring容器中获取Bean对象
redis‐rate‐limiter.replenishRate: 1 # 每秒钟只允许1个请求
redis‐rate‐limiter.burstCapacity: 10 # 令牌桶总容量,并发请求数
######并发模拟工具:Apache JMeter