SpringCloud2.x Greenwich版本搭建:(七) Gateway網關
標簽: springboot 微服務 springcloud java
1.Gateway是什么?
Spring Cloud Gateway 是 Spring Cloud 的一個全新項目,該項目是基于 Spring 5.0,Spring Boot 2.0 和 Project Reactor 等技術開發的網關,它旨在為微服務架構提供一種簡單有效的統一的 API 路由管理方式。
SpringCloud Gateway是基于WebFlux框架實現的,而WebFlux框架底層則使用了高性能的Reactor模式通信框架Netty。
Spring Cloud Gateway 作為 Spring Cloud 生態系統中的網關,目標是替代 Netflix Zuul,其不僅提供統一的路由方式,并且基于 Filter 鏈的方式提供了網關基本的功能,例如:安全,監控/指標,和限流。
Zuul是阻塞的,Gateway是非阻塞的,這么說是不嚴謹的,準確的講Zuul1.x是阻塞的,而在2.x的版本中,Zuul也是基于Netty,也是非阻塞的,如果一定要說性能,其實這個真沒多大差距。
2.創建springcloud-getway子項目
<?xml version="1.0" encoding="UTF-8"?>
<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">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.5.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.itlinli</groupId>
<artifactId>springcloud-geteway</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springcloud-geteway</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Greenwich.SR1</spring-cloud.version>
</properties>
<dependencies>
<!--這里不添加父依賴了,因為spring cloud gateway是基于webflux的,不要導入spring-boot-start-web-->
<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>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Spring Cloud Gateway 網關路由有兩種配置方式:
-
在配置文件 yml 中配置
-
通過@Bean自定義 RouteLocator,在啟動主類 Application 中配置
3.使用配置文件配置
server:
port: 8250
spring:
application:
name: geteway
cloud:
gateway:
discovery:
locator:
#開啟路由轉發
enabled: false #為true是時候http://localhost:8250/consumer-hystrix/hello/lisi 也可以訪問,開啟了2個路由。
# 服務名小寫開啟
lowerCaseServiceId: true
routes:
# 路由ID(一個路由配置一個ID)
- id : consumer-hystrix
# 通過注冊中心來查找服務名稱(lb代表從注冊中心獲取服務,并且負載均衡)
uri: lb://consumer-hystrix
predicates:
- Path=/gateway/** # 匹配到的以/gateway開頭的路徑都轉發到gateway的服務,相當于訪問 lb://consumer-hystrix/**
filters:
- StripPrefix=1 # 去掉匹配到的路徑的第一段
eureka:
client:
service-url:
defaultZone: http://localhost:8800/eureka/
我這里采用之前項目中的消費者進行調用測試。
4.啟動類
@SpringBootApplication
@EnableEurekaClient
public class SpringcloudGetewayApplication {
public static void main(String[] args) {
SpringApplication.run(SpringcloudGetewayApplication.class, args);
}
}
5.啟動測試
6.配置限流
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>
7.修改配置文件
server:
port: 8250
spring:
redis:
host: 192.168.221.150
port: 6379
application:
name: geteway
cloud:
gateway:
discovery:
locator:
#開啟路由轉發
enabled: false #為true是時候http://localhost:8250/consumer-hystrix/hello/lisi 也可以訪問,開啟了2個路由。
# 服務名小寫開啟
lowerCaseServiceId: true
routes:
# 路由ID(一個路由配置一個ID)
- id : consumer-hystrix
# 通過注冊中心來查找服務名稱(lb代表從注冊中心獲取服務,并且負載均衡)
uri: lb://consumer-hystrix
predicates:
- Path=/gateway/** # 匹配到的以/gateway開頭的路徑都轉發到gateway的服務,相當于訪問 lb://consumer-hystrix/**
filters:
- StripPrefix=1 # 去掉匹配到的路徑的第一段
- name: RequestRateLimiter #必須為filters名稱
args:
redis-rate-limiter.replenishRate: 1 #允許用戶每多少秒處理多少個請求
redis-rate-limiter.burstCapacity: 3 #令牌桶的容量,允許在一秒鐘內完成的最大請求數
key-resolver: "#{@ipKeyResolver}" #使用ip限流,可以使用其他的接口限流等
eureka:
client:
service-url:
defaultZone: http://localhost:8800/eureka/
8.添加限流配置類
package com.itlinli.config;
import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import reactor.core.publisher.Mono;
@Configuration
public class RateLimitConfig {
@Bean
KeyResolver userKeyResolver() {
return exchange -> Mono.just(exchange.getRequest().getQueryParams().getFirst("user"));
}
@Primary
@Bean
KeyResolver ipKeyResolver() {
return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getHostName());
}
@Bean
KeyResolver apiKeyResolver() {
return exchange -> Mono.just(exchange.getRequest().getPath().value());
}
}
9.啟動服務測試1秒內請求超過3次
10.getway整合sentinel實現限流
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-spring-cloud-gateway-adapter</artifactId>
<version>1.7.1</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
<version>2.1.2.RELEASE</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
<version>2.1.2.RELEASE</version>
</dependency>
11.配置文件
server:
port: 8250
spring:
main:
allow-bean-definition-overriding: true
redis:
host: 192.168.221.150
port: 6379
application:
name: geteway
cloud:
sentinel:
filter:
enabled: false
gateway:
discovery:
locator:
#開啟路由轉發
enabled: false #為true是時候http://localhost:8250/consumer-hystrix/hello/lisi 也可以訪問,開啟了2個路由。
# 服務名小寫開啟
lowerCaseServiceId: true
routes:
# 路由ID(一個路由配置一個ID)
- id : consumer-hystrix
# 通過注冊中心來查找服務名稱(lb代表從注冊中心獲取服務,并且負載均衡)
uri: lb://consumer-hystrix
predicates:
- Path=/gateway/** # 匹配到的以/gateway開頭的路徑都轉發到gateway的服務,相當于訪問 lb://consumer-hystrix/**
filters:
- StripPrefix=1 # 去掉匹配到的路徑的第一段
# - name: RequestRateLimiter #必須為filters名稱
# args:
# redis-rate-limiter.replenishRate: 1 #允許用戶每多少秒處理多少個請求
# redis-rate-limiter.burstCapacity: 3 #令牌桶的容量,允許在一秒鐘內完成的最大請求數
# key-resolver: "#{@ipKeyResolver}" #使用ip限流,可以使用其他的接口限流等
eureka:
client:
service-url:
defaultZone: http://localhost:8800/eureka/
12.添加配置文件
package com.itlinli.config;
import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayFlowRule;
import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayRuleManager;
import com.alibaba.csp.sentinel.adapter.gateway.sc.SentinelGatewayFilter;
import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.BlockRequestHandler;
import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.GatewayCallbackManager;
import com.alibaba.csp.sentinel.adapter.gateway.sc.exception.SentinelGatewayBlockExceptionHandler;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.cloud.gateway.filter.factory.RequestRateLimiterGatewayFilterFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.codec.ServerCodecConfigurer;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.server.ServerResponse;
import org.springframework.web.reactive.result.view.ViewResolver;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import javax.annotation.PostConstruct;
import java.util.*;
@Configuration
public class GatewayConfiguration {
private final List<ViewResolver> viewResolvers;
private final ServerCodecConfigurer serverCodecConfigurer;
public GatewayConfiguration(ObjectProvider<List<ViewResolver>> viewResolversProvider,
ServerCodecConfigurer serverCodecConfigurer) {
this.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList);
this.serverCodecConfigurer = serverCodecConfigurer;
}
@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() {
// Register the block exception handler for Spring Cloud Gateway.
return new SentinelGatewayBlockExceptionHandler(viewResolvers, serverCodecConfigurer);
}
@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
public GlobalFilter sentinelGatewayFilter() {
return new SentinelGatewayFilter();
}
@PostConstruct
public void doInit() {
initGatewayRules();
initBlockHandler();
}
/**
* 配置限流規則
*/
private void initGatewayRules() {
Set<GatewayFlowRule> rules = new HashSet<>();
rules.add(new GatewayFlowRule("consumer-hystrix") //consumer-hystrix對應配置文件中的路由ID
.setCount(3) // 限流閾值
.setIntervalSec(1) // 統計時間窗口,單位是秒,默認是 1 秒
);
GatewayRuleManager.loadRules(rules);
}
/**
* 自定義限流異常處理器
*/
private void initBlockHandler() {
BlockRequestHandler blockRequestHandler = new BlockRequestHandler() {
@Override
public Mono<ServerResponse> handleRequest(ServerWebExchange serverWebExchange, Throwable throwable) {
Map<String, String> result = new HashMap<>();
result.put("code", String.valueOf(HttpStatus.TOO_MANY_REQUESTS.value()));
result.put("message","限制請求次數!");
return ServerResponse.status(HttpStatus.TOO_MANY_REQUESTS)
.contentType(MediaType.APPLICATION_JSON_UTF8)
.body(BodyInserters.fromObject(result));
}
};
// 加載自定義限流異常處理器
GatewayCallbackManager.setBlockHandler(blockRequestHandler);
}
}
13.啟動測試
1秒請求超過3次
智能推薦
SpringCloud入門(八):網關Gateway 之 服務注冊與發現(Greenwich.SR2)
簡介 在實際的工作中,服務的相互調用都是依賴于服務中心提供的入口來使用,服務中心往往注冊了很多服務,如果每個服務都需要單獨配置的話,非常麻煩。Spring Cloud Gateway 提供了一種默認轉發的能力,只要將 Spring Cloud Gateway 注冊到服務中心,Spring Cloud Gateway 默認就會代理服務中心的所有服務 代碼實現 新建一個Module,命名為micros...
SpringCloud入門(十):網關Gateway 之 限流(Greenwich.SR2)
簡介 限流:在高并發系統中,往往需要在系統中限流,一方面是為了防止大量請求使服務器過載,導致服務的不可用,另一方面是為了防止網絡攻擊。 一般開發高并發系統常見的限流有:限制總并發數(比如數據庫連接池、線程池)、限制瞬時并發數(如 nginx 的 limit_conn 模塊,用來限制瞬時并發連接數)、限制時間窗口內的平均速率(如 Guava 的 RateLimiter、nginx 的 limit_r...
SpringCloud2.x(七)統一管理微服務配置——Spring Cloud Config
一、為什么要統一管理微服務配置 對于傳統的單體應用,通常使用配置文件管理所有配置。比如Spring Boot開發的單體應用,配置內容可以放在application.yml文件,需要切換環境的話可以設置多個Profile并在啟動應用時指定spring.pfofiles.active={profile}。 然而,在微服務架構中,配置管理一般有以下需求 集中管理配置:一個使用微服務架構的應用系統可能會包...
springCloud2.x版本集成elasticJob curator不兼容問題demo
springCloud2.x版本集成elasticJob curator不兼容問題demo 背景 elasticJob集成步驟 沖突原因(curator-framework/curator-client/curator-recipes) 版本沖突錯誤代碼: 排查問題原因 解決辦法: 結束 背景 最近公司需要我集成elasticjob到現有項目,編寫demo過程都很順利,但是集成到項目時發現了一些問...
SpringCloud2.x(二) 搭建完整Demo-搭建權限認證模塊、Eureka注冊中心
SpringCloud2.x(二) 搭建完整Demo-搭建權限認證模塊 1.搭建權限認證模塊 2.搭建Eureka注冊中心(服務注冊發現,加密配置,搭建集群) ------------------------------------------------------------------------------------------------------------------------...
猜你喜歡
SpringCloud第七章(服務網關GateWay)
目錄 1:什么是GateWay 2:網關的作用 3:GateWay特點 3.1:路由功能 3.2:斷言 3.3:過濾器 1:什么是GateWay Spring Cloud Gateway 是 Spring Cloud 新推出的網關框架,之前是 Netflix Zuul1,Gateway比 Zuul 2 更早的使用 Netty 實現異步 IO,從而實現了一個簡單、比 Zuul 1.x 更高...
微服務實戰系列(七)-網關springcloud gateway
1. 場景描述 springcloud剛推出的時候用的是netflix全家桶,路由用的zuul,但是據說zull1.0在大數據量訪問的時候存在較大性能問題,2.0就沒集成到springcloud中了,springcloud推出了自己的路由-springcloud gateway,親兒子,目前官網主推。 netfelix的zull路由: 2. 解決方案 2.1 新建springboot項目 在spr...
freemarker + ItextRender 根據模板生成PDF文件
1. 制作模板 2. 獲取模板,并將所獲取的數據加載生成html文件 2. 生成PDF文件 其中由兩個地方需要注意,都是關于獲取文件路徑的問題,由于項目部署的時候是打包成jar包形式,所以在開發過程中時直接安照傳統的獲取方法沒有一點文件,但是當打包后部署,總是出錯。于是參考網上文章,先將文件讀出來到項目的臨時目錄下,然后再按正常方式加載該臨時文件; 還有一個問題至今沒有解決,就是關于生成PDF文件...
電腦空間不夠了?教你一個小秒招快速清理 Docker 占用的磁盤空間!
Docker 很占用空間,每當我們運行容器、拉取鏡像、部署應用、構建自己的鏡像時,我們的磁盤空間會被大量占用。 如果你也被這個問題所困擾,咱們就一起看一下 Docker 是如何使用磁盤空間的,以及如何回收。 docker 占用的空間可以通過下面的命令查看: TYPE 列出了docker 使用磁盤的 4 種類型: Images:所有鏡像占用的空間,包括拉取下來的鏡像,和本地構建的。 Con...