完成gateway网关的路由转发学习
This commit is contained in:
47
javamemories-gateway/pom.xml
Normal file
47
javamemories-gateway/pom.xml
Normal 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>
|
||||||
17
javamemories-gateway/src/main/java/cn/mayiming/App.java
Normal file
17
javamemories-gateway/src/main/java/cn/mayiming/App.java
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
60
javamemories-gateway/src/main/resources/application.yml
Normal file
60
javamemories-gateway/src/main/resources/application.yml
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
server:
|
||||||
|
port: 8080
|
||||||
|
|
||||||
|
spring:
|
||||||
|
application:
|
||||||
|
name: gateway-service
|
||||||
|
cloud:
|
||||||
|
gateway:
|
||||||
|
discovery:
|
||||||
|
locator:
|
||||||
|
enabled: true # 自动从 nacos 发现服务
|
||||||
|
routes:
|
||||||
|
# 路由1:user-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}"
|
||||||
|
|
||||||
|
# 路由2:order-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
|
||||||
38
javamemories-gateway/src/test/java/cn/mayiming/AppTest.java
Normal file
38
javamemories-gateway/src/test/java/cn/mayiming/AppTest.java
Normal 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 );
|
||||||
|
}
|
||||||
|
}
|
||||||
2
pom.xml
2
pom.xml
@@ -91,6 +91,8 @@
|
|||||||
<module>javamemories-common</module>
|
<module>javamemories-common</module>
|
||||||
<module>user-service</module>
|
<module>user-service</module>
|
||||||
<module>order-service</module>
|
<module>order-service</module>
|
||||||
|
<module>javamemories-gateway</module>
|
||||||
|
<module>request-test</module>
|
||||||
</modules>
|
</modules>
|
||||||
|
|
||||||
<!-- 编译插件(确保 Java 版本兼容) -->
|
<!-- 编译插件(确保 Java 版本兼容) -->
|
||||||
|
|||||||
28
request-test/pom.xml
Normal file
28
request-test/pom.xml
Normal 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>
|
||||||
13
request-test/src/main/java/cn/mayiming/App.java
Normal file
13
request-test/src/main/java/cn/mayiming/App.java
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
package cn.mayiming;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hello world!
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class App
|
||||||
|
{
|
||||||
|
public static void main( String[] args )
|
||||||
|
{
|
||||||
|
System.out.println( "Hello World!" );
|
||||||
|
}
|
||||||
|
}
|
||||||
38
request-test/src/test/java/cn/mayiming/AppTest.java
Normal file
38
request-test/src/test/java/cn/mayiming/AppTest.java
Normal 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 );
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user