多点DMALL × Apache Kyuubi:构建统一SQL Proxy探索实践

news2024/11/25 9:44:38

伴随着国家产业升级的推进和云原生技术成熟,多点 DMALL 大数据技术也经历了从存算一体到存算分离的架构调整变迁。本文将从引入 Kyuubi 实现统一 SQL Proxy 的角度讲述这一探索实践的历程。

多点 DMALL 成立于2015年,提供一站式全渠道数字零售解决方案 DMALL OS,目前已与130+连锁零售企业、近1000家品牌达成合作,覆盖5个国家和地区。作为一站式全渠道数字零售解决方案服务商,多点 DMALL 通过数字化解构重构零售产业,提供端到端的商业 SaaS。方案整体涵盖了从商品选择、供应商引入、仓储供应链管理、门店经营、用户精准营销的整个产业链,实现了人人、事事、物物在线。

Apache Kyuubi 是网易数帆发起开源的一个分布式和多租户网关,用于在 Lakehouse 上提供 Serverless SQL,社区目前已聚集海内外百余名贡献者。

作为 DMALL OS 数字化能力的技术底座,大数据平台历经多次迭代平稳支撑了公司 To B 业务的开展。伴随着国家产业升级的推进和云原生技术成熟,多点 DMALL 大数据技术也经历了从存算一体到存算分离的架构调整变迁。本文将从引入 Kyuubi 实现统一 SQL Proxy 的角度讲述这一探索实践的历程。

技术背景

行业技术发展趋势

 

第一代的大数据技术主要采用传统 Hadoop 开源技术栈,几乎所有的企业搭建大数据集群都是从 HDFS、Hive 和 YARN 开始的。除了 Apache 开源组件组合外,许多企业也会选用 CDH、HDP 等商业发行套件,方便运维和部署。随着技术的成熟,传统的 Hadoop 技术开始暴露一些缺点:

1. 部署运维成本高

Hadoop 生态组件所需基础硬件资源较多,组建集群时需要慎重设计和调整,部署成本高,后期运维复杂度高。

2. 集群隔离,资源浪费

大数据集群部署时常常需要单独申请机器,与业务服务集群资源隔离。总体来看,两个集群的潮汐现象都存在,大数据集群白天较为空闲,业务服务集群夜间用户使用量低,隔离部署的方式会产生较大资源浪费。

3. 存储成本持续升高

大数据集群的数据量是一直增长的。纵使企业做了冷热分离的设计、定时归档的处理,也只是减缓了增长趋势,依旧无法解决存储成本一直升高的现状。当然,除了上述缺点,还有 NameNode 元数据压力过大、组件版本相互制约等问题。这些缺点对于企业内部使用尚且可以优化处理,但是作为一家需要为客户提供定制化服务的企业,尤其面对日益突出的“性能”、“成本”、“安全”、“稳定性”等核心问题,多点 DMALL 意识到必须做出改变。

To B 的大数据平台建设趋势

To B 的企业商业逻辑和 To C 的差别很大,在大数据领域的差别更大。

1. 精细的成本管理

To C 的大数据平台使用者多是企业内部员工。使用大数据平台产生的成本单独计算,个人用户不会为这些资源消耗直接买单。但在 To B 模式下,使用者基本都来自B端企业客户,客户要为其资源使用付费。这就意味着作为服务提供商需要精细化成本,尽最大可能降低成本才能获得客户的认可。

2. 更低的使用门槛

企业内部使用的大数据平台,员工背景可控。To B 的大数据平台面对的环境要复杂很多。客户当前的信息化程度、员工技能等都不相同,大数据平台需要提供更多方式、更低门槛来帮助客户的使用。

3. 更快的交付效率

需要进一步简化技术架构和实现,采用标准化的手段小时级交付新环境,节省时间同时进一步降低后续运维难度。这样以后逐渐形成快速规模化复制的能力,输出零售数据中台解决方案。

多点 DMALL的大数据技术发展

上述技术背景和商业背景的发展,对多点 DMALL 的大数据技术基座持续提出更高的要求。在持续优化升级的过程中,多点 DMALL 的大数据集群架构经历了从传统Hadoop生态迈向云原生,从存算一体到存算分离的架构变迁。

接下来,我们将详细讲述这一变迁的背景及其设计,以及 Kyuubi 在其中承担的角色和优化实践。

存算一体架构下的即席查询优化

架构背景

与其他大部分企业一样,多点 DMALL 最开始采用的是传统 Hadoop 技术栈构建数据中台 UniData,强依赖 CDH 发行版,采用 IDC 物理机/云主机集群部署。在即席查询中,我们采用自研的统一安全网关UniSQL连接用户和底层引擎。UniSQL 可为用户提供安全校验、血缘采集、SQL 审计、限流、白名单、查询降级、查询结果限制等平台管控级功能,最初只支持对接 Impala 和 Hive 查询引擎。很明显基于查询速度的优势,平台用户会优先选择 Impala 作为查询引擎。随着平台的推广和用户量的增加,我们发现这样的架构存在不少问题。

1. Impala 资源紧张

Impala 的资源紧张现象越来越频繁,因其本身资源隔离较为复杂,也没有 HiveServer2 提供的原生查询条件控制等,使得整体可用性降低。虽然我们在优化中通过平台层面补救进行部分 SQL 的拦截,但是依然无法完全阻挡部分占用大量资源的 SQL 执行。

2. Hive 查询速度不佳

相比于 Impala,Hive 查询速度不佳,用户体验较差。一方面,MapReduce 任务会产生大量临时小文件,影响运维人员的判断;另一方面,MapReduce 任务报错常常很隐晦,用户从 Hive 执行日志中无法直接获取,需要运维人员去 YARN 管理页面搜索查询详细信息,带来较大的运维成本。

3. YARN 集群潮汐现象严重

如图所示,YARN 所在的集群是为大数据独立搭建的基于 IDC/云主机的集群。实践中发现,YARN 集群的潮汐现象非常明显,凌晨时分伴随着大量离线任务的启动,集群资源非常紧张;白天任务量很少,Impala 的大量使用意味着 Hive 查询量少,集群总体使用量较为空闲。基于上述的原因,我们考虑引入 SparkSQL 作为即席查询的另一个可选项,在Impala资源紧张时,将Impala的查询资源引导入 YARN 集群中,同时减少 Hive 的查询以提升用户整体的查询速率。选型过程中 Kyuubi 进入了我们的视线。

架构设计

事实上,这不是我们第一次调研 Kyuubi。早在 Kyuubi 正式开源时,我们便尝试引入Kyuubi 作为多租户代理工具,正巧赶上当时公司技术发展方向的优先级调整,这一尝试暂时搁置。后来在需求的驱动下,我们开始重新引入 Kyuubi,这时 Kyuubi 已经到了1.5.2版本。现行的架构已经稳定在多个集群运行,为了尽可能减少架构调整,保证引入过程中集群其他任务及服务的稳定性,最终引入 Kyuubi 后即席查询涉及的总体架构图如下:

优化探索

线上环境中已经有 UniSQL 作为统一安全网关,Kyuubi 所承担的角色仅聚焦于多租户的 Spark SQL 代理。为了适配其他底层组件等原因,我们对 Kyuubi 进行了部分调整:

1. 在现有的 CDH 环境下,为了匹配 Sentry 的权限管控和 YARN 的资源调度,我们修改了 Kyuubi 提交 Spark 的执行命令,不使用 proxy-user 和 -queue 的参数,直接切换用户提交;

2. 由于安全组件使用 Sentry 进行权限管控的,在网上也没有开源产品可以提供SparkSQL 基于 Sentry 的校验,我们只好单独适配实现了针对 Sentry 的 Spark Extension;

3. 基于 Kyuubi 提供的 kyuubi.engine.initialize.sql 参数,将我们原来为 Hive 和Impala 提供的 UDF 迁移到 SparkSQL 服务中,Kyuubi 在初始化 Spark 时便自动加载对应的 jar 包和 Function,用户切换引擎时使用无感知;

4. 为了方便用户从 Impala 切换到 Spark SQL 查询,我们定制化支持了部分 SQL 语法,例如 invalidate metadata 进行元数据主动刷新等;在用户的使用中,我们也进行了一系列参数优化。例如设置 spark.files.overwrite=true方便部分用户重复提交 jar 包以及测试自定义 UDF 函数;设置 spark.sql.autoBroadcastJoinThreshold=-1 关闭自动 Broadcast 以提高稳定性等。

遗留问题

在原有架构中,我们以最简单的方式引入 Kyuubi,为客户提供了另一种查询引擎的可能,但是这样的引入很明显存在其短板:

1. JDBC 链路太长

用户从发起的 JDBC 连接到最终开始执行 SQL,中间需要分别经过 UniSQL 和 Kyuubi服务。多个连接池的管理提升了总体的连接管理复杂度,在报错时更是不易分析查找。有赖于 Kyuubi 和 UniSQL 的稳定,在实际使用中暂未发现因多个连接池连接导致的严重影响,但风险和隐患依旧存在。

2. SQL Proxy 角色重叠

同为 SQL Proxy,UniSQL 和 Kyuubi 的角色存在重叠,很明显这样冗余的设计并不利于未来架构的发展。

3. Spark 版本不统一

基于历史原因,现有架构中我们为用户提供的是 Spark 2.4.6和 Spark 2.3.1版本,但是Kyuubi 是需要搭载 Spark 3.x版本。引入 Spark SQL 查询,又不能贸然将之前的版本“一刀切”,我们只好暂时单独为 Kyuubi 部署 Spark3.x 版本。这就造成现在集群中存在不统一的 Spark 版本,增加运维的难度。

4. Zookeeper 版本不统一

我们使用的 CDH 发行版版本为5.16.2,搭载版本为3.4.5的 Zookeeper。Kyuubi 的 HA 同样需要依赖 ZooKeeper,但是经过我们测试,使用3.4.5的 Zookeeper 会出现删除节点失败的情况,从而导致 Kyuubi Server 自动关闭。经过分析,这一 BUG 在更高版本中修复完毕。最终,我们只好单独部署3.6.1版本的 Zookeeper 供 Kyuubi 使用。

5. Sentry 权限与 Spark 的对接不易

CDH 限定了集群的权限管理服务为 Sentry。众所周知,Sentry 的设计架构简单,缺失更细粒度的权限控制,包括视图、行、列等。而且 Spark 没有原生支持 Sentry 的权限管控方式。虽然我们开发了针对 Sentry 的 Spark Extension 进行权限管控,更细粒度的管控依旧是我们很头疼的地方。

存算分离架构下的统一 SQL Proxy 实践

架构背景

随着多点 DMALL 全面 To B 转型,为越来越多的B端客户提供零售全渠道解决方案,需要具备在多云部署环境下提供更具性价比、可复用的大数据底层基座和平台工具链。我们也终于等到了一个契机,彻底甩开历史包袱,设计搭建存算分离、轻量级、可扩展、云中立大数据集群架构。

幸运的是,Spark on K8s 的技术趋于成熟,我们得以全面拥抱云原生。在 K8s 的基座上,我们合并了大数据计算集群和业务服务集群,甩开 CDH 的版本限制,剥离 Hadoop 生态的强依赖,充分利用对象存储,简化运维和部署,降低用户使用成本。

考虑到上一版架构中的部分遗留问题,在升级架构设计中,经过详细的调研、分析和选型,Kyuubi 也正式替换 UniSQL 作为 SQL Proxy,负责多套查询引擎的统一代理服务。

升级架构设计

在升级架构中,我们充分考虑到之前版本不一致的情况,合并并简化了技术选型,使整体架构更轻量级和可扩展:

实践方案

使用 Kyuubi 作为统一 SQL Proxy,那么 Kyuubi 就需要满足之前 UniSQL 为代表的代理服务的全部辅助功能,包括审计日志、实时监控、限流、动态参数修改、权限管控等。因此我们深入学习了社区的实践经验和最优推荐,根据场景和需求,完善了 Kyuubi 的服务。以下为我们部分实践结果。

  • SQL审计

作为统一代理层,需要对所有 SQL 和连接进行详细的记录,包括用户、SQL、执行时间、执行结果等。这样的数据并非实时使用,而是用于后续回溯查找问题,或者进行用户操作习惯的统计分析。幸运的是,Kyuubi 提供了 EventHandler 的方式,收集了非常完整的信息。在 Kyuubi1.6.1中,支持使用下列参数将相关记录落在本地日志中:

kyuubi.backend.server.event.json.log.path
kyuubi.backend.server.event.loggers

本地日志并不方便统计分析,我们需要更灵活的方式。最终我们选择仿照原生JsonLoggingEventHandler类,继承EventHandler自定义将所需日志写入 Kafka 中。后续再通过大数据平台的功能,落地到 Hive 或其他引擎中用于回溯分析。

  • 实时监控

当前即席查询的使用情况如何、连接数量、失败原因等,都需要实时监控查看。Kyuubi 提供了非常完整的指标监控能力,我们也复用内部运维平台的监控体系,选用了 Prometheus + Grafana 作为实时监控的载体。

相关参数:

kyuubi.metrics.reporters
  • 限流

不同平台和用户的使用方式不同,容易导致连接数爆发,从而影响 Kyuubi 服务的稳定性。因此,限流是必须要纳入考虑的。Kyuubi 提供了部分参数进行限流:

kyuubi.server.limit.connections.per.user
kyuubi.server.limit.connections.per.ipaddress

虽然这些参数限制到了单用户的连接数,甚至单用户单 IP 的连接数,但是这些参数是对所有用户统一的,而且 Kyuubi 服务启动后不能动态修改。就我们的使用经验来看,支持针对不同用户动态设置不同的连接限制将是一种更灵活的方式。但当前的功能也能基本满足限流管控要求,最终决定针对这个场景我们不做代码修改,期待社区未来能够提供更精细的管控功能。

  • 参数动态传递

线上环境缺乏合适的方式进行参数传递,这个遗憾在新的架构中得以弥补。通过 Kyuubi提供的自定义动态参数传递方式,实现SessionConfAdvisor类后对接配置中心。参数将在每次启动Session的时候动态拉取,也能较好的满足不同用户不同资源分配的场景:

kyuubi.session.conf.advisor

当然,为了减少对不同环境参数的自定义jarb包管理,我们调整了传入该类的参数,添加了KyuubiConf,这样不同环境部署的 Kyuubi 自动可以传入对应的配置中心路径等信息,自定义的 jar 包也可以环境无关,减少代码运维的复杂度。

  • 基于 Ranger 的权限校验

甩开了 CDH 对于 Sentry 的强制要求,新的架构选用 Ranger 进行权限管控。因此可以直接使用 Kyuubi 提供的 auth-extension 进行权限校验。不过为了提升整体的鉴权效率,我们重新设计了鉴权体系,将鉴权能力集中在新的鉴权服务 RAC 中,避免每一个 Spark 任务都在 Driver 本地落地一份 Ranger 权限策略。在这样的思路下,对于 Kyuubi 提供的 auth-extension 也做了适配性的修改。不过这不影响这个工具的便捷性:

spark.sql.extensions=org.apache.kyuubi.plugin.spark.authz.rangerRangerSparkExtension

只不过,就社区的更新速度来看,auth-extension 更新频率很高,我们在测试中发现了一些问题,包括视图权限、临时 Function 权限等问题,修复后都还没来及脱敏贡献给社区,社区就在 master 分支修复发布了。实话说,这也导致我们的这个插件更新非常痛苦,我们需要不断修改,不断适配。这也是我们越来越拥抱社区的原因,只要社区提供了功能,经过测试后我们便删除自定义代码,方便未来更新,也是尽可能跟着社区一起成长吧。

  • 自动合并小文件

Kyuubi 提供的自动合并小文件工具是纯开箱即用的,Spark3.3 版本主要依靠 rebalance 逻辑。经过我们的测试,同样的来源表,同样写出10个分区,写出文件从近2000个缩小到10个,落地时间也从7min 缩小到40s,不仅降低了集群元数据的压力,更有效提升了整体任务效率。

spark.sql.extensions=org.apache.kyuubi.sql.KyuubiSparkSQLExtension
  • 查询条件限制和扫描分区数限制

即席查询中,绝大部分探索性的查询都不需要大量的数据,结果数据量过大会引起 Driver 的压力过大,从而影响查询的稳定性以及用户的体验。社区最新提供了 HTTP 的异步获取的方式,但是这样的方式涉及到上下游改动,还在性能测试中。

按照线上环境的经验,我们将结果条数限制为1000条,针对不同的场景,这个参数也可以动态修改,基本满足返回结果要求。

spark.sql.watchdog.forcedMaxOutputRows

Hive 支持限制查询 SQL 中分区表必须带分区条件的严格模式,Kyuubi 也提供了类似的功能,可支持控制扫描分区数的限制。只是控制扫描分区数对于不同场景的需要不同,我们还没有正式利用这个功能,需要在实践中动态添加参数使用。

spark.sql.watchdog.maxPartitions
  • 服务日志切分

之前运维经验发现,Kyuubi 服务在 logs 下写入的服务日志一直增量写入,发现的时候单文件日志已经达到了 90G。新架构下我们吸取教训,修改了 log4j2.properties,将日志按大小和日期拆分,仅保留最近7天的日志,彻底解决这个隐患。

  • 自由选择资源组

在公司的实际使用中,一个 user 是可以在多个 group 中的,按照 Kyuubi 原生的提供的以 group 为引擎隔离 level 的情况下,会默认取该用户的第一个 group。我们将其修改成了通过 JDBC 参数可以选择 group 的能力,当然也包括了安全性校验,不允许恶意使用不属于自己的 group。

  • Volcano 调度器的模板文件

Spark 官方文档中针对 Volcano 的调度器使用参数如下:

spark.kubernetes.scheduler.name=volcano
spark.kubernetes.driver.pod.featureSteps=org.apache.spark.deploy.k8s.features.VolcanoFeatureStep
spark.kubernetes.executor.pod.featureSteps=org.apache.spark.deploy.k8s.features.VolcanoFeatureStep
spark.kubernetes.scheduler.volcano.podGroupTemplateFile=podgroup-template.yaml

其中,最后这个参数 spark.kubernetes.scheduler.volcano.podGroupTemplateFile 需要是本地的 yaml 文件。我们针对这个修改了提交命令,支持动态生成模板文件进行提交。

下一步探索方向

我们也在根据原始架构中用户的使用反馈,持续优化升级版架构的设计,不断调整打造存算分离、轻量级、可扩展、云中立的大数据集群。

根据使用反馈,我们下一步将重点关注以下优化点:

1. 单点引擎稳定性不佳,当一个 SQL 将该引擎查挂后,下次再查询会先报错后启动新的引擎。这对于用户的使用不太友好。经过研究社区里其他企业的分享,下一步我们将关注资源池模式和引擎高可用的设计,以提升用户的使用友好度。

2. 精细化成本管控是升级架构的重中之重,但是原生的 Spark SQL 无法将资源拆分到SQL 粒度。这里也是我们下一步需要重点突破的内容,为用户提供清晰的成本数据。

3. 大数据基座上除了我们提供的大数据平台产品外,常有其他业务系统申请直接使用大数据相关资源,最典型的就是 JDBC 链接。白名单将是我们需要重点实现的功能。除了用户登录校验外,还能验证来源平台,对使用来源做出限制。

总结来看,我们从 Kyuubi 正式开源时开始关注,到如今的1.6.1版本,越来越欣喜地发现,每次升级都会有新的功能补充和思考。我们也在升级中逐渐减少自定义代码,使用 Kyuubi 社区提供的新特性。我们会持续跟踪社区动态,并将实践经验反哺社区,参与推动 Kyuubi 的发展。

【点击试用网易大数据产品】  

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

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

相关文章

STL的常用算法-查找 (20221130)

STL的常用算法 概述&#xff1a; 算法主要是由头文件<algorithm> <functional> <numeric> 组成。 <algorithm>是所有STL头文件中最大的一个&#xff0c;涉及比较、交换、查找、遍历等等&#xff1b; <functional>定义了一些模板类&#xff0…

使用记账软件记录生活收支明细,如何防止收支不被他人修改

坚持记账是每个人都必须要做的事情&#xff0c;日常生活中的生活开支都是一笔笔的支出&#xff0c;一个月挣来的工资&#xff0c;在不知不觉之中就花完了&#xff0c;可以使用——晨曦记账本记录生活明细&#xff0c;为了防止被他人修改&#xff0c;该如何操作呢&#xff1f;一…

Allegro调丝印规范操作指导

Allegro调丝印规范操作指导 Allegro和其它PCB设计软件一样,丝印的排布也是类似的,具体规范介绍如下 以下图为例 打开Setup-Design Parameter 选择text 设置丝印字体的参数 设置需要丝印的字体,比如3号字体,参数如下 然后点击OK Edit-Change需要调整丝印的字体

Linux-Hadoop部署

部署Hadoop一、Hadoop部署模式1、独立模式2、伪分布式模式3、完全分布式模式二、Hadoop集群规划1、集群拓扑2、角色分配三、JDK安装与配置1、下载JDK压缩包2、上传到master虚拟机3、在master虚拟机上安装配置JDK4、将JDK分发到slave1和slave2虚拟机5、将环境配置文件分发到slav…

图的初识·存储结构

邻接矩阵存储结构 用矩阵表示表示图中各个顶点之间的邻接关系和权值。如图G(V,E)G(V,E)G(V,E)&#xff0c;其中有N个结点&#xff0c;使用NxNNxNNxN的矩阵表示。 不带权值的图 Gij{1,无向图(vi,vj)或有向图的<vi,vj>是图中的边0,无向图的(vi,vj)或有向图的<vi,vj>…

猕猴桃的红色果肉受到特定的激活-抑制系统的控制

文章信息 题目&#xff1a;The red flesh of kiwifruit is differentially controlled by specific activation–repression systems 刊名&#xff1a;New Phytologist 作者&#xff1a;Wen-qiu Wang&#xff0c;Andrew C. Allan,Xue-ren Yin et al 单位&#xff1a;Zhejia…

猿如意开发工具|Sublime Text(4126)

文章目录 一、猿如意是什么&#xff1f; 二、如何使用猿如意下载安装Sublime Text 三、总结 一、猿如意是什么&#xff1f; 猿如意是一款面向开发者的辅助开发工具箱&#xff0c;包含了效率工具、开发工具下载&#xff0c;教程文档&#xff0c;代码片段搜索&#xff0c;全网搜…

【Pandas数据处理100例】(九十九):Pandas使用at_time()筛选出特定时间点的数据行

前言 大家好,我是阿光。 本专栏整理了《Pandas数据分析处理》,内包含了各种常见的数据处理,以及Pandas内置函数的使用方法,帮助我们快速便捷的处理表格数据。 正在更新中~ ✨ 🚨 我的项目环境: 平台:Windows10语言环境:python3.7编译器:PyCharmPandas版本:1.3.5N…

如何建立一套完善的销售管理体系?

怎样创建两套健全的产品销售体系&#xff1f;用工程建设观念管理工作产品销售项目组&#xff0c;创建健全的产品销售体系&#xff01; 逐步形成精确的最终目标虽说重要&#xff0c;但缺乏有效率的方式来破冰&#xff0c;最终目标可能将仅是这份无用。 篮球赛事球手的最终目标…

IOC 的底层原理和Bean管理XML方式、xml注入集合属性

目录 什么是IOC IOC底层管理 工厂模式 IOC 的过程 IOC 接口 IOC 操作Bean 原理 Bean 管理操作有两种方式 1. 基于xml 配置方式创建对象 2. 基于xml方式注入属性 第二种使用有参数构造注入 p 名称空间注入 ICO操作Bean管理&#xff08;xml 注入其他类型属性&#xff…

微信小程序的 websocket 以及 微信开发者工具测试 ws 协议没有数据的 离奇解决方案 记录

微信小程序的 websocket 在本地web能够使用ws协议去链接websocket&#xff0c;但是小程序不能使用。一、WSS 协议与 WS 协议二、业务场景记录 : 使用 ws 协议的 websocekt 做测试,但是在 h5中可以拿到实时数据,在微信开发者工具中以及真机调试中拿不到模拟数据的问题1. 首先在 …

2022安洵杯babybf

babybf 赛后分析了下&#xff0c;发现是一道很有意思的题目 Brainfuck是一种极小化的计算机语言&#xff0c;它是由Urban Mller在1993年创建的。由于fuck在英语中是脏话&#xff0c;这种语言有时被称为brainf*ck或brainf**k&#xff0c;甚至被简称为BF。 其实本题是一个c语言实…

三、【redux】异步action

文章目录1、不成熟的异步修改1.1、CODE1.1.1、count_action.js1.1.1、count_reducer.js1.2、异常2、异步action代码修正2.1、store.js2.2、count_action.js3、小总结action分两类&#xff1a; 同步&#xff1a;指action的值是Object类型的一般对象异步&#xff1a;指action的值…

在C#中使用Halcon开发视觉检测程序

本文的初衷是希望帮助那些有其它平台视觉算法开发经验的人能快速转入Halcon平台下&#xff0c;通过文中的示例开发者能快速了解一个Halcon项目开发的基本步骤&#xff0c;让开发者能把精力完全集中到算法的开发上面。 首先&#xff0c;你需要安装Halcon&#xff0c;HALCON 18.…

D. X-Magic Pair(辗转相除)

Problem - 1612D - Codeforces 给你一对整数&#xff08;a,b&#xff09;和一个整数x。 你可以用两种不同的方式改变这对整数。 设置&#xff08;分配&#xff09;a:|a-b|。 设置&#xff08;分配&#xff09;b:|a-b|。 其中|a-b|是a和b之间的绝对差值。 如果只用给定的操作就…

【Linux】shell命令行简单解释器

回顾一下&#xff0c;我们前面学习了进程创建&#xff0c;进程终止&#xff0c;进程等待&#xff0c;进程替换&#xff0c;通过这些内容我们可以来进行实现简单的shell命令行解释器&#xff01;&#xff01;&#xff01;下面我们直接来看一看如何去实现shell命令行解释器&#…

结合编辑器和PDFXplorer工具查看PDF文件结构

首先用编辑器打开PDF,可以看到如下结构 1.寻找文件结构入口 /Root k-value形式&#xff0c;/Root 98 0 R/ k是Root value是98 0 R 98 0 R 代表被引用&#xff0c;指向的对象是98 0 obj 用PDFExploer工具打开看&#xff0c;如下&#xff1a; 可以看出用工具打开的树形结构跟上…

[附源码]计算机毕业设计springboot快转二手品牌包在线交易系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

YonBuilder开发之后端函数

在前几期的文章中我们已经介绍过如何在YonBuilder中使用前端函数实现数据过滤功能。相对应于前端函数&#xff0c;在YonBuilder中还可以使用后端函数实现对于程序的扩展。通过前端函数实现的更多的是与页面交互相关的功能&#xff0c;而后端函数主要是用于预制按钮功能的扩展开…

Mybatis的介绍及使用

目录 Mybatis 搭建MyBatis开发环境 1、创建Maven工程&#xff0c;导入MyBatis依赖的组件 2、编写MyBatis核心配置文件(mybatis-config.xml) 3、创建实体类-POJO 4、创建SQL映射文件(mapper.xml) 5、创建测试类 Mybatis MyBatis是一款优秀的持久层框架&#xff0c;用于简…