前言:在微服务架构中,API 网关(API Gateway
)是一个重要的组件,负责请求的路由、负载均衡、认证授权、流量控制和监控等功能。它充当客户端和后端服务之间的中介,使得客户端不需要直接调用各个微服务,而是通过网关进行统一访问。下面介绍一下 API Gateway
的主要功能和使用方法。
主要功能
- 请求路由:将客户端请求路由到合适的后端服务,根据路径、方法等进行精确匹配和转发。
- 负载均衡:在多个后端服务实例之间分配请求,保证系统的高可用性和负载均衡。
- 身份认证和授权:在网关层进行身份验证和授权,保护后端服务免受未经授权的访问。
- 流量控制:对流量进行限流、熔断和降级,保护后端服务免受流量突增的影响。
- 日志记录和监控:记录请求和响应的日志,并提供监控和报警功能,帮助开发者及时发现和解决问题。
- 协议转换:支持
HTTP
、WebSocket
、gRPC
等多种协议的转换,提升系统的兼容性。
gateway 网关路由
正常情况,一般是在项目中创建一个子模块,专门用来作为网关,其他子模块的业务,由外界发送的网关,由网关来进行分发
创建网关模块
正常创建模块即可,不进行演示
maven引入
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
| <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 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>mall</artifactId> <groupId>com.listen</groupId> <version>1.0.0</version> </parent> <modelVersion>4.0.0</modelVersion>
<artifactId>gateway</artifactId> <properties> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> </properties> <dependencies> <!-- Spring Cloud Gateway --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency> <!-- Nacos Discovery --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <!-- Load Balancer --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-loadbalancer</artifactId> </dependency> <!--统一配置管理--> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> </dependency> <!--加载bootstrap--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-bootstrap</artifactId> </dependency> </dependencies> <build> <finalName>${project.artifactId}</finalName> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
|
配置路由
id
:路由的唯一标示
predicates
:路由断言,其实就是匹配条件
uri
:路由目标地址,lb://
代表负载均衡,从注册中心获取目标微服务的实例列表,并且负载均衡选择一个访问。
常规配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| spring: application: name: gateway cloud: nacos: server-addr: 192.168.58.101:8848 gateway: routes: - id: item uri: lb://item-service predicates: - Path=/items/**, - id: search uri: lb://search-service predicates: - Path=/search/** - id: cart uri: lb://cart-service predicates: - Path=/carts/** - id: user uri: lb://user-service predicates: - Path=/users/**,/addresses/** - id: trade uri: lb://trade-service predicates: - Path=/orders/** - id: pay uri: lb://pay-service predicates: - Path=/pay-orders/**
|
动态配置
动态路由,就是在nacos
里面声明一个路由,后期可以在nacos
里面动态更新路由规则
1 2 3 4 5 6 7 8 9 10
| spring: application: name: gateway cloud: nacos: server-addr: 192.168.58.101:8848 config: file-extension: yaml shared-configs: - data-id: shared-log.yaml
|
在gateway
模块创建route
文件夹,创建DynamicRouteLoader
,将以下内容导入,效果是动态的更新路由规则,无需在修改规则后,重启服务
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
| import cn.hutool.json.JSONUtil; import com.alibaba.cloud.nacos.NacosConfigManager; import com.alibaba.nacos.api.config.listener.Listener; import com.alibaba.nacos.api.exception.NacosException; import com.hmall.common.utils.CollUtils; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.cloud.gateway.route.RouteDefinition; import org.springframework.cloud.gateway.route.RouteDefinitionWriter; import org.springframework.stereotype.Component; import reactor.core.publisher.Mono;
import javax.annotation.PostConstruct; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.concurrent.Executor;
@Component @Slf4j @RequiredArgsConstructor public class DynamicRouteLoader { private final RouteDefinitionWriter writer; private final NacosConfigManager nacosConfigManager;
private final String dataId = "gateway-routes.json"; private final String group = "DEFAULT_GROUP"; private final Set<String> routeIds = new HashSet<>();
@PostConstruct public void initRouteConfigListener() throws NacosException { String configInfo = nacosConfigManager.getConfigService() .getConfigAndSignListener(dataId, group, 5000, new Listener() { @Override public Executor getExecutor() { return null; }
@Override public void receiveConfigInfo(String configInfo) { updateConfigInfo(configInfo); } }); updateConfigInfo(configInfo); }
private void updateConfigInfo(String configInfo) { log.debug("监听到路由配置变更,{}", configInfo); List<RouteDefinition> routeDefinitions = JSONUtil.toList(configInfo, RouteDefinition.class); for (String routeId : routeIds) { writer.delete(Mono.just(routeId)).subscribe(); } routeIds.clear(); if (CollUtils.isEmpty(routeDefinitions)) { return; } routeDefinitions.forEach(routeDefinition -> { writer.save(Mono.just(routeDefinition)).subscribe(); routeIds.add(routeDefinition.getId()); }); } }
|
在nacos中配置管理,新建配置
Data ID:gateway-routes.json
配置格式:json
配置内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
| [ { "id": "item", "predicates": [{ "name": "Path", "args": {"_genkey_0":"/items/**"} }], "filters": [], "uri": "lb://item-service" }, { "id": "search", "predicates": [{ "name": "Path", "args": {"_genkey_1":"/search/**"} }], "filters": [], "uri": "lb://search-service" }, { "id": "cart", "predicates": [{ "name": "Path", "args": {"_genkey_0":"/carts/**"} }], "filters": [], "uri": "lb://cart-service" }, { "id": "user", "predicates": [{ "name": "Path", "args": {"_genkey_0":"/users/**", "_genkey_1":"/addresses/**"} }], "filters": [], "uri": "lb://user-service" }, { "id": "trade", "predicates": [{ "name": "Path", "args": {"_genkey_0":"/orders/**"} }], "filters": [], "uri": "lb://trade-service" }, { "id": "pay", "predicates": [{ "name": "Path", "args": {"_genkey_0":"/pay-orders/**"} }], "filters": [], "uri": "lb://pay-service" } ]
|