Gateway网关
1.Spring Cloud Gateway
Spring Cloud Gateway作为Spring Cloud生态系统中的网关,目标是替代Netflix Zuul
其不仅提供统一的路由方式,并且还基于Filter链的方式提供了网关基本的功能。
目前最新版Spring Cloud中引用的还是Zuul 1.x版本,而这个版本是基于过滤器的,是阻塞IO,不支持长连接。
Zuul2.x版本一直跳票,2019年5月,Netflix 终于开源了支持异步调用模式的Zuul2.0版本。
但是Spring Cloud已经不再集成Zuul2.x了,那么是时候了解一下 Spring Cloud Gateway了。
Spring Cloud Gateway是基于Spring生态系统之上构建的API网关,包括: Spring5, Spring Boot 2和Project Reactor.
SpringCloud Gateway旨在提供一种简单而有效的方法来路由到API,并为它们提供跨领域的关注点,例如:安全性,监视/指标,限流等。
由于Spring 5.0支持Netty, Http2, 而Spring Boot 2.0支持Spring 5.0,因此Spring Cloud Gateway支持Netty和Http2顺理成章.
2.服务网关
API Gateway (APIGW/API网关) ,顾名思义,是出现在系统边界上的一个面向API的、串行集中式的强管控服务
这里的边界是企业IT系统的边界,可以理解为企业级应用防火墙,主要起到隔离外部访问与内部系统的作用。
在微服务概念的流行:之前,API网关就已经诞生了,例如银行、证券等领域常见的前置机系统,它也是解决访问认证、报文转换、访问统计等问题的。
API网关的流行,源于近几年来移动应用与企业间互联需求的兴起。
移动应用、企业互联,使得后台服务支持的对象,从以前单一的Web应用,扩展到多种使用场景,且每种使用场景对后台服务的要求都不尽相同。
这不仅增加了后台服务的响应量,还增加了后台服务的复杂性。随着微服务架构概念的提出,API网关成为了微服务架构的一个标配组件
API网关是一个服务器,是系统对外的唯一入口。 API 网关封装了系统内部架构,为每个客户端提供定制的API。
所有的客户端和消费端都通过统一的网关接入微服务,在网关层处理所有非业务功能。
API网关并不是微服务场景中必须的组件,不管有没有API网关,后端微服务都可以通过API很好地支持客户端的访问。
但对于服务数量众多、复杂度比较高、规模比较大的业务来说,引入API网关也有一系列的好处:
- 聚合接口使得服务对调用者透明,客户端与后端的耦合度降低
- 聚合后台服务,节省流量,提高性能,提升用户体验
- 提供安全、流控、过滤、缓存、计费、监控等API管理功能
3.为什么要使用网关
- 单体应用:浏览器发起请求到单体应用所在的机器,应用从数据库查询数据原路返回给浏览器,对于单体应用来说是不需要网关的。
- 微服务的应用可能部署在不同机房,不同地区,不同域名下。此时客户端(浏览器/手机/软件工具)想要请求对应的服务,都需要知道机器的具体IP或者域名URL,当微服务实例众多时,这是非常难以记忆的,对于客户端来说也太复杂难以维护。此时就有了网关,客户端相关的请求直接发送到网关,由网关根据请求标识解析判断出具体的微服务地址,再把请求转发到微服务实例。这其中的记忆功能就全部交由网关来操作了。
因此,我们需要网关介于客户端与服务器之间的中间层,所有外部请求率先经过微服务网关,客户端只需要与网关交互,只需要知道网关地址即可。这样便简化了开发且有以下优点: - 易于监控,可在微服务网关收集监控数据并将其推送到外部系统进行分析
- 易于认证,可在微服务网关上进行认证,然后再将请求转发到后端的微服务,从而无需在每个微服务中进行认证
- 减少了客户端与各个微服务之间的交互次数
4.解决问题
网关具有身份认证与安全、审查与监控、动态路由、负载均衡、缓存、请求分片与管理、静态响应处理等功能。当然最主要的职责还是与“外界联系”。
总结一下,网关应当具备以下功能:
- 性能: API高可用,负载均衡,容错机制。
- 安全:权限身份认证、脱敏,流量清洗,后端签名(保证全链路可信调用),黑名单(非法调用的限制)。
- 日志:日志记录,一旦涉及分布式,全链路跟踪必不可少。
- 缓存:数据缓存。
- 监控:记录请求响应数据,API耗时分析,性能监控。
- 限流:流量控制,错峰流控,可以定义多种限流规则。
- 灰度:线上灰度部署,可以减小风险。
- 路由:动态路由规则。
5.常用网关解决万案
5.1 Nginx + Lua
Nginx是一个高性能的HTTP和反向代理服务器。Ngnix一方面可以做反向代理,另外一方面做可以做静态资源服务器。
Nginx适合做门户网关,是作为整个全局的网关,对外的处于最外层的那种;
而Gateway属于业务网关,主要用来对应不同的客户端提供服务,用于聚合业务。各个微服务独立部署,职责单一, 对外提供服务的时候需要有一个东西把业务聚合起来。
Gateway可以实现熔断、重试等功能,这是Nginx不具备的。
5.2 Kong
Kong是Mashape提供的一款API管理软件,它本身是基于Ngnix+ Lua的,但比Nginx提供了更简单的配置方式,数据采用了
ApacheCassandra/PostgreSQL存储,并且提供了一些优秀的插件,比如验证,日志,调用频次限制等。Kong 非常诱人的地方就是
提供了大量的插件来扩展应用,通过设置不同的插件可以为服务提供各种增强的功能。
优点:基于Nginx所以在性能和稳定性上都没有问题。Kong 作为一款商业软件,在Nginx上做了很扩展工作,而且还有很多付费的商业插件
Kong 本身也有付费的企业版,其中包括技术支持、使用培训服务以及API分析插件。
缺点:如果你使用Spring Cloud, Kong 如何结合目前已有的服务治理体系?
5.3 Traefik
Traefik是一个开源的 GO语言开发的为了让部署微服务更加便捷而诞生的现代HTTP反向代理、负载均衡工具。
它支持多种后台(Docker, Swarm, Kubernetes, Marathon, Mesos, Consul, Etcd, Zookeeper, BoltDB, Rest API)来自动化、动态的应用它的配置文件设置。
Traefik 拥有一个基于 AngularJS编写的简单网站界面,支持RestAPI,配置文件热更新,无需重启进程。可用集群模式等。
相对Spring Cloud和Kubernetes而言,目前比较适合Kubernetes。
5.4 Spring Cloud Netflix Zuul
Zuul是Netlix公司开源的一个APL网关组件,Spring Cloud对其进行次基于Spring Boot的注解式封装做到开箱即用。
目前来说,结合Sring Cloud提供的服务治理体系,可以做到请求转发,根据配置或者默认的路由规则进行路由和Load Balance,无缝集成Hystrix.
虽然可以通过自定义Filter 实现我们想要的功能,但是由于Zuul本身的设计是基于单线程的接收请求和转发处理,是阻塞IO,不支持长连接。
目前来看Zuul就显得很鸡肋,随着Zuul2.x一直跳票(2019年5月发布了Zuul2.0 版本),Spring Cloud推出自己的Spring Cloud Gateway.
6.nginx实现
# 路由到商品服务
location /api-product {
proxy_pass http://localhost:7070/;
}
# 路由到订单服务
location /api-order {
proxy_pass http://localhost:9090/;
}
7.Gateway实现API网关
7.1 核心概念
- 路由(Route) :路由是网关最基础的部分,路由信息由ID、目标URI、一组断言和一组过滤器组成。如果断言路由为真,则说明请求的URI和配置匹配。
- 断言(Predicate) : Java8 中的断言函数。Spring Cloud Gateway中的断言函数输入类型是Spring 5.0框架中的ServerWebExchange
Spring Cloud Gateway中的断言函数允许开发者去定义匹配来自于Http Request中的任何信息,比如请求头和参数等。 - 过滤器(Filter) : 一个标准的Spring Web Filter. Spring Cloud Gateway中的Filter 分为两种类型,分别是Gateway Filter和Global Filter.过滤器将会对请求和响应进行处理。
7.2 原理
客户端向Spring Cloud Gateway 发出请求。再由网关处理程序Gateway Handler Mapping 映射确定与请求相匹配的路由,将其发送到网关Web处理程序Gateway Web Handler 。
该处理程序通过指定的过滤器链将请求发送到我们实际的服务执行业务逻辑,然后返回。过滤器由虚线分隔的原因是,过滤器可以在发送代理请求之前和之后运行逻辑。
所有pre过滤器逻辑均被执行。然后发出代理请求。发出代理请求后,将运行post过滤器逻辑。
7.3 实现
- pom.xml
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
- 配置文件
server:
port: 9000
spring:
application:
name: gatewayServer
#路由规则
cloud:
gateway:
routes:
- id: product-server #唯一id
uri: http://localhost:7070/ #目标URI
predicates: #断言(判断条件)
- Path=/product/**
7.4 根据服务名称从注册中心获取服务请求地址
uri: lb://provider #将uri改为这个
# 注册中心
eureka:
instance:
prefer-ip-address: true
instance-id: ${spring.cloud.client.ip-address}:${server.port}
client:
service-url:
defaultZone: http://localhost:8761/eureka/, http://localhost:8792/eureka/
7.5 服务发现
gateway:
discovery:
# 是否与服务发现组件进行结合,通过serviceId转发到具体服务
locator:
enabled: true
lower-case-service-id: true #是否将服务名称转小写
8.路由规则
Spring Cloud Gateway创建Route对象时,使用RoutePredicateFactory 创建Predicate对象,Predicate 对象可以赋值给Route.
- Spring Cloud Gateway包含许多内置的Route Predicate Factories.
- 所有这些断言都匹配HTTP请求的不同属性。
- 多个Route Predicate Factories可以通过逻辑与(and) 结合起来一起使用。
路由断言厂RoutePredicateFactory 包含的主要实现类如图所示,包括Datetime、请求的远端地址、 路由权重、 请求头
Host地址、请求方法、 请求路径和请求参数等类型的路由断言。
predicates: #断言(判断条件)
- Path=/product/**
- Query=token, abc. # 匹配请求参数中包含token并且其参数满足正则表达式abc的请求 如product/1?token=abc1
- Method=GET #只匹配Get方法
- After=2023-02-02T20:20:20.000+08:00[Asia/Shanghai] #匹配上海2023年2月2日 20点20分20秒之后的请求
- RemoteAddr=192.168.1.2/0 # 匹配地址为这个的请求 子网掩码为0
- Header=X-Request-Id, \d+ # 匹配请求头包含这个且其值为正则\d+的请求
9.网关过滤器 GatewayFilter
网关过滤器用于拦截并链式处理Web请求,可以实现横切与应用无关的需求,比如:安全、访问超时的设置等。
修改传入的HTTP请求或传出HTTP响应。Spring Cloud Gateway包含许多内置的网关过滤器工厂一共有22个,包括头部过滤器、路径类过滤器、Hystrix 过滤器和重写请求URL的过滤器,还有参数和状态码等其他类型的过滤器。根据过滤器工厂的用途来划分,可以分为以下几种: Header、 Parameter、 Path、 Body、 Status、 Session、 Redirect、 Retry、 RateLimiter 和Hystrix.
predicates:
# - Path=/product/**, /api-gateway/** 1
# - Path=/** 2 3
# - Path=/api/product/{segment} 4
# - Path=/api-gateway/** 56
filters:
# /api-gateway/product/1 重写为/product/1
- RewritePath=/api-gateway(?<segment>/?.*), $\{segment}
- PrefixPath=/product # 将/1重写为/product
- StripPrefix=2 #分割前俩个路径 将/api/123/product/1 重写为/product/1
- SetPath=/product/{segment} #/api/product/1 重写为 /product/1
- AddRequestParameter=flag, 1 #参数中添加flag=1
- SetStatus=404 #任何情况下响应状态为404
9.1 自定义网关过滤器
//自定义网关过滤器
public class MyGatewayFilter implements GatewayFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
return chain.filter(exchange); //继续向下执行
}
//过滤器执行顺序 数字越小 优先级越高
@Override
public int getOrder() {
return 0;
}
}
@Configuration
public class GatewayRoutersConfiguration {
@Bean
public RouteLocator routeLocator(RouteLocatorBuilder builder){
return builder.routes().route(r -> r
//断言
.path("/product/**")
.uri("lb://provider")
.filters(new MyGatewayFilter())
.id("gatewayServer"))
.build();
}
}
10.全局过滤器
全局过滤器不需要在配置文件中配置,作用在所有的路由上,最终通过GatewayFilterAdapter包装成GatewayFilterChain可识
别的过滤器,它是请求业务以及路由的URI转换为真实业务服务请求地址的核心过滤器,不需要配置系统初始化时加载,并作用在
每个路由上。
10.1 自定义全局过滤器
//自定义全局过滤器
@Component
public class MyGlobalFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
return chain.filter(exchange);
}
@Override
public int getOrder() {
return 0;
}
}
11.统一鉴权
@Component
public class AccessFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
//获取请求参数
String token = exchange.getRequest().getQueryParams().getFirst("token");
if(token == null){
ServerHttpResponse response = exchange.getResponse();
//响应类型
response.getHeaders().add("Content-Type", "application/json; charset=utf-8");
//响应状态码
response.setStatusCode(HttpStatus.UNAUTHORIZED);
//响应内容
String message = "{\"message\":\"" + HttpStatus.UNAUTHORIZED.getReasonPhrase() + "\"}";
DataBuffer buffer = response.bufferFactory().wrap(message.getBytes());
//请求结束
return response.writeWith(Mono.just(buffer));
}
return chain.filter(exchange);
}
@Override
public int getOrder() {
return 1;
}
}
12.网关限流
顾名思义,限流就是限制流量,就像你宽带包有1个G的流量,用完了就没了。通过限流,我们可以很好地控制系统的QPS,从而达到保护系统的目的。
12.1 为什么需要限流
比如Web服务、对外API,这种类型的服务有以下几种可能导致机器被拖垮:
- 用户增长过快(好事)
- 因为某个热点事件(微博热搜)
- 竞争对象爬虫
- 恶意的请求
这些情况都是无法预知的,不知道什么时候会有10倍甚至20倍的流量打进来,如果真碰上这种情况,扩容是根本来不及的。
12.2 限流算法
常见的限流算法有:
-
计数器算法
计数器算法是限流算法里最简单也是最容易实现的一种算法。比如我们规定,对于A接口来说,我们1分钟的访问次数不能超过100个。
那么我们可以这么做:在一开始的时候, 我们可以设置一个计数器 counter,每当一个请求过来的时候, counter 就加1,如果counter的值大于100并且该请求与第一个请求的间隔时间还在1分钟之内,触发限流;如果该请求与第一个请求的间隔时间大于1分钟,重置counter重新计数,具体算法的示意图如下:
这个算法虽然简单,但是有一个十分致命的问题, 那就是临界问题,我们看下图:
从上图中我们可以看到,假设有一个恶意用户, 他在0:59时,瞬间发送了100个请求,并且1:00又瞬间发送了100个请求,
那么其实这个用户在1秒里面,瞬间发送了200个请求。我们刚才规定的是1分钟最多100个请求,也就是每秒钟最多1.7 个请
求,用户通过在时间窗口的重置节点处突发请求,可以瞬间超过我们的速率限制。用户有可能通过算法的这个漏洞,瞬间压垮我
们的应用。 -
漏桶(Leaky Bucket)算法
漏桶算法其实也很简单,可以粗略的认为就是注水漏水的过程,往桶中以任意速率流入水,以一定速率流出水,当水超过桶流量则丢弃,因为桶容量是不变的,保证了整体的速率。
基于队列实现
-
令牌桶(Token Bucket) 算法
令牌桶算法是对漏桶算法的一种改进,漏桶算法能够限制请求调用的速率,而令牌桶算法能够在限制调用的平均速率的同时还允许一定程度的突发调用。在令牌桶算法中,存在一个桶,用来存放固定数量的令牌。算法中存在一种机制,以一定的速率往桶中放令牌。每次请求调用需要先获取令牌,只有拿到令牌,才有机会继续执行,否则选择选择等待可用的令牌、或者直接拒绝。放令牌这个动作是持续不断的进行,如果桶中令牌数达到上限,就丢弃令牌。
场景大概是这样的:桶中一直有大量的可用令牌,这时进来的请求可以直接拿到令牌执行,比如设置QPS为100/s,那么限流器初始化完成一秒后,桶中就已经有100个令牌了,等服务启动完成对外提供服务时,该限流器可以抵挡瞬时的100个请求。当桶中没有令牌时,请求会进行等待,最后相当于以一定的速率执行。
Spring Cloud Gateway内部使用的就是该算法,大概描述如下: -
所有的请求在处理之前都需要拿到一个可用的令牌才会被处理;
-
根据限流大小,设置按照一定的速率往桶里添加令牌;
-
桶设置最大的放置令牌限制,当桶满时、新添加的令牌就被丢弃或者拒绝;
-
请求到达后首先要获取令牌桶中的令牌,拿着令牌才可以进行其他的业务逻辑,处理完业务逻辑之后,将令牌直接删除;
-
令牌桶有最低限额,当桶中的令牌达到最低限额的时候,请求处理完之后将不会删除令牌,以此保证足够的限流。
漏桶算法主要用途在于保护它人,而令牌桶算法主要目的在于保护自己,将请求压力交由目标服务处理。假设突然进来很多请求,只要拿到令牌这些请求会瞬时被处理调用目标服务.
12.3 Gateway限流实现
- pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
- 配置文件
spring:
redis:
timeout: 10000
host: 127.0.0.1
port: 6379
password:
database: 0
lettuce:
pool:
max-active: 1024
max-wait: 10000
max-idle: 200
min-idle: 5
- 配置类
@Configuration
public class KeyResolverConfiguration {
//URI限流规则 该方法只能一个
// @Bean
public KeyResolver pathKeyResolver(){
return exchange -> Mono.just(exchange.getRequest().getURI().getPath());
}
//参数限流 url带userId=1
@Bean
public KeyResolver parameterKeyResolver(){
return exchange -> Mono.just(exchange.getRequest().getQueryParams().getFirst("userId"));
}
//IP限流
@Bean
public KeyResolver ipKeyResolver(){
return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getHostName());
}
}
- 配置文件
filters:
#限流过滤器
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 1 #令牌桶每秒填充速率
redis-rate-limiter.burstCapacity: 2 # 令牌桶总容量
# key-resolver: "#{@pathKeyResolver}"
key-resolver: "#{@parameterKeyResolver}"#使用SpEl表达式按名称引用bean
12.4 Sentinel过滤器
- pom.xml
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!-- 单独使用-->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-spring-cloud-gateway-adapter</artifactId>
</dependency>
- 配置文件
server:
port: 9001
spring:
application:
name: gatewaySentinel
cloud:
sentinel:
filter:
enabled: false
gateway:
discovery:
locator:
lower-case-service-id: true
enabled: true
routes:
- id: gatewaySentinel
uri: lb://consumer-feign
predicates:
- Path=/order/**
eureka:
instance:
prefer-ip-address: true
instance-id: ${spring.cloud.client.ip-address}:${server.port}
client:
service-url:
defaultZone: http://localhost:8761/eureka/, http://localhost:8792/eureka/
- 配置类
@Configuration
public class GatewayConfiguration {
private final List<ViewResolver> viewResolvers;
private final ServerCodecConfigurer serverCodecConfigurer;
public GatewayConfiguration(ObjectProvider<List<ViewResolver>> viewResolverProvider,
ServerCodecConfigurer serverCodecConfigurer){
this.serverCodecConfigurer = serverCodecConfigurer;
this.viewResolvers = viewResolverProvider.getIfAvailable(Collections::emptyList);
}
// 限流异常处理类
@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler(){
return new SentinelGatewayBlockExceptionHandler(viewResolvers,serverCodecConfigurer);
}
//限流过滤器
@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
public GatewayFilter sentinelGatewayFilter(){
return new SentinelGatewayFilter();
}
// Spring 容器初始化时候执行该方法 不加也可以初始化
@PostConstruct
public void doInit(){
// 加载网关限流
initGatewayRules();
}
// 网关限流规则
private void initGatewayRules(){
Set<GatewayFlowRule> rules = new HashSet<>();
/**
* resource: 资源名称 网关中的route名称或者用户自定义的API 分组名称
* count: 限流阈值
* intervalSec: 统计时间窗口 默认1s
*/
rules.add(new GatewayFlowRule("gatewaySentinel")
.setCount(3)
.setIntervalSec(60));
//加载网关限流限制
GatewayRuleManager.loadRules(rules);
}
}
12.4.1 自定义异常处理
- 配置类
// Spring 容器初始化时候执行该方法 不加也可以初始化
@PostConstruct
public void doInit(){
// 加载网关限流
initGatewayRules();
initBlockHandler();
}
//自定义限流异常处理器
private void initBlockHandler(){
BlockRequestHandler blockRequestHandler = new BlockRequestHandler() {
@Override
public Mono<ServerResponse> handleRequest(ServerWebExchange serverWebExchange, Throwable throwable) {
Map<String, String> res = new HashMap<>();
res.put("code", String.valueOf(HttpStatus.TOO_MANY_REQUESTS.value()));
res.put("message", HttpStatus.TOO_MANY_REQUESTS.getReasonPhrase());
res.put("route", "gatewaySentinel");
return ServerResponse.status(HttpStatus.TOO_MANY_REQUESTS)
.contentType(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromValue(res));
}
};
//加载自定义限流异常处理器
GatewayCallbackManager.setBlockHandler(blockRequestHandler);
}
12.4.2 分组限流
//分组限流
private void initCustomizedApis(){
Set<ApiDefinition> definitions = new HashSet<>();
ApiDefinition apiDefinition = new ApiDefinition("product")
.setPredicateItems(new HashSet<ApiPredicateItem>() {{
//匹配/product所有请求
add(new ApiPathPredicateItem().setPattern("/product/**")
.setMatchStrategy(SentinelGatewayConstants.URL_MATCH_STRATEGY_PREFIX));
}});
ApiDefinition apiDefinition1 = new ApiDefinition("order")
.setPredicateItems(new HashSet<ApiPredicateItem>() {{
//匹配/product所有请求
add(new ApiPathPredicateItem().setPattern("/order/**")
.setMatchStrategy(SentinelGatewayConstants.URL_MATCH_STRATEGY_PREFIX));
}});
definitions.add(apiDefinition);
definitions.add(apiDefinition1);
//加载限流分组
GatewayApiDefinitionManager.loadApiDefinitions(definitions);
}
// 网关限流规则
private void initGatewayRules(){
Set<GatewayFlowRule> rules = new HashSet<>();
rules.add(new GatewayFlowRule("product")
.setCount(3)
.setIntervalSec(60));
rules.add(new GatewayFlowRule("order")
.setCount(3)
.setIntervalSec(60));
GatewayRuleManager.loadRules(rules);
initCustomizedApis();
}
13. 高可用网关
业内通常用多少9来衡量网站的可用性,例如QQ的可用性是4个9,就是说QQ能够保证在一年里, 服务在99%的时间是
可用的,只有0.01%的时间不可用,大约最多53分钟。
对于大多数网站,2个9是基本可用; 3个9是叫高可用; 4个9是拥有自动恢复能力的高可用。
实现高可用的主要手段是数据的冗余备份和服务的失效转移,这两种手段具体可以怎么做呢,在网关里如何体现?主要有以
下几个方向:
- 集群部署
- 负载均衡
- 健康检查
- 节点自动重启
- 熔断
- 服务降级
- 接口重试
13.1 nginx实现
- http中加入
#网关集群
upstream gateway{
server 127.0.0.1:9000;
server 127.0.0.1:9001;
}
- server中
location / {
# root html;
# index index.html index.htm;
proxy_pass http://gateway;
}
一个请求过来,首先经过Nginx的一层负载,到达网关,然后由网关负载到真实后端,若后端有问题,网关会进行重试访问,
多次访问后仍返回失败,可以通过熔断或服务降级立即返回结果。而且,由于是负载均衡,网关重试时不一定会访问到出错的后端。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
2022-07-04 SpringIOC注入
2022-07-04 MVC分层思想