完成gateway网关的路由转发学习

This commit is contained in:
2026-03-02 19:14:58 +08:00
parent e09987fbbb
commit a2a8547bca
9 changed files with 292 additions and 0 deletions

View File

@@ -0,0 +1,47 @@
<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">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>cn.mayiming</groupId>
<artifactId>javamemories-parent</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>javamemories-gateway</artifactId>
<packaging>jar</packaging>
<name>javamemories-gateway</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- 网关 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!-- 注册到 Nacos -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>
<!-- Redis 客户端(可选,增强兼容性) -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,17 @@
package cn.mayiming;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* Hello world!
*
*/
@SpringBootApplication
public class App
{
public static void main( String[] args )
{
SpringApplication.run(App.class, args);
}
}

View File

@@ -0,0 +1,49 @@
package cn.mayiming.Config;
import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
/**
* 网关限流配置类
* 定义基于IP的限流解析器
*/
@Configuration
public class GatewayRateLimitConfig {
/**
* IP限流解析器
* 作用从请求中提取客户端IP作为限流的key
*/
@Bean
public KeyResolver ipKeyResolver() {
return exchange -> {
// 获取客户端IP地址
String ip = getClientIp(exchange);
return Mono.just(ip);
};
}
/**
* 处理X-Forwarded-For头获取真实客户端IP适配反向代理场景
*/
private String getClientIp(ServerWebExchange exchange) {
String ip = exchange.getRequest().getHeaders().getFirst("X-Forwarded-For");
if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
ip = exchange.getRequest().getHeaders().getFirst("Proxy-Client-IP");
}
if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
ip = exchange.getRequest().getHeaders().getFirst("WL-Proxy-Client-IP");
}
if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
ip = exchange.getRequest().getRemoteAddress().getAddress().getHostAddress();
}
// 处理多个IP的情况X-Forwarded-For可能包含多个IP取第一个
if (ip != null && ip.contains(",")) {
ip = ip.split(",")[0].trim();
}
return ip;
}
}

View File

@@ -0,0 +1,60 @@
server:
port: 8080
spring:
application:
name: gateway-service
cloud:
gateway:
discovery:
locator:
enabled: true # 自动从 nacos 发现服务
routes:
# 路由1user-service
- id: user-service
uri: lb://user-service # lb = 负载均衡
predicates:
- Path=/user/**
filters:
- RewritePath=/user/(?<segment>.*), /${segment}
# 全局限流配置
- name: RequestRateLimiter
args:
# 令牌桶填充速率:每秒生成 1 个令牌(即 10 秒 10 个)
redis-rate-limiter.replenishRate: 1
# 令牌桶最大容量:最多存 10 个令牌(允许突发 10 次请求)
redis-rate-limiter.burstCapacity: 10
# 按 IP 限流(默认)
key-resolver: "#{@ipKeyResolver}"
# 路由2order-service
- id: order-service
uri: lb://order-service
predicates:
- Path=/order/**
filters:
- RewritePath=/user/(?<segment>.*), /${segment}
# 全局限流配置
- name: RequestRateLimiter
args:
# 令牌桶填充速率:每秒生成 1 个令牌(即 10 秒 10 个)
redis-rate-limiter.replenishRate: 1
# 令牌桶最大容量:最多存 10 个令牌(允许突发 10 次请求)
redis-rate-limiter.burstCapacity: 10
# 按 IP 限流(默认)
key-resolver: "#{@ipKeyResolver}"
# Nacos 注册
nacos:
discovery:
server-addr: localhost:8848 # Nacos 服务地址(默认端口 8848
namespace: public # 命名空间(默认 public自定义需先在 Nacos 控制台创建)
group: DEFAULT_GROUP # 分组(默认 DEFAULT_GROUP
service: gateway-service
data:
redis:
host: localhost
port: 6379
password: ''
database: 0
timeout: 2000ms

View File

@@ -0,0 +1,38 @@
package cn.mayiming;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
/**
* Unit test for simple App.
*/
public class AppTest
extends TestCase
{
/**
* Create the test case
*
* @param testName name of the test case
*/
public AppTest( String testName )
{
super( testName );
}
/**
* @return the suite of tests being tested
*/
public static Test suite()
{
return new TestSuite( AppTest.class );
}
/**
* Rigourous Test :-)
*/
public void testApp()
{
assertTrue( true );
}
}

View File

@@ -91,6 +91,8 @@
<module>javamemories-common</module>
<module>user-service</module>
<module>order-service</module>
<module>javamemories-gateway</module>
<module>request-test</module>
</modules>
<!-- 编译插件(确保 Java 版本兼容) -->

28
request-test/pom.xml Normal file
View File

@@ -0,0 +1,28 @@
<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">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>cn.mayiming</groupId>
<artifactId>javamemories-parent</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>request-test</artifactId>
<packaging>jar</packaging>
<name>request-test</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,13 @@
package cn.mayiming;
/**
* Hello world!
*
*/
public class App
{
public static void main( String[] args )
{
System.out.println( "Hello World!" );
}
}

View File

@@ -0,0 +1,38 @@
package cn.mayiming;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
/**
* Unit test for simple App.
*/
public class AppTest
extends TestCase
{
/**
* Create the test case
*
* @param testName name of the test case
*/
public AppTest( String testName )
{
super( testName );
}
/**
* @return the suite of tests being tested
*/
public static Test suite()
{
return new TestSuite( AppTest.class );
}
/**
* Rigourous Test :-)
*/
public void testApp()
{
assertTrue( true );
}
}