【sentinel】Sentinel规则的持久化

Sentinel规则的推送有下面三种模式:

推送模式说明优点缺点
原始模式API将规则推送至客户端并直接更新到内存中简单,无任何依赖不保证一致性;规则保存在内存中,重启即消失。严重不建议用于生产环境
Pull模式扩展写数据源(WritableDataSource),客户端主动向某个规则管理中心定期轮询拉取规则,这个规则中心可以是RDBMS、文件等简单,无任何依赖;规则持久化不保证一致性;实时性不保证,拉取过于频繁也可能会有性能问题。
Push模式扩展读数据源(ReadableDataSource),规则中心统一推送,客户端通过注册监听器的方式时刻监听变化,比如使用Nacos、Zookeeper等配置中心。这种方式有更好的实时性和一致性保证。生产环境下一般采用push模式的数据源。规则持久化;一致性;快速引入第三方依赖

原始模式

如果不做任何修改,Dashboard的推送规则方式是通过API将规则推送至客户端并直接更新到内存中:


这种做法的好处是简单,无依赖;坏处是应用重启规则就会消失,仅用于简单测试,不能用于生产环境。

拉模式

pull模式的数据源(如本地文件、RDBMS等)一般是可写入的。使用时需要在客户端注册数据源:将对应的读数据源注册至对应的 RuleManager,将写数据源注册至transport的WritableDataSourceRegistry中。

首先Sentinel控制台通过API将规则推送至客户端并更新到内存中,接着注册的写数据源会将新的规则保存到本地的文件中。使用 pull模式的数据源时一般不需要对Sentinel控制台进行改造。这种实现方法好处是简单,坏处是无法保证监控数据的一致性。

具体使用方式如下:

引入依赖:

<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-datasource-extension</artifactId>
</dependency>

实现InitFunc接口,在init中处理DataSource初始化逻辑,并利用spi机制实现加载。

package com.morris.user.config;

import com.alibaba.csp.sentinel.datasource.FileRefreshableDataSource;
import com.alibaba.csp.sentinel.datasource.FileWritableDataSource;
import com.alibaba.csp.sentinel.datasource.WritableDataSource;
import com.alibaba.csp.sentinel.init.InitFunc;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
import com.alibaba.csp.sentinel.transport.util.WritableDataSourceRegistry;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;

import java.io.File;
import java.io.FileNotFoundException;
import java.util.List;

public class FileDataSourceInit implements InitFunc {

    private static final String RULE_FILE_PATH = System.getProperty("user.home") + File.separator;

    private static final String FLOW_RULE_FILE_NAME = "FlowRule.json";

    @Override
    public void init() throws Exception {

        //处理流控规则逻辑
        dealFlowRules();
    }


    private void dealFlowRules() throws FileNotFoundException {
        String ruleFilePath = RULE_FILE_PATH + FLOW_RULE_FILE_NAME;

        //创建流控规则的可读数据源
        FileRefreshableDataSource flowRuleRDS = new FileRefreshableDataSource(
                ruleFilePath, source -> JSON.parseObject((String) source,
                new TypeReference<List<FlowRule>>() {
                })
        );

        // 将可读数据源注册至FlowRuleManager 这样当规则文件发生变化时,就会更新规则到内存
        FlowRuleManager.register2Property(flowRuleRDS.getProperty());

        WritableDataSource<List<FlowRule>> flowRuleWDS = new FileWritableDataSource<>(
                ruleFilePath, this::encodeJson
        );

        // 将可写数据源注册至 transport 模块的 WritableDataSourceRegistry 中.
        // 这样收到控制台推送的规则时,Sentinel 会先更新到内存,然后将规则写入到文件中.
        WritableDataSourceRegistry.registerFlowDataSource(flowRuleWDS);
    }


    private <T> String encodeJson(T t) {
        return JSON.toJSONString(t);
    }

}

在META-INF/services目录下创建com.alibaba.csp.sentinel.init.InitFunc,内容如下:

com.morris.user.config.FileDataSourceInit

这样当在Dashboard中修改了配置后,Dashboard会调用客户端的接口修改客户端内存中的值,同时将配置写入文件FlowRule.json中,这样操作的话规则是实时生效的,如果是直接修改FlowRule.json的内容,这样需要等定时任务3秒后执行才能读到最新的规则。

推模式

生产环境下一般更常用的是push模式的数据源。对于push模式的数据源,如远程配置中心(ZooKeeper, Nacos, Apollo等等),推送的操作不应由Sentinel客户端进行,而应该经控制台统一进行管理,直接进行推送,数据源仅负责获取配置中心推送的配置并更新到本地。因此推送规则正确做法应该是配置中心控制台/Sentinel控制台 → 配置中心 → Sentinel数据源 → Sentinel,而不是经Sentinel数据源推送至配置中心。这样的流程就非常清晰了:

基于Nacos配置中心控制台实现推送

配置中心控制台 → 配置中心 → Sentinel数据源 → Sentinel

引入依赖:

<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-datasource-nacos</artifactId>
</dependency>

配置文件增加nacos的数据源:

spring:
  application:
    name: user-service
  cloud:
    sentinel:
      transport:
        dashboard: 127.0.0.1:8080
      web-context-unify: false # 默认将调用链路收敛,需要打开才可以进行链路流控
      datasource:
        flow-ds:
          nacos:
            server-addr: 127.0.0.1:8848
            dataId: ${spring.application.name}-flow
            groupId: DEFAULT_GROUP
            data-type: json
            rule-type: flow

最后在Nacos控制台新建一个user-service-flow的json配置,内容如下:

[
  {
    "resource": "/sentinel/chainB",
    "controlBehavior": 0,
    "count": 1,
    "grade": 1,
    "limitApp": "default",
    "strategy": 0
  }
]

这样直接在Nacos控制台修改规则就能实时生效了,缺点是直接在Sentinel Dashboard中修改规则配置,配置中心的配置不会发生变化。

思考:如何实现将通过sentinel控制台设置的规则直接持久化到nacos配置中心?

方法一:微服务增加基于Nacos的写数据源(WritableDataSource),发布配置到nacos配置中心。

//核心逻辑: 实现WritableDataSource#write方法,发布配置到nacos配置中心
@Override
public void write(T t) throws Exception {
    lock.lock();
    try {
        configService.publishConfig(dataId, groupId, this.configEncoder.convert(t), ConfigType.JSON.getType());
    } finally {
        lock.unlock();
    }
}

方法二:Sentinel Dashboard监听Nacos配置的变化,如发生变化就更新本地缓存。在Sentinel Dashboard端新增或修改规则配置在保存到内存的同时,直接发布配置到nacos配置中心;Sentinel Dashboard直接从nacos拉取所有的规则配置。Sentinel Dashboard和微服务不直接通信,而是通过nacos配置中心获取到配置的变更,也就是下面的基于Sentinel控制台实现推送。

AbstractDataSourceProperties

SentinelProperties内部提供了TreeMap类型的datasource属性用于配置数据源信息。

com.alibaba.cloud.sentinel.datasource.config.AbstractDataSourceProperties#postRegister

public void postRegister(AbstractDataSource dataSource) {
    switch (this.getRuleType()) {
    case FLOW:
        FlowRuleManager.register2Property(dataSource.getProperty());
        break;
    case DEGRADE:
        DegradeRuleManager.register2Property(dataSource.getProperty());
        break;
    case PARAM_FLOW:
        ParamFlowRuleManager.register2Property(dataSource.getProperty());
        break;
    case SYSTEM:
        SystemRuleManager.register2Property(dataSource.getProperty());
        break;
    case AUTHORITY:
        AuthorityRuleManager.register2Property(dataSource.getProperty());
        break;
    case GW_FLOW:
        GatewayRuleManager.register2Property(dataSource.getProperty());
        break;
    case GW_API_GROUP:
        GatewayApiDefinitionManager.register2Property(dataSource.getProperty());
        break;
    default:
        break;
    }
}

NacosDataSource从Nacos读取配置

NacosDataSource主要负责与Nacos进行通信,实时获取Nacos的配置。

public NacosDataSource(final Properties properties, final String groupId, final String dataId,
                       Converter<String, T> parser) {
    super(parser);
    if (StringUtil.isBlank(groupId) || StringUtil.isBlank(dataId)) {
        throw new IllegalArgumentException(String.format("Bad argument: groupId=[%s], dataId=[%s]",
            groupId, dataId));
    }
    AssertUtil.notNull(properties, "Nacos properties must not be null, you could put some keys from PropertyKeyConst");
    this.groupId = groupId;
    this.dataId = dataId;
    this.properties = properties;
    this.configListener = new Listener() {
        @Override
        public Executor getExecutor() {
            return pool;
        }

        @Override
        public void receiveConfigInfo(final String configInfo) {
            // 配置发送变更
            RecordLog.info("[NacosDataSource] New property value received for (properties: {}) (dataId: {}, groupId: {}): {}",
                properties, dataId, groupId, configInfo);
            T newValue = NacosDataSource.this.parser.convert(configInfo);
            // Update the new value to the property.
            getProperty().updateValue(newValue);
        }
    };
    // 监听配置
    initNacosListener();
    // 第一次读取配置
    loadInitialConfig();
}

private void loadInitialConfig() {
    try {
        T newValue = loadConfig();
        if (newValue == null) {
            RecordLog.warn("[NacosDataSource] WARN: initial config is null, you may have to check your data source");
        }
        getProperty().updateValue(newValue);
    } catch (Exception ex) {
        RecordLog.warn("[NacosDataSource] Error when loading initial config", ex);
    }
}

private void initNacosListener() {
    try {
        this.configService = NacosFactory.createConfigService(this.properties);
        // Add config listener.
        configService.addListener(dataId, groupId, configListener);
    } catch (Exception e) {
        RecordLog.warn("[NacosDataSource] Error occurred when initializing Nacos data source", e);
        e.printStackTrace();
    }
}

SentinelDataSourceHandler注入NacosDataSource

SentinelAutoConfiguration中注入了SentinelDataSourceHandler。

SentinelDataSourceHandler负责遍历配置文件中配置的DataSource,然后注入到spring容器中。
com.alibaba.cloud.sentinel.custom.SentinelDataSourceHandler#afterSingletonsInstantiated

public void afterSingletonsInstantiated() {
    this.sentinelProperties.getDatasource().forEach((dataSourceName, dataSourceProperties) -> {
        try {
            List<String> validFields = dataSourceProperties.getValidField();
            if (validFields.size() != 1) {
                log.error("[Sentinel Starter] DataSource " + dataSourceName + " multi datasource active and won't loaded: " + dataSourceProperties.getValidField());
                return;
            }

            AbstractDataSourceProperties abstractDataSourceProperties = dataSourceProperties.getValidDataSourceProperties();
            abstractDataSourceProperties.setEnv(this.env);
            abstractDataSourceProperties.preCheck(dataSourceName);
            this.registerBean(abstractDataSourceProperties, dataSourceName + "-sentinel-" + (String)validFields.get(0) + "-datasource");
        } catch (Exception var5) {
            log.error("[Sentinel Starter] DataSource " + dataSourceName + " build error: " + var5.getMessage(), var5);
        }

    });
}

基于Sentinel控制台实现推送

配置中心控制台 → 配置中心 → Sentinel数据源 → Sentinel

从Sentinel1.4.0开始,Sentinel控制台提供DynamicRulePublisher和DynamicRuleProvider接口用于实现应用维度的规则推送和拉取:

  • DynamicRuleProvider: 拉取规则
  • DynamicRulePublisher: 推送规则

可以参考Sentinel Dashboard test包下的流控规则拉取和推送的实现逻辑:

这里主要改造Dashboard端,客户端还是采用前面的配置。

引入nacos的依赖:

<dependency>
    <groupId>com.alibaba.nacos</groupId>
    <artifactId>nacos-client</artifactId>
    <version>1.3.0</version>
</dependency>

NacosConfig负责注入一些最基本的配置:

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

import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.FlowRuleEntity;
import com.alibaba.csp.sentinel.datasource.Converter;
import com.alibaba.fastjson.JSON;
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.List;

@Configuration
public class NacosConfig {

    public static final String GROUP_ID = "DEFAULT_GROUP";

    public static final String FLOW_DATA_ID_POSTFIX = "-flow";

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

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

    @Bean
    public ConfigService nacosConfigService() throws Exception {
        return ConfigFactory.createConfigService("localhost:8848");
    }
}

FlowRuleNacosProvider负责从Nacos读取配置:

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

import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.FlowRuleEntity;
import com.alibaba.csp.sentinel.dashboard.rule.DynamicRuleProvider;
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("flowRuleNacosProvider")
public class FlowRuleNacosProvider implements DynamicRuleProvider<List<FlowRuleEntity>> {

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

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

FlowRuleNacosPublisher负责将配置写入Nacos:

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

import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.FlowRuleEntity;
import com.alibaba.csp.sentinel.dashboard.rule.DynamicRulePublisher;
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;

@Component("flowRuleNacosPublisher")
public class FlowRuleNacosPublisher implements DynamicRulePublisher<List<FlowRuleEntity>> {

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

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

上面都是新增的类,最后还需要在Dashboard查询和修改规则时进行修改,具体修改是在FlowControllerV1

@Autowired
private FlowRuleNacosProvider flowRuleNacosProvider;

@Autowired
private FlowRuleNacosPublisher flowRuleNacosPublisher;

@GetMapping("/rules")
@AuthAction(PrivilegeType.READ_RULE)
public Result<List<FlowRuleEntity>> apiQueryMachineRules(@RequestParam String app,
                                                         @RequestParam String ip,
                                                         @RequestParam Integer port) {
... ...
    try {
        //List<FlowRuleEntity> rules = sentinelApiClient.fetchFlowRuleOfMachine(app, ip, port);
        List<FlowRuleEntity> rules = flowRuleNacosProvider.getRules(app);
        rules = repository.saveAll(rules);
        return Result.ofSuccess(rules);
    } catch (Throwable throwable) {
        logger.error("Error when querying flow rules", throwable);
        return Result.ofThrowable(-1, throwable);
    }
}

@PostMapping("/rule")
@AuthAction(PrivilegeType.WRITE_RULE)
public Result<FlowRuleEntity> apiAddFlowRule(@RequestBody FlowRuleEntity entity) {
    Result<FlowRuleEntity> checkResult = checkEntityInternal(entity);
    if (checkResult != null) {
        return checkResult;
    }
    entity.setId(null);
    Date date = new Date();
    entity.setGmtCreate(date);
    entity.setGmtModified(date);
    entity.setLimitApp(entity.getLimitApp().trim());
    entity.setResource(entity.getResource().trim());
    try {
        entity = repository.save(entity);
        publishRules(entity.getApp());
//            publishRules(entity.getApp(), entity.getIp(), entity.getPort()).get(5000, TimeUnit.MILLISECONDS);
        return Result.ofSuccess(entity);
    } catch (Throwable t) {
        Throwable e = t instanceof ExecutionException ? t.getCause() : t;
        logger.error("Failed to add new flow rule, app={}, ip={}", entity.getApp(), entity.getIp(), e);
        return Result.ofFail(-1, e.getMessage());
    }
}

private void publishRules(/*@NonNull*/ String app) throws Exception {
    List<FlowRuleEntity> rules = repository.findAllByApp(app);
    flowRuleNacosPublisher.publish(app, rules);
}

以流控规则测试,当在sentinel dashboard配置了流控规则,会在nacos配置中心生成对应的配置,这样客户端就能读取到这个流控规则配置了。

user-service-flow.json

[{"app":"user-service","clusterConfig":{"acquireRefuseStrategy":0,"clientOfflineTime":2000,"fallbackToLocalWhenFail":true,"resourceTimeout":2000,"resourceTimeoutStrategy":0,"sampleCount":10,"strategy":0,"thresholdType":0,"windowIntervalMs":1000},"clusterMode":false,"controlBehavior":0,"count":1.0,"gmtCreate":1686709073771,"gmtModified":1686709073771,"grade":1,"id":2,"ip":"127.0.0.1","limitApp":"default","port":8720,"resource":"chain","strategy":0}]

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

初学Nginx要掌握哪些概念

文章目录 为什么要使用Nginx&#xff1f;什么是Nginx&#xff1f;Nginx的作用&#xff1f;反向代理负载均衡动静分离 为什么要使用Nginx&#xff1f; 小公司项目刚刚上线的时候&#xff0c;并发量小&#xff0c;用户使用的少&#xff0c;所以在低并发的情况下&#xff0c;一个…

【链表复习】C++ 链表复习及题目解析 (2)

目录 牛客 CM11 链表分割 牛客 OR36 之链表的回文结构 Leetcode 160. 相交链表 LeetCode 141. 环形链表 LeetCode 138. 复制带随机指针的链表 本文继续延续前文&#xff0c;为大家带来几道经典的链表中等难度的题目。 牛客 CM11 链表分割 现有一链表的头指针 ListNode* p…

GUT|IF30+的联合分析文章:宏基因加代谢组

● 代谢组学是基于LC-MS/MS液质联用技术对生物样本中的小分子代谢物进行定性和相对定量分析&#xff1b; ● 宏基因组-代谢组的联合分析可以用来解释差异菌群与差异代谢物的关联性&#xff1b; ● 从而帮助建立微生物-代谢物-表型之间的逻辑关系。 凌恩生物的宏基因组学引入了…

JDK21要来了,并发编程更加丝滑了

大家好&#xff0c;我是风筝&#xff0c;公众号「古时的风筝」&#xff0c;专注于 Java技术 及周边生态。 我的个人网站&#xff1a;古时的风筝 目前 Java 的最新稳定版是 JDK 20&#xff0c;但这是个过渡版&#xff0c;JDK21就是 LTS 版的了&#xff0c;也快要发布了&#xff…

经典文献阅读之--A Review of Motion Planning(轨迹规划回顾)

0. 简介 对于自动驾驶以及机器人而言&#xff0c;除了SLAM以外&#xff0c;另一个比较重要的部分就是轨迹规划了。而最近作者看到了几篇比较好的文章&#xff0c;分别为《A Review of Motion Planning Techniques for Automated Vehicle》、《A review of motion planning alg…

Python中处理无效数据的详细教程(附案例实战)

&#x1f935;‍♂️ 个人主页&#xff1a;艾派森的个人主页 ✍&#x1f3fb;作者简介&#xff1a;Python学习者 &#x1f40b; 希望大家多多支持&#xff0c;我们一起进步&#xff01;&#x1f604; 如果文章对你有帮助的话&#xff0c; 欢迎评论 &#x1f4ac;点赞&#x1f4…

IDEA全局设置JDK、Maven、编码格式

本机已安装JDK版本&#xff1a; 本机已安装Maven版本&#xff1a; 一、IDEA设置全局JDK设置 File---->New Projects Settings---->Structure for New Projects... 先将本地安装的JDK添加到SDK 将项目SDK设置为刚刚添加的本地JDK版本 File---->New Projects Settings-…

8分钟让你完全掌握代理IP基础知识和实际应用

概念 代理IP可以理解为一个中转服务器&#xff0c;将用户和目标服务器之间的请求和响应进行转发和代理。使用代理IP的主要目的是隐藏用户的真实IP地址、访问被限制的内容、提高网络连接速度和保护用户隐私。 目录 概念 一、代理IP的工作原理 二、代理IP的类型 三、为什么…

Docker安装ClickHouse22.6.9.11并与SpringBoot、MyBatisPlus集成

背景 上一篇文章CentOS6.10上离线安装ClickHouse19.9.5.36并修改默认数据存储目录记录了在旧版的操作系统上直接安装低版本 ClickHouse &#xff08;脱胎于俄罗斯头号搜索引擎的技术&#xff09;的过程&#xff0c;开启远程访问并配置密码&#xff1b; 其实通过 Docker 运行 …

ESXi 7.0 U3m Cisco (思科) 定制版 OEM Custom Installer CD

VMware ESXi 7.0 Update 3m - 领先的裸机 Hypervisor (All OEM Customized Installer CDs) ESXi 7.0 U3m Standard (标准版) ESXi 7.0 U3m Dell (戴尔) 定制版 OEM Custom Installer CD ESXi 7.0 U3m HPE (慧与) 定制版 OEM Custom Installer CD ESXi 7.0 U3m Lenovo (联想) 定…

6个ChatGPT4的最佳用途

文章目录 ChatGPT 4’s Current Limitations ChatGPT 4 的当前限制1. Crafting Complex Prompts 制作复杂的提示2. Logic Problems 逻辑问题3. Verifying GPT 3.5 Text 验证 GPT 3.5 文本4. Complex Coding 复杂编码5.Nuanced Text Transformation 细微的文本转换6. Complex Kn…

提高你的小程序开发技能:五大重要步骤

对于任何开发人员来说&#xff0c;想要创建一个小程序并不是一件容易的事情。你需要为每个功能和应用程序编写代码&#xff0c;并且你需要不断地进行测试以确保它不会出错。 那么&#xff0c;我们该如何提高小程序的开发技能呢&#xff1f;通过下面这五个重要步骤&#xff0c;…

盖茨预言AI助理成标配,AI+RPA打破AI准入高门槛!

根据微软联合创始人比尔盖茨的预测&#xff0c;未来顶级的人工智能公司将会开发一种全新的“个人AI助理”。比尔盖茨表示&#xff0c;“个人AI助理”将会具有出色的功能&#xff0c;可以改变人们的生活方式以及工作方式。无论哪一家公司能够赢得AI助理竞争先机&#xff0c;都会…

ZipList(压缩链表)

基本概述 ZipList 是一种特殊的“双端链表” &#xff0c;由一系列特殊编码的连续内存块组成。可以在任意一端进行压入/弹出操作, 并且该操作的时间复杂度为 O(1)。 基本结构&#xff1a; 各部分所占字节、基本介绍&#xff1a; entry&#xff0c;节点占用字节不固定&#xff0…

Mind2Web: 首个全面衡量大模型上网能力的数据集

夕小瑶科技说 原创 作者 | 智商掉了一地、ZenMoore 在互联网的浩瀚世界中&#xff0c;存在着无数复杂而扑朔迷离的任务等待我们去解决。如果要设计一个解决很多问题的通用智能体&#xff08;AI agent&#xff09;&#xff0c;无论是关于购物、旅行、学习还是娱乐&#xff0c;…

MySQL高级篇第二天

文章目录 一、Mysql的体系结构概览 二、 存储引擎 三、优化SQL步骤 一、Mysql的体系结构概览 整个MySQL Server由以下组成 Connection Pool : 连接池组件 Management Services & Utilities : 管理服务和工具组件 SQL Interface : SQL接口组件 Parser : 查询分析器组件 O…

感觉被榨干了,被美团拷打一小时...

普通本科毕业后&#xff0c;进了一家互联网公司&#xff0c;这几年里不断在积累经验&#xff0c;最终选择跳到美团&#xff0c;涨薪了50%&#xff0c;下面分享一下我个人的面经和一些心得建议。 面经 面团一面 自我介绍专业技能一条条核对下来 有软件测试流程、用例设计方法…

快速入门教程:神经常微分方程 (Neural ODE)

神经常微分方程(Neural Ordinary Differential Equations,简称 Neural ODE)是一种基于常微分方程(Ordinary Differential Equations,ODEs)的深度学习方法,它结合了传统的ODE数值求解技术和神经网络模型。通过使用ODE来建模数据的演化过程,Neural ODE可以自动地学习数据…

力扣题库刷题笔记3--无重复字符的最长子串

1、题目如下&#xff1a; 2、个人Python代码实现如下&#xff1a; 代码如下&#xff1a; class Solution: def lengthOfLongestSubstring(self, s: str) -> int: temp "" #临时变量&#xff0c;记录当前连续不重复子串 out_put …

中国市场成为高阶智驾战略高地,博世/安波福包揽四项大奖

高工智能汽车研究院监测数据显示&#xff0c;2022年度中国市场&#xff08;不含进出口&#xff09;乘用车前装标配搭载辅助驾驶&#xff08;L0-L2&#xff09;交付1001.22万辆&#xff0c;首次突破千万辆规模&#xff0c;同时&#xff0c;前装搭载率也首次突破50%大关。 此外&a…