gatewaynacossentinel三剑客强强组合

编程

spring cloud gateway 响应式网关,基于nacos实现动态网关,基于sentinel实现动态限流,sentinel基于nacos数据持久化

软件架构

版本号:gateway、nacos、sentinel的版本号参考父级项目occo-parent

安装教程

  1. 启动注册中心和配置中心Nacos 文档地址:Nacos文档 下载地址:Nacos下载

  2. 启动限流服务Sentinel 文档地址:Sentinel文档 下载地址:Sentinel下载

  3. 启动网关

  • 下载occo-gateway启动项目
  • 启动gateway
  • 在nacos中建《路由》配置:

Data ID: gateway_router

Group:DEFAULT_GROUP (默认的)

配置内容:[{"id":"user-server","uri":"lb://kb-user-center","order":0,"predicates":[{"args":{"pattern":"/user/**"},"name":"Path"}],"filters":[{"name":"StripPrefix","args":{"_genkey_0":"1"}}]},{"id":"sso-server","uri":"lb://kb-user-center","order":0,"predicates":[{"args":{"pattern":"/sso/**"},"name":"Path"}],"filters":[{"name":"StripPrefix","args":{"_genkey_0":"1"}}]}] (JSON格式)

配置字段说明:

① id:路由的名字;

② uri:路由的地址,lb表示去那儿一个服务,kb-user-center是nacos注册中心的服务名;

③ order:0 ,直接配置为0,为1是请求的url就会带服务名;

④ predicates:

After路由匹配:匹配指定时间之后的请求: name=After ,_genkey_0=2020-01-20T17:42:47.789-07:00[America/Denver]

Before路由匹配:匹配指定时间之前的请求: name=Before,_genkey_0=2020-01-20T17:42:47.789-07:00[America/Denver]

Between路由匹配:匹配指定时间区间的请求: name=Before,_genkey_0=时间一 ,时间二 (PS:两个时间逗号隔开)

Cookie路由匹配:匹配指定Cookie的值匹配请求: name=Cookie, _genkey_0=chocolate, ch.p (PS:匹配cookie名为chocolate的值为ch.p的请求)

Header路由匹配:匹配指定header的值匹配请求: name=Header, _genkey_0=X-Request-Id, d+ (PS:匹配头信息X-Request-Id的值匹配d+的正则表达式)

Host路由匹配:Host匹配设定的表达式: name=Host, _genkey_0=**.fuse.org

Method路由匹配:匹配HttpMethod方法请求: name=Method, _genkey_0=GET

Path路由匹配:请求路径匹配设定表达式的请求: name=Path, _genkey_0=/foo/{segment} (PS:请求路径匹配路径匹配表达式/foo/{segment})

Path路由匹配:请求路径匹配设定值的请求 : name=Path, _genkey_0=/foo/** (PS:请求路径匹配路径以/foo开头)

Query路由匹配:请求参数匹配设定值或表达式的请求:name=Query, _genkey_0=baz (PS:请求参数中包含baz参数)

4、发布gateway_router配置,每次重新启动gateway都要重新发布一下这个配置,才能被gateway获取到《路由》配置。
5、在nacos中建《限流》配置如下:
Data ID: gateway-sentinel
Group:DEFAULT_GROUP (默认的)
配置内容:[{"resource":"user-server","controlBehavior":0,"count":2,"grade":1,"limitApp":"default","strategy":0}] (JSON格式)
配置说明:

  • resource:资源名,即限流规则的作用对象
  • limitApp:流控针对的调用来源,若为 default 则不区分调用来源
  • grade:限流阈值类型(QPS 或并发线程数);0代表根据并发数量来限流,1代表根据QPS来进行流量控制
  • count:限流阈值
  • strategy:调用关系限流策略
  • controlBehavior:流量控制效果(直接拒绝、Warm Up、匀速排队)
  • clusterMode:是否为集群模式

整合说明

1、GateWay支持跨域

import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import org.springframework.web.cors.CorsConfiguration;

import org.springframework.web.cors.reactive.CorsWebFilter;

import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;

import org.springframework.web.util.pattern.PathPatternParser;

import reactor.core.publisher.Mono;

@Configuration

public class GatewayConfig {

/**

* -跨域支持配置

*/

@Bean

public CorsWebFilter corsFilter() {

CorsConfiguration config = new CorsConfiguration();

config.addAllowedMethod("*");

config.addAllowedOrigin("*");

config.addAllowedHeader("*");

UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(new PathPatternParser());

source.registerCorsConfiguration("/**", config);

return new CorsWebFilter(source);

}

/**

* -远程地址键解析器

*/

@Bean(value = "remoteAddrKeyResolver")

public KeyResolver remoteAddrKeyResolver() {

return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getAddress().getHostAddress());

}

}

2、Gateway 整合Nacos

Ⅰ、整合需要的Jar

   <dependencies>

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-actuator</artifactId>

</dependency>

<dependency>

<groupId>org.springframework.cloud</groupId>

<artifactId>spring-cloud-starter-gateway</artifactId>

</dependency>

<dependency>

<groupId>com.alibaba.cloud</groupId>

<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>

</dependency>

<dependency>

<groupId>com.alibaba.cloud</groupId>

<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>

</dependency>

<dependency>

<groupId>org.projectlombok</groupId>

<artifactId>lombok</artifactId>

</dependency>

</dependencies>

Ⅱ、 Gateway获取Nacos的权重,在配置加入下面配置

    @Bean

@Scope(value = "prototype")

public IRule loadBalanceRule() {

return new NacosRule();

}

Ⅲ、动态获取nacos中gateway_router的路由配置

import com.alibaba.fastjson.JSONObject;

import com.alibaba.nacos.api.NacosFactory;

import com.alibaba.nacos.api.config.ConfigService;

import com.alibaba.nacos.api.config.listener.Listener;

import com.alibaba.nacos.api.exception.NacosException;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.beans.factory.annotation.Value;

import org.springframework.cloud.gateway.event.RefreshRoutesEvent;

import org.springframework.cloud.gateway.route.RouteDefinition;

import org.springframework.cloud.gateway.route.RouteDefinitionWriter;

import org.springframework.context.ApplicationEventPublisher;

import org.springframework.context.ApplicationEventPublisherAware;

import org.springframework.stereotype.Component;

import reactor.core.publisher.Mono;

import javax.annotation.PostConstruct;

import java.util.ArrayList;

import java.util.List;

import java.util.concurrent.Executor;

@Component

public class NacosDynamicRouteService implements ApplicationEventPublisherAware {

private static String DATAID = "gateway_router";

private static String GROUP = "DEFAULT_GROUP";

@Value("${spring.cloud.nacos.config.server-addr}")

private String serverAddr;

@Autowired

private RouteDefinitionWriter routeDefinitionWriter;

private ApplicationEventPublisher applicationEventPublisher;

private static final List<String> ROUTE_LIST = new ArrayList<>();

@PostConstruct

public void dynamicRouteByNacosListener() {

try {

ConfigService configService = NacosFactory.createConfigService(serverAddr);

configService.getConfig(DATAID, GROUP, 5000);

configService.addListener(DATAID, GROUP, new Listener() {

@Override

public void receiveConfigInfo(String configInfo) {

clearRoute();

try {

System.err.println(configInfo);

List<RouteDefinition> gatewayRouteDefinitions = JSONObject.parseArray(configInfo, RouteDefinition.class);

for (RouteDefinition routeDefinition : gatewayRouteDefinitions) {

addRoute(routeDefinition);

}

publish();

} catch (Exception e) {

e.printStackTrace();

}

}

@Override

public Executor getExecutor() {

return null;

}

});

} catch (NacosException e) {

e.printStackTrace();

}

}

private void clearRoute() {

for(String id : ROUTE_LIST) {

this.routeDefinitionWriter.delete(Mono.just(id)).subscribe();

}

ROUTE_LIST.clear();

}

private void addRoute(RouteDefinition definition) {

try {

routeDefinitionWriter.save(Mono.just(definition)).subscribe();

ROUTE_LIST.add(definition.getId());

} catch (Exception e) {

e.printStackTrace();

}

}

private void publish() {

this.applicationEventPublisher.publishEvent(new RefreshRoutesEvent(this.routeDefinitionWriter));

}

@Override

public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {

this.applicationEventPublisher = applicationEventPublisher;

}

}

 3、Gateway整合sentinel

Ⅰ、需要的jar

        <dependency>

<groupId>com.alibaba.cloud</groupId>

<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>

</dependency>

<dependency>

<groupId>com.alibaba.csp</groupId>

<artifactId>sentinel-spring-cloud-gateway-adapter</artifactId>

</dependency>

Ⅱ、 注入对应的 SentinelGatewayFilter 实例以及 SentinelGatewayBlockExceptionHandler 实例

@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();

}

}

Ⅲ、官方指导地址(什么都还是官方靠谱)

https://github.com/alibaba/Sentinel/wiki/%E7%BD%91%E5%85%B3%E9%99%90%E6%B5%81

4、Sentinel基于Nacos持久化

Ⅰ、添加jar

<dependency>

<groupId>com.alibaba.csp</groupId>

<artifactId>sentinel-datasource-nacos</artifactId>

</dependency>

Ⅱ、添加配置

import java.util.List;

import java.util.Properties;

import javax.annotation.PostConstruct;

import org.springframework.beans.factory.annotation.Value;

import org.springframework.stereotype.Component;

import com.alibaba.csp.sentinel.datasource.ReadableDataSource;

import com.alibaba.csp.sentinel.datasource.nacos.NacosDataSource;

import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;

import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;

import com.alibaba.fastjson.JSON;

import com.alibaba.fastjson.TypeReference;

import com.alibaba.nacos.api.PropertyKeyConst;

/**

* sentinel数据持久化到nacos

* @see https://github.com/alibaba/Sentinel/wiki/%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%99%E6%89%A9%E5%B1%95

* @author kinbug

*/

@Component

public class SentinelDataSourceNacos {

// nacos server addr

@Value("${spring.cloud.nacos.config.server-addr}")

private String serverAddr;

// nacos group

private static final String groupId = "DEFAULT_GROUP";

// nacos dataId

private static final String dataId = "gateway-sentinel";

// if change to true, should be config NACOS_NAMESPACE_ID

private static boolean isDemoNamespace = false;

// fill your namespace id,if you want to use namespace. for example:

// 0f5c7314-4983-4022-ad5a-347de1d1057d,you can get it on nacos"s console

private static final String NACOS_NAMESPACE_ID = "${namespace}";

@PostConstruct

public void initRules() {

if (isDemoNamespace) {

loadMyNamespaceRules();

} else {

loadRules();

}

}

private void loadRules() {

ReadableDataSource<String, List<FlowRule>> flowRuleDataSource = new NacosDataSource<>(serverAddr, groupId,

dataId, source -> JSON.parseObject(source, new TypeReference<List<FlowRule>>() {

}));

FlowRuleManager.register2Property(flowRuleDataSource.getProperty());

}

private void loadMyNamespaceRules() {

Properties properties = new Properties();

properties.put(PropertyKeyConst.SERVER_ADDR, serverAddr);

properties.put(PropertyKeyConst.NAMESPACE, NACOS_NAMESPACE_ID);

ReadableDataSource<String, List<FlowRule>> flowRuleDataSource = new NacosDataSource<>(properties, groupId,

dataId, source -> JSON.parseObject(source, new TypeReference<List<FlowRule>>() {

}));

FlowRuleManager.register2Property(flowRuleDataSource.getProperty());

}

}

Ⅲ、官方指导

https://github.com/alibaba/Sentinel/wiki/%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%99%E6%89%A9%E5%B1%95

以上是 gatewaynacossentinel三剑客强强组合 的全部内容, 来源链接: utcz.com/z/516029.html

回到顶部