当前位置: 首页 > article >正文

《ShardingSphere解读》18 执行引擎:如何把握 ShardingSphere 中的 Executor 执行模型?(上)

在上一篇中我们对 ShardingGroupExecuteCallback 和 SQLExecuteTemplate 做了介绍。从设计上讲前者充当 ShardingExecuteEngine 的回调入口而后者则是一个模板类完成对 ShardingExecuteEngine 的封装并提供了对外的统一入口这些类都位于底层的 sharding-core-execute 工程中。从今天开始我们将进入到 sharding-jdbc-core 工程来看看 ShardingSphere 中执行引擎上层设计中的几个核心类。AbstractStatementExecutor如上图所示根据上一篇中的执行引擎整体结构图可以看到SQLExecuteTemplate的直接使用者是AbstractStatementExecutor 类今天我们就从这个类开始展开讨论该类的变量比较多我们先来看一下//数据库类型 private final DatabaseType databaseType; //JDBC中用于指定结果处理方式的 resultSetType private final int resultSetType; //JDBC中用于指定是否可对结果集进行修改的 resultSetConcurrency private final int resultSetConcurrency; //JDBC中用于指定事务提交或回滚后结果集是否仍然可用的 resultSetConcurrency private final int resultSetHoldability; //分片 Connection private final ShardingConnection connection; //用于数据准备的模板类 private final SQLExecutePrepareTemplate sqlExecutePrepareTemplate; //SQL 执行模板类 private final SQLExecuteTemplate sqlExecuteTemplate; //JDBC的Connection列表 private final Collection connections new LinkedList(); //SQLStatement 上下文 private SQLStatementContext sqlStatementContext; //参数集 private final List- parameterSets new LinkedList(); //JDBC的Statement 列表 private final List statements new LinkedList(); //JDBC的ResultSet 列表 private final List resultSets new CopyOnWriteArrayList(); //ShardingExecuteGroup 列表 private final Collection executeGroups new LinkedList();从这个类开始我们会慢慢接触 JDBC 规范相关的对象因为 ShardingSphere 的设计目标是重写一套与目前的 JDBC 规范完全兼容的体系。这里我们看到的 Connection、Statement 和 ResultSet 等对象以及 resultSetType、resultSetConcurrency、resultSetHoldability 等参数都是属于 JDBC 规范中的内容我们在注释上做了特别的说明你对此也都比较熟悉。而像 ShardingSphere 自己封装的 ShardingConnection 对象也很重要我们已经在《03 | 规范兼容JDBC 规范与 ShardingSphere 是什么关系》中对这个类的实现方式以及如何兼容 JDBC 规范的详细过程做了介绍。在 AbstractStatementExecutor 中这些变量的展开会涉及很多 sharding-jdbc-core 代码工程关于数据库访问相关的类的介绍包括我们以前已经接触过的 ShardingStatement 和 ShardingPreparedStatement 等类所以我们在展开 AbstractStatementExecutor 类的具体实现方法之前需要对这些类有一定的了解。在 AbstractStatementExecutor 构造函数中我们发现了上一篇中介绍的执行引擎 ShardingExecuteEngine 的创建过程并通过它创建了 SQLExecuteTemplate 模板类相关代码如下所示public AbstractStatementExecutor(final int resultSetType, final int resultSetConcurrency, final int resultSetHoldability, final ShardingConnection shardingConnection) { … ShardingExecuteEngine executeEngine connection.getRuntimeContext().getExecuteEngine(); sqlExecuteTemplate new SQLExecuteTemplate(executeEngine, connection.isHoldTransaction()); }同时AbstractStatementExecutor 中如下所示的 cacheStatements 方法也很有特色该方法会根据持有的 ShardingExecuteGroup 类分别填充 statements 和 parameterSets 这两个对象以供 AbstractStatementExecutor 的子类进行使用protected final void cacheStatements() { for (ShardingExecuteGroup each : executeGroups) { statements.addAll(Lists.transform(each.getInputs(), new Function() { Override public Statement apply(final StatementExecuteUnit input) { return input.getStatement(); } })); parameterSets.addAll(Lists.transform(each.getInputs(), new Function() { Override public List apply(final StatementExecuteUnit input) { return input.getRouteUnit().getSqlUnit().getParameters(); } })); } }注意这里在实现方式上使用了 Google 提供的 Guava 框架中的 Lists.transform 方法从而完成了不同对象之间的转换过程这种实现方式在 ShardingSphere 中应用广泛非常值得你学习。然后我们来看 AbstractStatementExecutor 中最核心的方法即执行回调的 executeCallback 方法protected final List executeCallback(final SQLExecuteCallback executeCallback) throws SQLException { List result sqlExecuteTemplate.executeGroup((Collection) executeGroups, executeCallback); refreshMetaDataIfNeeded(connection.getRuntimeContext(), sqlStatementContext); return result; }显然在这里应该使用 SQLExecuteTemplate 模板类来完成具体回调的执行过程。同时我可以看到这里还有一个 refreshMetaDataIfNeeded 辅助方法用来刷选元数据。AbstractStatementExecutor 有两个实现类一个是普通的 StatementExecutor一个是 PreparedStatementExecutor接下来我将分别进行讲解。StatementExecutor我们来到 StatementExecutor先看它的用于执行初始化操作的 init 方法public void init(final SQLRouteResult routeResult) throws SQLException { setSqlStatementContext(routeResult.getSqlStatementContext()); getExecuteGroups().addAll(obtainExecuteGroups(routeResult.getRouteUnits())); cacheStatements(); }这里的 cacheStatements 方法前面已经介绍过而 obtainExecuteGroups 方法用于获取所需的 ShardingExecuteGroup 集合。要实现这个方法就需要引入 SQLExecutePrepareTemplate 和对应的回调 SQLExecutePrepareCallback。1.SQLExecutePrepareCallback从命名上看让人感觉 SQLExecutePrepareTemplate 和 SQLExecuteTemplate 应该是一对尤其是名称中有一个“Prepare”让人联想到 PreparedStatement。但事实上SQLExecutePrepareTemplate 与 SQLExecuteTemplate 没有什么关联它也不是像 SQLExecuteTemplate 一样提供了 ShardingExecuteEngine 的封装而是主要关注于 ShardingExecuteGroup 数据的收集和拼装换句话说是为了准备Prepare数据。在 SQLExecutePrepareTemplate 中核心的功能就是下面这个方法该方法传入了一个 SQLExecutePrepareCallback 对象并返回 ShardingExecuteGroup 的一个集合public Collection getExecuteUnitGroups(final Collection routeUnits, final SQLExecutePrepareCallback callback) throws SQLException { return getSynchronizedExecuteUnitGroups(routeUnits, callback); }为了构建这个集合SQLExecutePrepareTemplate 实现了很多辅助方法同时它还引入了一个 SQLExecutePrepareCallback 回调来完成 ShardingExecuteGroup 数据结构中部分数据的填充。SQLExecutePrepareCallback 接口定义如下可以看到 Connection 和 StatementExecuteUnit 这两个对象是通过回调来创建的public interface SQLExecutePrepareCallback { //获取 Connection 列表 List getConnections(ConnectionMode connectionMode, String dataSourceName, int connectionSize) throws SQLException; //获取 Statement 执行单元 StatementExecuteUnit createStatementExecuteUnit(Connection connection, RouteUnit routeUnit, ConnectionMode connectionMode) throws SQLException; }当我们获取了想要的 ShardingExecuteGroup 之后相当于完成了 StatementExecutor 的初始化工作。该类中剩下的就是一系列以“execute”开头的 SQL 执行方法包括 executeQuery、executeUpdate以及它们的各种重载方法。我们先来看用于查询的 executeQuery 方法public List executeQuery() throws SQLException { final boolean isExceptionThrown ExecutorExceptionHandler.isExceptionThrown(); //创建 SQLExecuteCallback 并执行查询 SQLExecuteCallback executeCallback new SQLExecuteCallback(getDatabaseType(), isExceptionThrown) { Override protected QueryResult executeSQL(final String sql, final Statement statement, final ConnectionMode connectionMode) throws SQLException { return getQueryResult(sql, statement, connectionMode); } }; //执行 SQLExecuteCallback 并返回结果 return executeCallback(executeCallback); }我们已经在上一篇中介绍过这个方法我们知道 SQLExecuteCallback 实现了 ShardingGroupExecuteCallback 接口并提供了 executeSQL 模板方法。而在上述 executeQuery 方法中executeSQL 模板方法的实现过程就是调用如下所示的 getQueryResult 方法private QueryResult getQueryResult(final String sql, final Statement statement, final ConnectionMode connectionMode) throws SQLException { //通过 Statement 执行 SQL 并获取结果 ResultSet resultSet statement.executeQuery(sql); getResultSets().add(resultSet); //根据连接模式来确认构建结果 return ConnectionMode.MEMORY_STRICTLY connectionMode ? new StreamQueryResult(resultSet) : new MemoryQueryResult(resultSet); }2.ConnectionModegetQueryResult 方法中完全基于 JDBC 中的 Statement 和 ResultSet 对象来执行查询并返回结果。但是这里也引入了 ShardingSphere 执行引擎中非常重要的一个概念即ConnectionMode连接模式它是一个枚举public enum ConnectionMode { MEMORY_STRICTLY, CONNECTION_STRICTLY }可以看到有两种具体的连接模式MEMORY_STRICTLY 和 CONNECTION_STRICTLY。MEMORY_STRICTLY 代表内存限制模式CONNECTION_STRICTLY 代表连接限制模式。ConnectionMode连接模式是 ShardingSphere 所提出的一个特有概念背后体现的是一种设计上的平衡思想。从数据库访问资源的角度来看一方面是对数据库连接资源的控制保护另一方面是采用更优的归并模式达到对中间件内存资源的节省如何处理好两者之间的关系是 ShardingSphere 执行引擎需求解决的问题。为此ShardingSphere 提出了连接模式的概念简单举例说明当采用内存限制模式时对于同一数据源如果有 10 张分表那么执行时会获取 10 个连接并进行并行执行而当采用连接限制模式时执行过程中只会获取 1 个连接而进行串行执行。那么这个 ConnectionMode 是怎么得出来的呢实际上这部分代码位于 SQLExecutePrepareTemplate 中我们根据 maxConnectionsSizePerQuery 这个配置项以及与每个数据库所需要执行的 SQL 数量进行比较然后得出具体的 ConnectionModeConnectionMode connectionMode maxConnectionsSizePerQuery type) throws SQLException; Object getCalendarValue(int columnIndex, Class type, Calendar calendar) throws SQLException; InputStream getInputStream(int columnIndex, String type) throws SQLException; boolean wasNull() throws SQLException; int getColumnCount() throws SQLException; String getColumnLabel(int columnIndex) throws SQLException; boolean isCaseSensitive(int columnIndex) throws SQLException; }如上图所示我们可以看到如果每个数据库连接所指向的 SQL 数多于一条时走的是内存限制模式反之走的是连接限制模式。3.StreamQueryResult VS MemoryQueryResult在了解了 ConnectionMode连接模式 的设计理念后我们再来看 StatementExecutor 的 executeQuery 方法返回的是一个 QueryResult。在 ShardingSphere中QueryResult 接口存在于 StreamQueryResult代表流式归并结果和 MemoryQueryResult 代表内存归并结果这两个实现类。ShardingSphere 采用这样的设计实际上跟前面介绍的 ConnectionMode 有直接关系。我们知道在内存限制模式中ShardingSphere 对一次操作所耗费的数据库连接数量不做限制而当采用连接限制模式时ShardingSphere严格控制对一次操作所耗费的数据库连接数量。基于这样的设计原理如上面的 ConnectionMode 的计算示意图所示在 maxConnectionSizePerQuery 允许的范围内当一个连接需要执行的请求数量大于 1 时意味着当前的数据库连接无法持有相应的数据结果集则必须采用内存归并反之则可以采用流式归并。StreamQueryResult我们通过对比 StreamQueryResult 和 MemoryQueryResult 的实现过程对上述原理做进一步分析在 StreamQueryResult 中它的 next 方法非常简单Override public boolean next() throws SQLException { return resultSet.next(); }显然这是一种流式处理的方式从 ResultSet 中获取下一个数据行。MemoryQueryResult我们再来看 MemoryQueryResult在它的构造函数中通过 getRows 方法把 ResultSet 中的全部数据行先进行获取并存储在内存变量 rows 中private Iterator getRows(final ResultSet resultSet) throws SQLException { Collection result new LinkedList(); while (resultSet.next()) { List rowData new ArrayList(resultSet.getMetaData().getColumnCount()); for (int columnIndex 1; columnIndex executeCallback new SQLExecuteCallback(getDatabaseType(), isExceptionThrown) { Override protected Boolean executeSQL(final String sql, final Statement statement, final ConnectionMode connectionMode) throws SQLException { //使用 Executor 进行执行 return executor.execute(statement, sql); } }; List result executeCallback(executeCallback); if (null result || result.isEmpty() || null result.get(0)) { return false; } return result.get(0); }这里多嵌套一层的目的是更好地分离代码的职责并对执行结果进行处理同样的处理技巧在 StatementExecutor 的 executeUpdate 方法中也有体现。PreparedStatementExecutor讲完 StatementExecutor 之后我们来看 PreparedStatementExecutor。PreparedStatementExecutor 包含了与 StatementExecutor 一样的用于初始化的 init 方法。然后我们同样来看它如下所示的 executeQuery 方法可以看到这里的处理方式与在 StatementExecutor 的一致public List executeQuery() throws SQLException { final boolean isExceptionThrown ExecutorExceptionHandler.isExceptionThrown(); //创建 SQLExecuteCallback 并执行 SQLExecuteCallback executeCallback new SQLExecuteCallback(getDatabaseType(), isExceptionThrown) { Override protected QueryResult executeSQL(final String sql, final Statement statement, final ConnectionMode connectionMode) throws SQLException { return getQueryResult(statement, connectionMode); } }; return executeCallback(executeCallback); }然后我们再来看它的 execute 方法就会发现有不同点public boolean execute() throws SQLException { boolean isExceptionThrown ExecutorExceptionHandler.isExceptionThrown(); SQLExecuteCallback executeCallback SQLExecuteCallbackFactory.getPreparedSQLExecuteCallback(getDatabaseType(), isExceptionThrown); List result executeCallback(executeCallback); if (null result || result.isEmpty() || null result.get(0)) { return false; } return result.get(0); }与 StatementExecutor 不同PreparedStatementExecutor 在实现 execute 方法时没有设计类似 Executor 这样的接口而是直接提供了一个工厂类 SQLExecuteCallbackFactorypublic final class SQLExecuteCallbackFactory { … public static SQLExecuteCallback getPreparedSQLExecuteCallback(final DatabaseType databaseType, final boolean isExceptionThrown) { return new SQLExecuteCallback(databaseType, isExceptionThrown) { Override protected Boolean executeSQL(final String sql, final Statement statement, final ConnectionMode connectionMode) throws SQLException { return ((PreparedStatement) statement).execute(); } }; } }注意到这里的静态方法 getPreparedSQLExecuteCallback 也就是返回了一个 SQLExecuteCallback 回调的实现而在这个实现中使用了 JDBC 底层的 PreparedStatement 完成具体 SQL 的执行过程。至此我们对 ShardingSphere 中两个主要执行器 StatementExecutor 和 PreparedStatementExecutor 都进行了详细介绍。从源码解析到日常开发本篇关于两种 QueryResult 的设计思想同样可以应用到日常开发中。当我们面对如何处理来自数据库或外部数据源的数据时可以根据需要设计流式访问方式和内存访问方式这两种访问方式在数据访问过程中都具有一定的代表性。通常我们会首先想到将所有访问到的数据存放在内存中再进行二次处理但这种处理方式会面临性能问题流式访问方式性能更高但需要我们挖掘适合的应用场景。小结与预告今天介绍了 ShardingSphere 执行引擎主题的第二个篇我们重点围绕执行引擎中的执行器展开讨论给出了 StatementExecutor 和 PreparedStatementExecutor 这两种执行器的实现方式也给出了 ShardingSphere 中关于连接模式的详细讨论。这里给大家留一道思考题ShardingSphere 中连接模式的概念和作用是什么欢迎你在留言区与大家讨论从类层结构而言StatementExecutor 和 PreparedStatementExecutor 都属于底层组件在下一篇我们会介绍包括 ShardingStatement 和 PreparedShardingStatement 在内的位于更加上层的执行引擎组件。

相关文章:

《ShardingSphere解读》18 执行引擎:如何把握 ShardingSphere 中的 Executor 执行模型?(上)

在上一篇中,我们对 ShardingGroupExecuteCallback 和 SQLExecuteTemplate 做了介绍。从设计上讲,前者充当 ShardingExecuteEngine 的回调入口;而后者则是一个模板类,完成对 ShardingExecuteEngine 的封装并提供了对外的统一入口&a…...

VR-Reversal:无需VR设备,轻松将3D视频转换为2D的终极指南

VR-Reversal:无需VR设备,轻松将3D视频转换为2D的终极指南 【免费下载链接】VR-reversal VR-Reversal - Player for conversion of 3D video to 2D with optional saving of head tracking data and rendering out of 2D copies. 项目地址: https://git…...

【CP AUTOSAR】Pwm(PWMDriver)配置实践与电源管理详解

1. PWM驱动基础与AUTOSAR架构解析 第一次接触AUTOSAR的PWM驱动时,我被各种专业术语搞得晕头转向。后来在实际项目中摸爬滚打才发现,理解PWM在AUTOSAR架构中的定位非常重要。PWM驱动属于MCAL(微控制器抽象层)的组成部分&#xff0c…...

Kappa系数详解:比准确率更靠谱的分类器评估方法(Python代码示例)

Kappa系数详解:比准确率更靠谱的分类器评估方法(Python代码示例) 在机器学习模型的评估中,准确率(Accuracy)常常被作为最直观的指标使用。但当我们面对类别分布极度不均衡的数据时,这个看似可靠…...

DDNS-GO 动态域名解析:从零搭建到高效运维

1. 为什么你需要DDNS-GO动态域名解析 家里有NAS的朋友一定遇到过这样的烦恼:明明设置了远程访问,过几天突然连不上了。检查路由器发现,运营商的公网IP又偷偷换了!这就是动态IP带来的困扰。我去年帮朋友调试家庭监控系统时&#xf…...

Nacos配置中@Value注解如何正确解析properties数组类型

1. 为什么Value注解解析properties数组会出问题? 在实际开发中,我们经常遇到这样的场景:需要在Nacos配置中心定义一组URL白名单,或者配置多个排除路径。按照常规思路,很多人会直接在properties文件中写成数组格式&…...

RT-Thread内核移植详解:libcpu与BSP双层实现

1. RT-Thread内核移植技术解析:从CPU架构适配到BSP工程实现嵌入式实时操作系统(RTOS)的移植是连接底层硬件与上层应用的关键桥梁。RT-Thread作为一款开源、中立、可裁剪的实时操作系统,其设计哲学强调“一次编写,多平台…...

告别编译踩坑:用Buildroot一键集成tcpdump到你的嵌入式Linux系统

告别编译踩坑:用Buildroot一键集成tcpdump到你的嵌入式Linux系统 在嵌入式Linux开发中,网络调试工具tcpdump的重要性不言而喻。它能帮助我们捕获和分析网络数据包,是排查网络问题的利器。然而,传统的交叉编译方式往往让开发者陷入…...

Spring_couplet_generation 模型背后的神经网络:从LSTM到现代架构

Spring_couplet_generation 模型背后的神经网络:从LSTM到现代架构 你有没有想过,当你输入一句“春风送暖”,AI就能对出“福气临门”这样工整的下联,它到底是怎么做到的?这背后,是一系列神经网络在默默工作…...

避坑指南:Unity调用Win32 API设置无边框窗口时容易忽略的3个细节

Unity无边框窗口实战:避开Win32 API调用的3个典型陷阱 当Unity开发者需要实现PC端无边框窗口效果时,Win32 API调用往往是绕不开的技术路径。但在这个过程中,从窗口初始化异常到多显示器适配问题,再到任务栏高度计算的坑&#xff0…...

MacBook远程办公神器:Microsoft Remote Desktop + cpolar内网穿透保姆级教程

MacBook远程办公终极方案:Microsoft Remote Desktop与内网穿透实战指南 远程办公已成为现代职场不可或缺的工作方式。想象一下这样的场景:你正在咖啡馆享受下午茶,突然接到紧急任务需要处理公司电脑上的文件;或是出差在外&#xf…...

保姆级避坑指南:在Ubuntu 22.04上为Unitree Go2配置ROS2 Humble开发环境(含网络、防火墙、DDS配置)

Unitree Go2机器人ROS2开发环境配置全攻略:从零避坑到实战部署 引言 当你第一次拿到Unitree Go2四足机器人时,那种兴奋感可能很快会被复杂的开发环境配置过程冲淡。作为一款前沿的机器人平台,Go2与ROS2 Humble的集成并非一帆风顺——网络配置…...

当前知识库暂无关于如何取消 sas_cspm_dp_cn-0s64mgf8q000v 的具体信息。根据该标识符的命名格式(包含 cspm 和地域标识 cn),它很可能与 云安全态势管理(CSPM)

收到阿里云的短信:您购买的云安全态势管理资源包用量已耗尽(如您账户内已无其它可用资源包,将产生账号扣费) 工作台产品消息:[余量预警] 尊敬的hi30489928aliyun.com 您购买的云安全态势管理资源包 (资源包实例: sas_…...

从零手写 miniGPT 02 | 数据工程与训练循环:GPT 是如何“学习“的?

上一节我们从 Block 层面解析了 GPT 的核心结构,包括多头注意力、前馈网络以及残差与归一化机制,这些模块共同构成了 Transformer 的基本计算单元,也是当前主流大模型共享的底层框架。 然而,模型能力的差异并不完全来源于结构本身…...

Qt Model/View设计模式详解:为什么你的表格数据总是不一致?

Qt Model/View设计模式深度解析:根治表格数据不一致的工程实践 在桌面应用开发中,数据展示与用户交互的稳定性直接影响用户体验。许多开发者在使用Qt标准控件时,常遇到表格数据显示异常、编辑结果丢失或数据源与界面不同步等问题。这些表象背…...

OpenClaw语音交互方案:ollama-QwQ-32B+Whisper实现语音指令控制

OpenClaw语音交互方案:ollama-QwQ-32BWhisper实现语音指令控制 1. 为什么需要语音交互方案 上周我在整理电脑文件时突然冒出一个想法:如果能用语音直接指挥AI完成操作,会不会比手动输入指令更高效?这个念头促使我开始探索OpenCl…...

RexUniNLU模型在STM32嵌入式设备上的轻量化部署方案

RexUniNLU模型在STM32嵌入式设备上的轻量化部署方案 1. 引言 想象一下,你正在开发一款智能家居设备,需要让设备理解用户的语音指令,比如"打开客厅的灯"或者"调高空调温度"。传统方案需要将语音数据上传到云端处理&…...

Ubuntu命令行终端启动全攻略(5种高效方式)

1. 最快捷的终端启动方式:快捷键组合 作为Ubuntu老用户,我最常用的就是CtrlAltT这个黄金组合键。这个快捷键就像给你的系统装了个紧急逃生舱——无论当前在运行什么程序,只要同时按下这三个键,终端窗口就会瞬间弹出。实测在Ubuntu…...

mkfile创建文件夹和文件脚本

资源地址 https://download.csdn.net/download/hashiqimiya/92753755https://download.csdn.net/download/hashiqimiya/92753755...

告别命令行!SQLMap图形化工具实战:从URL注入到POST请求全解析

SQLMap图形化工具实战指南:从入门到高效渗透测试 在渗透测试领域,SQL注入始终是最常见且危害巨大的安全漏洞之一。传统命令行工具虽然功能强大,但对于许多测试人员来说,记忆复杂参数和手动构造命令既耗时又容易出错。这正是SQLMap…...

用Excel手算Transformer前向传播:一个时间序列预测的保姆级实例

用Excel手算Transformer前向传播:一个时间序列预测的保姆级实例 当第一次接触Transformer模型时,很多人会被其复杂的数学公式和编程实现吓退。但如果我们换一种方式——用最熟悉的Excel表格来手动计算每一步,你会发现Transformer的核心机制其…...

2026程序员就业图鉴:AI岗位月薪6万碾压全场,70%的人连门都摸不着

引言2026年春招,AI赛道彻底炸了。据最新数据,AI新发岗位平均月薪达 60,738元,较新经济行业整体均值高出约 26%。其中:AI科学家/负责人:平均月薪 137,153元大模型算法工程师、AIGC算法工程师:约 7万元高性能…...

【MCP 2.0安全合规红线】:20年协议安全专家亲授3大高危漏洞识别法与零成本加固路径

第一章:【MCP 2.0安全合规红线】:20年协议安全专家亲授3大高危漏洞识别法与零成本加固路径 MCP 2.0(Managed Communication Protocol 2.0)作为新一代设备间可信通信基座,其安全设计直接决定IoT边缘网关、工业控制器及云…...

使用Cosmos-Reason1-7B自动化批改编程作业:代码逻辑与风格检查

使用Cosmos-Reason1-7B自动化批改编程作业:代码逻辑与风格检查 1. 引言 如果你是计算机课程的老师,或者负责带学生做项目,那你肯定对批改编程作业这件事深有体会。几十份、上百份代码看下来,眼睛都花了。更头疼的是,…...

Tailscale安装避坑指南:解决Ubuntu下常见报错(含curl缺失问题)

Tailscale在Ubuntu上的完整安装与排错实战指南 引言:为什么选择Tailscale? 在当今分布式办公和远程协作成为常态的环境下,安全便捷的网络连接工具变得尤为重要。Tailscale作为一种基于WireGuard的现代VPN替代方案,以其零配置、端到…...

GTE-Pro多行业落地案例:金融/政务/制造企业语义搜索实施路径

GTE-Pro多行业落地案例:金融/政务/制造企业语义搜索实施路径 1. 项目概述:重新定义企业搜索体验 GTE-Pro是基于阿里达摩院GTE-Large架构构建的企业级语义检索引擎,它彻底改变了传统的关键词匹配搜索方式。这个系统通过深度学习技术将文本转…...

参考文献崩了?AI论文平台千笔·专业学术智能体 VS 锐智 AI,专科生专属写作神器

毕业论文的写作过程总是让人感到压力山大,从选题到大纲,从初稿到文献,再到降重、查重、格式调整,最后还要准备答辩PPT,每一个环节都充满了挑战。对于专科生来说,时间有限、经验不足、资料匮乏,这…...

单片机/C/C++八股:(二十一)include <> 和 include ““ 的区别

上一篇下一篇指针常量和常量指针include <> 和 include “” 的区别 搜索路径不同&#xff1a; <>&#xff1a;只在标准库目录搜索。一般用于系统标准头文件。""&#xff1a;先在当前目录搜索&#xff0c;未找到再搜索标准库目录。一般用于自定义头文件…...

【国家级存算项目核心代码解密】:3个被工业界封存5年的C语言存内计算范式首次公开

第一章&#xff1a;存算一体架构演进与国家级项目背景存算一体&#xff08;Processing-in-Memory, PIM&#xff09;技术正从学术探索加速迈向工程落地&#xff0c;其核心驱动力源于传统冯诺依曼架构下“内存墙”问题日益严峻——数据在处理器与存储器间频繁搬运导致能效比急剧下…...

保姆级教程:用天问Block给ASR-PRO语音模块‘训练’自定义指令,联动Arduino

零代码玩转智能语音&#xff1a;天问BlockASR-PROArduino全流程指南 想象一下&#xff0c;只需对着设备说"打开台灯"&#xff0c;温暖的灯光立刻亮起&#xff1b;说"关闭风扇"&#xff0c;旋转的叶片应声停止——这种科幻电影般的交互体验&#xff0c;现在…...