首页 文章 精选 留言 我的

精选列表

搜索[告别],共769篇文章
优秀的个人博客,低调大师

告别SQL卡顿与混乱!AI如何赋能实时计算?

在当今数据驱动的商业环境中,SQL作为与数据库交互的核心语言,其编写效率和质量直接影响着企业的数据决策速度和系统性能。然而,我们在长期的企业服务实践中发现,数据库开发人员普遍面临以下痛点: SQL性能问题频发:约65%的性能问题源于低效SQL,但开发人员缺乏专业的优化指导 知识传承困难:复杂的业务SQL往往缺乏文档说明,新成员理解成本高 错误诊断耗时:平均每个SQL错误需要45分钟排查,严重影响开发效率 这些痛点导致企业SQL开发效率低下,平均每个开发人员每天要花费2-3小时在SQL相关问题的处理上。 基于以上问题,袋鼠云实时开发平台引入了智能AI,深度集成于企业数据库开发环境,提供从SQL编写、优化到运维的全生命周期智能支持。助力企业开发效率提升40%+、性能问题减少60%、有效缩短新人上手时间。 重点功能介绍 智能优化 平台提供SQL语句性能优化建议,并支持一键替换原SQL。 智能注释 对SQL语句添加注释,方便理解表的作用及SQL的作用。其中注释内容包含:各数据表的业务含义、SQL的总体功能描述、关键操作步骤说明。 智能解释 平台支持解析选中SQL的业务逻辑。其中解释内容包括:SQL的预期输出结果、各关键操作步骤的业务含义、涉及数据表的关系说明。 日志解析 解析SQL执行错误并提供解决方案。其中支持场景包含:语法错误定位与修正建议、运行时错误原因分析、资源不足等系统级问题诊断。 灵瞳(AI助手)对话 元数据智能检索 支持查询平台存储的元数据信息 可展示表结构、字段说明等详细信息 示例查询:"显示customer表的所有字段" ​ 知识库智能应答 自动匹配知识库中的解决方案 支持多轮对话上下文理解 知识来源:历史问题库、最佳实践文档 SQL智能补全 该功能可以基于当前编辑的SQL上下文提供建议,支持表名、字段名、函数名等智能补全,学习用户习惯提供个性化建议。 典型应用场景 场景一:金融行业复杂报表开发 用户痛点:某银行数据分析团队需要每日生成20+张监管报表,SQL平均长度超过500行,维护困难。 平台解决方案: 使用智能注释自动生成报表SQL的业务说明 通过执行计划分析识别全表扫描等性能问题 新人通过"解释"功能快速理解复杂业务逻辑 场景二:某公司数据仓库建设 用户痛点:某公司建设企业数据仓库,涉及300+数据表的关联查询。 平台解决方案: 通过元数据检索快速查找所需表结构 字段智能补全避免记忆大量表名 袋鼠云实时开发平台通过深度集成AI能力,致力于解决SQL开发中的核心痛点,平台提供从编写、注释、解释到诊断的全流程智能支持,显著提升开发效率,降低维护成本。袋鼠云始终坚持帮助企业数据团队释放潜能,让数据价值高效兑现! ​

优秀的个人博客,低调大师

OCAI + DeepSeek 满血版双 buff 加成,OS 运维从此告别焦虑

作者丨黄敏杰、李强 编辑丨cherry 审稿丨林青、郑力博 当遇到忘记的Shell命令参数,你是否还在使用“xxxx --help”查询使用帮助?当你遇到OS的疑难问题,是否还在全网苦苦搜索解决方案?今天,OpenCloudOS 社区重磅推出新一代OS智能助手OCAI-Agent,它集代码生成、场景化指南输出于一体,通过接入满血版 DeepSeek R1模型,让你通过简单的中文指令,即可实现秒级AI Agent调用。 一、OCAI工具概览 很多OS运维工程师常陷于「文档迷宫」:面对上千页的官方手册、散落全网的技术贴、版本迭代带来的参数变更,每一次故障排查都可能演变成耗时数小时的文档检索工程。但 OCAI 的诞生,可能一切都变了…… 先看一下这个,好像小白也可以实现对OS的运维: (划至文章底部可查看未加速操作版) 目前,OCAI已接入满血版 DeepSeek R1 模型,并将OpenCloudOS全量文档、社区运维案例、Gitee技术方案等异构数据,经向量化处理后形成动态知识图谱。 也就是说,针对OpenCloudOS的使用、运维管理操作等场景,OCAI可以帮为用户总结提炼并生成具体场景下的使用指南、命令、甚至代码,从而实现极大程度上的智能提效。 OCAI当前版本主要分为三种模式: Chat模式:通过提问,开始调用OCAI问答系统,并让系统进入思考、推理及结果输出过程。 Cmd模式:直接执行的Shell命令,并根据用户指示执行相应任务。 Code模式:生成执行代码。 1、Chat模式 安装完成并使配置生效后,在命令窗口中直接输入相关问题,无需加入任何命令前缀,即可方便调用OCAI智能助手的问答能力。 也可通过ocai chat <question>命令形式对问答能力进行调用。 2、Cmd模式 Cmd模式支持根据用户指示生成可直接执行的Shell命令,用户确认后可立即执行获取结果。 3、Code模式 Code模式下支持根据用户指示生成不同编程语言下的代码。 二、OCAI背后的技术实现原理 当前 OCAI 智能助手针对不同场景设计了多个 Agent 分别处理请求,采用RAG方式导入OpenCloudOS特有知识库信息,通过OCAI-Service与客户端进行交互,使用不同的底座模型对数据进行推理、总结和润色,最终输出给用户。 1、多Agents编排 OCAI智能助手针对不同场景和数据源创建了多个不同的 Agents,每个Agent负责特定的一个领域的处理逻辑(如对话、命令生成、代码生成),并通过指定逻辑将多个Agents组合编排,从而使使用入口得以统一,多个Agents可以协同工作。 2、RAG 针对通用模型缺少特定领域知识的情况,OCAI智能助手采用 RAG(Retrieval Augmented Generation) 方式,将特定领域的知识库(如 OpenCloudOS 文档库)数据进行处理清洗和切分后,计算成向量形式并存入向量数据库。用户提问将先从向量数据库中检索出相关程度较高的资料,再统一拼接成 prompt 提交给大模型进行总结和回答。 3、OCAI-Service OCAI-Service 是OCAI智能助手的接口层服务。在直接提供服务调用接口的同时,还支持了上下文管理、接口转发、用户识别、身份鉴权、配置管理、反馈收集、统计日志等真实使用情况下必不可少的基础能力。 OCAI-Service 也为多模型选择及函数调用提供了通道。 4、底座模型 OCAI智能助手在处理逻辑的各个阶段使用了 DeepSeek 和混元的各类大模型,包括但不限于 DeepSeek-R1、DeepSeek-V3、混元T1、混元Turbo等。 三、如何使用 当前 OCAI-Agent RPM包已在OpenCloudOS 8/9 软件源上线,使用上述版本的用户可直接执行yum install ocai-agent先进行安装。 RPM包安装链接: OC9:https://mirrors.opencloudos.tech/opencloudos/9.2/AppStream/x86_64/os/Packages/ocai-agent-1.0.0-2.oc9.x86_64.rpm OC8:https://mirrors.opencloudos.tech/opencloudos/8.10/Extras/x86_64/os/Packages/ocai-agent-1.0.0-2.oc8.x86_64.rpm 完成安装后,请在该网址(https://opencloudos.org/ospages/learnmore/ocai)内输入您的邮箱进行注册,并按照邮件中的指引配置访问密钥,即可开始使用。 为了确保服务的稳定性,OCAI-Agent 每天最多可调用 50 次。请合理安排您的使用频率,以免达到调用上限。如有更多需求,请关注后续更新或联系我们获取帮助。感谢您的理解与支持! OpenCloudOS 开源社区是由操作系统、云平台、软硬件厂商与个人携手打造中立开放、安全稳定且高性能的 Linux 操作系统及生态。欢迎上下游厂商、高校及组织加入社区,共建开放共享的安全生态。 扫码添加社区助手进群,添加时备注「OCAI」

优秀的个人博客,低调大师

告别 Kafka,拥抱 Databend:构建高效低成本的用户行为分析体系

用户行为数据埋点指标是数据仓库中不可或缺的重要数据源之一,同时也是企业最宝贵的资产之一。通常情况下,用户行为数据分析包含两大数据源:用户行为分析日志和上游关系型数据库(如 MySQL)。基于这些数据,企业可以进行用户增长分析、用户行为研究,甚至通过用户行为分析精准排查用户问题。 用户行为数据分析的挑战 用户行为数据分析的特点决定了要构建一套可扩展、灵活且低成本的分析架构并非易事,具体表现在以下几个方面: 高流量和大容量:用户行为数据的产生量非常大,对存储和分析能力要求高; 兼顾多种分析需求:既需支持 BI 报表的静态展示,也需满足灵活的 Adhoc 查询; 多样化 数据格式:用户行为数据通常包含结构化数据与半结构化数据(如 JSON); 实时性要求:需要对用户行为快速响应,实现及时反馈。 由于这些复杂性,大多数初创企业和中小型公司通常会选择通用埋点系统(如 Google Analytics、Mixpanel)作为用户行为分析的起点。这些系统只需在网站中插入 JSON 代码,或在 APP 中嵌入 SDK,即可自动采集并上传埋点数据,生成访问量、停留时间、转化漏斗等指标。 然而,通用埋点系统虽然简单易用,但在实际使用中存在以下不足: 数据 明细 的缺失。 通用埋点系统往往不会提供用户具体的访问明细日志,只能在 UI 中查询预设的报表; 自定义查询能力不足。 通用埋点系统的查询模式并非标准 SQL 查询接口,当数据科学家希望构建复杂的 adhoc 查询时,由于缺少 SQL 能力,难以支持复杂的自定义查询; 成本快速上升。 通用埋点系统一般采用阶梯计费模式,往往到了一个阶梯时,费用会翻倍。随着企业流量的持续增长,如果要查询更大范围的用户行为数据时,成本会迅速增加。 自建用户行为分析体系的复杂性 为了应对通用埋点系统的局限性,不少企业在业务增长到一定阶段后,往往都会选择自建一套用户行为埋点数据分析体系。通常情况下,传统自建架构多基于 Hadoop 大数据生态,典型实现流程如下: 在客户端(APP、网站)中埋入 SDK,采集用户行为日志 activity logs; 使用 Activity gateway 埋点指标网关,收集客户端发来的日志,并将日志转到 Kafka 消息总线; 利用 Kafka 将日志 logs 落到 Hive 或 Spark 等计算引擎; 通过 ETL 工具将数据导入数据仓库,生成用户行为分析报表。 虽然这一架构在功能上能够满足需求,但其复杂性和维护成本极高: Kafka 需要依赖 Zookeeper ,还需要配备 SSD 硬盘保障性能。 从 Kafka 到 Data Warehouse 需要 kafka-connect ; Spark 要运行在 YARN 上,ETL 需要 Airflow 管理; 当 Hive 存储达到上限,可能还需要将 MySQL 换成 TiDB 等分布式数据库。 这种架构不仅需要大量的技术团队投入,还极大增加了运维负担。而在企业不断追求降本增效的背景下,传统 Hadoop 架构已不再适合需要简单、高效的业务场景。 新选择:基于 Databend Cloud 的轻量化用户行为分析 随着技术的演进,企业在设计用户行为数据埋点架构时有了新的选择。Databend Cloud 凭借简洁的架构和灵活性,提供了一种高效且低成本的用户行为分析解决方案。 Databend Cloud 的架构特性 100% 面向对象存储,完全存储计算分离,显著降低存储成本; Rust 编写的 Query 引擎性能高,价格低廉。在计算资源闲置时自动休眠,不产生额外费用; 支持 100% ANSI SQL ,支持半结构化数据分析(JSON 和自定义 UDF)。当用户有一些比较复杂的 JSON,可以用内置的 JSON 分析能力或自定义的 UDF,分析半结构化数据; 内置 Task 调度驱动 ETL,完全无状态,自动弹性伸缩。 典型架构实现 企业可以通过以下流程快速搭建用户行为数据分析体系: 日志采集与存储:不再需要 Kafka,用户直接将埋点日志通过 vector 以 ndjson 格式落到 S3。 数据摄入与处理:在 Databend Cloud 中创建一个 copy task 任务,自动把日志拉出来,落到 S3。很多时候,S3 在 Databend Cloud 中可以当做一个 stage,落到 stage 里面的东西就可以被 Databend Cloud 自动吸进来,然后在 Databend Cloud 中进行处理,再从 S3 转出去。 查询与报表分析:通过自动休眠的 Warehouse 运行 BI 报表/即席查询,休眠时不产生任何费用。 通过上述方式,Databend Cloud 能够以最简化的方式实现企业对高效用户行为分析的需求。 案例:Databend Cloud 在用户行为分析的应用实践 某互联网应用公司有一个典型的用户行为分析场景,在做架构选型时选择了 Databend Cloud 进行用户行为数据分析体系的搭建。在使用 Databend Cloud 后,该用户放弃了 Kafka,直接用 Databend Cloud 建了一个 stage ,把用户行为日志落在 S3 中,再用 task 导进 Databend Cloud 中。最终,该公司仅用一个下午便完成了 POC,从复杂的 Hadoop 架构切换到 Databend Cloud,极大简化了运维和操作成本。 用户所需要的准备工作非常简单。首先,准备两个 Warehouse,一个用于 Task 摄入数据,一个用于 BI 报表查询。一般来说,摄入数据的时候可以用一个规格小点的 Warehouse,查询的 Warehouse 规格高一点,因为查询不会一直查,可以节省更多成本。 然后点击 connect 获得一个连接串,这个连接串可以放在 BI 报表用于查询。Databend 提供了各种语言的 Driver。 接下来的准备工作只有三步,一是建表,其中的字段与 NDJSON 格式的日志一致。然后创建一个 stage,将存放用户行为日志的 S3 目录录进来,然后再创建一个 task ,每一分钟或者十秒钟执行一次。它会自动把 stage 里的文件导进来,然后自动把它清理掉。准备工作完成后,就可以源源不断地把用户行为日志录进来。 架构对比与收益 通过对比通用埋点系统、传统 Hadoop 架构和 Databend Cloud,Databend Cloud 的优势显而易见: 架构简洁性:摆脱了复杂的大数据生态,无需 Kafka、Airflow 等组件。 成本优化:利用对象存储和弹性计算实现低成本的存储与分析。 灵活性与性能:支持高性能 SQL 查询,满足多样化的业务场景。 此外,Databend Cloud 提供了快照机制,支持数据的时点回溯(Timetravel),确保数据安全性和可恢复性。 在构建用户行为数据埋点系统时,除了存储、计算方面的成本,维护成本也是架构选型的重要因子。Databend Cloud 通过对象存储与计算分离的架构革新,彻底改变了传统用户行为数据分析体系的复杂性。企业可以轻松搭建一套高性能、低成本的埋点分析架构,实现从数据采集到分析的全流程优化。这一方案无疑为企业在降本增效的同时释放了数据的最大价值。 关于 Databend Databend 是一款开源、弹性、低成本,基于对象存储也可以做实时分析的新式数仓。期待您的关注,一起探索云原生数仓解决方案,打造新一代开源 Data Cloud。 👨‍💻‍ Databend Cloud:databend.cn 📖 Databend 文档:docs.databend.cn/ 💻 Wechat:Databend ✨ GitHub:github.com/databendlab... 询问AI

优秀的个人博客,低调大师

一文搞懂 Vue3 defineModel 双向绑定:告别繁琐代码!

前言 随着vue3.4版本的发布,defineModel也正式转正了。它可以简化父子组件之间的双向绑定,是目前官方推荐的双向绑定实现方式。 vue3.4以前如何实现双向绑定 大家应该都知道v-model只是一个语法糖,实际就是给组件定义了modelValue属性和监听update:modelValue事件,所以我们以前要实现数据双向绑定需要给子组件定义一个modelValue属性,并且在子组件内要更新modelValue值时需要emit出去一个update:modelValue事件,将新的值作为第二个字段传出去。 我们来看一个简单的例子,父组件的代码如下: <template> <CommonInput v-model="inputValue" /> </template> <script setup lang="ts"> import { ref } from "vue"; const inputValue = ref(); </script> 子组件的代码如下: <template> <input :value="props.modelValue" @input="emit('update:modelValue', $event.target.value)" /> </template> <script setup lang="ts"> const props = defineProps(["modelValue"]); const emit = defineEmits(["update:modelValue"]); </script> 上面的例子大家应该很熟悉,以前都是这样去实现v-model双向绑定的。但是存在一个问题就是input输入框其实支持直接使用v-model的,我们这里却没有使用v-model而是在input输入框上面添加value属性和input事件。 原因是因为从vue2开始就已经是单向数据流,在子组件中是不能直接修改props中的值。而是应该由子组件中抛出一个事件,由父组件去监听这个事件,然后去修改父组件中传递给props的变量。如果这里我们给input输入框直接加一个v-model="props.modelValue",那么其实是在子组件内直接修改props中的modelValue。由于单向数据流的原因,vue是不支持直接修改props的,所以我们才需要将代码写成上面的样子。 使用defineModel实现数据双向绑定 defineModel是一个宏,所以不需要从vue中import导入,直接使用就可以了。这个宏可以用来声明一个双向绑定 prop,通过父组件的v-model来使用。 基础demo 父组件的代码和前面是一样的,如下: <template> <CommonInput v-model="inputValue" /> </template> <script setup lang="ts"> import { ref } from "vue"; const inputValue = ref(); </script> 子组件的代码如下: <template> <input v-model="model" /> </template> <script setup lang="ts"> const model = defineModel(); model.value = "xxx"; </script> 在上面的例子中我们直接将defineModel的返回值使用v-model绑定到input输入框上面,无需定义 modelValue 属性和监听 update:modelValue 事件,代码更加简洁。defineModel的返回值是一个ref,我们可以在子组件中修改model变量的值,并且父组件中的inputValue变量的值也会同步更新,这样就可以实现双向绑定。 那么问题来了,从vue2开始就变成了单向数据流。这里修改子组件的值后,父组件的变量值也被修改了,那这不就变回了vue1的双向数据流了吗?其实并不是这样的,这里还是单向数据流,我们接下来会简单讲一下defineModel的实现原理。 实现原理 defineModel其实就是在子组件内定义了一个叫model的ref变量和modelValue的props,并且watch了props中的modelValue。当props中的modelValue的值改变后会同步更新model变量的值。并且当在子组件内改变model变量的值后会抛出update:modelValue事件,父组件收到这个事件后就会更新父组件中对应的变量值。 实现原理代码如下: <template> <input v-model="model" /> </template> <script setup lang="ts"> import { ref, watch } from "vue"; const props = defineProps(["modelValue"]); const emit = defineEmits(["update:modelValue"]); const model = ref(); watch( () => props.modelValue, () => { model.value = props.modelValue; } ); watch(model, () => { emit("update:modelValue", model.value); }); </script> 看了上面的代码后你应该了解到了为什么可以在子组件内直接修改defineModel的返回值后父组件对应的变量也会同步更新了吧。我们修改的其实是defineModel返回的ref变量,而不是直接修改props中的modelValue。实现方式还是和vue3.4以前实现双向绑定一样的,只是defineModel这个宏帮我们将以前的那些繁琐的代码给封装到内部实现了。 其实defineModel的源码中是使用 customRef 和 watchSyncEffect 去实现的,我这里是为了让大家能够更容易的明白defineModel的实现原理才举的ref和watch的例子。如果大家对defineModel的源码感兴趣,请在评论区留言,如果感兴趣的小伙伴比较多,我会在下一期出一篇defineModel源码的文章。 defineModel如何定义type、default等 既然defineModel是声明了一个prop,那同样也可以定义prop的type、default。具体代码如下: const model = defineModel({ type: String, default: "20" }); 除了支持type和default,也支持required和validator,用法和定义prop时一样。 defineModel如何实现多个 v-model 绑定 同样也支持在父组件上面实现多个 v-model 绑定,这时我们给defineModel传的第一个参数就不是对象了,而是一个字符串。 const model1 = defineModel("count1"); const model2 = defineModel("count2"); 在父组件中使用v-model时代码如下: <CommonInput v-model:count1="inputValue1" /> <CommonInput v-model:count2="inputValue2" /> 我们也可以在多个v-model中定义type、default等 const model1 = defineModel("count1", { type: String, default: "aaa", }); defineModel如何使用内置修饰符和自定义修饰符 如果要使用系统内置的修饰符比如trim,父组件的写法还是和之前是一样的: <CommonInput v-model.trim="inputValue" /> 子组件也无需做任何修改,和上面其他的defineModel例子是一样的: const model = defineModel(); defineModel也支持自定义修饰符,比如我们要实现一个将输入框的字母全部变成大写的uppercase自定义修饰符,同时也需要使用内置的trim修饰符。 我们的父组件代码如下: <CommonInput v-model.trim.uppercase="inputValue" /> 我们的子组件需要写成下面这样的: <template> <input v-model="modelValue" /> </template> <script setup lang="ts"> const [modelValue, modelModifiers] = defineModel({ // get我们这里不需要 set(value) { if (modelModifiers.uppercase) { return value?.toUpperCase(); } }, }); </script> 这时我们给defineModel传进去的第一个参数就是包含get和set方法的对象,当对modelValue变量进行读操作时会走到get方法里面去,当对modelValue变量进行写操作时会走到set方法里面去。如果只需要对写操作进行拦截,那么可以不用写get。 defineModel的返回值也可以解构成两个变量,第一个变量就是我们前面几个例子的ref对象,用于给v-model绑定。第二个变量是一个对象,里面包含了有哪些修饰符,在这里我们有trim和uppercase两个修饰符,所以modelModifiers的值为: { trim: true, uppercase: true } 在输入框进行输入时,就会走到set方法里面,然后调用value?.toUpperCase()就可以实现将输入的字母变成大写字母。 总结 这篇文章介绍了如何使用defineModel宏实现双向绑定以及defineModel的实现原理。 在子组件内调用defineModel宏会返回一个ref对象,在子组件内可以直接对这个ref对象进行赋值,父组件内的相应变量也会同步修改。 defineModel其实就是在子组件内定义了一个ref变量和对应的prop,然后监听了对应的prop保持ref变量的值始终和对应的prop是一样的。在子组件内当修改ref变量值时会抛出一个事件给父组件,让父组件更新对应的变量值,从而实现双向绑定。 使用defineModel({ type: String, default: "20" })就可以定义prop的type和default等选项。 使用defineModel("count")就可以实现多个v-model绑定。 通过解构defineModel()的返回值拿到modelModifiers修饰符对象,配合get和set转换器选项实现自定义修饰符。 关注公众号:【前端欧阳】,解锁我更多vue原理文章。还可以加我微信,让你的朋友圈多一位对vue有深入理解的人。也可以通过微信给我说你想看哪些vue原理文章,我会根据大家的反馈进行创作。

优秀的个人博客,低调大师

智能运维应用之道,告别企业数字化转型危机

云智慧 AIOps 社区是由云智慧发起,针对运维业务场景,提供算法、算力、数据集整体的服务体系及智能运维业务场景的解决方案交流社区。该社区致力于传播 AIOps 技术,旨在与各行业客户、用户、研究者和开发者们共同解决智能运维行业技术难题,推动 AIOps 技术在企业中落地,建设健康共赢的AIOps 开发者生态。 面临的问题及挑战 数据中心发展历程 2000年中国数据中心始建,至今已经历以下3大阶段。早期:离散型数据中心IT因以项目建设为导向,故缺乏规划且无专门运维管理体系,此外,开发建设完的项目均是独立运维维护,因此效率低下。中期:各行各业进行了应用大集中,逐步按照标准化体系建设了生产中心、灾备中心,且引入“两第三中心”的模式。此外,该阶段开始有了系统规范的运维体系,具有代表性的建立了IT服务体系、监控体系等运维框架。另一方面,也通过流程实现跨部门的运维协,有了清晰的开发、测试、运维的边界,各专业领域内的运维工具蓬勃发展。后期:自2015年后,由于IT技术的高速发展,业务需求的不断变化,数据中心逐步向多活混合云环境进行演进,从金融行业逐步扩展到运营商、能源、政府、军工等行业。数据中心开始围绕服务和资源的供给提供运维保证,运维工作逐步走向一体化、自动化,最终向着智能化演进。本篇文章表述的解决方案则主要是针对自动化运维场景。 数据中心现状分析 因当前大部分数据中心运维环境较为复杂,且IT技术栈具有多样性,故而导致运维对象愈发庞大,运维人员每日的运维工作越来越复杂繁琐。经统计,上述复杂的运维工作中的70%均是规律且重复性的,因此导致人力投入成本越来越大。此外,因缺乏标准化运维工作流程,所以运维工作质量只能通过技术人员个人主观因素来判定。另一方面,大部分企业运维工作人员沉底下来的知识无法有效复用,交接工作流于形式,因此导致运维工作效果一般。 除上述70%的重复性运维工作外,还有30%的运维工作是属于复杂且操作风险高的。企业经常会因为技术人员个人因素造成了业务的隐患。整体运维工作效率偏低,带来了业务中断时间长,应急处置效果低的问题。 自动化运维挑战与最佳实践 基于以上数据中心的运维问题,云智慧根据自身在自动化运维的多年经验,总结以往在进行自动化运维项目建设时遇到的挑战。如云智慧很多客户建设了自动化运维平台,但平台本身缺少开箱即用的场景;此外,部分客户项目的建设周期过长,且缺少行业最少实践的参考。 云智慧的Automation平台在各行各业都有交付,且将各行各业常用的自动化运维业务场景沉淀成了标准产品组件,真正做到了开箱即用。如海量的巡检指标,应用发布的标准化编排,灾切的最佳实践等,均能大幅缩短自动化平台建设周期情况下,给出最佳实践供企业参考选择。 传统的自动化平台大部分以脚本调度功能为主,缺少了各种无代理协议的远程采控机制。云智慧基于运维中台化的理解,打造了专门的全栈采控中心cdc,在支撑脚本类的调度功能以及开机即用的功能下,还支持了各种硬件、虚拟化、容器、微服务、业务类等封装好的采控API接口。如各类虚拟化的创建、扩缩容接口,硬件IPMI的采控协议,K8S的接口等。 云智慧采用分布式大数据架构和智能化调度引擎解决了高并发处理能力问题,支持百万级管理节点高效率高文档的工作状态。 以往的自动化工具缺少标准化和开箱即用的服务调用接口,现今其他运维工具很多缺少场景联通,容易形成自动化数据孤岛。云智慧依托自身的运维中台,具备开箱即用的标准化服务接口,不管是其他运维工具调用自动化工具,还是自动化工具接入第三方运维工具的数据,均可以满足。 解决方案与功能场景介绍 自动化运维平台架构图 下图为云智慧自动化运维平台的架构图,分为以下几个纬度: 纳管对象层:包含数据中心日常运维的全栈对象,例如操作系统、数据库、中间件、物理服务器、业务应用、网络设备、存储、云以及虚拟化资源等。 执行通道层:针对下图被管理的对象,云智慧采控中心cdc提供了agent代理模式,以及像ssh、ipmi、snmp、jdbc、smi-s、jmx和各类api等的无代理采控协议。 服务管理层:云智慧具有标准化的流程管理功能,如统一脚本管理、操作编排、脚本执行管理、定时任务、各类查询功能。上述通用化功能均会为上层自动化运维场景提供底层支撑能力。 运维场景层:该层包括应用发布管理、自动化巡检、软件安装、合规建立、运维工具箱、应急处置等。 互联互通:该模块中的运维工具可以是第3方的工具。云智慧作为智能化全栈运维的厂商,除了自动化模块外,同时也具备IT服务管理、监控、配置、可视化等运维通用化工具。因此可以帮助企业客户建立一整套的运维中台最佳实践。 功能场景介绍 高效的应用发布管理 由于传统的应用发布大部分依靠手工进行,所以发布一个系统大概需花费1-2个小时。使用云智慧的自动化应用发布发布后时间可缩短至10-30分钟有效的提高发布效率。云智慧自动化运维平台整体是基于DevOps理念,目的是加强开发、测试和运维之间沟通、协作和集成,实现应用发布交付的标准化。此外,平台整体发布模型采用“环境”+“组件”的设计,同时提供可视化的编排功能。云智慧可视化编排引擎使用的是自身运维中台中服务编排的通用化能力,支持复杂的串并行,节点可调用不同环境和组件,具有全局参数化等能力,同时支撑完全自动以及半自动化等不同场景。最后,平台支持节点处跳过、重复执行、暂停等通用化细节处理能力。 另一方面,云智慧自动化运维管理平台还提供发布驾驶舱功能、各种数据看板,可进行全局概览。云智慧借助自动化平台通用化能力,如命令、脚本集中管理等,支持有代理和无代理模式,细粒度、全方位的进行权限管理控制,来确保所有运维操作安全可控。 便捷的 自动化 巡检 云智慧自动化平台中内置了全栈式巡检模版,从常用的操作系统、数据库、中间件到网络、硬件、存储、云、容器、微服务等,完全地做到了开箱即用。依托云智慧运维中台指标体系能力,企业也可以自行维护编辑。 巡检执行可以手工触发,也可以依靠定时任务自动触发。传统巡检依靠人工进行,每次巡检时间30-60分钟不等,自动化巡检可将巡检时间降低至1-2分钟,此外,巡检报告还可以自动发送给管理或者领导,并将问题巡检项标注出来。巡检指标与基准值的比对设置是依托云智慧运维中台中指标管理下面的阈值管理。该项支持传统的静态阈值、动态阈值和巡检指标相结合,还支持巡检结果单人/双人复合,可按照业务系统纬度或者设备类型纬度进行自动巡检工作。此外,还可结合云智慧知识库,给出异常巡检项处理办法参考。 巡检还支持异常巡检项生成工单功能,企业可按需进行使用。云智慧运维中台指标体系拥有良好的高并发能力,可以同时支持百万级管理对象同时并行巡检。 灵活的运维工具箱 运维工具箱的关键技术在于开箱即用的原子工具沉淀。云智慧拥有10多年自动化运维经验,具有丰富的内置开箱即用原子化工具集。 企业运维管理人员通过云智慧提供的工具集,只需要输入指定的参数(如IP地址,文件系统目录等)自动化工具便可自动执行,还可同时并行调用多个工具或并行执行多个对象。此外,上述工具集后期是可以编辑维护的,企业可根据自身需求补充常用原子化工具集,经过审批后方能发布上线使用。所有自动化操作调度的执行过程都有日志留痕,所有的操作都支持后期审计,还可与企业堡垒机进行对接。可减少人工直接与生产环境进行交互,降低由人工误操作产生的生产风险。 安全稳健的批量 自动化 批量自动化主要应用于银行日间、日终的跑批业务,因此需要时刻保证整个自动化平台安全稳健的运行。并且在整个跑批过程中,需要全程监控,出现极端系统灾难后,要有灾难恢复机制。云智慧的自动化平台是可以取代control-m的功能的,除了常用的功能外,还支持批量的拓扑分析。在做control-m迁移时,可以将control-m导出xml文件中的关键要素字段与云智慧平台进行比对映射,然后将其转化成exl字段文件。此外,平台支持承接使用原系统上的脚本,将转化过的exl文件导入到云智慧的自动化平台里,可以自动生成批量调度的拓扑视图,再进行后期的参数化调整,便可以完成迁移工作。 一键式灾备切换 灾备切换的业务场景因涉及预案、灾切模型、签到等,故较为复杂。关键点在于数据中心级的灾备切换和灾切演练,一键式灾切是为应对突发事件时提升应急处理能力。自动化编排能力可以支撑复杂灾切流程编排。像灾切里面涉及到的环境、数据一致性、网络连通性、配置一致性检查,云智慧都有相关的功能做支撑。此外,云智慧额外提供沙盘演练的功能,整体的灾备模型可以与目标解耦,满足流程复用的要求。还有单独的移动pad作为灾切的控制端,体现一键切换,切换过程中的各项数据都会实时监控,反馈到灾切大屏上。 安全合规审计 云智慧提供开箱即用的行业基准,例如CIS、PCI DSS、SOX等,一套平台即可提供不仅仅是物理服务器和虚拟机,还包括数据库、中间件和网络等数据中心资源的合规审计。此外,还提供当前和历史的漏洞风险趋势详细报告,建立配置标准并监视变更情况,通过8,000多个开箱即用的自动化操作流程在问题修复时大大缩短修复时间。与此同时,还支持数以千计的设备类型、型号组合。 一键开闭市(券商) 对于证券行业,每天需要定时执行一系列业务操作,如开市流程、闭市流程。上述业务场景便要求运维人员需要根据业务规则在不同设备上的应用系统进行操作运行。此业务流程比较复杂,同时具有串行、分支、判断、并行、聚合、循环,为了降低流程的复杂性,需要各种子流程;此外,业务规则判断也比较复杂,需要根据业务数据来判断流程执行是否有错误;与此同时,在中间步骤执行错误时,需通过人工修复错误或者有管理员角色确认后,方能继续进行。云智慧提供的自动化运维平台对对流程执行有严格的安全控制,如权限控制、时间控制等。除了一键开闭市,还能为券商清算业务提供清算前准备工的自动化业务能力。除了日常运维工作,还有一部分业务操作也可以使用自动化工具来实现。 软件 自动化 管理 云智慧自动化运维平台中自带软件介质管理平台,可上传管理各类软件的介质版本,支持并行在多个目标对象上执行安装部署步骤。与此同时,平台提供丰富的交互参数,文件参数、加密参数等。除了安装功能,平台也支持卸载启动等等,依托云智慧运维中台中采控中心的通用化能力。 补丁 自动化 管理 为预防系统漏洞带来的安全隐患,系统运维人员必须定期为操作系统安装补丁。但在传统的运维模式下,系统运维人员很难直观了解每台机器的补丁安装情况,因此需要针对每一台机器执行漏洞扫描并根据扫描结果为每台机器安装补丁。这种手动操作的方式,不仅耗费大量时间,还容易出错。自动化作业产品提供补丁管理、主机扫描、补丁安装等功能,不仅能让运维人员了解服务器的健康状态,还能够根据扫描结果为服务器安装缺失的补丁,及时解决安全隐患。 云智慧的补丁自动化管理功能可以和合规审计功能一起使用,修复一些缺少的补丁问题。重点是在批量并发执行,主动扫描并发现当前主机操作系统、数据库、中间件补丁安装情况。与此同时,云智慧会定期更新补丁库。 应用发布一体化场景 应用发布的一体化场景是自动化运维的融合场景,主要出现在实际的发布场景中,场景包含了ITSM工具、配置管理工具、自动化发布工具、统一监控工具等多种工具。应用发布的一体化场景是典型的一体化协同联动场景。任务由导入生产排期信息同步到ITSM系统,经过ITSM审批,确定发布任务;修改任务状态(从待审批到待发布)时,ITSM会通知监控系统在发布期略过该业务系统的监控,等待发布时间后,可以由人工触发或者自动触发进行自动化发布;发布过程中,监控系统会过滤掉该业务系统的告警,发布完成后,发布任务状态同步回传给ITSM系统,ITSM结束发布流程发起配置流程,经过一系列的请求、采集、比对最终更新完该系统的最终配置信息到配置库里,一体化流程结束。 流程即服务应用场景 流程即服务的联动场景主要体现的是各类服务请求可以通过自动化平台进行自动交付的场景。企业通过服务门户选择各类服务请求,服务请求的工单经过审批后,按照不同业务场景触发自动化平台的API服务接口,ITSM工单中的参数同步到自动化平台中,自动化平台按照业务场景进行自动交付,自动交付完成后回传结果至ITSM平台,可以大幅缩短交付时间。像日常虚拟化资源扩缩容服务请求,标准化数据变更,标准化环境变更等。 故障处置一体化场景 故障处置一体化的场景里面涉及预案、处置流程编排、以及与ITSM联动。正常触发故障处置一体化的场景可以由管理员手工触发,也可以由监控告警自动触发,触发之后根据系统内置的预案(如进程启停、清理空间等)生成一张ITSM处置类或者变更类的工单,根据紧急度、影响度多种因素来影响ITSM流程流转的节点分级,包含紧急变更、一般变更、标准变更,每种类型涉及到审批人及审批流程均有不同。审批也可以包含自动审批、人工审批等,最终审批结束后触发处置工具进行自动化处置工作,调度结束后回传结果到ITSM工单进行审核。 案例分享 典型案例-某银行 企业背景:该企业由于数据中心的运维对象被管设备对象大概有3000多个,企业运维技术人员每天都要做多次完整的巡检,每次完整的巡检要花费1个小时以上,巡检完的结果也没有特别好的展现形式,都是填到一些制式的表里,他们的需求特别清晰,都是自动化巡检。 解决方案:云智慧经过3个月的项目建设,纳管了全行3000多的软硬件运维对象,用云智慧的自动化系统1分钟之内就可以完成1次完整的巡检工作,巡检完的结果,通过云智慧的巡检大屏幕以及数据看版,还可生成完整的巡检报告。如果在巡检过程中发现异常的点,还会推送到该企业的一体化告警平台,进行告警。这个项目是一个短平快的项目,依托云智慧内置的开箱即用的巡检指标,在极短的周期完成测试上线工作,而且直接提升了日常运维的效率。 典型案例-某制造业集团公司 企业背景:该企业在数字化转型过程中,发现缺乏体系化、规范化的运维流程。日常的运维工作过度依赖运维人员的能力和态度,风险比较高,有新的运维人员进来,如果技能不达标,会造成极高的业务风险。为了解决上述问题,该企业打算利用自动化平台来减少对运维人员技术能力的依赖,包含降低由于运维人员态度造成的风险。 解决方案:云智慧经过大概半年的建设,该企业整体运维工作效率提升了70%,降低了30%日常运维的的操作风险。企业应用发布纳管了56套应用系统,应用发布的自动化率在90%以上,每月常规发版次数超过80次。网络自动化模块,纳管了500多台网络设备,交换机、防火墙、路由器、负载均衡等都均被纳管,自动化率达到了95%,月均常规网络变更40多次。除了网络设备,该企业还纳管了2000多个像操作系统、数据库、中间件的运维对象,自动率达到了98%,运维工具内的原子化工具集超过2000种,每个月运维工具箱使用次数超过4000次。此外,该企业还做了灾备切换,将最重要的30套系统纳管进来了,灾切的自动化率在55%,在60分钟内就可以完成数据中心级的灾备切换。这30套重要的业务系统,还做了超过100套的应急处置预案,主要是固化下来一些日常的故障自愈场景。自动化平台内包含超过100种以上的软件版本介质包,日常软件安装的自动化率超过99% 。 价值与优势 自动化 运维全栈式采控能力 依托云智慧运维中台中全栈的采控能力,不光可以对各类平台设备,像操作系统、数据库、中间件进行采控调度,还支持各类异构的自动化作业,比如除了常见的各类脚本,还支持http作业、c/s架构的软件、as400的作业,像400属于金融行业比较老的系统了,但是这些都可以支持,还有像数据库的SQL、存储过程的作业、邮件的、FTP等等这些类型的作业都可以完美支持。 成熟的开箱即用 自动化 业务场景 云智慧提供的自动化平台,拥有成熟的开箱即用的业务场景,能极大的缩短项目的建设周期。下图常见的9个场景,加一体化的场景,都能比较好的支持,像应用发布、自动巡检、运维工具箱、灾切、批量、网络、应用处置、安全合规、软件安装。 安全可信的技术平台 云智慧提供安全可信的技术平台,云智慧的全栈产品都是自主研发的,规避了安全缺陷隐患。可以在国产化信创环境上运行,像国产化的cpu(鲲鹏)、国产化的操作系统(麒麟、统信)、数据库(人大金仓、达梦)、中间件(东方通、宝兰德)等等。国家近期发布了最新的数据安全法,云智慧的自动化平台符合国家的各项数据安全法规,不管是数据传输、存储、解析等等环节,都安全合规。这个平台经过了10年以上的长期迭代,稳定率超过了5个9,支持各类异常熔断、极端情况下的灾难恢复。 开源福利 云智慧已开源数据可视化编排平台 FlyFish 。通过配置数据模型为用户提供上百种可视化图形组件,零编码即可实现符合自己业务需求的炫酷可视化大屏。 同时,飞鱼也提供了灵活的拓展能力,支持组件开发、自定义函数与全局事件等配置, 面向复杂需求场景能够保证高效开发与交付。 点击下方地址链接,欢迎大家给 FlyFish 点赞送 Star。参与组件开发,更有万元现金等你来拿。 GitHub 地址: https://github.com/CloudWise-OpenSource/FlyFish Gitee 地址:https://gitee.com/CloudWise/fly-fish 万元现金活动: http://bbs.aiops.cloudwise.com/t/Activity 微信扫描识别下方二维码,备注【飞鱼】加入AIOps社区飞鱼开发者交流群,与 FlyFish 项目 PMC 面对面交流~

优秀的个人博客,低调大师

JustAuth v1.16.3 发布,新增 Builder 模式,告别 if 享受极致的体验!

更新内容 发布 v1.16.3 新增 集成“企业微信的第三方应用”平台登录 PR AuthRequst增加Builder构建方式,使用起来更简单。 (gitee *27) 使用 Github Action 添加发布快照的 workflow。 (#126) 新增了企业微信的第三方应用登录,AuthWeChatEnterpriseThirdQrcodeRequest。 (#127) 添加快照版本对应更详细的文档。 (#128) 修改 在 Gitee PR (*27) 的基础上重构代码,增加 Builder 方式创建 AuthRequest 解决 Line 登录的错误。#122 Builder 方式使用介绍 Builder 方式一 静态配置AuthConfig AuthRequest authRequest = AuthRequestBuilder.builder() .source("github") .authConfig(AuthConfig.builder() .clientId("clientId") .clientSecret("clientSecret") .redirectUri("redirectUri") .build()) .build(); Builder 方式二 动态获取并配置AuthConfig AuthRequest authRequest = AuthRequestBuilder.builder() .source("gitee") .authConfig((source) -> { // 通过 source 动态获取 AuthConfig // 此处可以灵活的从 sql 中取配置也可以从配置文件中取配置 return AuthConfig.builder() .clientId("clientId") .clientSecret("clientSecret") .redirectUri("redirectUri") .build(); }) .build(); Builder 方式支持自定义的平台 AuthRequest authRequest = AuthRequestBuilder.builder() // 关键点:将自定义实现的 AuthSource 配置上 .extendSource(AuthExtendSource.values()) // source 对应 AuthExtendSource 中的枚举 name .source("other") // ... 其他内容不变,参考上面的示例 .build();

优秀的个人博客,低调大师

告别祖传代码 -Java 8 语境下模板模式的再审视

点击上方“蓝字”关注我们 作者 | 乔迟,武汉事业群 编辑 | 陈婷 《设计模式:可复用面向对象软件的基础》这本书自 1994 年问世以来一直被视为面向对象理论的经典著作,尤其在 Java 世界,无数 Java 程序员将其视为软件开发架构设计的金科玉律。26 年以来,对于这本书里 23 种设计模式讨论与解读的书籍出版了一本又一本。令人遗憾的是,从 1994 年出版时算起,Java 已经从 1.0 版本迭代到了 14,而设计模式再版了几十次也并没有在内容上和 Java 技术的发展相适应。 老祖宗 26 年前留下的代码,在今天函数式编程满天飞的时代还能呼风唤雨经久不衰吗?在软件编程这个快速迭代的领域里,答案无疑是否定的,大神 Joshua Bloch 在近年最新的 Effective Java 第三版中就对常用的模板模式提出了批评: The Template Method pattern [..] is far less attractive. The modern alternative is to provide a static factory or constructor that accepts a function object to achieve the same effect. 本文就试图在 Java 8 语境下重新审视模板模式的设计与实现。 模板模式回顾 在经典的 GOF 23 种设计模式中,模板模式(或 称 模板方法模式)因为简单明了、实现方便,很快就成为了在日常开发中最受欢迎的设计模式之一,在各种系统实现中被广泛使用。 模板模式最常见的应用场景在处理流程算法相对固定的一类业务中,提炼出算法骨架和原子动作集合,通过骨架代码(模板模式中成为模板方法)对原子动作进行组装,形成最终的业务逻辑实现。在面对后续不同的子业务场景时,只需要继承实现不同的子类,覆盖对应的差异性原子动作,即可很快的完成对一个子业务场景的封装实现。 模板模式类图如下: 例如,一个业务可以分成三步,那么可以提炼出父类 AbstractProcessor public abstract class AbstractProcessor { public final void process() { step1(); step2(); step3(); } public abstract void step1(); public abstract void step2(); public abstract void step3();} 流程逻辑被封装在父抽象类的 process 方法中,客户端只需要调用父类的 process 骨架方法即可实现对应的业务逻辑: public class ClientLogic { private AbstractProcessor processor; public void foo() { processor.process(); }} 接着,根据某个实际场景开发对应的实体类,例如 public class ConcreteProcessor1 extends AbstractProcessor { @Override public void step1() { System.out.println("Step1 Logic in ConcreteProcessor1"); } @Override public void step2() { System.out.println("Step2 Logic in ConcreteProcessor1"); } @Override public void step3() { System.out.println("Step3 Logic in ConcreteProcessor1"); }} 假设现在有新的业务场景,第一步和第二步依然和 ConcreteProcessor1 的逻辑一致,仅第三步略有不同,此时就可以通过继承的方式编写 ConcreteProcessor2 覆盖 step3 方法: public class ConcreteProcessor2 extends ConcreteProcessor1{ @Override public void step3() { System.out.println("Step3 Logic in ConcreteProcessor2"); }} 这样一来,所有流程逻辑和相对稳定的原子动作都可以进行复用,在应对不同的业务场景时,只需要覆盖对应的原子动作就可以快速实现,提高了代码复用率,降低了维护成本。 老祖宗的代码看起来确实很香,然而在实际开发使用过程中模板模式有什么问题呢? 现实的问题 以我参与过的一个项目为例。 该项目需要对接上千家外部单位,虽然对接单位众多,但是业务流程相对固定,设计开发人员很快就意识到可以通过模板模式对整个业务流程进行封装,通过对业务流程的梳理提炼,很快设计了一个父类(示例代码): public abstract class AbstractProcessor { public final void process() { step1(); step2(); step3(); step4(); step5(); } public abstract void step1(); public abstract void step2(); public abstract void step3(); public abstract void step4(); public abstract void step5();} 并且开发了对应的默认实现类: public class DefaultProcessor extends AbstractProcessor { @Override public void step1() { System.out.println("default step1"); } @Override public void step2() { System.out.println("default step2"); } @Override public void step3() { System.out.println("default step3"); } @Override public void step4() { System.out.println("default step4"); } @Override public void step5() { System.out.println("default step5"); }} 于是形成了这样的树状类图关系: 接下来对于第一家外部对接单位 A,分析其业务逻辑发现只需要修改默认实现的第一步即可,于是类图变成下面这样: 接着开始实现外部单位 B,发现只需要修改默认实现的第二步,于是类图变成: 在对接外部单位 C 时发现,其第一步逻辑与外部单位 A 类似,因此可以进一步继承复用,于是形成如下的类图结构: 对接了几十家外部单位后,类图结构变成了一颗茁壮的树: 这时问题出现了,开发人员很快发现随着对接单位的增多,模板树状结构越来越复杂,随之而来的问题是: 1.对于任意一个叶子节点的模板,它的 5 个步骤原子方法逻辑分散在整个继承逻辑的父类之上,单独阅读叶子节点的代码根本无法理解完整的模板逻辑。 2.要加入一家新的外部单位,如果想要正确实现逻辑复用,就必须全面分析模板树,找到对应的继承挂载点。 3.如果交付时间紧张,很难完成对模板树的梳理,取而代之的是从一个最熟悉的叶子节点开始挂载,这样就产生了破窗效应,后续的模板大量倾斜挂载在某个叶子模板之下,完全背离了原有设计。 那么问题到底出在哪呢? 问题 回顾一下 GOF 的设计模式,其中有两条最为重要的原则: 1.Program to interface, not implementation 面向接口编程 2.Favor object composition over inheritance 聚合优于继承 而恰恰是 GOF 的模板模式,从一开始就违背了自己定下的原则,通过抽象类继承的方式进行实现。模板模式的这种实现方式在小规模的模板复用时尚且可以接受,一旦模板数量上升,整个模板继承的可维护性就会严重下降。在上面实际项目的实践中,正是违反了聚合优于继承的原则,导致整个设计在模板数量增长时,失去了可维护性,背离了设计目标。 观察一下现实生活就很容易发现聚合优于继承的情况。例如去西餐店吃饭,点餐时服务员会拿出菜单让顾客在前菜、主菜、饮料、甜点上分别选择,这就是一种典型的聚合实现的模板模式,前菜、主菜、饮料、甜点对应模板模式的原子方法,最终形成的菜单对应模板模式的模板方法。没有西餐店会提供一个基于继承的菜单服务,告诉客户如果您要将饮料从威士忌换成葡萄酒就需要选取套餐 5 而不是套餐 4。 那么聚合到底为什么优于继承呢?这就需要从面向对象理论中的耦合度计算说起。 理论 一个有趣的经验是,在我参与的很多面试中,如果问面试者为什么使用设计模式,对方会很快告诉你这是为了“解耦”,但是如果进一步追问”这两个相关的类,耦合到底有多紧”时,绝大部分面试者都是以下两种表情: 耦合度成为了开发者口中皇帝的新装式的概念,所有人都知道需要松耦合,但是耦合如何度量、到底如何松耦合、一个代码修改是消除耦合还是增加耦合这类问题大家往往一知半解。事实上,面向对象基础理论中对于耦合度是有公式可以度量的。 对于任意两个存在关联关系的类 A 和 B,它们的关系无外乎下面五种: 两个类 A、B,它们之间耦合度的计算公式为: 表示类 A 和类 B 之间共享代码的行数, 表示类 B 的代码总行数, 表示类 A 和类 B 的关系系数。 对于系数 ,取值范围从 0 到 1,0 表示没有关系,1 表示最大关系,可以将取值对应到 Dependency、Association、Aggregation、Composition、Inheritance 五类关系中,取值从小到大。 对于共享代码行数,如果类 A 被类 B 继承,那么等于类 A 所有非 private 修饰的代码行数;如果类 A 只是作为引用被类 B 调用,那么 等于类 A 所有 public 方法签名的行数。 从以上公式可以看出,在继承关系中,两个类的耦合度不仅关系系数取值更大,而且 取值也更大,从而导致耦合度更高。 解决方案 根据上面的理论分析可以看出,要优化现有的模板模式实现,其主要思想是降低耦合度。 可以通过将继承改为聚合的方式实现第一版的优化: public class TemplatePattern1 { private Step1Processor step1Processor; private Step2Processor step2Processor; private Step3Processor step3Processor; private Step4Processor step4Processor; private Step5Processor step5Processor; public interface Step1Processor { void step1(); } public interface Step2Processor { void step2(); } public interface Step3Processor { void step3(); } public interface Step4Processor { void step4(); } public interface Step5Processor { void step5(); } public void templateMethod() { step1Processor.step1(); step2Processor.step2(); step3Processor.step3(); step4Processor.step4(); step5Processor.step5(); }} 在上面的代码中,将原有以继承方式实现的模板各原子方法变为通过聚合方式引入的各个处理器接口引用,注入不同的原子方法处理器就可以很容易的改变模板方法的逻辑。 通过这种实现解决前面的实际问题,对于任意一个需要对接的外部单位,只需要明确该单位在模板每个步骤中具体应该采用的处理器类型,然后简单配置组合就可以快速形成新的模板处理逻辑。 进一步的,根据前面耦合度计算的公式,如果使用方法参数而非成员变量的方式传入各步骤处理器,将会进一步降低耦合度,这样就形成了第二版优化代码: public class TemplatePattern2 { public interface Step1Processor { void step1(); } public interface Step2Processor { void step2(); } public interface Step3Processor { void step3(); } public interface Step4Processor { void step4(); } public interface Step5Processor { void step5(); }public void templateMethod(Step1Processor step1Processor,Step2Processor step2Processor, Step3Processor step3Processor,Step4Processor step4Processor,Step5Processor step5Processor) { step1Processor.step1(); step2Processor.step2(); step3Processor.step3(); step4Processor.step4(); step5Processor.step5(); }} 接着,通过 Java 8 引入的接口静态方法实现静态工厂模式(这里也可以看作是函数式编程中高阶函数模式),并通过 Lambda 表达式进一步完善可读性后得到第三版代码: public interface TemplatePattern3 { void templateMethod(Step1Processor step1Processor, Step2Processor step2Processor, Step3Processor step3Processor, Step4Processor step4Processor, Step5Processor step5Processor); static TemplatePattern3 getTemplate(Step1Processor step1Processor, Step2Processor step2Processor, Step3Processor step3Processor, Step4Processor step4Processor, Step5Processor step5Processor){ return (step1Processor1, step2Processor1, step3Processor1, step4Processor1, step5Processor1) -> { step1Processor1.step1(); step1Processor1.step1(); step1Processor1.step1(); step1Processor1.step1(); step1Processor1.step1(); }; }} 这里需要补充的是,从前面的理论分析可以看出,要想尽量降低耦合度,接口的设计者就应该抛弃继承改为使用方法参数传值的方式,而承载这个思想最好的实现正是 Java 8 引入的 Lambda 表达式,因为 Lambda 表达式不拥有任何成员变量,所有的逻辑引用来源都必须是参数传入,从这个意义上来说,尽量选择 Lambda 表达式作为业务逻辑承载的主体是一种能够显著降低系统耦合度的最佳实践。 总结 1.《设计模式》中模板模式的原始实现存在缺陷,应通过聚合优于继承的思想进行改造; 2.类耦合度可以通过公式计量,最低的耦合关系是 Dependency,最高的耦合关系是继承; 3.Lambda 表达式天然适合实现 Dependency 关系,应该尽量选择作为业务逻辑封装的实现主体。 猜你喜欢 OCR数据处理(下篇) 政务服务体验设计背后的故事 | 云南办事通 APP 2.0 设计(文末招聘!!!) 首屏加载速度慢?试试这 6 个技巧 Docs as Code | (文末招聘!!!) 近期活动:金科大咖 云讲坛 如何融汇科技,打造数字化转型引擎? 如何共享资源,主动赋能同业与社会? 如何共建生态,构建无界多维的生态空间? 如何创新引领,成为新金融的实践者和先行者? 38位金融科技大咖应邀云端,与你探索未来科技前沿方向。豪华专家师资队伍,精选38项高端课程,尽在优源汇! 参与方式:关注公众号,点击“金科大咖”进入直播间 本文分享自微信公众号 - 金科优源汇(jkyyh2020)。如有侵权,请联系 support@oschina.cn 删除。本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

优秀的个人博客,低调大师

DataQL 4.1.3 发布,支持 SQL 执行,从此告别 Mapper、BO、VO、DO、DAO

新增 新增 Dataway 框架 dataway 通过数据库探测机制来实现确定 SQL 执行方案。 DataQL 增加可以构建多个独立的环境。其中 dataway 使用独立的环境。 DataQL 新增 SQL 代码片段执行器,开启 DataQL + SQL 模式。支持分页模式,并兼容多种数据库。 CorsFilter web框架增加一个跨域的 Filter 工具类。 DataQL-fxDataQL FragmentProcess 接口新增批量处理能力。 DataQL-fx增加完成事物函数库,完整支持 7种事务传播属性。 DataQL-fx增加 web 相关的 函数库 DataQL-fx增加 加密解密 udf 工具。 优化 DataQL 语法解析器新增支持 标识符可以通过 `` 来囊括特殊字符例如:+、-、*、/ 等符号 DataQL QueryApiBinder 的 bindFinder 支持 Supplier了。 修复 ApiBinderCreater 拼写错误 ApiBinderCreator。 2.mapjoin 函数名改为 mapJoin。 修复 Hasor-web:InvokerSupplier,修复 npe 问题。 ------------------------------------------------------------------------------------------------ SQL执行器的一些一些内容 关于SQL执行器 配置数据源 SQL方言 执行 SQL SQL 参数化 SQL 注入 Ognl 表达式 批量操作 执行结果拆包 分页查询 分页信息 数据库事务 作为Dao层 配置 Maven 插件 编写QL文件 执行QL查询 消息来源:https://www.hasor.net/web/dataql/index.html#sql

优秀的个人博客,低调大师

苹果彻底告别“芯片门” 安卓N最终预览版发布

1. iPhone 6s发生的“芯片门”时间让人记忆犹新,不过好消息是,根据台媒《电子时报》消息,苹果已经在今年处理器生产合作伙伴名单中花掉了三星的名字,也就是说今年所有的A10芯片都将由台积电生产。另外值得注意的是,报道还指出苹果的这一计划很可能还将延长至明年的iPhone 7s(或名为iPhone 8),因此台积电最早将在2017年第二季度开始进行A11芯片的小规模量产。 2. 尽管我们都知道Android N应该就是Android 7.0,不过在开发者预览阶段,谷歌当前仍然以Nougat牛轧糖代号来称呼它。今天早些时候,谷歌发布了Android N第5个开发者预览版,这也是新系统正式发布前的最后一个预览版本。Android N本身进行了大量改进,比如加入了原生多窗口模式,支持通知消息直接回复,优化续航和性能等。最新预览版并没有加入太多的新特性,主要还是集中于bug修复(最明显的体现在快捷设置菜单),唯一的新特性就是隐藏了一个彩蛋。 3. 日前有消息称索尼将在今年的IFA 2016柏林消费电子展上推出两款新机,型号为分别为Sony F8331 以及 F8332,而且预计隶属于Xperia Z系列。继此前F8331配置现身GFXBench基准测试数据库之后,现在GSMArena首次曝光了该机的真机照。 从谍照来看,我们可以发现索尼这次明显在手机的外观设计上下了更大的功夫,手机屏幕侧边微微弯曲,向机身有一个完美的过渡,另外索尼也首次尝试加入了Type-C接口。 4. 在几年前,苹果的MacBook Air的确给人留下了深刻的印象,但不可否认的是,如今MacBook Air的地位正变的越来越尴尬,一方面其便携性不如12英寸MacBook,而另一方面性能又比不上MacBook Pro。此前有消息称苹果正打算彻底放弃这一产品线,现在著名苹果分析师凯基证券郭明表达了相同的观点从,称苹果将放弃11英寸的MacBook Air系列,由12英寸的新版MacBook代替,而13英寸版本则会继续保留。 ====================================分割线================================ 本文转自d1net(转载)

优秀的个人博客,低调大师

告别Python,用神经网络编写的软件走向2.0时代

有时人们把神经网络称为“机器学习工具箱中的另一种工具”。有时你可以用它们来赢得Kaggle的比赛。但是,这种解释完全见木不见林。神经网络不只是另一种分类器,它们代表了我们如何编写软件的根本性转变的开始。可以说是软件的2.0时代。下文简称软件2.0。 我们所熟悉的软件1.0的“经典堆栈”是用Python、C++等语言编写的,它包含了程序员编写的计算机的显式指令。通过编写每行代码,程序员可以通过一些可取的行为来确定程序空间中的某个特定点。 相比之下,软件2.0是用神经网络的权重来编写的。没有人参与编写这段代码,因为有很多权重(典型的网络可能有数百万个),并且直接在权重中进行编码是很困难的。反而,我们指定了一些约束程序的行为(例如,一个输入输出对示例的数据集),并使用可自行支配的计算资源来搜索满足约束条件的程序空间。在神经网络的例子中,我们把搜索限制在程序空间的一个连续的子集上,在这个空间中,搜索过程有些出乎意料地可以使用反向传播和随机梯度下降算法。 事实证明,在现实世界中,收集数据要比明确地编写程序容易得多。过段时间以后,大部分程序员不会维护复杂的软件库,编写复杂的程序,或者分析它们的运行时间。但他们会收集、整理、操作、标签、分析和可视化馈送神经网络的数据。 软件2.0不会取代1.0(实际上,需要大量的1.0基础架构来进行“编译”2.0代码的训练和推测),但是它将会接管越来越多的软件1.0的责任。让我们来看看一些正在进行的过渡的例子,以使其更加具体: 视觉识别曾经是由一些带有机器学习的工程特性组成的(例如,SVM)。从那时起,我们开发了机器,以发现更强大的图像分析程序(在卷积架构中),并且最近我们也已经开始搜索架构。 语音识别曾经涉及大量的预处理、高斯混合模型和隐藏的马尔可夫模型,但目前几乎完全由神经网络组成。 语音合成一直以来都有各种各样的拼接(stitching)机制,但是现在,艺术模型的状态是产生原始音频信号输出的大的卷积(例如WaveNet)。 WaveNet地址:https://deepmind.com/blog/wavenet-launches-google-assistant/ 机器翻译通常是采用基于短语的统计技术的方法,但神经网络很快就会占据主导地位。我最喜欢的架构是在多语言环境中进行训练的,其中一个模型可以从任何源语言转换为任何目标语言,并且在弱监督(或完全不受监督的)环境中进行。 机器人技术将问题分解为感知、姿态估计、规划、控制、不确定性建模等,使用显式表示和算法多于中间表示。我们还没有完全做到这一点,但加州大学伯克利分校和谷歌的研究表明,软件2.0或许能够更好地代表所有这些代码。 软件2.0的好处 为什么我们更喜欢将复杂的程序移植到软件2.0中呢? 很明显,答案是因为它们在实践操作中表现得更好。但是,还有很多其他的方便的理由来选择这个堆栈。让我们来看看软件2.0(一个卷积神经网络)与软件1.0相比(一个生产级别的C++代码基数)的一些好处。软件2.0: 1.计算均匀:一个典型的神经网络,首先,由两个操作组成:矩阵乘法和在零点(ReLU函数)的阈值。将其与经典软件的指令集进行比较,后者明显更具有异构性和复杂性。因为你只需为少量的核心计算原语(例如,矩阵乘法)提供软件1.0实现,就可以更容易地做出各种正确的/性能的保证。 2.简单设置为硅:作为一个推论,由于神经网络的指令集相对较小,因此更容易实现将这些网络更靠近硅,例如自定义ASIC芯片,神经形态芯片等等。当低动力的智能变得无处不在时,情况又会发生变化。例如,小而便宜的芯片可以使用预先训练过的卷积神经网络、语音识别器和WaveNet语音合成网络,它们都集成在一个小的、可以连接到任何东西上的“原始大脑”中。 3.恒定的运行时间:典型的神经网络正向传递的每一次迭代都采用同样数量的FLOPS(即“每秒浮点运算次数”,“每秒峰值速度”)。零可变性基于你的代码的不同的执行路径,是可以通过一些庞大的C++代码库来实现的。当然,你可以拥有动态计算图,但是执行流通常仍然受到很大的限制。这样,我们几乎可以保证永远不会发现自己的操作在无意地进行无限循环。 4.持续的内存使用:与上面相关的是,在任何地方都没有动态分配的内存,因此也不大可能交换到磁盘,或是你必须在你的代码中追踪的内存泄漏。 5.它具有高度的可移植性:与经典的二进制文件或脚本相比,在任意计算配置上运行一个矩阵乘法序列要容易得多。 6.它非常敏捷:如果你有一个C++代码,并且有人想让你把它以两倍的速度为代价获得(如果需要的话),这将是非常重要的调优系统新规范。然而,在软件2.0中我们可以把我们的网络删除一半的通道,然后再次训练,——它完全是运行速度的两倍,并且运行的有些糟糕。相反地,如果你恰好得到了更多的数据/计算,你可以通过增加更多的通道和重新训练来让你的程序更好地工作。 7.模块可以融合为一个最优的整体:我们的软件经常被分解为通过公共函数,API或端点进行通信的模块。然而,如果两个最初训练的软件2.0模块相互作用,我们可以很容易地在整个过程中进行反向传播。想想看,如果你的web浏览器能够自动重新设计底层系统指令10个堆栈,直到加载web页面时获得更高的效率,那该多好。而对于2.0,这是默认的行为。 软件2.0的局限性 2.0堆栈也有一些自身的缺点。在优化的最后,我们剩下的是大型网络,它们运行得很好,但是我们很难知道它是如何运作的。在许多应用领域,我们将会选择使用我们所理解的90%的精确模型,或者99%的准确模型。 2.0堆栈可以以不直观和令人尴尬的方式失败,例如,通过在训练数据中默默地采用偏差,当它们的大小在数百万的大多数情况下,是很难正确地分析和检查的。 最后,我们还发现了这个堆栈的一些特殊属性。例如,对抗样本的存在突出了这个堆栈的不直观的本质。 对抗样本:https://blog.openai.com/adversarial-example-research/ 如果你把神经网络看作是一个软件堆栈,而不仅仅是一个很好的分类器,那么很快就会发现,它们拥有大量的优势和很大的潜力来转换软件。 从长远来看,软件2.0的未来是光明的,因为越来越多的人认为,当我们开发了AGI时,它肯定会写入软件2.0中。 本文由AiTechYun编译,转载请注明出处。更多内容关注微信公众号:atyun_com

优秀的个人博客,低调大师

告别繁琐!Blender 玲珑管理器为 Linux 开启 CUDA 渲染超能力

谁没在 Linux 上折腾Blender CUDA 渲染的时候遇到过三大魔咒: 驱动冲突: NVIDIA 官方 .run 包与系统预装驱动冲突; 依赖地狱: 配置相互匹配的 CUDA/GCC 环境依赖,步骤复杂冗余,高风险; 门槛劝退: 纯命令行操作,新手零容错率。 好不容易到最后,可能还越调越崩...... 现在不用愁了!如意玲珑社区与 Blender 中国社区联手推出“Blender 玲珑管理器”项目,从 “配置” 这个最头疼的痛点切入,再解决命令行恐惧,给 Linux 3D 创作者一套真正能用的 “一站式加速方案”。 它具有能够让你从“折腾地狱”到“高效渲染”的 4 大核心机制: 驱动兼容保障 本方案彻底规避高风险的 NVIDIA 官方 CUDA .run 包安装方式,明确兼容 apt 仓库或系统预装的 NVIDIA 驱动,彻底规避驱动冲突风险。 依赖环境一站式部署 用户通过“Blender 玲珑管理器”一键安装,即可自动配齐 CUDA 与 GCC 等环境依赖,彻底消除运行库版本困扰与手动配置。 零命令行封装的图形化操作 全程通过 deepin 25 应用商店搜索并安装管理器,实现零命令行依赖。仅需点击确认,新手小白也能轻松上手,彻底消除对“命令行”操作的恐惧。 加速效果的机制性保障 只要 NVIDIA 显卡在官方 CUDA 支持列表中,高性能渲染加速效果就能得到充分、可靠的发挥。 接下来,我们就为大家分享详细的使用及配置过程。 一、前置准备 重要提示 此版本为⾮⽣产⼒发⾏版本,具有试验性质,请遵循⽂档进⾏操作; 初版试验项⽬仅⽀持deepin 25,其他发⾏版本敬请期待; 初版试验项⽬仅⽀持 NVIDIA 驱动版本570.124,其他驱动版本敬请期待; 确保当前系统⽤⼾⽬录即"$HOME"剩余空间不少于 16GB; 本版本仅⽤于⽅案探索,具体实现效果可能会在后续版本中有所优化、变动。 使用条件 请确保当前启⽤的 NVIDIA 显卡⽀持 CUDA,可通过以下链接查询兼容型号。 https://developer.nvidia.com/cuda-gpus https://developer.nvidia.com/cuda-legacy-gpus 请确保当前系统的 NVIDIA 显卡驱动是通过 apt 软件仓库安装或在安装系统时预装。 dpkg-l nvidia-driver 注意,若通过 .run 安装 NVIDIA 官⽅驱动,请勿使⽤本试验项⽬,否则可能导致显⽰驱动冲突。 二、使用方法 2.1 安装必要运行库 由于 CUDA 计算需要使⽤ GCC 作为编译器使⽤, 且 CUDA12.2 需要⾄少 GCC12 编译器⽀持,因此提供了独⽴安装包⽤于管理必要运⾏库。 打开 deepin 应用商店,搜索“Blender 玲珑管理器”并安装 在启动器/开始菜单找到并安装刚刚下载的Blender 玲珑管理器测试资源并根据提⽰操作,若有不⽀持的条件将会终⽌安装。 此阶段将会向系统添加开发仓库,⽤⼾需要同意后⽅可进⾏后续操作,关闭窗⼝将视为终⽌安装。 运⾏库安装器部署完成后,将会提⽰成功的结果。由于该运⾏库安装体积较大,在提⽰成功前请勿关闭计算机。 在完成上述 CUDA12.2、GCC12运⾏库安装器部署后,需要运⾏对应的安装器。 2.2 GCC12运⾏库安装 打开启动器/Launcher,找到如意玲珑GCC12.3.0安装器。此阶段将会向⽤⼾⽬录安装资源,⽤⼾需要同意后⽅可进⾏后续操作,关闭窗⼝将视为终⽌安装。资源部署完成后, 将会提⽰成功的结果。 2.3 CUDA 12.2安装 打开启动器/Launcher, 找到如意玲珑CUDA 12.2安装器。此阶段将会向⽤⼾⽬录安装资源,⽤⼾需要同意后⽅可进⾏后续操作,关闭窗⼝将视为终⽌安装。 资源部署完成后, 将会提⽰成功的结果。由于该运⾏库安装体积较⼤,在提⽰成功前请勿关闭计算机。 2.4 Blender LTS 4.x for Linyaps 安装 打开 deepin 应⽤商店,搜索如意玲珑版本的“Blender LTS”并安装,请确保包名为 org.blender.lts。 启动 Blender LTS,满⾜条件后即可启⽤ CUDA 能⼒。 三、卸载方法 必要运⾏库安装器⽬前⽀持同时管理安装/卸载功能。 通过启动器/开始菜单找到安装 Blender 玲珑管理器测试资源 并根据提⽰操作。 打开 deepin 应⽤商店,进⼊“ 应⽤管理”板块找到 Blender 玲珑管理器并卸载。 四、常见问题 4.1 必要运⾏库安装阶段 问题1:“NVML 驱动版本不在⽀持范围内” 检查当前系统是否已经正确加载受⽀持的NVIDIA显卡驱动模块 确认当前系统驱动是否通过apt软件仓库安装或系统预装 确认当前系统显卡驱动是否在受兼容范围内 问题2:“已经存在仓库请移除” 请根据提⽰的仓库名称,检查系统中是否已经配置同名仓库: ll-cli reposhow 注:为确保使⽤的是官⽅开发仓库,因此设置了强制检查阶段。 4.2 Blender 玲珑管理器运 提⽰/错误 问题1:“CUDA 计算能⼒缺失或 CUDA 安装异常” 通过终端执⾏命令 nvidia-smi ,重新启动Blender 玲珑管理器,当前测试版本可能存在加载延后问题导致检测错误; 检查当前系统是否已经正确加载受⽀持的 NVIDIA 显卡驱动模块; 确认当前系统驱动是否通过 apt 软件仓库安装或系统预装; 确认当前系统显卡驱动是否在受兼容范围内; 确认当前显卡是否受 NVIDIA CUDA ⽀持。 问题2:“Blender 玲珑管理器⽆法启动” NVIDIA 580 驱动仍未稳定,若之前使⽤ NVIDIA 570 驱动运⾏⾮玲珑版本Blender,可能存在 GPU缓存冲突问题,需要备份配置⽂件后清理缓存: ~/.cache/blender ~/.config/blender 一些其他使用建议 安装玲珑版 Blender 后,请在“偏好设置”➜“系统”中,将后端保持设置为OpenGL。如果切换至 Vulkan,可能因程序兼容性问题导致卡死或闪退(目前 Blender 对 Vulkan 的支持尚不稳定)。如已误设为 Vulkan,移除 Blender 的配置文件即可恢复默认设置。 以上便是Blender 玲珑管理器项目的完整介绍及使用指南,我们衷心感谢Blender中国社区在此过程中的大力支持与贡献。 从“望而却步”到“轻松启用”,Blender 玲珑管理器项目是两大社区以用户需求为核心的诚意之作。无论你是deepin资深玩家,还是 Blender 新人,都能借它省去技术折腾,专注创意。 如果你身边有 deepin+Blender 的使用者,不妨把这个“加速神器”分享给 TA!也欢迎在评论区聊聊你过往配置 CUDA 的经历,一起感受如意玲珑带来的创作生态升级~

优秀的个人博客,低调大师

告别数据无序:得物数据研发与管理平台的破局之路

一、背景介绍 为什么得物需要自建大数据研发与管理平台? 得物作为一家数据驱动型互联网企业,数据使用的效率、质量、成本,极大影响了公司的商业竞争力。而数据链路上最关键的系统是计算存储引擎和数据研发平台。其中计算存储引擎决定了数据的使用成本,数据研发平台则决定了数据的交付效率、数据质量以及数据架构合理性。 得物数据生产链路 过去整套大数据基础设施我们都使用云上商业化产品(下文简称“云平台”),但在各方面已远无法匹配上得物长期的业务发展。目前得物大数据面临着如下挑战: 因此24年技术部正式启动大数据系统自建,Galaxy数据研发与管理平台为其中一个重要项目,负责面向参与数据生产的用户,提供离线和实时数据的采集同步、研发运维、加工生产、数据资产管理以及安全合规的能力,满足业务长期发展对于数据架构、数据质量、数据交付效率的诉求。 二、产品功能架构 下图为整体产品功能架构,其中蓝色部分为当前已落地功能,灰色部分为规划中的功能。 Galaxy数据研发与管理平台产品功能架构 24年立项开始至今,我们主要专注在4个最核心能力的建设,分别为:数据研发套件、数据架构技术、数据质量技术、智能化数据研发。如果把数据研发平台比喻成一辆汽车,那么这四部分的定位如下图所示: 下文会对这些关键技术实现、落地进展以及Galaxy数据研发平台的架构演进,进行解析。 三、数据建设的“驾驶舱” - 数据研发套件 3.1 系统架构解析 数据研发套件包含数据研发IDE、数据资产系统、离线任务调度系统三部分,在平台中的定位类似于“汽车的驾驶舱”,为数据工程师提供丰富的工具集,控制全公司的数据流动与计算。整体系统架构如下图所示: 3.2 数据同步技术解析 数据同步也叫数据集成,它是Galaxy数据研发平台的核心组件之一,主要用于公司各种异构数据源与数据仓库进行数据传输,打通数据孤岛。它作为大数据链路加工的起点和终点,不仅用于数仓ODS层(Operational Data Store,保存原始数据)的入仓构建,也负责将数仓数据回流(出仓)到消费侧的各种数据源中。 离线数据同步 离线数据同步是最为主流的一种数据同步模式,以批量读写的形式将源表以全量或增量的形式周期性的写入目标表。目前Galaxy数据研发套件支持了多种类型数据源的离线同步,包括: 目前Galaxy数据研发套件的离线同步内核基于Spark Jar进行实现,下图为离线数据同步架构: Galaxy数据研发套件离线数据同步架构 离线数据同步的具体实现执行流程(以MySQL同步至得物自建离线存储系统为例): MySQL离线同步至得物自建离线存储系统的执行流程 实时数据同步 离线数据同步存在着一些局限性,主要有: 对在线数据库压力大,即使是读库也可能影响线上部分业务的稳定性。而如果单独为数据入仓申请一个备库,又会带来较大的额外成本; 大表同步时间长(可达7小时)此类任务基本无法保障下游重要数据产出的SLA; 需要在短时间传输大量数据,对网络带宽依赖高; 数据时效差,最快也是T+H的延迟,无法满足实时报表等对时效性敏感场景的需求。 因此需要实时数据同步的能力对此类场景进行补充。我们主要支持两种实时同步方案: 1)基于业务库binlog的的实时入仓 对比离线数据入仓,基于binlog的实时入仓可以避免对数据库造成压力,减少了对网络带宽的依赖,同时对于超大规模的表可以大幅缩短基线加工时长。但此方案依然需要(小时/天)将增量数据和全量数据做Merge处理和存储,这会产生冗余的计算和存储成本,且时效性也较差,因此本质上只能为离线数仓场景服务。 2)实时镜像同步 通过实时计算引擎Flink CDC将变更数据实时更新到存储系统中,保持数仓ODS表和来源数据库表的增全量同步,整体架构更加简单,并减少ODS层的批计算和冗余存储成本。目前规划通过Paimon、Iceberg等开放Lakehouse能力来实现离线存储系统的实时事务性更新。根据实际业务场景,也可以直接将数据实时写入StarRocks等支持更新的OLAP数据库中。 3.3 数据研发套件任务迁移方案解析 在过去得物的全部数据加工任务全部运行在云上数据平台,因此除了对齐产品能力外,我们还需要将数据加工任务从云平台“平滑”的迁移到Galaxy研发平台。 由于调度系统的故障风险极大,一旦异常很可能由于依赖错乱导致数据异常或停止调度导致的数据产出延迟。因此我们将Galaxy研发套件的平台层迁移和调度层迁移进行解耦,以便将调度系统的迁移节奏放缓。 首先进行风险较低的研发平台层迁移,让业务可以尽快上线,便于优化数据研发流程和数据资产管理能力。此阶段任务的调度依然运行在云平台。之后再进行调度层的迁移,这个阶段用户基本无感,完成后则彻底不再依赖云平台。 因此架构上一套研发平台需要同时适配两套调度系统(云任务调度+Galaxy自研调度系统 ),并支持逐步往自研Galaxy调度的平滑演进。 为了让调度迁移的过程需要如同“数据库主备切换”一样,尽量让用户无感,我们使用了影子节点的方案,以实现迁移流程的业务无感、可灰度、可回滚。影子节点本质是一个Shell任务,当调度系统启动它后,它会通过Rest API检测对方调度系统中实体节点的状态,并与它保持状态同步。通过影子节点,我们可以实现按照任意调度任务id进行灰度迁移,调度迁移本质就是将云平台的实体节点替换为影子节点。如下所示: 基于“影子节点”的双调度互通方案 3.4 功能建设与迁移进展 1)功能对齐与优化 目前Galaxy研发套件已完成与原云数据研发平台的主链路功能对齐,具备数据研发与资产管理的全套流程,同时还针自建Spark引擎查询和运维、在线数据入仓等方面进行定向优化。提效成果: 临时SQL查询性能优化 通过简化调用链路+Spark Driver预启动等查询加速技术,平均每个Query可以比原云数据研发平台固定节约35s+。 减少查询等待时间:290+人日/月 在线数据入仓自动化提效 通过工单申请即可实现MySQL数据入仓。自动帮用户创建同步数据源、增/全量ODS表、同步任务、增量Merge任务,并自动赋权以及数据初始化。根据用户调研和埋点分析,每个数据入仓需求可提效30min+。 提效效果:20+人日/月 2)业务迁移进展 目前我们已完成数据平台、数据挖掘、数据分析团队的全部任务迁移(占得物全域的44%),并完成了算法团队的POC。同时还将上述团队的临时取数业务迁移到了自建Spark引擎,从而实现云上商业版计算引擎的DEV资源缩容400+cu,总计可节省临时取数计算成本约2万+/月。 四、公司数据资产的“底盘”-数据架构技术 目前,公司业务用数越来越敏捷和频繁,而数据资产却没有做到“好找敢用”,大量的重复数据和数据烟囱也随之出现。这不仅导致大量数据二义性问题,同时也使计算存储成本难以控制。以离线数仓社区&交易的试点域为例,重复冗余表达到了54%,重复指标达到了35%。这本质上是缺乏数据架构体系的建设,数据架构是公司数据管理的“骨架”和“路线图”,它如同“汽车的底盘”,忽视数据架构可能导致数据的无序增长以及业务的决策错误。 4.1 Onedata数据架构方法论 及工具体系 Galaxy数据研发平台基于“Onedata”的数据架构方法论,建立了统一的数据采集和生产规范,使数据的新增更加合理、易用,提高数据的复用度、研发效率、交付质量,降低使用成本。这是一种“内啡肽”式的数据建设,前期需要花费一定时间进行数据模型的设计并遵守数据研发规范,但从业务的长远发展来看,这是必须要走的一步。 目前我们已在数据采集入仓和数据研发两个环节完成了数据架构能力建设,确保数据的入口(ODS)以及数据仓库的规范性,并再后续通过旁路数据治理的手段进行存量数据的规范化。如下图所示: Onedata数据架构工具体系 融入了Onedata数据架构技术体系(红色部分)后的Galaxy数据研发平台架构如下图所示: 融入Onedata规范数据生产能力(红色部分)的 Galaxy研发平台技术架构 下文主要对两个关键模块,统一ODS自动化入仓平台、Onedata数据建模的实现方案进行解析。 4.2 统一ODS自动化采集入仓方案解析 ODS(Operational Data Store),为操作数据层,是整个数仓最基础的一层,是原始数据采集入仓的第一个环节。Onedata的核心理念之一是所有的数据采集有统一的规范和入口。因为随意的从在线库进行采集同步会导致大量重复的数据存储,以及过长浪费的表存储生命周期。 由于数据的采集入仓本身没有过度复杂的业务逻辑,因此Galaxy数据研发平台实现了自动化数据采集入仓能力,提供在线数据源到数仓ODS层的标准化采集和管理能力。无需研发代码的同时,产生的数据都是严格满足架构规范的。具体价值有: 避免重复ODS数据存储 通过库owner+数仓owner双重审批,避免不合理的数据入仓 控制ODS表生命周期,避免存储成本浪费 全流程自动化,提高ODS层数据研发效能 目前支持MySQL和TiDB的全量采集同步和增量采集同步。同时,开启自动更新模式的入仓任务,还会订阅来源MySQL表的变更消息,并自动更新同步任务。关键流程如下: 自动化数据入仓流程 4.3 规范数据建模与自动化指标研发方案解析 Onedata在数据研发环节,核心采用维度建模的理论。它构建了公司级的一致性维度、标准化的事实表以及可灵活分析的汇总表和无二义性的指标。并将数据进行清晰的分层,将公司内部分散、异构的数据整合成一套可信、可复用、可分析的数据资产。其主要价值有: 保证维度和指标一致性:通过维度和业务过程的概念建模,确保维度表和事实表的全局唯一性;同时通过原子要素的指标建模,确保指标口径的全局无二义性。 提升开发效率:数据工程师无需重复构建维度表和基础事实表,直接复用数仓公共层的成果;同时指标原子要素定义完成后,指标和汇总表的代码全部可以系统自动化生成和优化,大幅提高效率,也减少出错的可能性。 增强数据可解释性:明确的表业务描述以及字段关联的指标和维度,以及清晰的星型/雪花模型关系,使数据的消费侧更方便的使用数据。 事前治理:严格根据架构规范进行数据研发,禁止重复表的新增,约束数据表的生命周期、数据依赖等,避免事后运动式治理。 Onedata核心概念、建模流程以及配合工具如下图所示: Onedata的数据建模流程 其中最为关键部分为“指标建模”。我们将指标的口径组成拆成了三部分组成:原子指标、业务限定、统计周期,同时在其物化到表上的时候再确定统计粒度。通过原子要素的组合定义指标可以确保同样的指标在公司全局只会有一个,以及标识出不同的汇总表、应用表中的指标是否为同一个。另外当原子口径发生了变化,系统也可以根据血缘关系找到受影响的指标和表,让owner进行握手确认,确保口径变更一致性。例如下图所示: 1个原子指标口径变更,影响了7个关联指标、 2张表的同步变更 从上图我们也可以看到,原子口径的变更影响非常大,即使可以基于血缘进行变更握手管控,人工修改逻辑也容易改错或遗留。因此我们实现了自动化指标代码生成的能力,基于原子口径自动化生成指标及其物化表的加工逻辑。 指标代码自动化生成方案: 将指标按来源表分组,并将其的组成原子要素(原子指标+业务限定+统计周期+统计粒度)进行SQL逻辑的组装、优化、方言翻译,具体流程为: 数据建模与指标SQL生成案例: 1.数据建模 2.代码生成 3.代码优化 - 指标SQL优化规则 4.4 当前落地进展与效果 1)统一自动化ODS采集入仓 目前已实现通过工单申请的方式一键完成MySQL和TiDB的数据进行增/全量自动化采集入仓能力,无需人工编写代码即可实现规范的数据入仓。产品效果如下: 业务成果: 业务域落地:目前已在得物内部各域全面落地统一ODS入仓能力。2025年Q3,得物全域新增的入仓任务93.6%是通过Galaxy自动化采集入仓平台自动化生成的; 表生命周期规范:25年新增ODS表生命周期定义率较24年Q4提升7.4倍,节约了大量离线存储; ODS存储增量控制:通过源头规范数据入仓,配合数据治理团队使数仓ODS层存储季度增幅降低:32%->8% 2)规范建模与自动化指标代码生成 目前已完成数仓规划->概念建模->明细表维度建模->指标建模->指标代码自动化生成->汇总表代码自动化生成的Onedata规范建模研发全流程,产品效果如下: 业务成果: 商家域数仓Onedata一期落地效果:完成了40+数据资产沉淀与规范化汰换改造,以及190+应用指标定义与上架,同时沉淀了100+公共派生指标。通过数据规范化重构、二义性问题的解决以及自动化代码生成的能力,可实现商家数据需求数仓开发效率提升40+%,每迭代线上需求吞吐量提升75%->90%。 社区域数仓Onedata一期落地效果:完成1200+应用指标的定义与上架,实现100%无二义性。通过精品资产的规范建设与切换,通过复用公共层数据,实现5+万/月的成本下降。由于数据二义性的解决以及资产规范度的提高,实现数仓和分析师用于口径oncall和业务取数的人力成本减少约10+人日/月。 五、数据生产的“刹车片” - 数据质量技术 得物数仓发展至今,不仅用于高管决策以及数据报表的场景,同时和得物线上业务做了非常强的耦合,各域均存在P0级资损风险场景,例如:社区数仓的运营投放、算法数仓的新品商业化、交易数仓的费率折扣、营销域、用户域等等。这些数据直接应用于线上业务,任何的数据质量问题都可能导致公司、商家、用户的利益受损,以及业务对数仓的信心丢失。 然而过往数仓的数据交付只是停留在快速提供数据以发挥业务价值这一步,业务和研发对数据质量和稳定性保障重视度严重不够,并且没有明确生产变更和数据质量校验的SOP,同时也没有健全的工具体系支撑,全靠数据工程师的自我修养,导致历史上很多核心数据加工任务没有保障或者保障不全面,不断引发P级故障。 5.1 Galaxy的数据质量工具体系 数据质量的相关工具就如同“汽车的刹车片”,可以想象没有刹车在路上行驶是如何的危险。因此我们在Galaxy数据研发平台建设之初就同步进行了数据质量工具的开发。目前所建立起来的离线数仓质量加固SOP及配合的工具如下: 离线数仓质量加固SOP 目前重点建设的2个核心功能,分别为:数据质量校验规则,用于监控生产数据质量并进行及时阻断止血,避免下游数据污染;以及数据变更管控流水线,在数据生产变更的环节嵌入消费场景打标、自动化风险扫描、code review、自动化数据测试、发布审批等功能,以全面保障数据质量。融入了数据质量技术体系(红色部分)后的Galaxy数据研发平台架构如下图所示: 融入数据质量能力(红色部分)后的Galaxy数据研发平台架构 5.2 当前落地进展与效果 数据质量校验规则 Galaxy数据研发平台已经实现了完善的数据质量规则校验能力,用户在Galaxy数据研发IDE上面向数据标准进行高效的质量规则定义,系统会自动生成校验SQL随着任务的发布一起下发到调度系统中执行。同时支持了强规则(主路执行,数据异常阻断任务执行)和弱规则(旁路执行,数据异常进行告警)两种规则运行场景,应对不同的场景诉求。产品效果如下所示: 场景覆盖方面已经实现了表非空校验、表波动校验、字段主键校验、字段非空校验、字段波动校验、字段枚举校验、自定义SQL校验等15种规则,覆盖了离线数仓100%的校验场景。 同时通过批量导入、弱转强等提效工具帮助离线数仓团队在25年Q3新增了1200+质量规则,全量P0任务质量规则覆盖率达到96%,非P0任务86%。并结合发布管控流水线能力,实现了P0场景任务100%变更覆盖表级规则,且金额等高风险字段100%变更覆盖字段级规则。 数据变更流水线 目前已经完成了完整的变更管控流水线的能力,主要功能包括:消费场景打标、静态风险扫描、Code Review、冒烟测试、数据探查、数据比对、发布审核。产品效果如下所示: 其中,场景打标方面,离线数仓末端任务(ADS和回流)98.3%打标了数据消费场景,对于全链路分析数据重要性和消费场景起到了巨大的作用;变更管控方面,静态扫描节点已实现了48个风险扫描规则,覆盖了94%的已知风险场景,当前系统自动化风险识别率98%(剩余为人工CR发现的问题),平均每双周可事前拦截600+起风险事件。 六、数据研发之路的“辅助驾驶”-智能化数据研发 过去10年,通过开源大数据组件的兴起,大幅度降低了企业构建大数据Infra的难度,在一定程度上实现了企业间的“数据平权”。而在企业内部,由于数据同步、ETL研发调度、资产管理、数据治理等复杂的技术导致找数和用数门槛非常高,因此大部分场景都是提需求给数仓团队进行数据加工,那么数据团队的交付效率就变成了公司各业务线数据化经营决策的瓶颈。 6.1 Galaxy的智能化演进路线 我们计划分3个阶段(L1~L3)建设Galaxy数据研发平台的智能化能力,来提升数据研发效率,降低业务自主进行数据研发的门槛,实现公司内部不同部门和岗位间的“数据平权”。如下所示: Galaxy数据研发智能化演进路径 当前我们处于L1的Copilot阶段,通过在数据研发流程中,旁路嵌入基于专家经验规则和大模型的智能SQL代码续写、智能任务诊断、智能SQL代码纠错与优化、 智能质量规则推荐等应用,辅助用户进行高效数据研发。嵌入Copilot后的Galaxy研发平台整体架构如下,主要关注红色部分: 数据智能化L1阶段的Galaxy研发平台技术架构 下文主要对当前较为成熟的功能,智能SQL代码续写的实现方案进行解析。 6.2 智能SQL代码续写方案解析 SQL代码续写的重点在于工程链路,大模型上我们选择适合代码生成的小参数模型,当前使用了Qwen-2.5-coder,后续会进行其他模型的实验。系统流程如下: 智能SQL代码续写系统流程 关键模块功能描述: 6.3 当前落地进展与效果 目前Galaxy研发平台已经落地了智能代码续写、智能任务诊断、智能SQL纠错与优化3个Copilot应用,具体业务效果如下: 其中高活用户的智能代码续写功能开启率为98.5%,整体采纳率趋势和我们做的优化动作如下: 智能SQL续写采纳率趋势 (2025年04月25日~2025年09月09日) 七、后续规划 后续Galaxy数据研发平台会持续完善现有功能提升产品体验,同时在智能ETL Agent、Data Fabric、数据逻辑化三个前沿方向进行探索,通过技术先进性为公司数据业务带来更多的价值。 7.1 长期规划一:智能ETL Agent 核心目标:数据研发提效,并降低数据研发门槛 ETL Agent核心能力是需要将用户的自然语言业务需求翻译成数据表的SQL加工逻辑,其本质上就是“NL2SQL”的传统命题。然而,如果让大模型直接分析用户的问题,那么它需要尝试从底层混乱的物理表结构中生成目标SQL,这会将业务语义的复杂性完全压给大模型,导致同一指标因表结构理解偏差或字段映射错误而产生不同结果。 Galaxy的ETL Agent会采用“NL2Metric2SQL”的方案。通过大模型进行自然语言的解析,结合向量数据库的相似度匹配实现NL2Metric的能力,然后基于Onedata数据模型和指标语义层,将自然语言的用数需求准确翻译为指标原子要素(原子口径、业务限定、统计周期、统计维度),并自动构建ETL加工链路。如下图案例: 智能ETL Agent用户流程案例 这也是Galaxy智能化的L2阶段,这个阶段将数据研发分成了专家数据研发以及智能数据研发。专家模式依然按传统SQL任务进行数据研发。而智能研发则以自然语言形式的数据需求作为输入,通过提前将Onedata数据模型存储在RAG的向量数据库中,然后根据数据需求内容进行分词,按相似度从RAG中匹配出相关的指标要素构建出提示词,并请求大模型获得正确的指标要素。 实现智能ETL Agent后的智能化L2阶段Galaxy研发平台架构(红色部分为Agent相关模块) 7.2 长期规划二:Data Fabric 核心目标:减少非必要的离线数据存储成本 传统的数据集成(数据入仓)方案是通过离线或实时数据同步工具将公司内部各数据源的数据全量或增量地抽取、清洗、加载到一个中心化的数据仓库中。但这种方案在技术上存在三个问题: 离线存储成本大:传统的数据集成方式,离线数仓的ODS层会拷贝全部所需在线数据的副本。然而其中很大一部分的数据仅用于短期分析,或用于对RT不敏感的查询场景,这些数据在离线数仓中物化存储的ROI极低,造成了大量存储成本浪费。 数据搬迁成本大:随着业务的发展,公司的数据源可能分布在不同地域、不同云环境。周期性的将海量数据同步至中心化数仓,将产生巨大的网络带宽成本和入仓等待时间。同时入仓需要与数仓工程师进行需求沟通,也存在大量协作成本。 数据一致性问题:数据同步有显著延迟,在离线同步的场景下,分析的数据会有天级延迟。 Data Fabric(数据编织)是一种全新的数据集成架构方案,核心理念是 “不移动数据,移动计算”。 技术实现方案上以外表的形式来封装源端表,通过统一的元数据系统,将源端表(外表)和离线表(内表)统一管理起来,使用起来对用户无感。在执行计算时,通过Spark引擎的跨源联邦查询能力,直接从各源端数据库(一般为备库或抽数库)将数据查询回来后进行分布式计算。下图展示了Data Fabric与传统数据集成的区别: 7.3 长期规划三:数据逻辑化 核心目标:计算存储成本降低,数据研发与运维提效 通过视图或参数化视图进行整条数据链路的构建,那么整条链路就完全不需要任何存储成本,计算成本也仅在视图查询时才发生。但这样会导致一个问题,当视图逻辑复杂,嵌套层级多时,查询效率非常低,且对相同视图的查询都需要重新计算。因此我们需要对一些关键的视图进行物化,物化后的视图,在查询时可以直接访问其物化表,实现查询性能的大幅提升。 数据逻辑化架构,会存在两层,上层为由用户定义的物理表以及虚拟视图组成的逻辑层,对用户感知;下层为物理表和系统自动生成的视图物化表组成的物理层,对用户不感知,具体如下图所示: 数据逻辑化的架构分层 数据逻辑化的关键技术之一为视图物化表的命中。当某个视图存在物化表时,需要将对应查询范围的数据直接翻译成物化表的查询,而不去展开视图查询,以提升查询性能。技术链路如下图所示: 数据逻辑化的视图物化命中改写链路 另一项关键技术为视图的物化策略与回收策略。系统需要定期通过算法识别出在满足产出时效的前提下,整体计算和存储成本最低的物化方案。例如下方案例: 数据逻辑化的视图物化与回收策略 目前全域优化场景简单且有效的算法有遗传算法、模拟退火算法等。通过评估在一定存储成本限制下,哪些视图的物化组合,可以使用整体计算cost最低。 将数据虚拟化技术和ETL Agent能力结合,我们可以实现系统自托管的智能数据研发,即Galaxy智能化的L3阶段。 往期回顾 1. 从一次启动失败深入剖析:Spring循环依赖的真相|得物技术 2. Apex AI辅助编码助手的设计和实践|得物技术 3. 从 JSON 字符串到 Java 对象:Fastjson 1.2.83 全程解析|得物技术 4. 用好 TTL Agent 不踩雷:避开内存泄露与CPU 100%两大核心坑|得物技术 5. 线程池ThreadPoolExecutor源码深度解析|得物技术 文 /宇贤 关注得物技术,每周更新技术干货 要是觉得文章对你有帮助的话,欢迎评论转发点赞~ 未经得物技术许可严禁转载,否则依法追究法律责任。

优秀的个人博客,低调大师

JeecgBoot 代码生成器 1.5.1 重磅升级:一键生成,告别手工迁移

前言 作为 JeecgBoot 开发者,你是否还在为每次生成代码后需要手动复制前端文件到项目而烦恼? 本次 1.5.1 版本升级将彻底解决这些痛点! ✨ 升级亮点 1. 前端代码直通项目 旧痛点 手动复制前端代码效率低且易出错 新特性 配置ui_project_path参数即可自动写入前端项目 jeecg_config.properties 新增前端项目地址配置 # 生成到前端VUE3项目路径 ui_project_path=E:\\JeecgBoot\\jeecgboot-vue3 2. 菜单 SQL 自动迁移 优化点 自动将生成的 Flyway 格式的菜单 SQL 文件,迁移到 start 项目的 flyway 目录 jeecg-module-system/jeecg-system-start/src/main/resources/flyway/sql/mysql └── V20230819__init_menu_for_moduleX.sql ⚡ 升级步骤 1. 升级代码生成器依赖版本号 修改根目录下的 pom.xml,升级 codegenerate 版本号到 1.5.1 <codegenerate.version>1.5.1</codegenerate.version> 2. 增加前端项目配置 修改jeecg-module-system/jeecg-system-start/src/main/resources/jeecg/jeecg_config.properties,设置下前端项目路径和后台JAVA项目路径业务包路径 # 生成到后端Java项目那个模块路径 project_path=E:\\JeecgBoot\\jeecg-boot\\jeecg-boot-module\\jeecg-module-demo # 生成到前端VUE3项目路径 ui_project_path=E:\\JeecgBoot\\jeecgboot-vue3 # 业务包路径 bussi_package=org.jeecg.modules.demo 升级价值 减少 85% 的前端文件迁移工作 节省 60% 的菜单 SQL 初始化时间 预计每周为开发者节省 1-2 小时 💬 开发者说 "升级后开发效率提升 30%,前端联调更顺畅" —— 某电商项目负责人 🔗 相关资源 GitHub 提交 PR 记录 代码生成配置文档 代码生成使用文档

优秀的个人博客,低调大师

告别 DOM 的旧时代:从零重塑 Web 渲染的未来

引言 浏览器这玩意儿现在真够诡异的。WebAssembly 在服务器端混得风生水起,但客户端还是那副老样子,跟十年前没啥区别。 WASM 粉会跟你吹,通过点 JS 胶水代码就能调原生 Web API。但核心问题是:为啥非得用 DOM?这东西就是个默认选项罢了。本文直击 DOM 和相关 API 的痛点,为什么该让它们退场了,顺便脑洞下怎么改进。 作者不是浏览器全栈专家——没人能全懂了,这正是症结所在:东西太杂太乱。 DOM 的“文档”模型:臃肿得像个大胖子 DOM 烂到什么程度?Chrome 里document.body有 350+个键值,大致分类: 节点操作:appendChild、removeChild之类的。 样式相关:style对象塞了 660 个 CSS 属性。 事件处理:那些过气的onevent属性,比如onclick,基本没人用了。 杂七杂八:innerHTML、className等。 属性和方法界限模糊,很多 getter 会偷偷触发重排,setter 藏在暗处。还有一堆历史遗毒。 DOM 不瘦身,还在发福。你是否感受到这痛苦,取决于你是搞静态页还是 Web App。作为开发者,我们大多避开直接操 DOM,转而用框架。但偶尔有纯 DOM 党吹它牛逼——纯属自欺欺人。DOM 的声明式功能,比如innerHTML,跟现代 UI 模式八竿子打不着。同一件事 DOM 有 N 种方式,全都不优雅。 Web Components 的尴尬处境 Web Components 是浏览器原生组件方案,但来得太晚,人气不高。API 设计笨重,Shadow DOM 加了层嵌套和作用域,调试起来头大。粉丝的辩护听着像在找借口。以下是一个简单的示例: class HelloWorld extends HTMLElement { connectedCallback() { const shadow = this.attachShadow({ mode: 'closed' }); const template = document.getElementById('hello-world').content.cloneNode(true); const hwMsg = `Hello ${this.getAttribute('name')}`; Array.from(template.querySelectorAll('.hw-text')).forEach(n => n.textContent = hwMsg); shadow.append(template); } } customElements.define('hello-world', HelloWorld); 看起来还行?但实际开发中,Shadow DOM 的复杂性和 DOM 的字符串化特性(stringly typed)让开发者头疼。相比之下,React、Vue 等框架的虚拟 DOM 完全避开了这些问题,因为它们的语法只是“长得像 XML”,而不是真的依赖 DOM。 HTML 的停滞不前 HTML10-15 年没大动静。ARIA 是亮点,但只是补语义 HTML 的漏。语义 HTML 从 2011 年就开始推,但到现在都没<thread>或<comment>标签。嵌套<article>来模拟评论?指导原则也奇葩。 HTML 总像在嫉妒纸媒,没能真正拥抱超文本本质,也不信开发者能守规矩。 WHATWG(浏览器厂商)接管后,没啥愿景,就在边边角角加补丁。CSS 甚至长出了表达式——每个模板语言都想变编程语言。 编辑 HTML?contentEditable理论上行,但实际搞成可用编辑器是黑魔法。Google Docs 和 Notion 的工程师肯定有吐不完的槽。 渐进增强、 markup/style 分离?做 App 的开发者早不信这套了。 现在 App 大多用 HTML/CSS/SVG 拼凑 UI,但开销巨大,越来越不像正经 UI 工具箱。 比如 Slack 的输入框:用一堆 div 模拟富文本。剪贴板 hack 用隐藏元素。列表/表格得手动虚拟化,自管布局、重绘、拖拽。聊天窗滚动条粘底每次都得重写。虚拟化越深,越得重造页面搜索、右键菜单等。 Web 混淆了 UI 和流式内容,当年新鲜,现在过时。UI 陈旧,内容同质化。 CSS 的“内外倒挂”:别用错心智模型 CSS 口碑一般,但问题在哪?很多人误以为它是约束求解器。看这例子: <div> <div style="height: 50%">...</div> <div style="height: 50%">...</div> </div> <div> <div style="height: 100%">...</div> <div style="height: 100%">...</div> </div> 第一个想分一半高?第二个自相矛盾?实际 CSS 忽略height,父元素收缩包裹内容。 CSS 是两趟约束:先外到内传尺寸,再内到外集内容大小。App 布局外到内:分空间,内容不影响面板大小。文档内到外:段落撑开父级。 CSS 默认内到外,文档导向。要外到内,得手动传约束,从body { height: 100%; }开始。这就是垂直对齐难的原因。 Flexbox 给显式控制: 用flex-grow/shrink做无溢出自适应布局,加 gap 间距。 但 Flex 混淆了简单模型:需先“猜测”子自然尺寸,布局两次——一次假设浮空,一次调整。递归深了可能爆栈,虽少见,但大内容一丢,一切变形。 避坑:用contain: size隔离,或手动设flex-basis。 CSS 有contain、will-change这类直击布局的,暴露底层层级本质。代替position: absolute包裹。 本质上,这些切断 DOM 全局约束流——默认太宽泛,太文档化。 CSS 的好地方? Flexbox 懂了这些坑,还挺靠谱。嵌套行列+gap,直观适配尺寸。CSS 好部分在这,但得用心打磨。Grid 类似,但语法太 CSS 味儿,啰嗦。 从零设计布局,不会这样:不会用减法 API 加屏障提示。会拆成组件,用外/内容器+放置模型,按需组合。 inline-block/inline-flex示意:内部 block/flex,外部 inline。盒模型两正交面。 文本/字体样式是特例:继承如font-size,为<b>工作。但 660 属性大多不继承——边框不递归子级,那会傻。 CSS 至少两东西混搭:继承的富文本样式系统 + 非继承的嵌套布局系统。用同语法/API 是错。 em相对缩放过时,现在逻辑/设备像素更 sane。 SVG 无缝入 DOM,动态形状/图标调色。但 SVG 非 CSS 子/超集,重叠处微差,如transform。坐标字符串化,烦。 CSS 加圆角/渐变/剪裁,有 SVG 嫉妒,但远不及。SVG 做多边 hit-testing,CSS 不行。SVG 有自己图形效果。 选 HTML/CSS 还是 SVG?基于具体 trade-off,全是向量后端。 注意一下的坑: text-ellipsis只截单行文本,非段落。检测/测量文本 API 烂,大家数字母凑合。 position: sticky零抖动滚动固定,但有 bug。无条件 sticky 需荒谬嵌套,本该简单。 z-index绝对层级战,z-index-war.css 里 +1/-1 比拼。无相对 Z 概念。 API 设计难,得迭代建真东西,找漏。 SVG 与 CSS 的权衡 SVG 在 Web 中用于动态生成图形或调整图标样式,但它与 CSS 并非完全兼容。例如,SVG 的 transform 与 CSS 的变换属性有微妙差异,且 SVG 的坐标全是字符串序列化,增加了开发复杂性。 国内场景:假设你在开发一个数据可视化仪表盘,类似 ECharts 的柱状图。你可以选择用 SVG 绘制图形,或者用 CSS 实现类似效果。SVG 支持多边形点击检测(hit-testing),而 CSS 不行;但 CSS 的圆角、渐变等功能又让 SVG 显得多余。最终,你可能需要在两者间做痛苦的权衡。 Canvas 上的油画:HTML in Canvas 的坑 DOM 坏,CSS 几成好,SVG 丑但必备……没人修? 诊断:中间层不合用。HTML6 先砍东西起步。 但关键解放现有功能。理想:用户空间 API 同逃生口,狗食自家。 HTML in Canvas 提案:画 HTML 到<canvas>,控视觉。不是好法。 API 形因塞 DOM:元素须 canvas 后代参与布局/样式/无障碍。离屏用有“技术关切”。 例子:旋转立方体交互用 hit 矩形+paint 事件。新 hit API,但只 2D——3D 纯装饰?问题多。 从零设计,不会这样!尤其浏览器有 CSS 3D transform,何须为自定义渲染全接交互? 未覆盖用例如曲面投影,需复杂 hit。想过下拉菜单吗? 像没法统 CSS/SVG 滤镜,或加 CSS shader。经 canvas 是剩选项。“至少可编程”?截 DOM 一好用,但非卖点。 Canvas 上复杂 UI 是为绕 DOM:虚拟化、JIT 布局/样式、效果、手势/hit 等。全低级。预备 DOM 内容反生产。 反应性上,路由回同树设循环。渲染 DOM 的 canvas 非文档元素了。 Canvas 真痛:无系统字体/文本布局/UI 工具。从零实现 Unicode 分词,就为包裹文本。 提案“DOM 黑箱内容”,但知套路:还得 CSS/SVG 拼凑。text-ellipsis仍破,得从 90 年代 UI 重造。 全或无,要中道。下层需开。 未来的方向:重新设计 DOM DOM 和 CSS 的问题根源在于它们背负了太多的历史包袱。以下是一些可能的改进方向: 精简的数据模型:未来的 DOM 需要大幅减少属性数量(从 350+精简到几十个),专注于核心功能。类似 React 的虚拟 DOM,但直接内置于浏览器中。在开发类似头条的信息流应用时,开发者需要快速渲染大量卡片。精简的 DOM 模型可以减少不必要的 API 调用,提高性能。 统一的布局系统:将 CSS 的内外布局模式明确分开,支持更直观的“外部约束”和“内部自适应”。例如,垂直居中应该像 align-items: center 一样简单。在电商平台的商品详情页中,开发者希望轻松实现复杂的布局(例如商品图片和描述的动态对齐),而不是依赖一堆 CSS hack。 WebGPU 的潜力:WebGPU 提供了更底层的渲染能力,可以完全抛弃 DOM 的复杂性。例如,Use.GPU 项目展示了一个基于 WebGPU 的简洁布局系统,代码量仅为传统 DOM/CSS 的几分之一。在开发类似 B 站的弹幕播放器时,WebGPU 可以用来高效渲染动态弹幕,省去 DOM 的性能开销。 多线程与隔离:现代浏览器已经是多进程架构,但 DOM 的设计没有跟上。未来的 DOM 需要支持更好的多线程和跨源隔离,适应复杂的 Web 应用需求。在企业级应用(如钉钉的协作平台)中,开发者需要集成第三方服务(如 OAuth 登录)。一个支持多线程的 DOM 可以显著提高安全性和性能。 结论 HTML、CSS 和 DOM 的现状就像一辆老旧的马车,虽然还能跑,但早已不适合现代 Web 应用的复杂需求。国内开发者在开发小程序、电商平台或社交应用时,常常需要用框架和 hack 来弥补 DOM 的不足。未来的 Web 需要一个更精简、更灵活的渲染模型,可能基于 WebGPU 或全新的 API 设计。 与其修补 DOM 的漏洞,不如从第一性原理出发,重新设计一个适合现代应用的 Web 渲染层。就像当年的 Netscape 开启了 Web 时代,今天的我们也有机会重新定义浏览器的未来。

优秀的个人博客,低调大师

新一代国产 ORM 框架,sagacity-sqltoy-5.2.59 发版,告别 mybatis

开源地址: github:https://github.com/sagframe/sagacity-sqltoy gitee:https://gitee.com/sagacity/sagacity-sqltoy idea 插件 (可直接在 idea 中检索安装):https://github.com/threefish/sqltoy-idea-plugins sqltoy 脚手架项目:https://gitee.com/momoljw/sss-rbac-admin sqltoy lambda 项目:https://gitee.com/gzghde/sqltoy-plus 更新内容 1、优化updateByQuery适配公共属性设置(updateSqlTimeFields)2、优化NumberUtil数字转英文金额格式3、为提供根据pojo自动创建表或修改表做好结构性准备4、针对公共属性赋值以数据库时间为准的字段(sqlTimeFields)且涉及强制修改(forceUpdateFields)在更新和创建记录时统一规则以数据库时间为准5、未匹配数据库方言(主要是适配hive)分页Long类型根据数据大小转Integer(hive jdbc setLong报错) sqltoy 的关键优势: //------------------了解 sqltoy的关键优势: -------------------------------------------------------------------------------------------*/ //1、最简最直观的sql编写方式(不仅仅是查询语句),采用条件参数前置处理规整法,让sql语句部分跟客户端保持高度一致 //2、sql中支持注释(规避了对hint特性的影响,知道hint吗?搜oracle hint),和动态更新加载,便于开发和后期维护整个过程的管理 //3、支持缓存翻译和反向缓存条件检索(通过缓存将名称匹配成精确的key),实现sql简化和性能大幅提升 //4、支持快速分页和分页优化功能,实现分页最高级别的优化,同时还考虑到了cte多个with as情况下的优化支持 //5、支持并行查询 //6、根本杜绝sql注入问题 //7、支持行列转换、分组汇总求平均、同比环比计算,在于用算法解决复杂sql,同时也解决了sql跨数据库问题 //8、支持保留字自动适配 //9、支持跨数据库函数自适配,从而非常有利于一套代码适应多种数据库便于产品化,比如oracle的nvl,当sql在mysql环境执行时自动替换为ifnull //10、支持分库分表 //11、提供了取top、取random记录、树形表结构构造和递归查询支持、updateFetch单次交互完成修改和查询等实用的功能 //12、sqltoy的update、save、saveAll、load 等crud操作规避了jpa的缺陷,参见update(entity,String...forceUpdateProps)和updateFetch //13、提供了极为人性化的条件处理:排它性条件、日期条件加减和提取月末月初处理等 //14、提供了查询结果日期、数字格式化、安全脱敏处理,让复杂的事情变得简单,大幅简化sql或结果的二次处理工作 //-----------------------------------------------------------------------------------*/ sqltoy 特点介绍: sqltoy 的核心构建思想 sqltoy 的对比 mybatis (plus) 的核心点:查询语句编写、可阅读性、可维护性 对象化 crud 是基础,但 sqltoy 有针对性的改进:update、updateSaveFetch、updateFetch 等 sqltoy 的缓存翻译,大幅减少表关联简化 sql,让你的查询性能成几何级提升 极致的分页,同样帮助你实现查询的性能大幅提升 快速分页:@fast () 实现先取单页数据然后再关联查询,极大提升速度 分页优化器:page-optimize 让分页查询由两次变成 1.3~1.5 次 (用缓存实现相同查询条件的总记录数量在一定周期内无需重复查询 sqltoy 的分页取总记录的过程不是简单的 select count (1) from (原始 sql);而是智能判断是否变成:select count (1) from 'from 后语句 ', 并自动剔除最外层的 order by sqltoy 支持并行查询:parallel="true",同时查询总记录数和单页数据,大幅提升性能 便利的跨数据库统计计算:数据旋转 便利的跨数据库统计计算:无限极分组统计 (含汇总求平均) 便利的跨数据库统计计算:同比环比 5、树形表排序汇总 6、扩展集成

优秀的个人博客,低调大师

让测试告别点点点:ZadigX 全流程自动化测试解决方案

01、测试行业现状分析 快速获得反馈以了解在软件交付生命周期内更改所产生的影响,是构建高质量软件的关键。以前,团队依靠人工测试和代码检查来验证系统的正确性。此类检查和测试工作通常在开发完成后的一个单独阶段进行。然而,这种方法存在一些缺点: 手动回归测试耗时且费用高昂,成为整个流程中的瓶颈,导致无法频繁发布软件,开发者无法快速获得反馈。 人工检查和测试不可靠,人们在手动回归测试等重复性任务中通常表现不佳,并且很难通过检查来预测复杂软件系统的更改会产生什么样的影响。 开发者必须等待很长时间才能获取其更改的相关反馈,并且需要大量工作来对缺陷进行分类和修复。性能、安全性和可靠性问题通常需要进行设计更改,如果在此阶段发现这些问题,费用更高。 较长的反馈周期让开发者难以了解如何构建质量代码,质量有时会被视为“其他人的问题”。 开发者不负责测试自己的代码,很难了解如何编写可测试的代码。 对于不断改进的系统,及时更新测试文档需要大量的努力。 相反,团队应该: 在软件交付生命周期内持续执行所有类型的测试。 创建并定制快速可靠的自动化测试套件,在持续交付流水线[1]中运行自动化测试。 ZadigX 具备管理软件开发全生命周期能力,几乎支持市面上所有测试工具和服务、以及平台系统,同时支持多种测试框架和不同的测试类型,通过强大的运行时环境治理和自定义工作流能力,为测试团队提供强有力的工程支撑 ZadigX 帮助测试团队,将测试服务和能力左移、右移到开发团队、运维团队等全生命周期中,尽早发现问题,让其他角色也参与到质量建设中来,规避因修复此类问题而造成额外成本。 02、持续测试实践思路 持续测试[2]是一种具体的工程实践,旨在确保系统在可靠性、安全性、操作性能和可用性方面的稳定性。它涵盖了多种测试类型,包括左移测试、右移测试、冒烟测试、单元测试、集成和消息传递测试、性能测试、功能测试、回归测试和用户验收测试等等。将持续测试[3]融入 ZadigX 的整个 DevOps 流程,能够实现高效的业务部署、快速发现和修复错误、改善用户体验,并最小化业务中断的成本。 03、用 ZadigX 落地持续测试 编排不同测试类型 静态代码扫描 支持主流的静态安全工具例如 SonarQube、Coverity,和任何自定义扫描工具。 如何配置:以 SonarQube 示例,新增代码扫描,指定扫描工具<SonarQube>,配置待扫描的代码库、扫描脚本,开启质量门禁检查并配置触发器,具体的配置步骤可参考文档:如何配置静态代码扫描[4]。 如何编排:编辑自定义工作流,在指定阶段(比如:构建之前)添加<代码扫描>任务即可。 单元测试 支持对 Java、Golang、Python、C++、JavaScript、C#、PHP、Ruby 等各种语言的技术栈执行单元测试 如何配置:新增测试,配置基本信息、代码信息和测试脚本,在<测试报告配置>中指定报告目录,添加触发器配置并增加 IM 通知,具体的配置步骤可参考文档:如何配置测试[5]。 如何编排:编辑自定义工作流,在指定阶段(比如:部署之后,执行自动化测试)添加<测试>任务即可。 集成测试 支持的测试类型包括但不限于:API 接口测试、UI 测试、端到端测试、压力测试、场景测试... 配置过程和单元测试类似,此处不再赘述。具体编排:编辑自定义工作流,添加<测试>任务并填写配置,以下图示例说明参数: 任务名称:根据实际语义配置,比如 apitest-for-service 任务类型:选择服务测试 服务组件:选择待测试的服务组件,配置服务组件和测试的关联,当部署服务后将会运行指定的测试 此外,为自定义工作流配置触发器和通知,实现基于代码变更自动运行测试、测试结果及时同步 IM。参考文档:触发器配置[6]、通知配置[7]。 系统测试 支持产品级别的测试,对产品进行全面的系统测试,从整体充分把握系统质量。测试配置中的任务类型选择<产品测试>,其他的配置和集成测试类似,此处不再赘述。 运行持续测试场景 开发阶段:静态扫描打基础 流程:代码实现 > 代码提交 > 自动触发静态代码扫描质量门禁 > 开发人员及时获得反馈 > 有的放矢改进 代码开发完毕提交 PR 后会自动触发代码扫描执行,可有效拦截未通过质量门禁的代码变更。扫描结果会自动 comment 在代码变更中,开发人员可点击快速获得扫描结果,针对反馈进一步优化代码。从代码源头来规避质量风险,做到 fail fast > feedback fast > fix fast。 测试阶段:组合策略赋能力 流程:静态扫描(开启质量门禁) > 构建 > 部署 > 自动化测试 > IM 通知 ZadigX 可一键拉起独立的开发、测试环境(参考文档:创建环境[8]),只需要将测试编排进自定义工作流中就可以实现在开发环境、测试环境分别建设自动化测试套件,将测试能力编排进团队日常合作的每一个环节中: 开发自测阶段,更新开发自测环境并执行自动化测试。 多名开发联调测试阶段,可以将多人的改动同时部署更新进行集成测试验证。 测试工程师验收阶段,可在 ZadigX 中分析测试报告,并根据覆盖情况持续补充自动化用例集,确保自动化测试套件与业务功能一同迭代,持续为团队提供价值,测试工程师的能力也在平台中得到充分展现。 此外,工作流运行结果可及时通知到 IM 群中,团队内每个人都能及时感知自动化执行情况,为质量负责。 发布阶段:多重保障保质量 流程:发布质量门禁 > 发布委员会人工审核 > 分批次灰度发布 > 系统测试 > IM 通知 测试验收通过后进行发布上线操作,建议几种配置策略: 建设发布门禁,通过自定义任务自动获取安全扫描、单元测试、集成测试等质量结果来判断是否允许上线,作为上线过程的卡点,确保版本验收通过并且符合质量要求后再做上线操作。 灵活编排蓝绿、金丝雀、分批次灰度、Istio 等发布策略,以确保发布可靠性,可参考:发布工作流[9]。 发布工作流适当增加测试团队人工审批,以确保业务流程上的发布合规性。 04、One More Thing:如何度量持续测试效果 任何实践都要讲求投入产出比,而持续测试的效果可以通过:测试的编写人员比例,发现的 Bug 数量,自动化测试的有效性,以及是否在 CI/CD 中运行自动化测试来衡量等方面来度量,具体如下: 05、小结 通过 ZadigX 支撑持续测试和自动化测试的实施,帮助测试团队更好地应对当前的测试行业挑战,确保软件交付的质量和稳定性,提高开发和交付过程的效率。 参考链接 阅读原文https://mp.weixin.qq.com/s/meO6yqzZdMQfBoEsAcr1Ig [1]持续交付流水线:https://continuousdelivery.com/implementing/patterns/#the-deployment-pipeline [2]持续测试:https://cloud.google.com/architecture/devops/devops-tech-test-automation [3]持续测试:https://www.ibm.com/cn-zh/topics/continuous-testing [4]如何配置静态代码扫描:https://docs.koderover.com/zadig/ZadigX%20v1.5.0/project/scan/ [5]如何配置测试:https://docs.koderover.com/zadig/ZadigX%20v1.5.0/project/test/ [6]触发器配置:https://docs.koderover.com/zadig/ZadigX%20v1.5.0/project/common-workflow/#触发器配置 [7]通知配置:https://docs.koderover.com/zadig/ZadigX%20v1.5.0/project/common-workflow/#通知配置 [8]创建环境:https://docs.koderover.com/zadig/ZadigX%20v1.5.0/project/env/k8s/ [9]发布工作流:https://docs.koderover.com/zadig/ZadigX%20v1.5.0/project/release-workflow/

优秀的个人博客,低调大师

告别纽交所!纽交所维持三大运营商退市决定

5月7日,三大运营商发布公告称纽交所称将对三家中国电信运营商启动退市程序。 公告显示纽约证交所委员会维持了纽约证交所监管部门重新启动本公司美国存托证券ADR下市程序的决定,预计纽约证交所将向美国证券交易委员会提交25表格以撤销本公司美国存托证券的上市及注册(退市)。 2020年11月12日,特朗普政府公布一项行政命令,禁止美国投资者对中国军方拥有或控制的企业进行投资。该规定可能会影响到包括中国电信、中国移动、海康威视等31家中国企业。此举旨在阻止美国投资公司、养老基金和其他机构买卖这些中国企业的股票,这些中国企业今年早些时候被美国国防部认定为受中国军方支持。行政命令将于明年1月11日生效。该命令将禁止美国投资者对上述中国企业的证券进行任何交易。同时,它还禁止美国人在被认定为“中国军事企业”的60天内买卖这些企业的证券。 有专家表示,三大运营商都是在香港上市,在美国市场ADR的退市对他们在香港的正常交易不会有很大影响,更多的是体现在预期和信心上。而影响投资者对运营商未来预期的更主要的因素其实还是他们在国内市场的表现。所以说对运营商来说,根本的还是做好自己在国内市场的工作。只要国内市场稳健发展,外界这些影响就都是可控的。 3月9日,中国电信在港交所发布公告指出,为把握数字化发展机遇,完善公司治理,拓宽融资渠道,加快改革发展,推动战略落地,实现高质量发展,中国电信拟申请本次A股发行并在上海证券交易所主板上市。公告显示,在符合上市地最低发行比例等监管规定的前提下,中国电信拟公开发行A 股数量不超过12,093,342,392股(即不超过本次A股发行后公司已发行总股本的13%,超额配售选择权行使前)。且在相关法律、行政法规、部门规章和相关规范性文件的规定下,制定本次发行方案。所募资金将用于5G产业互联网建设项目、云网融合新型信息基础设施项目及科技创新研发项目。

资源下载

更多资源
优质分享App

优质分享App

近一个月的开发和优化,本站点的第一个app全新上线。该app采用极致压缩,本体才4.36MB。系统里面做了大量数据访问、缓存优化。方便用户在手机上查看文章。后续会推出HarmonyOS的适配版本。

腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

用户登录
用户注册