十四、網(wǎng)關Gateway整合Sentinel持久化到nacos

前面已經(jīng)講了:微服務整合Sentinel持久化到nacos勿锅。
這里我們說下網(wǎng)關整合sentinel帕膜,網(wǎng)關用的gateway。sentinel官網(wǎng)這里也介紹了網(wǎng)關流控的一些內容溢十。
在前面講微服務整合sentinel持久化到nacos時垮刹,我們把測試代碼中sentinel和nacos交互的類拷貝到了rule模塊中。
在網(wǎng)關gateway中也需要添加類似的代碼张弛。
首先我們看一下官網(wǎng)的介紹:

資源維度

什么意思荒典?

  1. 路由維度:也就是我們在gateway網(wǎng)關中配置的路由酪劫,如果觸發(fā)sentinel能夠識別到,并支持添加規(guī)則寺董。


    gateway路由配置

    這個路由配置可以在sentinel中發(fā)現(xiàn)覆糟。


    sentinel-gateway

    路由鏈路
  2. 自定義api維度:我們可以像官方給出的那樣,提前自定義api組遮咖,也可以被sentinel識別滩字,然后添加規(guī)則。我們更多的會用這個御吞,但是我們一般不會提前寫在代碼中麦箍,而是在web頁面自定義api組。官網(wǎng)例子:


    api組

說這么多陶珠,主要是想告訴大家挟裂,gateway整合sentinel的時候,不像在微服務中那樣(在微服務中揍诽,sentinel可以直接識別到url粒度的資源话瞧,然后在這些url資源上添加規(guī)則,nacos只需要處理規(guī)則)寝姿,有2個地方需要自己改動:

    1. 自定義的api資源組交排,需要和nacos交互
    1. 針對以上資源做的規(guī)則(也包括路由維度的資源),需要和nacos交互

1. sentinel-board后臺源碼修改

注意:這次修改饵筑,是在上次微服務整合sentinel修改完成之后的埃篓,所以是包含上次的修改的。
參考上次sentinel修改的代碼:微服務整合Sentinel持久化到nacos

1.1 添加一些常量根资,用于在nacos中規(guī)則名字的后綴架专、組別:

// 添加 gateway 后綴
public static final String GATEWAY_API_DATA_ID_POSTFIX = "-gateway-api-group";
public static final String GATEWAY_FLOW_DATA_ID_POSTFIX = "-gateway-flow-rules";

上次移過來的nacos的類中:com.alibaba.csp.sentinel.dashboard.rule.nacos.NacosConfigUtil

常量

1.2 nacos的連接中添加bean

上次可以看出,nacos中保存的是json字符串玄帕,是由一些entity直接轉的部脚。上次移過來的,里面只處理了微服務規(guī)則實體和json字符串互轉裤纹。我們現(xiàn)在要添加的是gateway的api組實體委刘、流控規(guī)則實體和json互轉。

    /** 新增gateway使用的entity和json串互轉  **/
    @Bean
    public Converter<List<GatewayFlowRuleEntity>, String> gatewayFlowRuleEntityEncoder() {
        return JSON::toJSONString;
    }

    @Bean
    public Converter<String, List<GatewayFlowRuleEntity>> gatewayFlowRuleEntityDecoder() {
        return s -> JSON.parseArray(s, GatewayFlowRuleEntity.class);
    }

    @Bean
    public Converter<List<ApiDefinitionEntity>, String> gatewayApiEntityEncoder() {
        return JSON::toJSONString;
    }

    @Bean
    public Converter<String, List<ApiDefinitionEntity>> gatewayApiEntityDecoder() {
        return s -> JSON.parseArray(s, ApiDefinitionEntity.class);
    }
json串轉換

1.3 添加規(guī)則和api組對接nacos的實現(xiàn)類

這個就是參考上次的微服務對接nacos的類寫的鹰椒,entity換一下就行锡移,4個,com.alibaba.csp.sentinel.dashboard.rule.gateway包下:

新加對接nacos的類

GatewayApiNacosProvider.png

import java.util.ArrayList;
import java.util.List;

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

import com.alibaba.csp.sentinel.dashboard.datasource.entity.gateway.ApiDefinitionEntity;
import com.alibaba.csp.sentinel.dashboard.rule.DynamicRuleProvider;
import com.alibaba.csp.sentinel.dashboard.rule.nacos.NacosConfigUtil;
import com.alibaba.csp.sentinel.datasource.Converter;
import com.alibaba.csp.sentinel.util.StringUtil;
import com.alibaba.nacos.api.config.ConfigService;

@Component("gatewayApiNacosProvider")
public class GatewayApiNacosProvider implements DynamicRuleProvider<List<ApiDefinitionEntity>> {
    
    @Autowired
    private ConfigService configService;
    @Autowired
    private Converter<String, List<ApiDefinitionEntity>> converter;

    @Override
    public List<ApiDefinitionEntity> getRules(String appName) throws Exception {
        String rules = configService.getConfig(appName + NacosConfigUtil.GATEWAY_API_DATA_ID_POSTFIX, 
                NacosConfigUtil.GROUP_ID, 3000);
        if (StringUtil.isEmpty(rules)) {
            return new ArrayList<>();
        }
        return converter.convert(rules);
    }

}
GatewayApiNacosPublisher.png
import java.util.List;

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

import com.alibaba.csp.sentinel.dashboard.datasource.entity.gateway.ApiDefinitionEntity;
import com.alibaba.csp.sentinel.dashboard.rule.DynamicRulePublisher;
import com.alibaba.csp.sentinel.datasource.Converter;
import com.alibaba.csp.sentinel.dashboard.rule.nacos.NacosConfigUtil;
import com.alibaba.csp.sentinel.util.AssertUtil;
import com.alibaba.nacos.api.config.ConfigService;

@Component("gatewayApiNacosPublisher")
public class GatewayApiNacosPublisher implements DynamicRulePublisher<List<ApiDefinitionEntity>> {

    @Autowired
    private ConfigService configService;
    @Autowired
    private Converter<List<ApiDefinitionEntity>, String> converter;

    @Override
    public void publish(String app, List<ApiDefinitionEntity> rules) throws Exception {
        AssertUtil.notEmpty(app, "app name cannot be empty");
        if (rules == null) {
            return;
        }
        configService.publishConfig(app+ NacosConfigUtil.GATEWAY_API_DATA_ID_POSTFIX,
                NacosConfigUtil.GROUP_ID, converter.convert(rules));
    }

}
GatewayFlowRuleNacosProvider.png
import java.util.ArrayList;
import java.util.List;

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

import com.alibaba.csp.sentinel.dashboard.datasource.entity.gateway.GatewayFlowRuleEntity;
import com.alibaba.csp.sentinel.dashboard.rule.DynamicRuleProvider;
import com.alibaba.csp.sentinel.dashboard.rule.nacos.NacosConfigUtil;
import com.alibaba.csp.sentinel.datasource.Converter;
import com.alibaba.csp.sentinel.util.StringUtil;
import com.alibaba.nacos.api.config.ConfigService;

@Component("gatewayFlowRuleNacosProvider")
public class GatewayFlowRuleNacosProvider implements DynamicRuleProvider<List<GatewayFlowRuleEntity>> {
    
    @Autowired
    private ConfigService configService;
    
    @Autowired
    private Converter<String, List<GatewayFlowRuleEntity>> converter;

    @Override
    public List<GatewayFlowRuleEntity> getRules(String appName) throws Exception {
        String rules = configService.getConfig(appName + NacosConfigUtil.GATEWAY_FLOW_DATA_ID_POSTFIX,
                NacosConfigUtil.GROUP_ID, 3000);
        if (StringUtil.isEmpty(rules)) {
            return new ArrayList<>();
        }
        return converter.convert(rules);
    }

}
GatewayFlowRuleNacosPublisher.png
import java.util.List;

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

import com.alibaba.csp.sentinel.dashboard.datasource.entity.gateway.GatewayFlowRuleEntity;
import com.alibaba.csp.sentinel.dashboard.rule.DynamicRulePublisher;
import com.alibaba.csp.sentinel.dashboard.rule.nacos.NacosConfigUtil;
import com.alibaba.csp.sentinel.datasource.Converter;
import com.alibaba.csp.sentinel.util.AssertUtil;
import com.alibaba.nacos.api.config.ConfigService;

@Component("gatewayFlowRuleNacosPublisher")
public class GatewayFlowRuleNacosPublisher implements DynamicRulePublisher<List<GatewayFlowRuleEntity>> {
    
    @Autowired
    private ConfigService configService;
    
    @Autowired
    private Converter<List<GatewayFlowRuleEntity>, String> converter;

    @Override
    public void publish(String app, List<GatewayFlowRuleEntity> rules) throws Exception {
        AssertUtil.notEmpty(app, "app name cannot be empty");
        if (rules == null) {
            return;
        }
        configService.publishConfig(app + NacosConfigUtil.GATEWAY_FLOW_DATA_ID_POSTFIX,
                NacosConfigUtil.GROUP_ID, converter.convert(rules));
    }

}

GatewayApiNacosProvider:從nacos中讀取已保存的api分組
GatewayApiNacosPublisher:保存gateway中api分組到nacos
GatewayFlowRuleNacosProvider:讀取nacos中保存的流控規(guī)則的
GatewayFlowRuleNacosPublisher:保存gateway中流控規(guī)則到nacos

1.4 修改conrtoller漆际,調用上一步添加的實現(xiàn)類

要修改的內容在com.alibaba.csp.sentinel.dashboard.controller.gateway包下面淆珊,2個controller:

controller

1.4.1 GatewayApiController
    1. 注入我們自己的實現(xiàn)類


      注入實現(xiàn)類
    1. 保存的時候有一個中間的小方法,我們重寫一下


      重寫小保存方法
    // 重寫保存規(guī)則的方法奸汇,通過新加的實現(xiàn)類保存到nacos
    private void publishApis(String app) {
        List<ApiDefinitionEntity> apis = repository.findAllByApp(app);
        try {
            rulePublisher.publish(app, apis);
        } catch (Exception e) {
            logger.error("推送apis到nacos異常");
        }
    }
    1. 修改查


      apis查
    1. 修改增


      apis增
    1. 修改刪和改 2處
      和增一樣施符,找到地方改


      apis刪查
1.4.2 GatewayFlowRuleController
    1. 注入我們自己的實現(xiàn)類


      注入實現(xiàn)類
    1. 重寫小方法


      重寫小方法
    // 重寫保存規(guī)則的方法往声,通過新加的實現(xiàn)類保存到nacos
    private void publishApis(String app) {
        List<GatewayFlowRuleEntity> apis = repository.findAllByApp(app);
        try {
            rulePublisher.publish(app, apis);
        } catch (Exception e) {
            logger.error("推送流控規(guī)則到nacos異常");
        }
    }
    1. 修改增刪改查


      1-查

      增刪改

2. gateway網(wǎng)關服務

2.1 引入jar包

gateway-sentinel依賴

pom.xml文件:

<?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>com.zrb.test</groupId>
        <artifactId>sentinel-test</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <artifactId>gateway-sentinel-server</artifactId>
    <version>1.0.0</version>
    <name>gateway-sentinel-server</name>
    <description>gateway網(wǎng)關</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        
        <!-- openfein -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <!-- SpringCloud在Hoxton.M2版本之后不再使用Ribbon而是使用spring-cloud-loadbalancer,需要自己引入 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-loadbalancer</artifactId>
        </dependency>
        
        <!--nacos客戶端 -->
        <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>
        
        <!--sentinel依賴-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-datasource-nacos</artifactId>
        </dependency>
        
    </dependencies>
    

    <build>
        <finalName>gateway-sentinel-server</finalName>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

2.2 配置文件

配置文件

application.yml文件:

# 1.server
server:
  port: 8000 
# 2.log
logging:
  level:
    '[org.springframework.cloud.gateway]': info
    '[org.springframework.jdbc.core]': debug
# 3.spring
spring: 
  # 服務名稱必須帶上戳吝,不然nacos服務列表中沒有浩销,也不會有注冊成功的信息
  application: 
    name: gateway-server
  # 統(tǒng)一設置返回的時間格式
  jackson: 
    date-format: yyyy-MM-dd HH:mm:ss
    time-zone: GMT+8
    default-property-inclusion: NON_NULL
  cloud: 
    nacos: 
      config: 
        import-check:
          enabled: false
#        server-addr: 192.168.50.89:8848
#        file-extension: yaml
      discovery: 
        server-addr: 192.168.50.89:8848
    sentinel:
       transport:
         dashboard: 192.168.50.89:8080
         port: 8723
       datasource:
        gw-flow:
          nacos:
            server-addr: 192.168.50.89:8848
            namespace: 
            groupId: SENTINEL_GROUP
            dataId: ${spring.application.name}-gateway-flow-rules
            dataType: json
            rule-type: gw-flow
        gw-api-group:
          nacos:
            server-addr: 192.168.50.89:8848
            namespace: 
            groupId: SENTINEL_GROUP
            dataId: ${spring.application.name}-gateway-api-group
            dataType: json
            rule-type: gw-api-group
    # gateway
    gateway:
      discovery:
        locator:
          enabled: false
          lowerCaseServiceId: true
      routes:
          # 自定義路由 ID
        - id: user_route
          # 采用 LoadBalanceClient 方式請求,以 lb:// 開頭骨坑,后面的是注冊在 Nacos 上的服務名
          uri: lb://user-demo
          # Predicate 斷言撼嗓,主要作用是匹配用戶的請求路徑柬采,有很多種用法
          predicates:
            # 路徑匹配欢唾,一般是指要走網(wǎng)關時要寫的路徑地址
            - Path=/api/**
          filters:
            # 指路由到其他服務時去掉path中幾層路徑,如值為1粉捻,則去掉1層礁遣,即去掉/api
            - StripPrefix=1

2.3 加上官方文檔中給的config類

這個可以不用加了,加了會沖突肩刃。順著提示找了一下祟霍,com.alibaba.cloud.sentinel.gateway.scg.SentinelSCGAutoConfiguration中已經(jīng)有了,而且默認就是開啟了:

默認開啟

所以這類不用加了
config類

import java.util.Collections;
import java.util.List;

import org.springframework.beans.factory.ObjectProvider;
import org.springframework.cloud.gateway.filter.GlobalFilter;
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.codec.ServerCodecConfigurer;
import org.springframework.web.reactive.result.view.ViewResolver;

import com.alibaba.csp.sentinel.adapter.gateway.sc.SentinelGatewayFilter;
import com.alibaba.csp.sentinel.adapter.gateway.sc.exception.SentinelGatewayBlockExceptionHandler;

@Configuration
public class GatewayConfig {
    
    private final List<ViewResolver> viewResolvers;
    private final ServerCodecConfigurer serverCodecConfigurer;

    public GatewayConfig(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(-1)
    public GlobalFilter sentinelGatewayFilter() {
        return new SentinelGatewayFilter();
    }

}

2.4 啟動語句添加配置

網(wǎng)關類型的配置:-Dcsp.sentinel.app.type=1

java -Dcsp.sentinel.app.type=1 -jar *.jar

3. nacos中添加配置文件

分別添加api組和流控規(guī)則的配置文件


nacos配置

4. 測試

將sentinel-dashboard和gateway以及user服務打包啟動盈包。


監(jiān)控

路由

4.1 添加api組

開始

添加2個

nacos中有

4.2 添加流控規(guī)則

規(guī)則

10s

5s

nacos中

4.3 請求測試

post

get

修改完規(guī)則重啟或者等一分鐘沸呐,避免不必要的麻煩


參考文章:https://blog.csdn.net/admin_15082037343/article/details/130530211

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市呢燥,隨后出現(xiàn)的幾起案子崭添,更是在濱河造成了極大的恐慌,老刑警劉巖叛氨,帶你破解...
    沈念sama閱讀 210,914評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件呼渣,死亡現(xiàn)場離奇詭異,居然都是意外死亡寞埠,警方通過查閱死者的電腦和手機屁置,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,935評論 2 383
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來仁连,“玉大人蓝角,你說我怎么就攤上這事》苟” “怎么了帅容?”我有些...
    開封第一講書人閱讀 156,531評論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長伍伤。 經(jīng)常有香客問我并徘,道長,這世上最難降的妖魔是什么扰魂? 我笑而不...
    開封第一講書人閱讀 56,309評論 1 282
  • 正文 為了忘掉前任麦乞,我火速辦了婚禮蕴茴,結果婚禮上,老公的妹妹穿的比我還像新娘姐直。我一直安慰自己倦淀,他們只是感情好,可當我...
    茶點故事閱讀 65,381評論 5 384
  • 文/花漫 我一把揭開白布声畏。 她就那樣靜靜地躺著撞叽,像睡著了一般。 火紅的嫁衣襯著肌膚如雪插龄。 梳的紋絲不亂的頭發(fā)上愿棋,一...
    開封第一講書人閱讀 49,730評論 1 289
  • 那天,我揣著相機與錄音均牢,去河邊找鬼糠雨。 笑死,一個胖子當著我的面吹牛徘跪,可吹牛的內容都是我干的甘邀。 我是一名探鬼主播,決...
    沈念sama閱讀 38,882評論 3 404
  • 文/蒼蘭香墨 我猛地睜開眼垮庐,長吁一口氣:“原來是場噩夢啊……” “哼松邪!你這毒婦竟也來了?” 一聲冷哼從身側響起哨查,我...
    開封第一講書人閱讀 37,643評論 0 266
  • 序言:老撾萬榮一對情侶失蹤逗抑,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后解恰,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體锋八,經(jīng)...
    沈念sama閱讀 44,095評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,448評論 2 325
  • 正文 我和宋清朗相戀三年护盈,在試婚紗的時候發(fā)現(xiàn)自己被綠了挟纱。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,566評論 1 339
  • 序言:一個原本活蹦亂跳的男人離奇死亡腐宋,死狀恐怖紊服,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情胸竞,我是刑警寧澤欺嗤,帶...
    沈念sama閱讀 34,253評論 4 328
  • 正文 年R本政府宣布,位于F島的核電站卫枝,受9級特大地震影響煎饼,放射性物質發(fā)生泄漏。R本人自食惡果不足惜校赤,卻給世界環(huán)境...
    茶點故事閱讀 39,829評論 3 312
  • 文/蒙蒙 一吆玖、第九天 我趴在偏房一處隱蔽的房頂上張望筒溃。 院中可真熱鬧,春花似錦沾乘、人聲如沸怜奖。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,715評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽歪玲。三九已至,卻和暖如春掷匠,著一層夾襖步出監(jiān)牢的瞬間滥崩,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,945評論 1 264
  • 我被黑心中介騙來泰國打工槐雾, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留夭委,地道東北人幅狮。 一個月前我還...
    沈念sama閱讀 46,248評論 2 360
  • 正文 我出身青樓募强,卻偏偏與公主長得像,于是被迫代替她去往敵國和親崇摄。 傳聞我的和親對象是個殘疾皇子擎值,可洞房花燭夜當晚...
    茶點故事閱讀 43,440評論 2 348

推薦閱讀更多精彩內容