友情提示:要下载源码进行改造,本文基于Sentinel-1.8.2。

以下内容摘自个人的技术文档,相关资料主要来自SpringCloudAlibaba和Github-Sentinel。正文是部分节选内容,仅供参考。

4.1.2. 网关流控

网关限流规则,是针对 API Gateway 的场景定制的限流规则,可以针对不同 route 或自定义的 API 分组进行限流,支持针对请求中的参数、Header、来源 IP 等进行定制化的限流。

与普通的应用流控相同,网关流控触发后同样会返回这样的结果。

{"code":429,"message":"Sentinel block exception","route":"/"
}

4.1.2.1. 基础结构

前端代码

  • 前端页面:webapp/resources/app/views/gateway/flow.html
  • js文件:webapp/resources/app/scripts/controllers/gateway/flow.js

后台代码

  • Package:com.alibaba.csp.sentinel.dashboard.controller.gateway
  • Class:GatewayFlowRuleController
    • GET /gateway/flow/list.json - 查询流控规则
    • POST /gateway/flow/new.json - 新增流控规则
    • PUT /gateway/flow/save.json - 修改流控规则
    • DELETE /gateway/flow/delete.json - 删除流控规则

4.1.2.2. 查询流控规则

接口入参

参数名 类型 规则约束 说明
app String 字符串非空 gateway网关ApplicationName,对应网关配置文件中spring.application.name属性的值
ip String 字符串非空 网关服务器IP
port Integer 非空 网关服务器端口,对应网关配置文件中sentinel.transport.port的值

内部逻辑

4.1.2.3. 新增流控规则

接口入参

参数名 类型 规则约束 说明
app String 字符串非空 应用名称
ip String 字符串非空 应用IP
port Integer 应用端口号
resource String 字符串非空 流控针对的资源
resourceMode Integer 非空,RESOURCE_MODE_ROUTE_ID=0;RESOURCE_MODE_CUSTOM_API_NAME=1 资源模式
grade Integer 非空,0为线程数,1为qps 限流指标维度,同限流规则的 grade 字段
count Double 大于等于0 限流阈值
interval Long 大于0 统计间隔,默认是 1
intervalUnit Integer 秒、分、时、天 统计间隔单位,默认是秒
controlBehavior Integer 非空,0-快速失败 2-匀速排队 流量整形的控制效果,同限流规则的 controlBehavior 字段,目前支持快速失败和匀速排队两种模式,默认是快速失败。
burst Integer 快速失败时必填,大于等于0 应对突发请求时额外允许的请求数目
maxQueueingTimeoutMs Integer 匀速排队时必填,大于等于0 匀速排队模式下的最长排队时间,单位是毫秒,仅在匀速排队模式下生效
paramItem GPFIV 参数限流配置

GPFIV:GatewayParamFlowItemVo若不提供,则代表不针对参数进行限流,该网关规则将会被转换成普通流控规则;否则会转换成热点规则。

参数名 类型 规则约束 说明
parseStrategy Integer 0-ClientIP 1-Remote Host 2-Header 3-URL参数 4-Cookie 从请求中提取参数的策略
fieldName String 当参数属性为2-Header 3-URL参数 4-Cookie时,参数名称必填 若提取策略选择 Header 模式或 URL 参数模式,则需要指定对应的 header 名称或 URL 参数名称
pattern String 参数值的匹配模式,只有匹配该模式的请求属性值会纳入统计和流控;若为空则统计该请求属性的所有值。(1.6.2 版本开始支持)
matchStrategy Integer 精确匹配(PARAM_MATCH_STRATEGY_EXACT)、子串匹配(PARAM_MATCH_STRATEGY_CONTAINS)、正则匹配(PARAM_MATCH_STRATEGY_REGEX 参数值的匹配策略(1.6.2 版本开始支持)

内部逻辑

4.1.2.4. 修改流控规则

接口入参

除了用id替代了部分参数外,其他参数都与新增接口的入参相同

参数名 类型 规则约束 说明
id Long 非空 规则id
grade Integer 非空,0为线程数,1为qps 限流指标维度,同限流规则的 grade 字段
count Double 大于等于0 限流阈值
interval Long 大于0 统计间隔,默认是 1
intervalUnit Integer 秒、分、时、天 统计间隔单位,默认是秒
controlBehavior Integer 非空,0-快速失败 2-匀速排队 流量整形的控制效果,同限流规则的 controlBehavior 字段,目前支持快速失败和匀速排队两种模式,默认是快速失败。
burst Integer 快速失败时必填,大于等于0 应对突发请求时额外允许的请求数目
maxQueueingTimeoutMs Integer 匀速排队时必填,大于等于0 匀速排队模式下的最长排队时间,单位是毫秒,仅在匀速排队模式下生效
paramItem GPFIV 参数限流配置

内部逻辑(与新增相同)

4.1.2.5. 删除流控规则

接口入参

参数名 类型 规则约束 说明
id Long 非空 规则id

内部逻辑(大致与新增、修改相同,不再赘述)

5. 动态数据源

5.1. 前置知识

5.1.1. 什么是动态数据源

开源框架中(至少截止1.8.2版本),所有的规则都是存储在内存中(JVM中以Map形式存在)。但是在生产环境中,我们通常希望有一个固定的配置文件或者数据源来完成这些规则的持久化及使用,这就是动态数据源。

本项目是Sentinel Dashboard,而不是Sentinel。由于Dashboard提供了比较完善的规则管理功能,所以我们期望通过Dashboard来进行规则配置,而不是通过Nacos这样的配置中心对文本进行修改。那么,为了满足这样的需求,就需要把动态数据源集成入Dashboard中,从而将用户在Dashboard中配置的规则持久到动态数据源中。

Sentinel(也包括Dashboard)提供了两种动态数据源方案:

  • 拉模式,客户端(集成Sentinel的应用)主动向某个规则管理中心定期轮询拉取规则,这个规则中心可以是 RDBMS、文件,甚至是 VCS 等。这样做的方式是简单,缺点是无法及时获取变更;

  • 推模式,规则中心统一推送,客户端(集成Sentinel的应用)通过注册监听器的方式时刻监听变化,比如使用 Nacos、Zookeeper 等配置中心。这种方式有更好的实时性和一致性保证。

Sentinel 目前支持以下数据源扩展:

  • Pull-based: 动态文件数据源、Consul, Eureka
  • Push-based: ZooKeeper, Redis, Nacos, Apollo, etcd

5.1.2. 拉模式拓展

实现拉模式的数据源最简单的方式是继承 AutoRefreshDataSource 抽象类,然后实现 readSource() 方法,在该方法里从指定数据源读取字符串格式的配置数据。比如 基于文件的数据源。

5.1.3. 推模式拓展

实现推模式的数据源最简单的方式是继承 AbstractDataSource 抽象类,在其构造方法中添加监听器,并实现 readSource() 从指定数据源读取字符串格式的配置数据。比如 基于 Nacos 的数据源。

控制台通常需要做一些改造来直接推送应用维度的规则到配置中心。功能示例可以参考 AHAS Sentinel 控制台的规则推送功能。改造指南可以参考 在生产环境中使用 Sentinel 控制台。

5.1.4. 注册数据源

本小节内容是单独使用Sentinel时需要做的步骤,如果使用SpringCloudAlibaba集成Sentinel,则不需要。

通常需要调用以下方法将数据源注册至指定的规则管理器中:

ReadableDataSource<String, List<FlowRule>> flowRuleDataSource = new NacosDataSource<>(remoteAddress, groupId, dataId, parser);
FlowRuleManager.register2Property(flowRuleDataSource.getProperty());

若不希望手动注册数据源,可以借助 Sentinel 的 InitFunc SPI 扩展接口。只需要实现自己的 InitFunc 接口,在 init 方法中编写注册数据源的逻辑。比如:

package com.test.init;public class DataSourceInitFunc implements InitFunc {@Overridepublic void init() throws Exception {final String remoteAddress = "localhost";final String groupId = "Sentinel:Demo";final String dataId = "com.alibaba.csp.sentinel.demo.flow.rule";ReadableDataSource<String, List<FlowRule>> flowRuleDataSource = new NacosDataSource<>(remoteAddress, groupId, dataId,source -> JSON.parseObject(source, new TypeReference<List<FlowRule>>() {}));FlowRuleManager.register2Property(flowRuleDataSource.getProperty());}
}

接着将对应的类名添加到位于资源目录(通常是 resource 目录)下的 META-INF/services 目录下的 com.alibaba.csp.sentinel.init.InitFunc 文件中,比如:

com.test.init.DataSourceInitFunc

这样,当初次访问任意资源的时候,Sentinel 就可以自动去注册对应的数据源了。

5.1.5. 官方拓展示例

Sentinel官方在源码中提供了针对应用流控规则的动态数据源拓展示例。Sentinel开源版提供了基于内存的规则引擎,为了使用数据源进行持久化,有必要对其进行改造。

官方针对Nacos作为动态数据源的情况写了专门的样本代码,该样本针对的是流控规则。

回顾一下流控规则的后台代码:

  • Package:com.alibaba.csp.sentinel.dashboard.controller
  • Class:FlowControllerV1
    • GET /v1/flow/rules - 查询流控规则
    • POST /v1/flow/rule - 新增流控规则
    • PUT /v1/flow/save.json - 修改流控规则
    • DELETE /v1/flow/delete.json - 删除流控规则

样本代码则是:

  • Package:com.alibaba.csp.sentinel.dashboard.controller.v2
  • Class:FlowControllerV2
    • GET /v2/flow/rules - 查询流控规则
    • POST /v2/flow/rule - 新增流控规则
    • PUT /v2/flow/save.json - 修改流控规则
    • DELETE /v2/flow/delete.json - 删除流控规则

Sentinel官方在dashboard的test包中提供了nacos的关键样例(test/com.alibaba.csp.sentinel.dashboard.rule.nacos),也包括了Apollo和Zookeeper。以下主要介绍基于Nacos作为动态数据源如何操作。

5.1.5.1. 拷贝样例类

位于test/com.alibaba.csp.sentinel.dashboard.rule.nacos下,有4个类:

  • FlowRuleNacosProvider
  • FlowRuleNacosPublisher
  • NacosConfig
  • NacosConfigUtil

将它们拷贝到SentinelDashboard中。由于NacosConfig中填写的Nacos服务地址是localhost,我们要改为ip:port的格式,通常我们会将它定义个配置项,挪到配置文件中定义或者用启动参数指定。

5.1.5.2. 添加数据源依赖

由于官方将数据源依赖设置为了test范围,我们需要将其开放使用,只要将pom.xml中下面的< scope>标签注释掉即可。

     <!-- for Nacos rule publisher sample --><dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-datasource-nacos</artifactId><scope>test</scope></dependency>

5.1.5.3. 修改前端路由

默认前端访问的后端接口上面提到了,是这些:

  • GET /v1/flow/rules - 查询流控规则
  • POST /v1/flow/rule - 新增流控规则
  • PUT /v1/flow/save.json - 修改流控规则
  • DELETE /v1/flow/delete.json - 删除流控规则

现在要改为/v2/……,所以要把前端改造一下。虽然前端是Angular开发的,但对于全栈来说,不用担心看看就知道是怎么回事。

Angular和Vue差不多,需要用node.js进行编译打包之类的操作,所以这里需要安装node.js,建议使用11.15.0,否则可能会遇到一些奇奇怪怪的问题。如果希望同时管理多个node版本,可以参考这篇博客。

node相关命令:

# 安装包
npm -install# 运行(开发)
npm start# 打包(生产)
npm run build

前端工程的结构大概是这样的(只摘录必要的结构,其他的已省略):

  • webapp/resources/

    • app

      • scripts

        • controllers

          • flow_v1.js ------------------------------ 原始流控前端js
          • flow_v2.js ------------------------------ 动态数据源前端js
        • services
          • flow_service_v1.js ------------------- 原始流控后端API定义
          • flow_service_v2.js ------------------- 动态数据源后端API定义
        • directives
          • sidebar

            • sidebar.html --------------------- 定义路由
        • app.js ------------------------------------------ 定义全局的控件,是核心配置
      • views
        • flow_v1.html --------------------------------- 原始流控规则配置页面
        • flow_v2.html --------------------------------- 动态数据源流控规则配置页面
    • dist ---------------------------------------------------------- 存放生产环境编译打包后的文件

    • tmp ---------------------------------------------------------- 存放开发环境编译打包后的文件

    • gulpfile.js -------------------------------------------------- service 文件定义的地方(后续扩展新的代码要用)

此处有两个关键,app.js和sidebar.html,在app.js中定义了两个state,是我们可以直接用的,内容如下:

      .state('dashboard.flowV1', {templateUrl: 'app/views/flow_v1.html',url: '/flow/:app',controller: 'FlowControllerV1',resolve: {loadMyFiles: ['$ocLazyLoad', function ($ocLazyLoad) {return $ocLazyLoad.load({name: 'sentinelDashboardApp',files: ['app/scripts/controllers/flow_v1.js',]});}]}}).state('dashboard.flow', {templateUrl: 'app/views/flow_v2.html',url: '/v2/flow/:app',controller: 'FlowControllerV2',resolve: {loadMyFiles: ['$ocLazyLoad', function ($ocLazyLoad) {return $ocLazyLoad.load({name: 'sentinelDashboardApp',files: ['app/scripts/controllers/flow_v2.js',]});}]}})

对应的,控制台左侧的导航中的连接,则是在sidebar.html中定义:

<!-- 原始流控规则导航 -->
<li ui-sref-active="active" ng-if="!entry.isGateway"><a ui-sref="dashboard.flowV1({app: entry.app})"><i class="glyphicon glyphicon-filter"></i>&nbsp;&nbsp;流控规则</a>
</li>
<!-- 改成动态数据源流控规则导航 -->
<li ui-sref-active="active" ng-if="!entry.isGateway"><a ui-sref="dashboard.flow({app: entry.app})"><i class="glyphicon glyphicon-filter"></i>&nbsp;&nbsp;流控规则</a>

很显然标签中的dashboard.flowV1就是app.js中state所定义的组件。

前端改好后,可以直接启动或者打包后启动来调试,看看是否成功。

5.2. 基于SpringCloudGateway

SpringCloudGateway由于Sentinel官方已经做好了适配,所以集成起来还是比较简单。

Gateway相关的代码基本都在gateway包或者目录下,很好找。

此处为了保留原始代码,基本上都是新建类、页面和js等进行扩展,不在原有代码上直接改,以下仅针对流控过程扩展供参考。

5.2.1. 新增Publisher和Provider

根据原始的GatewayFlowRuleController,可以知道,接口内使用的实体对象都是GatewayFlowRuleEntity,所以直接为它提供转换器并编写PublisherProvider即可。

Provider

import com.alibaba.csp.sentinel.dashboard.config.NacosConfigUtil;
import com.alibaba.csp.sentinel.dashboard.datasource.entity.gateway.GatewayFlowRuleEntity;
import com.alibaba.csp.sentinel.datasource.Converter;
import com.alibaba.csp.sentinel.util.StringUtil;
import com.alibaba.nacos.api.config.ConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;import java.util.ArrayList;
import java.util.List;@Component("gatewayFlowRuleNacosProvider")
public class GatewayFlowRuleNacosProvider implements DynamicRuleProvider<List<GatewayFlowRuleEntity>> {@Autowiredprivate ConfigService configService;// 规则对象的转换器,获取到的数据根据使用的数据类型的不同,需要用不同的转换器转化后使用@Autowiredprivate Converter<String, List<GatewayFlowRuleEntity>> converter;@Overridepublic List<GatewayFlowRuleEntity> getRules(String appName) throws Exception {String rules = configService.getConfig(appName + NacosConfigUtil.FLOW_DATA_ID_POSTFIX,NacosConfigUtil.GROUP_ID, 3000);if (StringUtil.isEmpty(rules)) {return new ArrayList<>(0);}return converter.convert(rules);}
}

Publisher

import com.alibaba.csp.sentinel.dashboard.config.NacosConfigUtil;
import com.alibaba.csp.sentinel.dashboard.datasource.entity.gateway.GatewayFlowRuleEntity;
import com.alibaba.csp.sentinel.datasource.Converter;
import com.alibaba.csp.sentinel.util.AssertUtil;
import com.alibaba.nacos.api.config.ConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;import java.util.List;/*** <h3>Sentinel动态数据源的网关流控规则发布器</h3>** <p>把通过控制台配置好的规则发布到动态数据源(nacos)中,当前使用的是push模式,* 规则被推送至nacos后,网关将会通过监听器自动获取最新的规则,并更新到网关的本地缓* 存中。* </p>*/
@Component("gatewayFlowRuleNacosPublisher")
public class GatewayFlowRuleNacosPublisher implements DynamicRulePublisher<List<GatewayFlowRuleEntity>> {// 数据源的配置服务@Autowiredprivate ConfigService configService;/*** <p>数据通信的转换器。* <p>在config包下的NacosConfig类中声明的Spring Bean对象。* <p>负责将实体对象转换为json格式的字符串</p>*/@Autowiredprivate Converter<List<GatewayFlowRuleEntity>, String> converter;@Overridepublic void publish(String app, List<GatewayFlowRuleEntity> rules) throws Exception {AssertUtil.notEmpty(app, "app name cannot be empty");if (rules == null) {return;}/** 将规则发布到动态数据源作持久化,第一个参数是app+后缀,此处用的是-flow-rules的后缀;* 第二个参数是nacos分组id,这个用默认提供的sentinel预留项即可;最后一个参数是数据转换* 器,要将对象转换成统一的格式后,网络传输到nacos。*/configService.publishConfig(app + NacosConfigUtil.FLOW_DATA_ID_POSTFIX,NacosConfigUtil.GROUP_ID, converter.convert(rules));}
}

5.2.2. 添加Converter

添加一个Converter<List< GatewayFlowRuleEntity>, String>类型的转换器,可以直接在前面拷贝的NacosConfig中添加:

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

5.2.3. GatewayFlowRuleControllerV2

  1. 新增一个GatewayFlowRuleControllerV2,内容可以直接拷贝GatewayFlowRuleController

  2. 将原来的接口地址改一下:/gateway/flow -> /v2/gateway/flow

  3. 去掉原来的sentinelApiClient

    @Autowired
    private SentinelApiClient sentinelApiClient;
    
  4. 加入Provider和Publisher

    @Autowired
    @Qualifier("gatewayFlowRuleNacosProvider")
    private DynamicRuleProvider<List<GatewayFlowRuleEntity>> ruleProvider;
    @Autowired
    @Qualifier("gatewayFlowRuleNacosPublisher")
    private DynamicRulePublisher<List<GatewayFlowRuleEntity>> rulePublisher;
    
  5. 修改publishRules()方法

    private boolean publishRules(String app, String ip, Integer port) {List<GatewayFlowRuleEntity> rules = repository.findAllByMachine(MachineInfo.of(app, ip, port));return sentinelApiClient.modifyGatewayFlowRules(app, ip, port, rules);
    }
    // 改为/*** <h3>发布规则统一逻辑</h3>** <p>规则都是存在本地内存中的,先从内存中获取所有当前要发布规则应用的规则,是一个List</p>* <p>将全量的规则以一定的格式发布到数据源中,进行统一更新</p>** @param app 应用名称* @param ip 应用IP* @param port 应用端口* @throws Exception 远程发布,会发生异常,要进行异常处理*/private void publishRules(String app, String ip, Integer port) throws Exception {List<GatewayFlowRuleEntity> rules = repository.findAllByMachine(MachineInfo.of(app, ip, port));rulePublisher.publish(app, rules);}
    
  6. 修改controller中的逻辑,主要针对读取规则和保存规则两块:

    • queryFlowRules

      List<GatewayFlowRuleEntity> rules = sentinelApiClient.fetchGatewayFlowRules(app, ip, port).get();
      // 改为
      List<GatewayFlowRuleEntity> rules = ruleProvider.getRules(app);
      
    • addFlowRule

      try {entity = repository.save(entity);
      } catch (Throwable throwable) {logger.error("add gateway flow rule error:", throwable);return Result.ofThrowable(-1, throwable);
      }if (!publishRules(app, ip, port)) {logger.warn("publish gateway flow rules fail after add");
      }
      // 改为
      try {entity = repository.save(entity);publishRules(entity.getApp(), entity.getIp(), entity.getPort());
      } catch (Throwable throwable) {logger.error("add gateway flow rule error:", throwable);return Result.ofThrowable(-1, throwable);
      }
      
    • updateFlowRule(与addFlowRule类似)

    • deleteFlowRule(与addFlowRule类似)

5.2.4. 前端改造

  1. app.js中定义新的gateway state

    // 新增的state.state('dashboard.gatewayFlowV2', {templateUrl: 'app/views/gateway/flow_v2.html',url: '/gateway/flow/:app',controller: 'GatewayFlowCtlV2',resolve: {loadMyFiles: ['$ocLazyLoad', function ($ocLazyLoad) {return $ocLazyLoad.load({name: 'sentinelDashboardApp',files: ['app/scripts/controllers/gateway/flow_v2.js',]});}]}})// 这是原来的,在最底部.state('dashboard.gatewayFlow', {templateUrl: 'app/views/gateway/flow.html',url: '/gateway/flow/:app',controller: 'GatewayFlowCtl',resolve: {loadMyFiles: ['$ocLazyLoad', function ($ocLazyLoad) {return $ocLazyLoad.load({name: 'sentinelDashboardApp',files: ['app/scripts/controllers/gateway/flow.js',]});}]}});
    
  2. 改造sidebar.html,添加新导航到新的controller,旧的注释掉

    <li ui-sref-active="active" ng-if="entry.isGateway"><a ui-sref="dashboard.gatewayFlowV2({app: entry.app})"><i class="glyphicon glyphicon-filter"></i>&nbsp;&nbsp;网关流控规则</a>
    </li>
    
  3. 新增一个网关流控页面,views/gateway/flow_v2.html

  4. 拷贝controllers/gateway/flow.js -> controllers/gateway/flow_v2.js,只改带V2的地方即可

    app.controller('GatewayFlowCtlV2', ['$scope', '$stateParams', 'GatewayFlowServiceV2', 'GatewayApiService', 'ngDialog', 'MachineService',function ($scope, $stateParams, GatewayFlowServiceV2, GatewayApiService, ngDialog, MachineService) {
  5. 拷贝services/gateway/flow_service_v1.js -> services/gateway/flow_service_v2.js

    app.service('FlowServiceV2', ['$http', function ($http) {

    FlowService改为 FlowServiceV2,然后把所有的请求路径加上 /v2 前缀

  6. gulpfile.js中添加FlowServiceV2的定义:

    const JS_APP = [……,'app/scripts/services/gateway/flow_service_v2.js',
    ]
    
  7. 执行npm run build,清空浏览器缓存后测试即可。

SentinelDashboard-Nacos动态数据源-SpringCloudGateway相关推荐

  1. nacos windows部署_Sentinel-Go 集成 Nacos 实现外部动态数据源

    导读:2020年,Sentinel 推出 Go 原生版本Sentinel-Golang,在云原生领域继续突破.本文将从实际出发 结合案例说明 在Sentinel-Golang中如何集成Nacos,使其 ...

  2. Sentinel-Go 集成 Nacos 实现外部动态数据源

    **导读:**2020年,Sentinel 推出 Go 原生版本Sentinel-Golang,在云原生领域继续突破.本文将从实际出发 结合案例说明 在Sentinel-Golang中如何集成Naco ...

  3. nacos动态配置数据源_Jasper 怎么配置动态数据源

    Jasper 本身是不支持动态数据源的,能用的解决方式是通过 api 自定义数据源,实际操作就是根据条件判断后动态设定 jdbc 的 url.用户名及密码等连接属性.比如: String userNa ...

  4. synamic-datasource-spring-boot-starter实现动态数据源Mysql和Sqlserver

    场景 若依前后端分离版本地搭建开发环境并运行项目的教程: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/108465662 若依微 ...

  5. sentinel 1.8. 2持久化Nacos动态规则热点规则和授权规则不生效的问题

    sentinel 1.8.2 持久化Nacos动态规则热点规则和授权规则不生效的问题 问题:规则持久化到nacos之后,我在本地测试时候只有热点和授权规则不生效,我慢慢的在客户端sentinel-cs ...

  6. Spring 下,关于动态数据源的事务问题的探讨

    点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! 作者:青石路 cnblogs.com/youzhibing ...

  7. Spring Boot 动态数据源(多数据源自己主动切换)

    本文实现案例场景: 某系统除了须要从自己的主要数据库上读取和管理数据外.另一部分业务涉及到其它多个数据库,要求能够在不论什么方法上能够灵活指定详细要操作的数据库. 为了在开发中以最简单的方法使用,本文 ...

  8. SpringBoot+Mybatis 实现动态数据源切换方案

    背景 最近让我做一个大数据的系统,分析了一下,麻烦的地方就是多数据源切换抽取数据.考虑到可以跨服务器跨数据库抽数,再整理数据,就配置了这个动态数据源的解决方案.在此分享给大家. 实现方案 数据库配置文 ...

  9. Echarts图表在VUE项目中使用动态数据源

    动态数据源问题:目前我使用的方法是当后台查询到数据时,直接传递给option中的对应data内: 例如柱状图,可以直接将x轴数据注入到 this.option.xAxis.data 中,如 this. ...

最新文章

  1. Nature:揭示大脑中的免疫记忆
  2. opengl代码实例_OpenGL-打开一个窗口
  3. 【PAT甲级 U形打印】1031 Hello World for U (20 分) Java版 6/6通过
  4. 通过界面生成时不存在的数据刷新界面引起的卡顿问题
  5. cos大乱斗服务器维护,《COS大乱斗》服务器数据互通公告
  6. 加载本地json文件,并利用批处理调用Chrome显示html
  7. 基于canvas的视频遮罩插件
  8. mysql数据库enum部分乱码_要慎用mysql的enum字段的原因
  9. 关于Spring注入方式的几道面试题,你能答上么?
  10. MySQL技术内幕 InnoDB存储引擎【二】后台线程
  11. 那些精贵的3D视觉系统学习资源总结(附书籍、网址与视频教程)
  12. python逐行写入txt文件_Python中将变量按行写入txt文本中的方法
  13. hadoop、spark、hive、solr、es与YDB在车辆即席分析上的对比分析
  14. Xshell上传文件方法
  15. (纪中)2223. 母鸡下蛋(hen)
  16. 华为HCNA笔记-TO-BE-CONTINUED
  17. CI/CD流水线技术方案
  18. js 数字转为千分符格式
  19. mysql大批量数据插入技巧
  20. 微信小程序初体验-苏州实时公交API

热门文章

  1. 什么是均方误差损失函数
  2. 【微信小程序控制硬件16 】 安信可 ESP32-S 开发板实现移植腾讯物联开发平台蓝牙 llsync 协议,实现一键蓝牙快速配网+远程控制。(附带源码)
  3. c语言构成数组的各个元素,c语言习题六(数组部分)习题及答案.doc
  4. java包装类和基本类型_你知道Java中基本类型和包装类的区别吗
  5. 计算机考研和法学考研哪个容易,法学考研科目这几件事你必须知道
  6. ocsp协议_什么是在线证书状态协议(OCSP)和示例教程?
  7. Unity文字转语音
  8. 分别是什么意思_注塑机的螺杆参数分别是什么意思?
  9. oracle正则身份证,oracle正则表达式
  10. 这样使用Node.js压缩PNG图片,效果高达75%