sentinel-1.8.7与nacos-2.3.0实现动态规则配置、双向同步

news2024/12/23 18:50:40
😊 @ 作者: 一恍过去
💖 @ 主页: https://blog.csdn.net/zhuocailing3390
🎊 @ 社区: Java技术栈交流
🎉 @ 主题: sentinel-1.8.7与nacos-2.3.0实现动态规则配置、双向同步
⏱️ @ 创作时间: 2024年04月2日

目录

  • 1、为什么整合Nacos
  • 2、源码拉取
  • 3、创建公共配置
  • 4、控制台规则配置
    • 4.1、流控规则
    • 4.2、熔断降级规则
    • 4.3、热点规则
    • 4.4、系统规则
    • 4.5、授权规则
  • 5、网关控制台规则配置
    • 5.1、API管理
    • 5.2、流程规则
    • 5.3、降级规则
    • 5.4、系统规则
  • 6、效果测试
  • 7、整合Cloud使用
  • 8、打包部署
  • 9、源码包下载

1、为什么整合Nacos

默认情况下Sentinel配置的规则是储存的内存中,在重新Sentinel服务后,配置会显示,我们通过整合第三方中间件实现,配置的持久化,比如使用Nacos

我们要实现SentinelNacos的双向同步持久化,就需要对sentinel-dashboard的源码包进行修改。

2、源码拉取

1、下载源码压缩包
在Sentinel-github下载需要版本的压缩包,比如Sentinel-1.8.7.zip,或者直接从Git上将代码Clone

2、加载源码
将下载好的Sentinel-1.8.7.zip解压,使用IDE工具,打开sentinel-dashboard工程,或者直接从Git上将代码Clone
在这里插入图片描述

3、创建公共配置

在进行规则代码修改之前需要创建Nacos配置文件,在com.alibaba.csp.sentinel.dashboard.rule包下创建nacos包,并且在包下创建四个类:RuleNacosConfigRuleNacosProviderRuleNacosPublisherNacosConfigUtil
在这里插入图片描述

RuleNacosConfig:

package com.alibaba.csp.sentinel.dashboard.rule.nacos;

import com.alibaba.nacos.api.PropertyKeyConst;
import com.alibaba.nacos.api.config.ConfigFactory;
import com.alibaba.nacos.api.config.ConfigService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Properties;


@Configuration
public class NacosConfig {

    @Bean
    public ConfigService nacosConfigService() throws Exception {
        Properties properties = new Properties();
        properties.put(PropertyKeyConst.SERVER_ADDR, "localhost:8848");
        // properties.put(PropertyKeyConst.NAMESPACE, "xxx");
        properties.put(PropertyKeyConst.USERNAME, "nacos");
        properties.put(PropertyKeyConst.PASSWORD, "nacos");
        return ConfigFactory.createConfigService(properties);
    }
}

RuleNacosProvider:

package com.alibaba.csp.sentinel.dashboard.rule.nacos;

import com.alibaba.nacos.api.config.ConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class RuleNacosProvider {

    @Autowired
    private ConfigService configService;

    public String getRules(String dataId) throws Exception {

        // 将服务名称设置为GroupId
        return configService.getConfig(dataId, NacosConfigUtil.GROUP_ID, 3000);
    }
}

RuleNacosPublisher:

package com.alibaba.csp.sentinel.dashboard.rule.nacos;

import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.exception.NacosException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class RuleNacosPublisher {

    @Autowired
    private ConfigService configService;

    public void publish(String dataId, String rules) {
        try {
            if (rules == null) {
                return;
            }
            configService.publishConfig(dataId, NacosConfigUtil.GROUP_ID, rules);
        } catch (NacosException e) {
            throw new RuntimeException(e);
        }
    }
}

NacosConfigUtil:

package com.alibaba.csp.sentinel.dashboard.rule.nacos;

/**
 * @author Eric Zhao
 * @since 1.4.0
 */
public final class NacosConfigUtil {

    public static final String GROUP_ID = "SENTINEL_GROUP";

    public static final String FLOW_DATA_ID_POSTFIX = "-flow-rules";

    public static final String GATEWAY_FLOW_DATA_ID_POSTFIX = "-gateway-rules";

    public static final String AUTHORITY_FLOW_DATA_ID_POSTFIX = "-authority-rules";

    public static final String SYSTEM_FLOW_DATA_ID_POSTFIX = "-system-rules";

    public static final String DEGRADE_FLOW_DATA_ID_POSTFIX = "-degrade-rules";

    public static final String PARAM_FLOW_DATA_ID_POSTFIX = "-param-rules";

    public static final String CLUSTER_MAP_DATA_ID_POSTFIX = "-cluster-map";

    /**
     * cc for `cluster-client`
     */
    public static final String CLIENT_CONFIG_DATA_ID_POSTFIX = "-cc-config";
    /**
     * cs for `cluster-server`
     */
    public static final String SERVER_TRANSPORT_CONFIG_DATA_ID_POSTFIX = "-cs-transport-config";
    public static final String SERVER_FLOW_CONFIG_DATA_ID_POSTFIX = "-cs-flow-config";
    public static final String SERVER_NAMESPACE_SET_DATA_ID_POSTFIX = "-cs-namespace-set";

    private NacosConfigUtil() {
    }
}

4、控制台规则配置

通过修改源码,实现流控规则、降级规则、热点规则、系统规则、授权规则的持久化操作;

4.1、流控规则

修改FlowControllerV1:
RuleNacosPublisherRuleNacosProvider注入到FlowControllerV1

// 加入以下代码:
@Autowired
private RuleNacosProvider ruleProvider;
@Autowired
private RuleNacosPublisher rulePublisher;

修改读取逻辑:

// 修改位置如下:
List<FlowRuleEntity> rules = sentinelApiClient.fetchFlowRuleOfMachine(app, ip, port);

// 将上面代码修改为以下代码:
String ruleStr = ruleProvider.getRules(app + NacosConfigUtil.FLOW_DATA_ID_POSTFIX);
List<FlowRuleEntity> rules = new ArrayList<>();
if (ruleStr != null) {
     rules = JSON.parseArray(ruleStr, FlowRuleEntity.class);
     if (rules != null && !rules.isEmpty()) {
         for (FlowRuleEntity entity : rules) {
              entity.setApp(app);
         }
    }
}

修改推送逻辑:

// 1、修改位置如下:
private CompletableFuture<Void> publishRules(String app, String ip, Integer port) {
     List<FlowRuleEntity> rules = repository.findAllByMachine(MachineInfo.of(app, ip, port));
     return sentinelApiClient.setFlowRuleOfMachineAsync(app, ip, port, rules);
}

// 将上面代码修改为以下代码:
private void publishRules(String app) {
   List<FlowRuleEntity> rules = repository.findAllByApp(app);
   String ruleStr = JSON.toJSONString(rules);
   rulePublisher.publish(app + NacosConfigUtil.FLOW_DATA_ID_POSTFIX, ruleStr);
}
=======================================================================================

// 2、修改位置如下:有两处
publishRules(entity.getApp(), entity.getIp(), entity.getPort()).get(5000, TimeUnit.MILLISECONDS);

// 将上面代码修改为以下代码:
publishRules(entity.getApp());
=======================================================================================

// 3、修改位置如下:
publishRules(oldEntity.getApp(), oldEntity.getIp(), oldEntity.getPort()).get(5000, TimeUnit.MILLISECONDS);

// 将上面代码修改为以下代码:
publishRules(oldEntity.getApp());

4.2、熔断降级规则

修改DegradeController:
RuleNacosProviderRuleNacosPublisher注入到DegradeController

// 加入以下代码:
@Autowired
private RuleNacosProvider ruleProvider;
@Autowired
private RuleNacosPublisher rulePublisher;

修改读取逻辑:

// 修改位置如下:
List<DegradeRuleEntity> rules = sentinelApiClient.fetchDegradeRuleOfMachine(app, ip, port);

// 将上面代码修改为以下代码:
String ruleStr = ruleProvider.getRules(app + NacosConfigUtil.DEGRADE_FLOW_DATA_ID_POSTFIX);
List<DegradeRuleEntity> rules = new ArrayList<>();
if (ruleStr != null) {
    rules = JSON.parseArray(ruleStr, DegradeRuleEntity.class);
    if (rules != null && !rules.isEmpty()) {
        for (DegradeRuleEntity entity : rules) {
            entity.setApp(app);
       }
    }
}
rules = repository.saveAll(rules);
return Result.ofSuccess(rules);

修改推送逻辑:

// 1、修改位置如下:
private boolean publishRules(String app, String ip, Integer port) {
   List<DegradeRuleEntity> rules = repository.findAllByMachine(MachineInfo.of(app, ip, port));
   return sentinelApiClient.setDegradeRuleOfMachine(app, ip, port, rules);
}

// 将上面代码修改为以下代码:
private boolean publishRules(String app) {
   List<DegradeRuleEntity> rules = repository.findAllByApp(app);
   String ruleStr = JSON.toJSONString(rules);
   rulePublisher.publish(app + NacosConfigUtil.DEGRADE_FLOW_DATA_ID_POSTFIX, ruleStr);
   return true;
}
=======================================================================================

// 2、修改位置如下:有两处
if (!publishRules(entity.getApp(), entity.getIp(), entity.getPort())) {
     logger.warn("Publish degrade rules failed, app={}", entity.getApp());
}

// 将上面代码修改为以下代码:
if (!publishRules(entity.getApp())){
     logger.warn("Publish degrade rules failed, app={}", entity.getApp());
}
=======================================================================================

// 3、修改位置如下:
if (!publishRules(oldEntity.getApp(), oldEntity.getIp(), oldEntity.getPort())) {
   logger.warn("Publish degrade rules failed, app={}", oldEntity.getApp());
}

// 将上面代码修改为以下代码:
if (!publishRules(oldEntity.getApp())){
     logger.warn("Publish degrade rules failed, app={}", entity.getApp());
}

4.3、热点规则

修改ParamFlowRuleController:
RuleNacosProviderRuleNacosPublisher注入到ParamFlowRuleController

// 加入以下代码:
@Autowired
private RuleNacosProvider ruleProvider;
@Autowired
private RuleNacosPublisher rulePublisher;

修改读取逻辑:

// 修改位置如下:
return sentinelApiClient.fetchParamFlowRulesOfMachine(app, ip, port)
                .thenApply(repository::saveAll)
                .thenApply(Result::ofSuccess)
                .get();

// 将上面代码修改为以下代码:
String ruleStr = ruleProvider.getRules(app + NacosConfigUtil.PARAM_FLOW_DATA_ID_POSTFIX);
List<ParamFlowRuleEntity> rules = new ArrayList<>();
if (ruleStr != null) {
    rules = JSON.parseArray(ruleStr, ParamFlowRuleEntity.class);
    if (rules != null && !rules.isEmpty()) {
        for (ParamFlowRuleEntity entity : rules) {
           entity.setApp(app);
   		}
    }
}
rules = repository.saveAll(rules);
return Result.ofSuccess(rules);

修改推送逻辑:

// 1、修改位置如下:
private CompletableFuture<Void> publishRules(String app, String ip, Integer port) {
    List<ParamFlowRuleEntity> rules = repository.findAllByMachine(MachineInfo.of(app, ip, port));
    return sentinelApiClient.setParamFlowRuleOfMachine(app, ip, port, rules);
}

// 将上面代码修改为以下代码:
private void publishRules(String app) {
   try {
       List<ParamFlowRuleEntity> rules = repository.findAllByApp(app);
       String ruleStr = JSON.toJSONString(rules);
       rulePublisher.publish(app + NacosConfigUtil.PARAM_FLOW_DATA_ID_POSTFIX, ruleStr);
   } catch (Exception e) {
     e.printStackTrace();
   }
}
=======================================================================================

// 2、修改位置如下:有两处
try {
   entity = repository.save(entity);
   publishRules(entity.getApp(), entity.getIp(), entity.getPort()).get();
   return Result.ofSuccess(entity);
} catch (ExecutionException ex) {
	....
}
// 将上面代码修改为以下代码:
try {
   entity = repository.save(entity);
   publishRules(entity.getApp());
   return Result.ofSuccess(entity);
} catch (Exception ex) {
	....
}
=======================================================================================

// 3、修改位置如下:
try {
 	repository.delete(id);
    publishRules(oldEntity.getApp(), oldEntity.getIp(), oldEntity.getPort()).get();
    return Result.ofSuccess(id);
} catch (ExecutionException ex) {
	....
}

// 将上面代码修改为以下代码:
try {
 	repository.delete(id);
    publishRules(oldEntity.getApp());
    return Result.ofSuccess(id);
} catch (Exception ex) {
	....
}

4.4、系统规则

修改SystemController:
RuleNacosProviderRuleNacosPublisher注入到SystemController

// 加入以下代码:
@Autowired
private RuleNacosProvider ruleProvider;
@Autowired
private RuleNacosPublisher rulePublisher;

修改读取逻辑:

// 修改位置如下:
List<SystemRuleEntity> rules = sentinelApiClient.fetchSystemRuleOfMachine(app, ip, port);

// 将上面代码修改为以下代码:
String ruleStr = ruleProvider.getRules(app + NacosConfigUtil.SYSTEM_FLOW_DATA_ID_POSTFIX);
List<SystemRuleEntity> rules = new ArrayList<>();
if (ruleStr != null) {
    rules = JSON.parseArray(ruleStr, SystemRuleEntity.class);
    if (rules != null && !rules.isEmpty()) {
        for (SystemRuleEntity entity : rules) {
             entity.setApp(app);
        }
    }
}

修改推送逻辑:

// 1、修改位置如下:
private boolean publishRules(String app, String ip, Integer port) {
   List<SystemRuleEntity> rules = repository.findAllByMachine(MachineInfo.of(app, ip, port));
   return sentinelApiClient.setSystemRuleOfMachine(app, ip, port, rules);
}

// 将上面代码修改为以下代码:
private boolean publishRules(String app) {
    List<SystemRuleEntity> rules = repository.findAllByApp(app);
    String ruleStr = JSON.toJSONString(rules);
    rulePublisher.publish(app + NacosConfigUtil.SYSTEM_FLOW_DATA_ID_POSTFIX, ruleStr);
    return true;
}
=======================================================================================

// 2、修改位置如下
if (!publishRules(app, ip, port)) {
    logger.warn("Publish system rules fail after rule add");
}

// 将上面代码修改为以下代码:
if (!publishRules(entity.getApp())) {
    logger.warn("Publish system rules fail after rule add");
}
=======================================================================================

// 3、修改位置如下
if (!publishRules(entity.getApp(), entity.getIp(), entity.getPort())) {
    logger.info("publish system rules fail after rule update");
}

// 将上面代码修改为以下代码:
if (!publishRules(entity.getApp())) {
    logger.warn("Publish system rules fail after rule add");
}
=======================================================================================

// 4、修改位置如下:
if (!publishRules(oldEntity.getApp(), oldEntity.getIp(), oldEntity.getPort())) {
    logger.info("publish system rules fail after rule delete");
}

// 将上面代码修改为以下代码:
if (!publishRules(oldEntity.getApp())) {
    logger.info("publish system rules fail after rule delete");
}

4.5、授权规则

修改AuthorityRuleController:
RuleNacosPublisherRuleNacosProvider注入到AuthorityRuleController

// 加入以下代码:
@Autowired
private RuleNacosProvider ruleProvider;
@Autowired
private RuleNacosPublisher rulePublisher;

修改读取逻辑:

// 修改位置如下:
List<AuthorityRuleEntity> rules = sentinelApiClient.fetchAuthorityRulesOfMachine(app, ip, port);

// 将上面代码修改为以下代码:
String ruleStr = ruleProvider.getRules(app + NacosConfigUtil.SYSTEM_FLOW_DATA_ID_POSTFIX);
List<AuthorityRuleEntity> rules = new ArrayList<>();
if (ruleStr != null) {
     rules = JSON.parseArray(ruleStr, AuthorityRuleEntity.class);
     if (rules != null && !rules.isEmpty()) {
         for (AuthorityRuleEntity entity : rules) {
              entity.setApp(app);
         }
    }
}

修改推送逻辑:

// 1、修改位置如下:
private boolean publishRules(String app, String ip, Integer port) {
    List<AuthorityRuleEntity> rules = repository.findAllByMachine(MachineInfo.of(app, ip, port));
    return sentinelApiClient.setAuthorityRuleOfMachine(app, ip, port, rules);
}

// 将上面代码修改为以下代码:
private boolean publishRules(String app) {
   List<AuthorityRuleEntity> rules = repository.findAllByApp(app);
   String ruleStr = JSON.toJSONString(rules);
   rulePublisher.publish(app + NacosConfigUtil.AUTHORITY_FLOW_DATA_ID_POSTFIX, ruleStr);
   return true;
}
=======================================================================================

// 2、修改位置如下:有两处
if (!publishRules(entity.getApp(), entity.getIp(), entity.getPort())) {
    logger.info("Publish authority rules failed after rule update");
}

// 将上面代码修改为以下代码:
if (!publishRules(entity.getApp())) {
    logger.info("Publish authority rules failed after rule update");
}
=======================================================================================

// 3、修改位置如下:
if (!publishRules(oldEntity.getApp(), oldEntity.getIp(), oldEntity.getPort())) {
   logger.error("Publish authority rules failed after rule delete");
}

// 将上面代码修改为以下代码:
if (!publishRules(oldEntity.getApp())) {
   logger.error("Publish authority rules failed after rule delete");
}

5、网关控制台规则配置

配置网关控制台规则,在启动网关时需要加上参数:-Dcsp.sentinel.app.type=1

本次源码修改中暂时没有做处理,如果需要可以参照下面的代码示例。

5.1、API管理

修改GatewayApiController:
RuleNacosPublisherRuleNacosProvider注入到GatewayApiController

// 加入以下代码:
@Autowired
private RuleNacosProvider ruleProvider;
@Autowired
private RuleNacosPublisher rulePublisher;

修改读取逻辑:

// 修改位置如下:
List<ApiDefinitionEntity> apis = sentinelApiClient.fetchApis(app, ip, port).get();

// 将上面代码修改为以下代码:
String ruleStr = ruleProvider.getRules(app + NacosConfigUtil.GATEWAY_FLOW_DATA_ID_POSTFIX);
List<ApiDefinitionEntity> apis = new ArrayList<>();
if (ruleStr != null) {
    apis = JSON.parseArray(ruleStr, ApiDefinitionEntity.class);
    if (apis != null && !apis.isEmpty()) {
        for (ApiDefinitionEntity entity : apis) {
             entity.setApp(app);
        }
    }
}
  

修改推送逻辑:

// 1、修改位置如下:
private boolean publishApis(String app, String ip, Integer port) {
   List<ApiDefinitionEntity> apis = repository.findAllByMachine(MachineInfo.of(app, ip, port));
   return sentinelApiClient.modifyApis(app, ip, port, apis);
}

// 将上面代码修改为以下代码:
private boolean publishApi(String app) {

List<ApiDefinitionEntity> apis= repository.findAllByApp(app);
String ruleStr = JSON.toJSONString(apis);
rulePublisher.publish(app + NacosConfigUtil.GATEWAY_FLOW_DATA_ID_POSTFIX, ruleStr);
return true;
}
=======================================================================================

// 2、修改位置如下
if (!publishApis(app, ip, port)) {
     logger.warn("publish gateway apis fail after add");
}

// 将上面代码修改为以下代码:
if (!publishApis(entity.getApp())) {
     logger.warn("publish gateway apis fail after add");
}
=======================================================================================

// 3、修改位置如下
if (!publishApis(app, entity.getIp(), entity.getPort())) {
    logger.warn("publish gateway apis fail after update");
}

// 将上面代码修改为以下代码:
if (!publishApis(entity.getApp())
=======================================================================================

// 4、修改位置如下:
if (!publishApis(oldEntity.getApp(), oldEntity.getIp(), oldEntity.getPort())) {
    logger.warn("publish gateway apis fail after delete");
}

// 将上面代码修改为以下代码:
if (!publishApis(oldEntity.getApp())) {
    logger.warn("publish gateway apis fail after delete");
}

5.2、流程规则

使用的是控制台规则配置中的流控规则接口,无需在做操作,参考《4.1、流控规则》。

5.3、降级规则

使用的是控制台规则配置中的降级规则接口,无需在做操作,参考《4.2、降级规则》。

5.4、系统规则

使用的是控制台规则配置中的系统规则接口,无需在做操作,参考《4.4、系统规则》。

6、效果测试

我们以流控规则为例,演示一个数据同步持久化的操作;

1、nacos同步到sentinel:

需要注意的是,nacos中的分组必须为SENTINEL_GROUP

在nacos中,新增配置文件,文件的DataId为user-service-flow-rules,内容为:

[
    {
    	"app":"user-service",// 服务名称
        "resource": "/list", //资源名称
        "count": 1, //阀值
        "grade": 1, //阀值类型,0表示线程数,1表示QPS;
        "limitApp": "default", //来源应用	
        "strategy": 0,// 流控模式,0表示直接,1表示关联,2表示链路;
        "controlBehavior": 0 //流控效果,0表示快速失败,1表示Warm Up,2表示排队等待
    }
]

在这里插入图片描述

查看Sentinel控制台:数据已经实现了同步
在这里插入图片描述

2、sentinel同步到nacos:

我们在sentinel控制台,建立任意流控规则,如下:
在这里插入图片描述

查看Nacos控制台:配置数据已经实现了同步
在这里插入图片描述

7、整合Cloud使用

整合cloud使用时,需要调整配置文件,以流控规则热点规则为例,其他的规则可以参考着进行配置,配置中的rule-typegroupIddataId需要写对(与nacos匹配)

spring:
  cloud:
    sentinel:
      transport:
        port: 9999 #跟控制台交流的端口,随意指定一个未使用的端口即可
        dashboard: 127.0.0.1:8080 # 指定控制台服务的地址
      #添加Nacos数据源配置
      datasource:
        #名字自定义即可,配置流控规则
        sentinel-flow:
          nacos:
            server-addr: 127.0.0.1:8848
            username: nacos
            password: nacos
            rule-type: flow
            groupId: SENTINEL_GROUP
            #namespace: public
            dataId: user-service-flow-rules
        #名字自定义即可,配置热点规则
        sentinel-param:
          nacos:
            server-addr: 127.0.0.1:8848
            username: nacos
            password: nacos
            rule-type: param-flow
            groupId: SENTINEL_GROUP
            #namespace: public
            dataId: user-service-param-rules

8、打包部署

进入到sentinel-dashboard所在目的,通过mvn clean install package -DskipTests=true进行打包。

部署jar参考:
《Linux搭建Sentinel 控制台环境》
《Docker搭建Sentinel 控制台环境》

9、源码包下载

对于上述修改的代码,源码下载地址:
https://gitee.com/lhzlx/sentinel-nacos.git

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1622307.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2024年大数据应用、智能控制与软件工程国际会议(BDAICSE2024)

2024年大数据应用、智能控制与软件工程国际会议(BDAICSE2024) 会议简介 我们诚挚邀请您参加2024年大数据应用、智能控制和软件工程国际会议&#xff08;BDAICSE2024&#xff09;。这次会议将在美丽的长沙市举行。 本次大会旨在汇聚全球大数据应用、智能控制、软件工程等领…

常见大厂面试题(SQL)02

小鹏面试题: 小鹏汽车充电每辆车连续快充最大次数 原表charging_data idcharge_timecharge_typeXP10012023/11/20 8:45快充XP10012023/11/21 20:45快充XP10012023/11/22 8:45快充XP10012023/11/23 8:45慢充XP10012023/11/25 8:45快充XP10022023/11/25 8:45快充XP10022023/11/…

kubernetes中Pod资源的使用限制

一、概述 当kubernetes调度创建Pod后&#xff0c;Pod是否有足够的资源来运行容器&#xff0c;是非常重要的。资源分为两种类型——容器请求的资源和容器被限制的资源。 请求和限制是kubernetes控制集群cpu和内存等资源的重要方式&#xff0c;他们是两种不同的机制 容器请求的资…

C语言之回调函数+可变参数__VA_ARGS__:用法实例(四十八)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…

GaussDB数据库SQL系列-聚合函数

背景 在这篇文章中&#xff0c;我们将深入探讨GaussDB数据库中聚合函数的使用和优化。聚合函数是数据库查询中非常重要的工具&#xff0c;它们可以对一组值执行计算并返回单个值。例如&#xff0c;聚合函数可以用来计算平均值、总和、最大值和最小值。 这些功能在数据分析和报…

C语言 | Leetcode C语言题解之第48题旋转图像

题目&#xff1a; 题解&#xff1a; void swap(int* a, int* b) {int t *a;*a *b, *b t; }void rotate(int** matrix, int matrixSize, int* matrixColSize) {// 水平翻转for (int i 0; i < matrixSize / 2; i) {for (int j 0; j < matrixSize; j) {swap(&matr…

Linux_网络基础2_3

文章目录 一、应用层协议1.我写的socket是在干什么&#xff1f;2.再谈"协议"1.问题1 # 2.问题23.造轮子——定制应用协议4.使用json来完成应用协议1.安装库2.使用 —— 序列化3.使用 —— 反序列化 二、HTTP协议1.认识URL2.http协议的请求格式和响应格式3.编写响应 -…

大模型(e.g., ChatGPT)里面的一些技术和发展方向

文章目录 如何炼成ChatGPT如何调教ChatGPT如何武装ChatGPT一些大模型的其他方向prompt tuningInstruction tuning 这个是基于视频 https://www.bilibili.com/video/BV17t4218761&#xff0c;可以了解一下大模型里面的一些技术和最近的发展&#xff0c;基本都是2022你那以来的发…

Spring Boot整合Redisson的两种方式

项目场景 Spring Boot整合Redisson的两种方式&#xff0c;方式一直接使用yml配置&#xff0c;方式二创建RedissonConfig配置类。 前言 redisson和redis区别&#xff1a; Redis是一个开源的内存数据库&#xff0c;支持多种数据类型&#xff0c;如字符串、哈希、列表、集合和有序…

tailwindcss在使用cdn引入静态html的时候,vscode默认不会提示问题

1.首先确保vscode下载tailwind插件&#xff1a;Tailwind CSS IntelliSense 2.需要在根目录文件夹创建一个tailwind.config.js文件 export default {theme: {extend: {// 可根据需要自行配置&#xff0c;空配置项可以正常使用},}, }3.在html文件的标签中引入配置文件&#xf…

基础环境:wsl2安装Ubuntu22.04 + miniconda

服务器相关信息&#xff1a; Thinkpad p1 gen5 64G 2T 3080ti&#xff0c;自带的有nvidia-smi显卡驱动。使用wsl2安装Ubuntu22.04 miniconda目标&#xff1a;安装gpu版本的PyTorch2.1.2&#xff08;torch2.1.2/cu117 torchvision0.16.2/cu117&#xff09; 处理器 12th Gen I…

ADS8866 ADC转换芯片驱动调试

目录 ADS8866 ADC转换芯片驱动调试 开发环境&#xff1a; ADS8866功能简介 硬件连接 SPI3的软件驱动 ADS8866通讯时序分析 ADS8866驱动 ADS8866 ADC转换芯片驱动调试 开发环境&#xff1a; 主控芯片&#xff1a;STM32F103RCT6、ADS8866转换芯片、使用HAL库进行开发。 …

Chitosan-Rhodamine B 罗丹明B标记壳聚糖

Chitosan-Rhodamine B 罗丹明B标记壳聚糖 【中文名称】罗丹明B标记壳聚糖 【英文名称】Chitosan-RB 【结 构】 【品 牌】碳水科技&#xff08;Tanshtech&#xff09; 【纯 度】95%以上 【保 存】-20℃ 【规 格】50mg,100mg,500mg,1g,5g,10g 【产品特性】 Rh…

libVLC 专栏介绍

本专栏主要界面libVLC的使用&#xff0c;详细介绍了相关用法&#xff0c;使用Qt作为显示界面&#xff0c;不仅可以了解Qt的使用&#xff0c;QSS的美化&#xff0c;更能够熟悉libVLC核心接口的使用&#xff0c;最后打造一款属于自己的精美播放器。 每一节都有单独的源码供查看。…

企业微信hook接口协议,ipad协议http,发送小程序

发送小程序 参数名必选类型说明uuid是String每个实例的唯一标识&#xff0c;根据uuid操作具体企业微信send_userid是long要发送的人或群idisRoom是bool是否是群消息 请求示例 {"uuid":"543ed7f3-6ec1-4db8339a140f7","send_userid":788130255…

gps路径压缩算法

公司的gps点位特别多,导致数据存储以及查询都会造成一定的压力. 所以我们需要使用gps路径压缩算法 我调研了两种: k-means 和 Douglas-Peucker k-means 压缩的底层原理是: 自定义簇的数量,假设是100个,那么就会计算所有gps点,把最相近的点,放在一个簇里,以此类推,计算出100个…

你如何看待AIGC技术?

你如何看待AIGC技术&#xff1f; AIGC技术&#xff08;Artificial Intelligence Generated Content&#xff09;是指由人工智能生成的内容。它在许多领域都有应用&#xff0c;包括自然语言处理、图像生成、音频合成等。虽然这些技术可以提高效率和创造力&#xff0c;但也需要注…

机器学习和深度学习-- 李宏毅(笔记与个人理解)Day22

Day 22 Transformer seqence to seqence 有什么用呢&#xff1f; Encoder how Block work 仔细讲讲Residual 的过程&#xff1f; 重构 Decoder - AutoRegressive Mask 由于是文字接龙&#xff0c;所以无法考虑右边的 info 另一种decoder Encoder to Decoder – Cross Attend…

【算法】五子连线

题目描述 五子棋是世界智力运动会竞技项目之一&#xff0c;是一种两人对弈的纯策略型棋类游戏&#xff0c;通常双方分别使用黑白两色的棋子&#xff0c;下在棋盘直线与横线的交叉点上&#xff0c;先形成连续的五子连线&#xff08;横、竖、斜&#xff09;者获胜。 棋盘一般为…

电脑回收站的东西还原后会在哪里?一文给你答案!

“很奇怪&#xff0c;想问问大家&#xff0c;我电脑回收站里还原的文件会被保存在哪里呀&#xff1f;刚刚恢复文件的时候本来想直接将它拖出&#xff0c;却发现文件不见了&#xff0c;这种情况应该怎么解决呢&#xff1f;” 电脑回收站是一个特殊的文件夹&#xff0c;用于临时存…