\\n \\n );\\n});
在TemperatureConverter组件中,useWatch$用来创建一个副作用,当celsius状态发生变化时,它会以华氏温度为单位记录温度。track函数用于指定哪个状态应该触发副作用。
Qwik的反应性得益于其智能的差分(diffing)算法,该算法能够根据状态变化确定可能发生变化的最小的DOM范围。这是通过使用“存储”来实现的,它是一个轻量级代理,用于跟踪状态的访问和变化。
当组件渲染时,Qwik会创建一个访问属性的快照。当发生改变状态的事件时,Qwik会将新状态与快照进行对比,并且只更新DOM中依赖已变更属性的部分。
import { component$, useStore } from \'@builder.io/qwik\';\\n\\n\\nexport const StoreExample = component$(() => {\\n const store = useStore({ name: \'Qwik\' });\\n\\n\\n return (\\n
\\n (store.name = event.target.value)}\\n />\\n Hello, {store.name}!
\\n
\\n );\\n});
在StoreExample中,useStore创建了一个带有name属性的反应式存储。当输入的值发生变化时,name属性就会更新,Qwik会自动更新
标签,以反映新的名称。
import { component$, useStore } from \'@builder.io/qwik\';\\n\\n\\nexport const DiffingExample = component$(() => {\\n const store = useStore({ firstName: \'John\', lastName: \'Doe\' });\\n\\n\\n return (\\n
\\n (store.firstName = event.target.value)}\\n />\\n (store.lastName = event.target.value)}\\n />\\n \\n Full Name: {store.firstName} {store.lastName}\\n
\\n
\\n );\\n});
在DiffingExample中,每个输入字段都会更新存储中的不同属性。Qwik的差分算法确保输入First Name字段时,只会更新
标签的firstName部分,Last Name字段同样如此。
Qwik的反应式模型不仅关系到性能,还涉及到开发人员的体验。该框架提供了一系列最佳实践和工具,它们使得编写高效的反应式代码更容易:
内联处理器(Inline Handler):通过内联事件处理器,Qwik可以更高效地优化应用程序的反应性。
import { component$, useStore } from \'@builder.io/qwik\';\\n\\n\\nexport const InlineExample = component$(() => {\\n const state = useStore({ active: false });\\n\\n\\n return (\\n (state.active = !state.active)}>\\n {state.active ? \'Active\' : \'Inactive\'}\\n \\n );\\n});
在本例中,点击处理器是内联定义的,这样Qwik就能将处理器与按钮元素序列化,从而提高加载和交互效率。
延迟加载(Lazy Loading):事件处理器和副作用只有在需要时才会进行加载,从而减少初始的JavaScript载荷。
import { component$, useStore } from \'@builder.io/qwik\';\\n\\n\\nexport const LazyLoadingExample = component$(() => {\\n const state = useStore({ loaded: false });\\n\\n\\n return (\\n
\\n {\\n state.loaded = true;\\n await import(\'./HeavyComponent\');\\n }}\\n >\\n Load Heavy Component\\n \\n {state.loaded && }\\n
\\n );\\n});
在LazyLoadingExample中,HeavyComponent在用户点击按钮前并不会加载,这展示了Qwik是如何优化资源加载的。
序列化(Serialization):Qwik的事件处理器是可以序列化的,这意味着它们可以存储在DOM中,并在不需要加载整个组件代码的情况下再次生成(rehydrate)。
mport { component$, useStore } from \'@builder.io/qwik\';\\n\\n\\nexport const SerializationExample = component$(() => {\\n const state = useStore({ count: 0 });\\n\\n\\n return (\\n
\\n state.count++}>\\n Increment\\n \\n Count: {state.count}\\n
\\n );\\n});
在SerializationExample中,onClick$处理器会与按钮一起序列化。当点击按钮时,Qwik能够知道只需加载递增操作所需的代码。
通过应用这些优化技术,开发人员可以确保他们的Qwik应用程序不仅性能优异,而且还能提供无缝的用户体验。Qwik对优化的重视体现在其API设计中,它鼓励开发人员只需编写代码即可,性能更好的应用程序是水到渠成的。
Qwik的反应式状态管理印证了该框架对性能和可扩展性的承诺。通过了解和利用其反应性模型,开发人员可以创建出不仅速度快捷、反应灵敏,而且可维护性强、易于使用的web应用。
随着web开发的不断发展,像Qwik这样的框架正在引领着潮流。凭借其神奇的底层技术,Qwik将成为重视性能和用户体验的开发人员的最爱。
","description":"本文最初发表于Medium网站\\",由InfoQ中文站翻译分享。 \\n\\n在现代Web开发中,状态管理是交互式应用程序的基石。在前端框架领域,Qwik是很有前景的新成员,它引入了一种高效且新颖的反应式模型。本文将揭开Qwik的反应式状态管理的神秘面纱,让我们一窥其内部运行原理,并展示如何利用它构建性能优异的动态用户界面。\\n\\n、\\n\\nQwik反应式的基本知识\\n\\n \\n\\n就其本质而言,Qwik的反应式系统是围绕细粒度反应性(fine-grained reactivity)的概念设计的。与依赖虚拟DOM跟踪变化的传统框架不同,Qwik直接在实际DOM上运行…","guid":"https://www.infoq.cn/article/XmUdOs1YpDpKYJJByhBf","author":"作者:Roman Sypchenko","authorUrl":null,"authorAvatar":null,"publishedAt":"2025-03-23T03:00:00.066Z","media":null,"categories":["后端"],"attachments":null,"extra":null,"language":null},{"title":"通过SBOM确保Java应用的供应链安全","url":"https://www.infoq.cn/article/2Gg5mTG5HEXSWBuOxENv","content":"本文最初发表于作者的个人站点\\",经作者Thomas Vitale\\"授权,由InfoQ中文站翻译分享。
软件供应链的安全性从未像现在这么重要,保护我们的系统免受不良行为者和漏洞的侵害是一项持续的挑战。对于Java应用程序中的所有库和依赖关系,你是否具备完全的可见性和透明度呢?
准确了解应用程序中包含的每个组件对于执行漏洞扫描和许可证合规性检查等操作都至关重要。如果不知道软件系统的内部结构,又如何确保其安全性呢?
软件物料清单(Software Bill of Materials,SBOM)是“软件的嵌套清单,是构成软件组件的配料列表”(NTIA)。在本文中,我将解释为何我们要使用SBOM作为供应链安全策略的一部分,以及业界都有哪些可用的标准。
然后,我将向你展示如何在软件生命周期的不同阶段为Java应用程序生成SBOM,并解释每项技术的优缺点。你将会看到如何为Java源码、JAR制品(artifact)、GraalVM原生可执行文件和容器镜像创建SBOM。我还将介绍如何使用Gradle或Maven将生成SBOM作为构建的一部分。让我们开始吧!
本文实例的源码可以在GitHub\\"上获取。
在设计供应链安全策略时,SBOM是关键的一环。SBOM能够“识别并列出软件组件、组件的相关信息以及它们之间的供应链关系”(NTIA)。例如,对于每个软件组件,SBOM可以包含版本号、许可证描述符、供应商的详细信息、哈希摘要值、是否为传递依赖等。
通过这份清单文件,扫描器可以检查每个组件的完整性、已知的安全漏洞、是否符合许可策略以及是否有更新的版本。来自SBOM的数据还可以输入资产管理和采购的企业流程。这些用例是我们需要SBOM的部分原因。
此外,我们行业的主要安全框架和流程都推荐使用SBOM。根据美国总统第14028号行政命令(Executive Order,EO):“提高国家的网络安全”\\",向美国联邦机构提供的软件必须使用SBOM。不久之后,软件供应商也必须遵守欧盟的“网络弹性法案\\"”。
在本文中,我将重点介绍如何为Java应用程序生成高质量的SBOM。后续的文章将会深入介绍如何使用它们来解决供应链安全策略中的多个使用场景。例如,我将会讨论使用Trivy\\"进行漏洞扫描以及使用Dependency Track\\"进行持续供应链风险管理。
我们希望得到结构化的SBOM文档,以便于自动化系统能够处理它的数据。CycloneDX和SPDX是两种最广泛使用的且机器可读的SBOM格式。
CycloneDX\\"是“一种全栈物料清单(BOM)标准,能够为降低网络风险提供先进的供应链功能”。该规范支持SBOM和其他使用场景,比如VEX(漏洞可利用性交换,Vulnerability Exploitability eXchange)和VDR(漏洞披露报告,Vulnerability Disclosure Reports),我将会在以后关于漏洞管理的文章中介绍这些使用场景。它还支持各种类型的物料清单,比如SaaSBOM(软件即服务物料清单,Software-as-a-Service Bill of Materials)、KBOM(Kubernetes物料清单,Kubernetes Bill of Materials)和ML-BOM(机器学习物料清单,Machine Learning Bill of Materials)。CycloneDX是OWASP\\"的旗舰项目,目前正在寻求国际Ecma的标准化。
SPDX\\"(软件包数据交换,Software Package Data Exchange)是“交流软件物料清单信息的开放标准,包括出处、许可证、安全性和其他相关的信息”。目前正在开发的SPDX 3.0将支持SBOM之外的更多使用场景,比如VEX和其他类型的BOM。该规范得到了Linux基金会\\"的支持,并被认定为国际标准ISO/IEC 5962:2021。
这两种格式都在业界得到了应用,并在供应链安全生态系统中获得了广泛支持。我不打算讨论该采用哪种格式,因为这取决于预期的使用场景、企业的具体需求以及与当前系统集成的可能性。目前,有一些工具能够将其中的某种格式转换成另一种格式。
在本文中,我将使用CycloneDX,因为现在它在Java生态系统中得到了更好地支持。在可能实现的地方,我都会给出如何将示例转换为使用SPDX的提示。
在选择了定义SBOM的标准格式后,那么我们该讨论一下什么才算好的SBOM了。影响SBOM质量的因素有很多。
清单中每个组件包含的信息决定了SBOM可用于哪些使用场景。如果你想将SBOM用于许可证合规性检查,那么每个组件都必须包含许可证的详细信息。如果你想要遵循美国总统第14028号行政命令(Executive Order,EO):“提高国家的网络安全”\\",那么每个SBOM中都必须包含一组最基本的元素\\"。
应用程序最终SBOM中所包含的详细信息的深度会受到软件生命周期中SBOM生成时机的影响。创建SBOM的工具也会影响最终结果的质量。在下面的章节中,我将带领你使用一些不同的工具,在不同阶段(源代码、构建、可执行文件)生成SBOM。
由于生成和使用SBOM的方式多种多样,因此评估SBOM的质量可能是一项很具挑战性的事情。OWASP软件组件验证标准\\"项目背后的社区发布了一个BOM成熟度模型\\",该模型提供了“一个正式的结构,在此结构中可以对物料清单的各种能力进行评估”。该模型还支持将BOM信息组织成与使用场景相关的类别(如应用程序的安全性、许可证和采购信息)以及验证其合规性的配置文件。
此外,还出现了可以扫描SBOM并根据特定标准进行评分的工具。例如,你可以使用sbomqs\\"(SBOM质量评分,SBOM Quality Score),这是SBOM Benchmark\\"项目的一个实验性工具。
假设你已经组装了Java制品(JAR或容器镜像)。在这种情况下,我们可以使用扫描制品的工具生成SBOM,并搜索其中包含的软件包。
在软件生命周期的这一阶段创建的SBOM应该能够保证最终应用制品的所有组件的可见性,包含运行时所需的依赖项,如操作系统库和Java运行时(适用于容器镜像)。最终结果在很大程度上依赖于生成SBOM的工具,也就是它能找到多少个组件?
即便好的工具可以识别应用程序制品中包含的(几乎)所有软件组件,但是每个组件的信息深度可能会有所不足。但这是一件坏事儿吗?这要看具体情况。例如,在本阶段生成的SBOM可能非常适合进行漏洞扫描。相比之下,它们可能缺少验证许可证合规性或跟踪依赖关系所需的必要信息。根据你的需求,可以考虑是否有必要将SBOM生成转移到软件生命周期的更早阶段(稍后将会进行讲解),以解决现阶段无法实现的使用场景。
对于第三方应用程序,我建议要求供应商在交付时就提供SBOM,而不是自己通过他们的制品生成SBOM。根据你所在的国家和行业,这甚至可能是(或很快成为)法律要求。如果是开源项目,可以考虑使用本文中学到的技术,提交pull request以添加SBOM的生成。
为打包成JAR制品的Java应用生成SBOM需要一个支持从JAR中查找和提取信息的工具。Syft\\"是一款用于生成SBOM的流行开源工具,可用于JAR制品。
你可以查阅它的文档,了解如何在你的机器上安装该工具。在macOS和Linux上,可以使用Homebrew软件包管理器。
brew install syft
接下来,下载包含本文所有样例的Git仓库\\",并导航至本节将使用的应用程序。该样例是基于Spring Boot的,但是本文所涉及的内容同样适用于所有Java应用,与框架无关。
git clone https://github.com/ThomasVitale/supply-chain-security-java\\ncd sbom/cyclonedx/gradle
然后,将样例应用程序打包成JAR制品。该项目配置了Java 21,如果你还有安装它的话,请参考SDKMAN\\"进行安装。
./gradlew bootJar
借助SDKMAN\\",安装Java 21只需一条sdk install java 21-tem命令即可。
最后,你可以使用Syft从Java制品开始为应用程序生成SBOM。
syft build/libs/demo-sbom-cdx-gradle-1.0.jar -o cyclonedx-json --file bom-syft.cdx.json
请参阅生成的SBOM(bom-syft.cdx.json)以熟悉CycloneDX格式的结构。
要生成基于SPDX格式的SBOM,请将-o cyclonedx-json替换为-o spdx-json。
要为打包成容器镜像的Java应用程序生成SBOM,需要一种支持从JAR中查找和提取信息、识别操作系统包和Java运行时。Syft也支持这种使用场景。
我们使用与上一个样例相同的应用程序,将其打包为容器镜像。在继续之前,请确保已经运行Podman或Docker。Spring Boot依赖Cloud Native Buildpacks构建生产级别的容器映像,无需任何 Dockerfile。
./gradlew bootBuildImage
如果你使用Quarkus的话,你可以选择使用Cloud Native Buildpacks集成。首先,在属性文件中配置构建器镜像:quarkus.buildpack.jvm-builder-image=paketobuildpacks/builder-jammy-tiny。然后,运行./gradlew build -Dquarkus.container-image.build=true命令来构建镜像。
然后,就可以使用Syft从容器镜像开始为应用程序生成SBOM。
syft demo-sbom-cdx-gradle:1.0 -o cyclonedx-json --file bom-oci-syft.cdx.json
要生成基于SPDX格式的SBOM,请将-o cyclonedx-json替换为-o spdx-json。
如果你查看生成的SBOM(bom-oci-syft.cdx.json),就会发现与之前相同的Java依赖关系,但是还包含了Syft可以在镜像内的Ubuntu文件系统中找到的所有软件包的列表。
在上一节中,我们使用了Spring Boot的bootBuildImage Gradle task来容器化Java应用程序。在幕后,Spring Boot使用了Cloud Native Buildpacks,这是一种无需Dockerfile就能将应用程序源代码转换为容器镜像的规范。
更具体地说,Spring Boot使用了Paketo Buildpacks\\"实现,该实现使用Syft为构建的镜像的每一层均生成一个SBOM。当需要为使用Buildpacks构建的容器镜像创建SBOM时,你可以从镜像中提取自动生成的SBOM,而不用像之前那样显式创建。
如果你想要提取由Buildpacks生成的SBOM,请安装pack\\" CLI。你可以查阅其文档\\"了解如何在你的机器上安装该工具。在macOS和Linux上,可以使用Homebrew软件包管理器。
brew install buildpacks/tap/pack
然后,使用pack从镜像的每一层抽取SBOM。
pack sbom download demo-sbom-cdx-gradle:1.0 -o sbom-layers
你可以在sbom-layers目录中找到SBOM。在下面的示例中,你可以看到每一层都有一个或多个不同格式的SBOM。
$ tree sbom-layers\\n\\n\\nsbom-layers\\n└── layers\\n └── sbom\\n └── launch\\n ├── buildpacksio_lifecycle\\n │ └── launcher\\n │ ├── sbom.cdx.json\\n │ ├── sbom.spdx.json\\n │ └── sbom.syft.json\\n ├── paketo-buildpacks_ca-certificates\\n │ └── helper\\n │ └── sbom.syft.json\\n ├── paketo-buildpacks_executable-jar\\n │ ├── sbom.cdx.json\\n │ └── sbom.syft.json\\n ├── paketo-buildpacks_native-image\\n │ ├── sbom.cdx.json\\n │ └── sbom.syft.json\\n └── sbom.legacy.json
这是Buildpacks一个便利的特性,它可以生成比镜像构建后更高质量的SBOM。不过,从镜像中提取SBOM,而且与供应链生态系统中的其他工具集成也有些难度。此外,它的行为可以更加具有一致性。不同的buildpacks会生成不同格式的SBOM。上述样例中唯一不变的是Syft格式,这需要在集成场景中明确转换为CycloneDX或SPDX 格式。
有关Cloud Native Buildpacks中SBOM支持的更多信息,请查看 Buildpacks\\"和Paketo\\"的文档。
JReleaser\\"是编排软件发布的强大工具,为Java项目提供了许多有用的特性。其中,JReleaser可以为我们编排SBOM的生成。它基于最终的应用程序制品(JAR或容器镜像),并使用Syft或CycloneDX CLI来生成SBOM。
你可以查阅项目的文档\\",了解如何配置该特性。关于JReleaser的阐述值得单独写一篇文章,在此我就不再展开叙述了,但是我依然建议你了解一下这个工具。
如果你可以访问Java应用程序的源码,那么就可以采用某种工具来生成SBOM,该工具会扫描项目并搜索其中引用的软件包。
在软件开发生命周期的这个阶段创建SBOM能够确保应用程序项目的所有组件的可见性,包括构建和测试所需的依赖项,比如注解处理器和测试库。它的结果在很大程度上取决于生成SBOM所使用的工具,但是我们希望它能够比前一种策略更加详细,因为工具可以完全访问源代码。
在本阶段生成的SBOM非常适合进行许可证合规性检查,以及查找影响软件项目中所使用组件的已知漏洞。相比之下,它们可能会遗漏运行时所需的依赖关系,这通常对应以容器镜像分发应用程序的情况。此外,这些SBOM通常会包含比最终制品更多的内容(比如测试依赖项),因此不太适合用在采购这样的场景中。
正如前文所述,SBOM可以根据特定的使用场景进行定制。根据你所需要的能力,可以考虑在软件生命周期的不同阶段创建SBOM,并使用它们来满足特定的需求。
CycloneDX项目提供了一个名为cdxgen\\"的工具,它可以全面了解Java项目中使用的所有依赖,同时支持Gradle和 Maven。这就是我们接下来要使用的工具。
请查阅文档\\"了解如何在你的机器上安装cdxgen。在macOS和Linux上,可以使用Homebrew软件包管理器。
brew install cdxgen
你可以在本文Git仓库\\"所包含的应用程序(sbom/cyclonedx/gradle)中尝试这一策略。我们可以使用cdxgen从项目源代码开始为应用程序生成SBOM。
FETCH_LICENSE=true cdxgen -o bom-cdxgen.cdx.json --spec-version 1.5
请查看生成的SBOM(bom-cdxgen.cdx.json),并将其与之前用Syft创建的SBOM进行对比,你注意到有什么差异吗?
要生成SPDX格式的SBOM,可以使用Trivy\\"并执行命令trivy fs --format spdx-json --output bom-trivy.spdx.json .。对于Maven项目,该命令开箱即用。对于Gradle项目,则需要启用依赖版本锁定\\"特性,否则Trivy将不知道如何找到Java依赖关系。
在本文的Git仓库\\"中,还有一个使用Maven的Java应用样例(sbom/cyclonedx/maven),你可以使用它来测试基于cdxgen来生成SBOM。结果与Gradle样例非常类似。
cdxgen工具非常强大,它支持多种语言和生态系统,甚至还能通过profile提供专用的选项,从而根据使用场景(应用安全性、研究、运维、安全危险建模和许可证合规性)来生成SBOM。你可以在该项目的网站上找到更多信息。
通过profile,cdxgen可以生成针对特定使用场景定制和优化的 SBOM。例如,如果你需要用于研究目的的SBOM,可以运行以下命令: cdxgen -o bob-research.cdx.json --spec-version 1.5 --profile research,这将启用深度和证据模式。你可以尝试将结果与迄今为止生成的SBOM进行比较,发现它们之间的差异了吗?
在讨论了从应用程序制品(JAR、容器镜像)和源码生成SBOM的方案之后,现在我们研究一下如何将生成过程作为构建生命周期的一部分。对于Java应用,我们需要有一个工具挂接到构建过程中,并提取用来组装软件的每个组件的信息。
在软件开发生命周期这一阶段创建SBOM应该能够保证用于构建应用程序的所有组件的可见性。由于生成过程与构建生命周期挂钩,所以我们可以完全控制包含哪些组件,并获得比其他策略更深入的结果。
在这一阶段生成的SBOM非常适合大多数使用场景,比如漏洞扫描、许可证合规性和采购。通常来讲,我们可以对操作进行定制,以便于在最终的SBOM中只包含某些特定类型的依赖(比如,如果你想排除掉测试依赖,这就非常有用)。但是,这些SBOM可能会遗漏运行时所需的依赖,在使用容器镜像分发的应用程序中通常会遇到这种情况。
我建议将SBOM生成作为Java构建生命周期的一部分,因为这样可以生成质量更高、更详细的文档,实现供应链风险管理所需的众多功能。然后,基于具体情况和需求,你可能希望用其他阶段生成的SBOM来完善生成的文档,并对构建生命周期中无法实现的使用场景进行定制。
CycloneDX项目\\"为Gradle和Maven提供了两个方便的插件,能够使SBOM生成过程成为构建生命周期的一部分。我们接下来就将使用这两个插件。
我们首先探讨一下如何使用CycloneDX Gradle插件\\"为Java应用程序生成SBOM。你可以在本文Git仓库\\"(sbom/cyclonedx/gradle)包含的应用程序中尝试这一策略。
首先,将插件添加到build.gradle文件中。
plugins {\\n id \'org.cyclonedx.bom\' version \'1.8.1\'\\n}
该插件添加了一个cyclonedxBom task,用来为应用程序生成SBOM。我们尝试一下。
./gradlew cyclonedxBom
默认情况下,SBOM会生成在build/reports/bom.json文件中。你可以将结果与其他阶段创建的SBOM进行比较,是否能够发现有什么差异?
我们可以根据需要自定义插件。例如,我们将其配置为使用JSON的CycloneDX模式1.5版。你还可以将其作为构建步骤的一部分,这样每次构建应用程序的时候都会自动生成SBOM。
cyclonedxBom {\\n projectType = \\"application\\"\\n outputFormat = \\"json\\"\\n schemaVersion = \\"1.5\\"\\n}\\ntasks.build.finalizedBy \'cyclonedxBom\'
该插件提供了多种定制化,包括希望在最终的SBOM中都包含哪些依赖项(运行时、编译和测试)。你还可以传递有关应用程序的其他元数据,比如组织的联系方式以及项目使用的许可证。请参阅插件文档\\",以了解所有可用的配置。
如果要生成基于SPDX格式的SBOM,可以使用SPDX Gradle插件\\"。
我们探讨一下如何使用CycloneDX Maven\\"插件为Java应用程序生成SBOM。你可以在本文Git仓库(sbom/cyclonedx/maven)包含的应用程序中尝试这一策略。
首先,将插件添加到pom.xml文件中。
\\n \\n \\n org.cyclonedx\\n cyclonedx-maven-plugin\\n 2.7.10\\n \\n \\n
该插件添加了一个makeAggregateBom goal来为应用程序生成SBOM。我们尝试一下。
./mvnw cyclonedx:makeAggregateBom
默认情况下,SBOM会生成在target/bom.json文件中。你可以将结果与其他阶段创建的SBOM进行比较,是否能够发现有什么差异?
我们可以根据需要自定义插件。例如,我们将其配置为使用JSON的CycloneDX模式1.5版。你还可以将其作为构建步骤的一部分,这样每次构建应用程序的时候都会自动生成SBOM。
\\n \\n \\n org.cyclonedx\\n cyclonedx-maven-plugin\\n 2.7.10\\n \\n \\n package\\n \\n makeAggregateBom\\n \\n \\n \\n \\n application\\n json\\n 1.5\\n \\n \\n \\n
该插件提供了多种定制化,包括希望在最终的SBOM中都包含哪些依赖项(运行时、编译和测试)。你还可以传递有关应用程序的其他元数据,比如组织的联系方式以及项目使用的许可证。请参阅插件文档\\",以了解所有可用的配置。
如果要生成基于SPDX格式的SBOM,可以使用SPDX Maven插件\\"。
在最后一节中,我将介绍在使用GraalVM将Java应用程序编译为原生可执行文件时,生成SBOM的方案。
GraalVM\\"的原生镜像模式具有很多优势,比如即时启动时间、即时峰值性能和更低的内存消耗。从安全的角度来看,与标准的JVM应用程序相比,使用GraalVM编译的原生可执行文件的攻击面也更小。原因在于,GraalVM只编译从main()方法开始的代码中可达的路径。其他任何内容均不会包含在最终结果中。
关于GraalVM提供的额外安全功能,我将在今后有关漏洞管理的文章中详细阐述。现在,我想指出的是,最终制品将不包含任何JAR文件,这意味着扫描器在使用常规技术分析原生可执行文件时无法找到任何组件。
在处理原生可执行文件时,我们无法直接扫描最终制品以生成 SBOM。相反,我们需要将SBOM的生成步骤转移到软件开发生命周期的早期阶段。我之前介绍过的源代码和构建生命周期策略都是可行的,但它们包含的可能是编译到最终可执行文件中的实际依赖项的超集。
为了获得更准确的结果,Oracle GraalVM发行版在编译应用程序时提供了一个试验性的SBOM生成特性\\"。该功能在底层使用了Syft,目前仅支持CycloneDX格式。
作为GraalVM编译过程的一部分而生成的SBOM的质量与我在本文中提到的第一种策略大致相同。例如,它适用于漏洞管理场景,但不适用于许可证合规性检查的场景,因为最终结果中可能缺少必要的信息。
在继续示例之前,请确保已安装Oracle GraalVM并将其设置为项目中的默认Java版本和发行版。您可以使用SDKMAN\\"执行此操作。
sdk install java 21-graal\\nsdk use java 21-graal
我们看一下如何使用Gradle为GraalVM的原生应用程序生成SBOM。你可以在本文Git仓库\\"(sbom/cyclonedx/gradle-native)所包含的应用程序中尝试这一策略。
首先,在build.gradle文件中配置GraalVM Gradle插件,启用SBOM生成功能。
graalvmNative {\\n binaries {\\n configureEach {\\n buildArgs.add(\\"--enable-sbom=cyclonedx,export\\")\\n }\\n }\\n}
然后,将应用编译为原生可执行文件。
./gradlew nativeCompile
作为原生编译过程的一部分,这里会使用Syft并按照CycloneDX 格式生成SBOM。SBOM的一个副本会包含在制品本身中,因为我们在配置中添加了export标记,所以它也会导出到build/native/nativeCompile/demo-sbom-cdx-gradle-native.sbom.json中。你可以使用原生镜像探查工具(Native Image Inspection Tool)\\"检查导出的SBOM,甚至提取嵌入到原生可执行文件中的SBOM。
目前,我们不能使用SPDX格式生成SBOM。Oracle GraalVM仅支持CycloneDX。
我们看一下如何使用Maven为GraalVM的原生应用程序生成SBOM。你可以在本文Git仓库\\"(sbom/cyclonedx/maven-native)所包含的应用程序中尝试这一策略。
首先,在pom.xml文件中配置GraalVM Maven插件以启用SBOM生成功能。
\\n \\n \\n org.graalvm.buildtools\\n native-maven-plugin\\n \\n \\n --enable-sbom=cyclonedx,export\\n \\n \\n \\n \\n
然后,将应用编译为原生可执行文件。
./mvnw -Pnative native:compile
作为原生编译过程的一部分,这里会使用Syft并按照CycloneDX 格式生成SBOM。SBOM的一个副本会包含在制品本身中,因为我们在配置中添加了export标记,所以它也会导出到target/demo-sbom-cdx-maven.sbom.json中。你可以使用原生镜像探查工具(Native Image Inspection Tool)\\"检查导出的SBOM,甚至提取嵌入到原生可执行文件中的SBOM。
目前,我们不能使用SPDX格式生成SBOM。Oracle GraalVM仅支持CycloneDX。
本文介绍了软件物料清单(SBOM)的概念及其对软件供应链安全至关重要的原因。文章介绍了在软件开发生命周期的三个不同阶段为 Java应用程序生成SBOM的主要策略,即源代码、构建和制品阶段。除此之外,我还讨论了Gradle、Maven和GraalVM中专门的集成方案。
创建SBOM只是开始。它真正的价值在于积极使用SBOM来管理软件的供应链安全风险。在今后的文章中,我将讨论如何将SBOM作为构建流水线的一部分进行分发,以及如何将它们用于漏洞扫描、许可证合规性、依赖关系管理和其他使用场景。敬请期待!
","description":"本文最初发表于作者的个人站点\\",经作者Thomas Vitale\\"授权,由InfoQ中文站翻译分享。 \\n\\n软件供应链的安全性从未像现在这么重要,保护我们的系统免受不良行为者和漏洞的侵害是一项持续的挑战。对于Java应用程序中的所有库和依赖关系,你是否具备完全的可见性和透明度呢?\\n\\n \\n\\n准确了解应用程序中包含的每个组件对于执行漏洞扫描和许可证合规性检查等操作都至关重要。如果不知道软件系统的内部结构,又如何确保其安全性呢?\\n\\n \\n\\n软件物料清单(Software Bill of Materials,SBOM)是“软件的嵌套清单,是构成软件组件的配料列表”(NTIA)。在本文中…","guid":"https://www.infoq.cn/article/2Gg5mTG5HEXSWBuOxENv","author":"作者:Thomas Vitale","authorUrl":null,"authorAvatar":null,"publishedAt":"2025-03-22T07:00:00.112Z","media":null,"categories":["编程语言"],"attachments":null,"extra":null,"language":null},{"title":"如何在Java中基于LangChain编写大语言模型应用","url":"https://www.infoq.cn/article/8HSamdS5C15xXZWGwte2","content":"本文最初发表于Baeldung网站\\",由InfoQ中文站翻译分享。
在本教程中,我们将会研究LangChain\\"的细节,这是一个利用语言模型开发应用程序的框架。首先,我们会介绍有关语言模型的基本概念,这将对本教程有一定的辅助作用。
尽管LangChain主要提供了Python和JavaScript/TypeScript语言的版本,但是也有在Java中使用LangChain的可选方案。我们将会讨论组成LangChain框架的构建基块,然后在Java中进行实验。
在深入探讨为何需要一个框架来构建语言模型驱动的应用程序之前,我们必须首先了解什么是语言模型,除此之外,我们还会介绍在使用语言模型时遇到的一些典型的复杂问题。
语言模型是自然语言的一个概率模型,可以生成一系列单词的概率。大语言模型\\"(LLM)是以规模庞大为特征的一种语言模型。它们是人工智能网络,可能会有数十亿个参数。
LLM通常会使用自监督\\"和半监督\\"学习技术,在大量无标记的数据上进行预训练。然后,使用微调和提示工程等各种技术对预训练模型进行调整,使其适用于特定的任务:
这些LLM能够执行多种自然语言处理任务,如语言翻译和内容摘要。它们还能完成内容创建等生成型任务。因此,它们在问题回答这样的应用中极具价值。
几乎所有主流的云服务提供商都在它们的软件产品中加入了大语言模型。例如,微软Azure\\"提供了Llama 2和 OpenAI GPT-4等LLM。Amazon Bedrock\\"提供了来自 AI21 Labs、Anthropic、Cohere、Meta和Stability AI的模型。
LLM是在大量文本数据集上训练的基础模型。因此,它们可以捕获人类语言内在的语法和语义。但是,我们必须对其进行调整,以便于让其执行我们希望它们执行的特定任务。
提示工程\\"是调整LLM最快的方法之一。这是一个构建文本的过程,文本可以被LLM解释和理解。在这里,我们使用自然语言文本来描述希望LLM执行的任务:
我们创建的提示有助于LLM执行上下文内的学习\\",这种学习是临时性的。我们可以使用提示工程来促进LLM的安全使用,并构建新的能力,比如利用领域知识和外部工具来增强LLM。
这是一个活跃的研究领域,新技术层出不穷。但是,像思路链(chain-of-thought)提示\\"这样的技术已经非常流行。该技术的理念是让LLM在给出最终答案之前,通过一系列的中间步骤来解决问题。
正如我们看到的,LLM能够处理大量的自然语言文本。如果我们将自然语言中的单词表示为词嵌入(word embedding)\\",那么LLM的性能就会大大提高。这是一种实值向量(real-valued vector),能够对单词的含义进行编码。
通常,词嵌入是通过Tomáš Mikolov的Word2vec\\"或斯坦福大学的GloVe\\"等算法生成的。GloVe是一种无监督学习算法,根据语料库中全局的单词-单词间共现(co-occurrence)统计数据进行训练:
在提示工程中,我们将提示转换为词嵌入,使模型能够更好地理解提示并做出响应。除此之外,它还有助于增强我们提供给模型的上下文,使它们能够提供更多符合上下文的答案。
例如,我们可以从现有的数据集生成词嵌入,并将其存储到向量数据库中。此外,我们还可以使用用户提供的输入对该向量数据库执行语义搜索。然后,我们将搜索结果作为模型的附加上下文。
正如我们已经看到的,创建有效的提示是在所有应用中成功利用LLM的关键因素。这包括让与语言模型的交互具有上下文感知的能力,并且能够依靠语言模型进行推理。
为此,我们需要执行多项任务,包括创建提示模板、调用语言模型以及从多个数据源向语言模型提供用户特定的数据。为了简化这些任务,我们需要一个像LangChain这样的框架,将其作为LLM技术栈的一部分:
在开发需要链接多个语言模型的应用,并且需要调用过去与语言模型交互生成的信息时,该框架会非常有用。此外,还有一些更复杂的用例,涉及到将语言模型作为推理引擎。
最后,我们还可以执行日志记录、监控、流式处理以及其他必要的维护和故障排除任务。LLM技术栈正在快速发展,以解决其中的许多问题。不过,LangChain正在迅速成为LLM技术栈的重要组成部分。
LangChain\\"在2022年以开源项目的形式启动,并很快在社区的支持下赢得了广泛关注。它最初由Harrison Chase用Python语言开发,很快就成为人工智能领域发展最快的初创公司之一。
2023年初,继Python版本后,LangChain又推出了JavaScript/TypeScript版本。它很快就变得非常流行,并开始支持多种JavaScript环境,如Node.js、Web浏览器、CloudFlare Worker、Vercel/Next.js、Deno和Supabase Edge函数。
遗憾的是,目前还没有适用于Java/Spring应用的LangChain官方Java版本。不过,有一个名为LangChain4j\\"的LangChain Java社区版本。它适用于 Java 8或更高版本,支持Spring Boot 2和3。
LangChain的各种依赖可以从Maven中央仓库\\"获取。我们可能需要在应用程序中添加一个或多个依赖项,这取决于我们要使用的特性:
\\n dev.langchain4j\\n langchain4j\\n 0.23.0\\n
例如,在本教程的后续章节中,我们还将需要一些依赖,以便于继续支持与OpenAI模型集成\\"、提供嵌入式支持\\"以及类似all-MiniLM-L6-v2的句子转换器(sentence-transformer)模型\\"。
LangChain4j的设计目标与LangChain相同,它提供了一个简单而一致的抽象层以及众多的实现。它已经支持多个语言模型供应商(如OpenAI)和嵌入数据存储商(如Pinecone)。
不过,由于LangChain和LangChain4j都在快速发展,Python或JS/TS版本支持的特性可能在Java版本中还不存在。不过,基本概念、一般结构和词汇在很大程度上是相同的。
LangChain以模块组件的形式为我们提供了多个有价值的提议。模块化组件提供了有用的抽象,以及一系列用于处理语言模型的实现。我们以Java为例,讨论其中的一些模块。
在使用任何语言模型时,我们都需要与之进行交互的能力。LangChain提供了必要的构建基块,比如模板化提示以及动态选择和管理模型输入的能力。同时,我们还可以使用输出解析器从模型输出中提取信息:
提示模板是为语言模型生成提示的预定义配方,可能包括说明、few-shot样例\\"和特定的上下文:
PromptTemplate promptTemplate = PromptTemplate\\n .from(\\"Tell me a {{adjective}} joke about {{content}}..\\");\\nMap variables = new HashMap<>();\\nvariables.put(\\"adjective\\", \\"funny\\");\\nvariables.put(\\"content\\", \\"computers\\");\\nPrompt prompt = promptTemplate.apply(variables);
在这里,我们创建了一个可以接受多个变量的提示模板。这些变量是我们从用户输入中接收到的,并输入到提示模板中。
LangChain支持与两种模型集成,即语言模型和聊天模型。聊天模型也由语言模型支持,但提供聊天的能力:
ChatLanguageModel model = OpenAiChatModel.builder()\\n .apiKey()\\n .modelName(GPT_3_5_TURBO)\\n .temperature(0.3)\\n .build();\\nString response = model.generate(prompt.text());
在这里,使用特定的OpenAI模型和相关的API秘钥创建了一个聊天模型。我们可以通过免费注册从OpenAI获取API秘钥。参数temperature用来控制模型输出的随机性。
最后,语言模型的输出可能不够结构化,不足以进行展示。LangChain提供的输出解析器可以帮助我们对语言模型的响应进行结构化处理,例如,以Java的POJO的形式从输出中提取信息。
通常,利用LLM的应用程序都会有一个对话界面。所有对话的一个重要方面就是要能够参考对话早期引入的信息。存储过去交互信息的能力被称为记忆内存(memory):
LangChain提供了为应用程序添加记忆内存的关键功能。我们需要从记忆内存中读取信息的能力,以增强用户的输入。然后,我们需要将当前运行的输入和输出写入记忆内存的能力:
ChatMemory chatMemory = TokenWindowChatMemory\\n .withMaxTokens(300, new OpenAiTokenizer(GPT_3_5_TURBO));\\nchatMemory.add(userMessage(\\"Hello, my name is Kumar\\"));\\nAiMessage answer = model.generate(chatMemory.messages()).content();\\nSystem.out.println(answer.text()); // Hello Kumar! How can I assist you today?\\nchatMemory.add(answer);\\nchatMemory.add(userMessage(\\"What is my name?\\"));\\nAiMessage answerWithName = model.generate(chatMemory.messages()).content();\\nSystem.out.println(answer.text()); // Your name is Kumar.\\nchatMemory.add(answerWithName);
在这里,我们使用TokenWindowChatMemory实现了一个固定窗口的聊天内存,它允许我们读写与语言模型交换的聊天信息。
LangChain还提供了更复杂的数据结构和算法,以便于从记忆内存中返回选定的信息,而不是所有的信息。例如,它支持返回过去几条信息的摘要,或者只返回与当前运行相关的信息。
大语言模型通常是在大量的文本语料库中训练出来的。因此,它们在一般任务中相当高效,但是在特定领域任务中可能就没有那么有用了。因此,我们需要检索相关的外部数据,并在生成步骤将其传递给语言模型。
这个过程被称为“检索增强生成(Retrieval Augmented Generation,RAG)\\"”。它有助于将模型建立在相关的准确信息之上,并让我们深入了解模型的生成过程。LangChain为创建RAG应用程序提供了必要的构建基块:
首先,LangChain提供了文档加载器,用于从存储位置检索文档。其次,还提供了用于准备文档的转换器(transformer),以便于进一步的处理。例如,我们可以让它将大文档拆分为小块:
Document document = FileSystemDocumentLoader.loadDocument(\\"simpson\'s_adventures.txt\\");\\nDocumentSplitter splitter = DocumentSplitters.recursive(100, 0, \\n new OpenAiTokenizer(GPT_3_5_TURBO));\\nList segments = splitter.split(document);
在这里,我们使用FileSystemDocumentLoader从文件系统加载文档。然后,使用OpenAiTokenizer将文档拆分为小块。
为了提高检索效率,通常会将文档转换为嵌入内容,并将其存储在向量数据库中。LangChain支持多种嵌入式提供商和方法,并且能够与几乎所有的向量存储集成:
EmbeddingModel embeddingModel = new AllMiniLmL6V2EmbeddingModel();\\nList embeddings = embeddingModel.embedAll(segments).content();\\nEmbeddingStore embeddingStore = new InMemoryEmbeddingStore<>();\\nembeddingStore.addAll(embeddings, segments);
在这里,我们使AllMiniLmL6V2EmbeddingModel创建文档片段的嵌入内容。然后,我们将嵌入内容存储在基于内存的向量存储中。
现在,我们已经将外部数据以嵌入的形式保存在向量存储中了,并且做好准备进行检索了。LangChain支持多种检索算法,如简单的语义搜索以及复杂的复合检索:
String question = \\"Who is Simpson?\\";\\n//The assumption here is that the answer to this question is contained in the document we processed earlier.\\nEmbedding questionEmbedding = embeddingModel.embed(question).content();\\nint maxResults = 3;\\ndouble minScore = 0.7;\\nList> relevantEmbeddings = embeddingStore\\n .findRelevant(questionEmbedding, maxResults, minScore);
我们创建了用户问题的嵌入,然后使用问题嵌入从向量存储中检索相关的匹配项。现在,我们可以将检索到的匹配项作为上下文进行发送,将其添加到我们想要发送给模型的提示中。
到目前为止,我们已经了解了如何使用单个组件创建基于语言模型的应用程序。LangChain还提供了用于创建更复杂应用的组件。例如,我们可以使用链和代理来构建功能更强的自适应应用。
一般来讲,应用程序需要按照特定顺序调用多个组件。这就是LangChain中所说的链(chain)。它简化了复杂应用程序的开发过程,使得调试、维护和改进都变得更加容易。
它对于组合多个链以形成更复杂的应用程序也很有用,因为这些应用可能需要与多个语言模型交互。LangChain提供了创建此类链的便捷方法,并提供了很多预构建的链:
ConversationalRetrievalChain chain = ConversationalRetrievalChain.builder()\\n .chatLanguageModel(chatModel)\\n .retriever(EmbeddingStoreRetriever.from(embeddingStore, embeddingModel))\\n .chatMemory(MessageWindowChatMemory.withMaxMessages(10))\\n .promptTemplate(PromptTemplate\\n .from(\\"Answer the following question to the best of your ability: {{question}}\\\\n\\\\nBase your answer on the following information:\\\\n{{information}}\\"))\\n .build();
在这里,我们使用了一个预构建的链ConversationalRetreivalChain,它允许我们使用聊天模型、检索器、记忆内存和提示模板。现在,我们只需要使用该链就可以执行用户查询:
String answer = chain.execute(\\"Who is Simpson?\\");
链自带默认的记忆内存和提示模板。创建自定义链也很容易。创建链的功能使得复杂应用程序的模块化实现变得更加容易。
LangChain还提供了更强大的结构,如代理(agent)。与链不同的是,代理使用语言模型作为推理引擎来决定采取哪些行动以及行动的顺序。我们还可以让代理访问恰当的工具,以执行必要的行为。
在LangChain4j中,代理是作为AI服务的形式来使用的,可以用来声明式地定义复杂的行为。我们看一下是否能够以工具的形式为AI服务提供一个计算器,并使语言模型能够执行运算。
首先,我们定义一个具有基本计算器功能的类,并使用自然语言描述每个功能,以便于模型理解:
public class AIServiceWithCalculator {\\n static class Calculator {\\n @Tool(\\"Calculates the length of a string\\")\\n int stringLength(String s) {\\n return s.length();\\n }\\n @Tool(\\"Calculates the sum of two numbers\\")\\n int add(int a, int b) {\\n return a + b;\\n }\\n }
然后,我们定义AI服务的接口,并以此为基础进行构建。这个接口非常简单,但是它也能描述更复杂的行为:
interface Assistant {\\n String chat(String userMessage);\\n}
现在,我们使用刚刚定义的接口和创建的工具,通过LangChain4j提供的构建器工厂创建一个AI服务:
Assistant assistant = AiServices.builder(Assistant.class)\\n .chatLanguageModel(OpenAiChatModel.withApiKey())\\n .tools(new Calculator())\\n .chatMemory(MessageWindowChatMemory.withMaxMessages(10))\\n .build();
就是这么简单!现在,我们可以开始向语言模型发送一些包含计算的问题了:
String question = \\"What is the sum of the numbers of letters in the words \\\\\\"language\\\\\\" and \\\\\\"model\\\\\\"?\\";\\nString answer = assistant.chat(question);\\nSystem.out.prtintln(answer); // The sum of the numbers of letters in the words \\"language\\" and \\"model\\" is 13.
运行这段代码后,我们会发现语言模型现在可以执行计算了。
需要注意的是,语言模型在执行一些需要它们具有时间和空间的概念或执行复杂运算程序的任务时会遇到困难。不过,我们可以随时通过为模型补充必要的工具来解决这个问题。
在本教程中,我们介绍了利用大语言模型创建应用程序的一些基本元素。此外,我们还讨论了将LangChain这样的框架作为开发此类应用程序的技术栈的一部分的价值。
基于此,我们探索了LangChain4j的一些核心要素,LangChain4j是LangChain的Java版本。这些库会在未来迅速发展。但是,它们也已让开发由语言模型驱动的应用程序的过程变得更加成熟而有趣!
读者可以在GitHub\\"上查看本文的完整源代码。
","description":"本文最初发表于Baeldung网站\\",由InfoQ中文站翻译分享。 引言\\n\\n在本教程中,我们将会研究LangChain\\"的细节,这是一个利用语言模型开发应用程序的框架。首先,我们会介绍有关语言模型的基本概念,这将对本教程有一定的辅助作用。\\n\\n \\n\\n尽管LangChain主要提供了Python和JavaScript/TypeScript语言的版本,但是也有在Java中使用LangChain的可选方案。我们将会讨论组成LangChain框架的构建基块,然后在Java中进行实验。\\n\\n \\n\\n背景\\n\\n在深入探讨为何需要一个框架来构建语言模型驱动的应用程序之前,我们必须首先了解什么是语言模型…","guid":"https://www.infoq.cn/article/8HSamdS5C15xXZWGwte2","author":"作者:Kumar Chandrakant","authorUrl":null,"authorAvatar":null,"publishedAt":"2025-03-22T03:00:00.066Z","media":[{"url":"https://static001.geekbang.org/infoq/6a/6a182f8e0ccc69a5d6599590b04d1413.jpeg","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/e7/e78d0b8d82cd84d15ff3f5506625cc2b.jpeg","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/bd/bd7e7dbfc766f8b4f3333ab9a69f74c9.jpeg","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/ae/ae14a8c502bff78e80c8659f0641a7ff.jpeg","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/f6/f60576ea7b1206ce4b7fb3cb3e6c052f.jpeg","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/b7/b72b0fe0d5e1ab1efc115b01255a6838.jpeg","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/6f/6f0b827c7a6a7e1a25bbbf25013ec621.jpeg","type":"photo","width":0,"height":0,"blurhash":""}],"categories":["编程语言"],"attachments":null,"extra":null,"language":null},{"title":"AI 时代下图数据库的智能化探索 | QCon北京","url":"https://www.infoq.cn/article/JbJq4fjwKvVQKJVTGJ1m","content":"2025 年 4 月 10 - 12 日,QCon 全球软件开发大会\\"将在北京召开,大会以 “智能融合,引领未来” 为主题,将汇聚各领域的技术先行者以及创新实践者,为行业发展拨云见日。
蚂蚁集团技术专家戚仕鹏、蚂蚁集团开发工程师吕松霖已确认出席并发表题为《TuGraph + AI:AI 时代下图数据库的智能化探索》\\"的主题分享,重点聚焦蚂蚁集团 TuGraph 团队在不断探索 TuGraph 与 AI 相结合可能性的过程中,在 Text2GQL、GraphRAG、MAS 等多方面的探索成果,并展望图数据库与 AI 的未来结合点。
戚仕鹏是LDBC FinBench 作者,目前在蚂蚁集团担任图计算 TuGraph 团队技术专家、标准与测试基准负责人、开源高校业务负责人,同时兼任 LDBC (国际关联数据委员会)董事,他的主要工作研究方向是图计算标准、测试基准、开源教育、图数据库内核开发。吕松霖目前就职于蚂蚁集团 TuGraph 团队任开发工程师,专注于图计算 Benchmark、GraphRAG、Text2GQL 等方向的开发工作,以及开源教育合作。两位嘉宾在本次会议的详细演讲内容如下:
演讲提纲1. RAG 技术的现状与趋势大模型的幻觉问题RAG 增强 AI 检索RAG 技术现状2. GraphRAG 增强 AI 搜索GraphRAG 的技术优势向量驱动的 GraphRAG 检索NLU+Text2GQL 驱动的 GraphRAG3. 从自然语言到 GraphRAGText2GQL 模型微调与评测Text2GQL 语料生成4. 总结与展望GraphRAG 实践分析RAG 技术赋能 MAS您认为,这样的技术在实践过程中有哪些痛点?模型微调的复杂性用户需求多样性和动态变化演讲亮点Graph+AI 的深度融合高性能图数据库的实际应用案例听众收益了解图技术与 AI 结合的最新进展获取实际应用的技术方案
除此之外,本次大会还策划了多模态大模型及应用\\"、AI 驱动的工程生产力\\"、面向 AI 的研发基础设施\\"、不被 AI 取代的工程师\\"、大模型赋能 AIOps\\"、云成本优化\\"、Lakehouse 架构演进\\"、越挫越勇的大前端\\"等专题,届时将有来自不同行业、不同领域、不同企业的100+资深专家在QCon北京现场带来前沿技术洞察和一线实践经验。
现在报名即可以享受 9 折优惠,单张门票立省 680 元,详情可扫码或联系票务经理 18514549229 咨询。
随着 Wasm 得到更广泛的采用,WebAssembly 的使用可能会成为满足安全性合规性要求的强制性要求,同时解决其他正在进行的安全难题。
根据美国国家标准与技术研究所(NIST)一篇论文 《云原生应用程序的数据保护方法》(作者:LeakSignal 的 Wesley Hales;NIST 的主管级计算机科学家 Ramaswamy Chandramouli)的说法,WebAssembly 可以而且应该集成到云原生服务网格领域,以增强安全性。论文中概述的框架可能会导致未来对 WebAssembly 或云原生环境的合规性要求,同时也为更广泛地使用 WebAssembly 的安全性奠定了基础。
该论文强调了 WebAssembly 模块如何通过其原位或代理方法,使 WebAssemblys 成为数据在服务之间传输时进行数据分类的有力候选者。借助 Wasm,可以对分布在一个或多个云原生环境中的任何类型的数据进行数据检查。
“很多人都有 eBPF 锤子思想,对他们来说,一切看起来都像钉子,但事实并非如此,”该报告的合著者 Hales 告诉 The New Stack。“eBPF 的目的只有一个。”
eBPF 最初是为了防御侧通道攻击而设计的,例如 Heartbleed 漏洞(该漏洞破坏了 OpenSSL 的加密库),以及其他内核级相关漏洞。Hale 解释说,eBPF 允许我们在发现某些内容后进行修补并阻止该活动。
Hale 说:“人们用它来做任何的事情,因为它是一个简单的插入点。这是 eBPF 的优点之一——它易于安装,并提供了一定程度的可见性。但是,它不能利用第 7 层人类可读的文本,因为它是在内核空间中运行的。”。
将来自第 4 层 eBPF 的数据包带入用户空间进行分析需要先对数据包进行镜像,然后再在容器中进行分析。“这会产生一个弗兰肯斯坦式的过程,根本不可能有性能”Hales 说。“Wasm 真正满足了我们的目的。我们实际上对 eBPF 进行了原型设计,但它根本不适合我们。”
将 eBPF 的安全性与 Wasm 的安全性进行比较,该论文的作者写道:
“与 eBPF 等技术相比,使用 Wasm 在第 4 到第 7 层解析人类可读的文本具有几个优势,特别是在处理复杂的应用层数据(如 HTTP)方面。虽然 eBPF 在内核内直接进行数据捕获和操作方面功能强大,但对于某些应用程序来说,使用它来解析详细的 HTTP 流量可能会很复杂,甚至是大材小用。这种复杂性源于需要在内核内处理 HTTP 的复杂性——如果管理不当,这项任务可能会限制性能并引入安全性问题。此外,eBPF 还施加了许多限制,需要付出额外的努力来进行数据处理和通用计算。”
“Wasm 提供了一个安全的沙箱环境,适用于跨多个平台高效执行代码和解析应用层协议。Wasm 可以在用户空间和服务器环境中使用,允许更容易地与现有的解析库和工具集成,降低复杂性,并可能提高解析操作的可靠性。它的可移植性和嵌入各种运行时环境的能力使其成为网络流量分析任务的实用选择,包括涉及处理人类可读文本的协议的任务。”
在云原生世界中,所有的数据流量都是通过服务网格(service mesh)Istio 的代理和 Wasm 的模块化或“沙箱”设计强制通过的。“Istio 代理后面可能有 10000 个容器,而所有的日志流量、所有的网络流量,甚至数据库流量都必须进入代理,然后到达目的地。”Hales 说道。“所以我们可以用 Wasm 来研究所有这些问题。”
从这篇论文中得到的一个结论并不是 WebAssembly 的安全性优于 eBPF。这里要重申一下,它是说,退一步的时候——无论是在可观测性、安全性、全面的解决方案或战略,还是最佳实践方面,都不应该是用其中一个来代替另一个。因此,举例来说,美国政府不太可能突然强制使用 WebAssembly,而不为某些用例实施或强制使用 eBPF。在商业领域中,一个全面的安全性或可观测性参与者或产品应该包括 eBPF 的一系列用例,以及 WebAssembly 和其他用例。
“eBPF 从来就不是一个通用的计算平台,它既有算法约束,也有内存限制。从安全性的角度来看,当功能可以在 Wasm 这样的用户空间中完成时,将功能推送到内核空间(eBPF 所在的地方)本身也是一种糟糕的做法。”ARMO 的首席技术官兼联合创始人 Ben Hirschberg 表示。“因此,在 Wasm 中实现复杂的可观测性逻辑,并在 eBPF 中保留所需的最小功能,这更有意义。”
事实上,WebAssembly 从一开始就是为所谓的沙箱安全而设计的。Fermyon 联合创始人兼首席执行官 Matt Butcher 表示:“我保证你现在正在运行的就是使用最广泛的沙箱应用程序环境:一个 Web 浏览器。浏览器是一个本质上为运行不受信任的代码而构建的环境。WebAssembly 基于浏览器的传统是其拥有一流沙箱技术的原因。”。与容器和 eBPF 不同,安全性不是事后才应考虑的;从一开始到现在,它都是一个核心特性。看到 Wasm 在安全性的敏感环境中得到普及,我并不感到惊讶。”
Hales 解释说,除了 Istio 的代理之外,Wasm 还提供了比 eBPF 更广泛的覆盖范围,包括覆盖通过 HTTP、gRPC 或 GraphQL 的数据传输,或网络流量能够流向的任何地方。Hales 说:“这并不重要,因为它们仍然都在通过第 4 层到第 7 层的管道。”。
“将 Wasm 视为一种具有明确定义扩展方法的灵活的核心技术是有用的。它是与平台无关的,这意味着它可以在许多操作系统和系统架构上运行。并且现在几乎所有的主要编程语言都支持它了。”Butcher 表示。“本质上,这使得 Wasm 比 eBPF 更具适应性。简而言之:Wasm 是为通用性而构建的,而 eBPF 却不是。”
原文链接:
https://thenewstack.io/the-feds-push-for-webassembly-security-over-ebpf/\\"
","description":"随着 Wasm 得到更广泛的采用,WebAssembly 的使用可能会成为满足安全性合规性要求的强制性要求,同时解决其他正在进行的安全难题。 根据美国国家标准与技术研究所(NIST)一篇论文 《云原生应用程序的数据保护方法》(作者:LeakSignal 的 Wesley Hales;NIST 的主管级计算机科学家 Ramaswamy Chandramouli)的说法,WebAssembly 可以而且应该集成到云原生服务网格领域,以增强安全性。论文中概述的框架可能会导致未来对 WebAssembly 或云原生环境的合规性要求,同时也为更广泛地使用…","guid":"https://www.infoq.cn/article/MbVw0auvVEtfLECfJBNo","author":"作者:B. Cameron Gain","authorUrl":null,"authorAvatar":null,"publishedAt":"2025-03-22T01:00:00.866Z","media":null,"categories":["后端"],"attachments":null,"extra":null,"language":null},{"title":"Java近期新闻:Java稳定值、Spring Modulith、Open Liberty、Quarkus、JReleaser、Gradle","url":"https://www.infoq.cn/article/eHaWlxl5BAwRcLOzlRUb","content":"JEP 502(稳定值(预览)\\")已从Candidate状态进入到Proposed to Target状态,目标版本为JDK 25。该JEP此前叫作计算常量(预览),引入了计算常量的概念,即最多初始化一次的不可变值持有者。这一特性提供了final字段的性能和安全性,同时在初始化时间上提供了更大的灵活性。评审于2025年3月7日结束。
JEP 503(移除32位x86移植\\")已从JEP Draft 8345168进入到Candidate状态。该JEP提议“移除对32位x86移植版本源代码和构建的支持。”这是JEP 501(弃用32位x86移植版本\\")的后续工作,计划在即将到来的JDK 24版本中发布。
JDK 24早期访问构建版本\\"的当前版本仍然是Build 36\\",更多细节可在发布说明\\"中找到。
JDK 25早期访问构建版本\\"的Build 12\\"也已发布,包含自Build 11以来的更新,修复了各种问题\\"。更多关于此版本的细节可在发布说明\\"中找到。
对于JDK 24\\"和JDK 25\\",开发者可以通过Java Bug Database\\"报告问题。
在每周的Hashtag Jakarta EE\\"博客中,Eclipse基金会Jakarta EE开发布道师Ivar Grimstad\\"提供了有关Jakarta EE 11和Jakarta EE 12的更新\\":
随着Jakarta EE 11 Web Profile的TCK工作接近完成,Jakarta EE 12的规划进入了一个新阶段。作为Jakarta EE 12的发布负责人,Jared Anderson要求各组件规范在2025年4月15日前提交发布计划。其中一些已经准备好了计划评审材料。Jakarta NoSQL 1.0的发布评审正在进行中(将于2025年3月11日结束)。
Jakarta EE 11的发布历程包含了四个里程碑版本,在2024年12月发布的Core Profile,以及在2025年第一季度Web Profile的候选发布版本和2025年第二季度平台的通用发布版本之前根据需要可能发布的候选版本。
到目前为止,Jakarta EE 12的计划评审已经提交了Jakarta Context and Dependency Injection\\" 5.0、Jakarta Data\\" 1.1和Jakarta Faces\\" 5.0。
Spring Modulith\\" 1.4.0第二个里程碑版本以及服务版本1.3.3和1.2.9发布,包含了错误修复和依赖项升级。1.4.0-M2版本的新功能包括:增加新类ApplicationModuleIdentifiers\\"和ApplicationModuleMetadata\\",分别作为应用模块标识符的有序集合和生成元数据的抽象,向下游基础设施组件公开所需信息;ApplicationModulesExporter\\"类的实例暴露ApplicationModuleInitializer\\"接口bean的能力。这些版本的更多细节可在1.4.0-M2版本\\"、1.3.3版本\\"和1.2.9版本\\"的发布说明中找到。
Quarkus\\" 3.19发布,包含了错误修复、依赖项升级和新功能,例如:默认切换到Red Hat Universal Base Image\\" 9;一个新的从当前使用Micrometer实现的指标到OpenTelemetry格式的桥接;以及对JEP 483(预先类加载和链接\\")的支持,该功能将在即将发布的JDK 24中发布。更多关于此版本的细节可在发布说明\\"中找到。
Quarkus团队还宣布\\",他们解决了影响3.15和3.8系列版本的多个CVE,包括:
CVE-2025-24970\\",Netty 4.1.91.Final到4.1.117.Final的一个漏洞,当SslHandler\\"类实例在接收到特制数据包时未能正确处理验证,可能导致崩溃。CVE-2025-1247\\",Quarkus REST(Jakarta RESTful Web Services规范的实现)的一个缺陷,攻击者可能操纵请求数据、冒充用户或访问敏感信息。如果端点使用字段注入而没有CDI作用域,可能导致并发请求之间的请求参数泄露。CVE-2025-1634\\",Quarkus RESTEasy Classic\\"扩展的一个缺陷,当客户端请求超时时,缓冲区未能正确释放,导致内存使用增加,最终因OutOfMemoryError导致应用崩溃。CVE-2024-12225,目前处于保密状态,与默认启用的WebAuthn回调端点相关,现在需要显式配置。
这些CVE在Quarkus 3.19.1以及服务版本3.15.3.1\\"和3.8.6.1\\"中得到修复和缓解。
IBM发布Open Liberty\\" 25.0.0.2,支持AES-256密码加密;更新了指南,帮助用户构建具有集成用户界面和后端逻辑的动态Web应用\\",并新增MicroProfile 7.0和无版本特性\\"指南;解决了CVE-2024-47535\\",这是Netty 4.1.114及以下版本中的一个漏洞,攻击者可利用Windows系统环境文件的不安全读取进行拒绝服务攻击并导致应用崩溃。
Camel Quarkus\\" 3.19.0发布,与Quarkus保持一致,包含Camel 4.10.0和Quarkus 3.19.0。该版本带来了一些显著的变化,例如:通过Quarkus NativeMonitoringBuildItem\\"类自动启用原生监控功能;移除了/observe端点的可观测性服务配置变通方法。更多关于此版本的细节可在发布说明\\"中找到。
Apache Groovy\\" 4.0.26和3.0.24发布(分别在这里\\"和这里\\"),包含了错误修复、依赖项升级和一个改进:将Groovy编译器的parameter标志传给javac命令。更多细节可在4.0.26版本\\"和3.0.24版本\\"的发布说明中找到。
JReleaser\\" 1.17.0发布,这是一个简化项目发布的Java工具,包含了错误修复、文档改进、依赖项升级和新功能,例如:使用新的Matrix\\"部分参数化分发的能力;支持使用mavenCentral部署器发布-SNAPSHOT扩展工件;添加自定义Scoop\\"清单的能力。更多关于此版本的细节可在发布说明\\"中找到。
Gradle\\" 8.13.0发布,引入了一个新的自动配置\\"工具,可自动下载Gradle守护进程\\"所需的JVM。其他显著改进包括:为Scala插件\\"显式配置Scala版本,以便自动解析所需的Scala工具链依赖项;JUnit XML测试事件时间戳的精度提升至毫秒级。更多关于此版本的细节可在发布说明\\"中找到。
原文链接:
https://www.infoq.com/news/2025/03/java-news-roundup-feb24-2025/\\"
","description":"OpenJDK JEP 502(稳定值(预览)\\")已从Candidate状态进入到Proposed to Target状态,目标版本为JDK 25。该JEP此前叫作计算常量(预览),引入了计算常量的概念,即最多初始化一次的不可变值持有者。这一特性提供了final字段的性能和安全性,同时在初始化时间上提供了更大的灵活性。评审于2025年3月7日结束。\\n\\nJEP 503(移除32位x86移植\\")已从JEP Draft 8345168进入到Candidate状态。该JEP提议“移除对32位x86移植版本源代码和构建的支持。”这是JEP 501(弃用32位x86移植版…","guid":"https://www.infoq.cn/article/eHaWlxl5BAwRcLOzlRUb","author":"Michael Redlich","authorUrl":null,"authorAvatar":null,"publishedAt":"2025-03-21T00:00:00.781Z","media":null,"categories":["编程语言"],"attachments":null,"extra":null,"language":null},{"title":"运行13年后,Serverless数据库Fauna即将停止服务","url":"https://www.infoq.cn/article/xTGCvtKvvbYo9ycjHDBk","content":"美国当地时间3月19日,事务性数据库Fauna公司发布一则公告,宣布将在未来几个月内停止 Fauna 服务。
Fauna 是一个灵活的、对开发人员友好的事务性数据库,作为具有原生 GraphQL 的安全且可扩展的云 API 交付。Fauna 将 NoSQL 系统的灵活性与 SQL 数据库的关系查询和事务功能相结合。
完整公告如下:
今天,我们发布了一些有关 Fauna 服务的未来以及我们的核心技术的重要公告。 Fauna 的使命是让每个软件开发团队都能高效、可扩展且安全地处理运营数据。多年来,Fauna 构建了一个革命性的新文档关系数据库,该数据库让全球数千个开发团队感到满意,并为数百个付费客户的业务提供支持。然而,经过深思熟虑,我们做出了艰难的决定,将在未来几个月内停止 Fauna 服务。 推动广泛采用一种在全球范围内以服务形式运行的新运营数据库需要大量资金。在当前的市场环境下,我们的董事会和投资者已确定不可能单独筹集实现该目标所需的资金。虽然我们将不再接受新客户,但现有的 Fauna 客户不会立即发生变化。我们将逐步让客户退出 Fauna,并致力于确保未来几个月内顺利完成这一过程。有关更多详细信息,请参阅下面的常见问题解答。 致力于开源 Fauna 技术 通过这一变化,我们还承诺将发布 Fauna 核心数据库技术的开源版本以及我们现有的开源驱动程序和 CLI 工具。这确保了 Fauna 的独特功能(我们的事务功能、文档关系数据模型和我们的数据库语言 (FQL))将可供社区使用。我们希望这既能成为数据库从业者的宝贵参考,又能为更广泛的开发者社区提供持续的价值。 我们非常感谢我们的客户、合作伙伴和投资者,他们为 Fauna 的发展做出了不可或缺的贡献。如果没有你们的支持,我们不可能取得如今的成就。我们明白,这对许多人来说将是一个颠覆性的变化,我们完全致力于与现有客户合作,帮助他们在未来几个月内迁移服务。虽然这标志着付费 Fauna 服务的结束,但团队期待与更广泛的社区分享 Fauna 技术。
Fauna的故事开始于2012年。Evan Weaver是Fauna数据库的创始人。
Evan Weaver 对软件开发的热情始于他 8 或 9 岁 时。当时,他尝试用 QBasic 编写了一个带有图形的老虎机程序,展现了他对技术的早期兴趣。得益于父亲在大学的工作,Evan 很早就接触到了互联网,并通过 Gopher 下载共享软件,尽管他坦言这些软件“很糟糕”。
Evan 的职业生涯始于对开源和 Ruby on Rails 的兴趣。他在 CNET Networks 担任 DBA 和后端开发人员,与 Chris Wanstrath 和 PJ Hyett(GitHub 的创始人)一起工作。2008 年,Evan 加入 Twitter,成为第 15 名员工,并负责组建和管理后端基础设施团队。在 Twitter,他参与了分布式存储系统的构建,并致力于优化 Ruby 和 Hotspot 的性能。
Evan Weaver
在 Twitter 的工作经历让 Evan 深刻认识到现代数据库的局限性。在当时,Twitter 是云时代之前诞生的最后一批互联网巨头之一,当时并没有随需应对的硬件支持。随着短信和智能手机的普及,Twitter 的用户增长迅速,但当时现存的数据库系统无法满足其可扩展性和性能需求。
Evan 的团队在 Twitter 期间构建了许多单点解决方案,例如社交图谱和时间线数据库,这些系统至今仍在 Twitter 中使用。然而,Evan 意识到,市场上缺乏一个真正通用的、云原生的数据库平台,能够同时满足可扩展性、效率和全球可用性的需求。
这一洞察促使 Evan 在 2012年 离开 Twitter,与联合创始人 Matt Freels(同样来自 Twitter 团队)共同创立了 Fauna。最初,Fauna 与 NVIDIA 合作,进行了大量的联合开发和非经常性工程,以确保产品能够满足真实的市场需求。经过多年的研发,FaunaDB 在 2017年 正式发布,迅速吸引了包括 NVIDIA、CapitalOne 和 Nextdoor 在内的早期客户。
FaunaDB 使用 Scala 编写,并在 JVM 上运行。Evan 表示,选择 Scala 是因为它提供了现代的内存安全语言和高级类型系统,同时能够提供可预测的高性能。JVM 的跨平台特性也使 FaunaDB 具有极高的可移植性,真正实现了“一次编写,随处运行”的目标。
Fauna 的起步采用了混合融资方式,包括自有资金和为客户提供可扩展性咨询的收入。2016 年,Fauna 从 CRV 获得了种子轮融资,并推出了 FaunaDB Serverless Cloud。随后,Fauna 从 Point72 和 Google Ventures 获得了 A 轮融资,进一步加速了产品开发和市场扩展。
2020年7月,又迎来了一笔 2700 万美元的新资金。从技术上讲,此次融资是该公司 2017 年 A 轮融资的延续,由 Madrona Venture Group 领投,Addition、GV、CRV、Quest Ventures 和一些个人投资者参投。据该公司称,此次融资后,融资总额达到了 5700 万美元。
与此同时,该公司还增加了一些高管,宣布聘请前 Okta 首席产品官 Eric Berg 担任CEO,前 Snowflake 首席执行官 Bob Muglia 担任董事长。
但2018年以后,Serverless数据库市场随着更多玩家的进入,竞争日渐白热化。Amazon DynamoDB、Firebase、MongoDB Atlas等背后拥有着强大生态系统和开发者社区支持的数据库占据着越来越多的市场份额,而FaunaDB 虽然同样功能强大,但其技术栈(如 Scala 和 JVM)可能对部分开发者来说存在一定的学习曲线。
此外,Fauna 的多模型支持和强一致性特性虽然先进,但也可能增加了使用和管理的复杂性。加之研发投入的增大和盈利能力较弱带来的财务压力也让Fauna不堪重负。
如今,Fauna终于撑不下去了,这件事情在国外技术社区Hacker News上引发了网友热议。
在Hacker News上,有位自称是Fauna客户的用户评论称,Fauna 在接受风险投资并任命新 CEO 之后就已经在走下坡路了。
我是 Fauna 的客户,也曾与他们合作,为他们的博客和文档提供技术写作服务。有一次,甚至有出版商联系我,让我写一本关于 Fauna 的书。然而,随着时间的推移,我观察到 Fauna 的发展轨迹发生了变化,尤其是在他们接受风险投资并任命新 CEO 之后。 在我看来,Fauna 的战略似乎从专注于开发者转向了向企业销售产品。这种转变虽然带来了更多资金,但我觉得这并不符合逻辑。Fauna 的核心优势在于其无服务器和分布式数据库的特性,但这些特性在本地 SQL 密集型环境中并不具备竞争力。对于某些需要全局化的用例,Fauna 作为辅助数据库是有意义的,但谁会将它作为没有后备方案的高风险主数据库呢?也许一些小项目会这样做,但大公司或重要产品肯定不会冒这个险。 十年前,边缘计算、无服务器架构和分布式数据被认为是未来的趋势,Fauna 在这一愿景中确实非常有吸引力。然而,随着时间推移,我逐渐意识到,大多数数据并不需要复杂的分布式解决方案。例如,缓存 CDN 或某些键值存储(KV)中的读取数据子集,完全可以通过更简单的服务实现。像 Cloudflare Workers KV 这样的服务,可能正是导致 Fauna 失去吸引力的原因之一。它们提供了更轻量、更直接的解决方案,满足了许多原本可能需要 Fauna 的场景。 总的来说,Fauna 的技术虽然先进,但在实际应用中,许多场景并不需要如此复杂的分布式数据库。随着市场需求的演变,Fauna 可能未能及时调整其定位,导致其逐渐失去竞争力。
还有使用了Fauna很多年的用户在评论区现身说法。
我们已经使用 Fauna 好几年了,投入了大量时间学习和使用它,并围绕它开发了许多功能。Fauna 的 FQL(Fauna Query Language)和Time Travel功能是我们最欣赏的特性之一,尤其是Time Travel功能,它为我们实现了一些非常有趣的功能。 然而,由于种种原因,我们最终不得不放弃 Fauna,并决定在 Postgres 上实现一个与 FQL 兼容的解决方案。这个解决方案是用 JavaScript/TypeScript 编写的,并通过 Postgres 的 plv8 扩展 运行。它基本上模拟了 Fauna 的核心功能,同时利用了 Postgres 的稳定性和灵活性。
Fauna 的技术在无服务器架构、全球分布式数据库和强一致性方面有着一定的先进性。然而,技术的先进性并不总是直接转化为市场成功。许多企业并不需要如此复杂的解决方案,尤其是在大多数场景下,简单的数据库(如 Postgres 或键值存储)已经足够满足需求。Fauna 的落寞可能说明了一个问题:技术必须与市场需求相匹配,技术必须与市场需求相匹配,否则终将被市场边缘化。
","description":"美国当地时间3月19日,事务性数据库Fauna公司发布一则公告,宣布将在未来几个月内停止 Fauna 服务。 Fauna 是一个灵活的、对开发人员友好的事务性数据库,作为具有原生 GraphQL 的安全且可扩展的云 API 交付。Fauna 将 NoSQL 系统的灵活性与 SQL 数据库的关系查询和事务功能相结合。\\n\\n \\n\\n完整公告如下:\\n\\n \\n\\n今天,我们发布了一些有关 Fauna 服务的未来以及我们的核心技术的重要公告。 Fauna 的使命是让每个软件开发团队都能高效、可扩展且安全地处理运营数据。多年来,Fauna 构建了一个革命性的新文档关系数据库…","guid":"https://www.infoq.cn/article/xTGCvtKvvbYo9ycjHDBk","author":"李冬梅","authorUrl":null,"authorAvatar":null,"publishedAt":"2025-03-20T08:03:56.808Z","media":[{"url":"https://static001.geekbang.org/infoq/69/69f180927907a929fef20a0a3b785de5.png","type":"photo","width":1280,"height":1600,"blurhash":"LAJHpo=p.X?I:hNM4{nm^*xcn4xs"}],"categories":["数据库"],"attachments":null,"extra":null,"language":null},{"title":"我们如何引入DeepSeek R1来做领域特定语言训练的?","url":"https://www.infoq.cn/article/eQ3T5A2xrBpfvZmJQXMW","content":"作者 | 刘东、韩其琛、赵雨森
在网易 CodeWave 智能开发平台中,NASL(NetEase Application Specific Language)可视化编程语言 作为产品核心,主要有以下三大作用:
承载完整应用不同粒度、多种领域的可视化编程结构的精确描述。 大到一个页面节点、一个流程节点,小到一个表达式、一个运算符。有通用的 基础语言部分,也有 Web 应用常见的特定领域(如数据定义、数据查询、页面、流程、权限等)子语言部分。统一前后端各子领域的表达方式,降低学习门槛。NASL 统一了数据库、服务端逻辑、接口定义、页面逻辑、样式等的各种类型和表达式的编写形式。对接各类语言设施,集成多种开发功能,** 增强综合使用体验。** 围绕 NASL 的语言设施有很多,比如提供增删改查、复制粘贴等功能的各类可视化设计器,提供多人协作、备份还原等功能的代码仓库,提供类型检查、查找引用等功能的 Language Server,提供断点调试、变量监视等功能的 Debugger,能生成前后端源码的语言生成器,提供局部模板、依赖库导入导出等功能的资产中心,……
而在大模型时代下,NASL 又起到了一大新的作用:AI 友好和快速落地 AI 功能 的作用。AI 友好主要体现在不需要让大模型生成传统编程的各种语言框架,减少代码量即 token 数、以及各层次之间的转换问题。快速落地 AI 功能主要体现在只要提供 AI 服务 + 交互输入 代替或融入原来可视化设计器的交互形式即可将 AI 能力快速引入到产品中。
CodeWave 引入 AI 功能的产品架构图
然而让大模型生成一门新的语言,也给 CodeWave 技术团队带来了挑战。由于当前各家大模型均不具备 NASL 相关知识,经过产品实践,直接使用提示工程生成的内容在某些细节方面不太理想。下表是基于通用大模型 + 提示工程生成的 NASL 逻辑使用 HumanEval Benchmark 的评测,总体上只有 55.3% 的通过率。除了 25% 左右是工程侧和语言方面可以优化的问题,仍有 18.3% 的分数如果不通过模型训练就提升不了。
早期使用 HumanEval Benchmark 对生成 NASL 逻辑的评测
因此 CodeWave 技术团队持续研究对已有模型怎么进行微调训练,增加其在 NASL 领域的相关能力,来提升 CodeWave 中自然语言生成逻辑、代码补全等 AI 产品功能的效果。
类似针对通用编程代码模型的训练工作,NASL 大模型的训练也大致包含以下环节:
模型训练的首要环节是选择一个合适的基座模型。
对于基座模型,一般会在六个关键方面进行评测,包括代码生成、代码补全、代码推理、长上下文生成、一般自然语言理解、数学推理。根据 NASL 语言的特点,我们主要测重对前四个方面进行评测,考察了目前最流行和最强大的各个开源语言模型基座,包括 DeepSeek Coder 系列、Qwen Coder 系列、StarCoder2 系列等,进行具体评测:
(1) 代码生成能力(Code Generation)
代码生成能力是代码模型处理更复杂任务的基础,流行的代码生成基准测试是 HumanEval 和 MBPP。HumanEval 包含 164 个手动编写的编程任务,每个任务都提供一个 Python 函数签名和一个文档字符串作为模型的输入。而 MBPP 包含 974 个开源贡献者创建的问题,包括一个问题描述(即文档字符串)、一个函数签名和三个测试用例。
为了确保更准确的评估,23 年 HumanEval+ 增加了 80 倍的测试用例,修正了 HumanEval 中不准确的真实答案。同样,MBPP+ 也提供了是原始 MBPP 35 倍的测试用例。
Qwen2.5-Coder 在基础代码生成任务上表现得最出色,在相同规模的开源模型中达到最先进的水平。
(2) 代码补全能力(Code Completion)
许多智能编程辅助工具依赖于基于前后代码片段的代码补全能力,CodeWave 的 NASL 补全也不例外。流行的代码补全基准测试包括 HumanEval-FIM、CrossCodeEval、CrossCodeLongEval、RepoEval 和 SAFIM 等。但 NASL 的补全需要根据用户数据自行构造。同时要考虑代码补全的体验重在即时性,对模型的规模有较大限制。
经过测评,NASL 代码补全选择 DeepSeek-Coder-1.3B-Base 的效果最好。
(3) 代码推理能力(Code Reasoning)
代码是一种高度抽象的逻辑语言,代码推理能力能判断模型是否真正理解了代码背后的推理流程。一般选择 CRUXEval 作为基准测试,包含 800 个 Python 函数及其对应的输入输出示例。它包含两个不同的任务:CRUXEval-I,要求大型语言模型(LLM)根据给定的输入预测输出;CRUXEval-0,要求模型根据已知的输出推断输入。对于 CRUXEval-I 和 CRUXEval-0,一般使用思维链(CoT)方法,要求 LLM 在模拟执行过程中按顺序输出步骤。
(4) 长上下文理解能力(Long Context Modeling)
长上下文理解能力对于代码大模型在处理复杂需求时很重要,它是理解仓库级代码和成为代码智能体的必要能力。然而,当前大多数代码模型对输入长度的支持仍非常有限,这阻碍了它们的实际应用潜力。在 CodeWave 的智能生成场景中,一般需要携带很多上下文,如实体、数据结构、逻辑定义等 应用上下文,扩展组件、依赖库、接口定义、连接器等平台资产上下文,以及用户打开的标签页、光标位置等 交互上下文。因此我们对支持 128k token 以上输入长度的模型特别关注,并进行了调研评测。
数据准备是模型训练中的关键环节。
虽然 CodeWave AI 工程化平台收集到了一定量的用户数据,但用户提供的高质量代码数量有限,远不及通用编程语言的数量。因此如何突破 “数据冷启动” 实现 NASL 大模型训练,是数据准备阶段面临的主要问题。经过对已采集的数据进行清洗和分析,我们决定主要采用数据合成的方式来构造数据。需要合成的数据主要是 “自然语言指令 -> NASL 代码答案”的问答对形式,下面是一个简单示例:
// 用户指令:接受一个字符串列表,并返回最短的字符串。如果有多个,返回第一个出现的字符串。\\n// 合成的 NASL 代码:\\nlogic findShortest(strings: List) => result {\\n let lengths: List;\\n let minLength: Integer;\\n let shortestString: String;\\n\\n if (Length(strings) == 0) {\\n result = \'\';\\n end;\\n }\\n lengths = ListTransform(strings, { item => Length(item) });\\n minLength = ListMin(lengths);\\n shortestString = ListFind(strings, { item => Length(item) == minLength });\\n result = shortestString;\\n end;\\n}\\n
(1) 指令收集和构造
和传统编程大模型的数据准备工作类似,我们汇总了多个开源代码数据集,提取了大量自然语言指令、代码答案和测试用例,结合 Codewave 使用场景合成了低代码指令作为补充。英文指令使用 LLM 翻译为中文,去重后共计 10W+ 的指令数据。
为了全面评价问答对的质量,我们为每个样本引入了多个维度的打分点:
问题和答案的一致性: 问答是否一致,是否正确,以便进行微调。问答相关性: 问答是否与 Web 编程领域、CodeWave 产品功能相关。问答难度: 问答是否具有足够的挑战性。代码语法的正确性: 评价代码是否有语法错误,是否能解析回 NASL AST。代码静态语义的正确性: 评价代码是否能通过静态检查,如类型检查、重名校验、参数范围等。代码动态运行的正确性: 评价代码是否能通过测试用例,运行结果符合预期。易理解性和最佳实践: 评价代码是否容易理解,是否遵循 CodeWave 使用的最佳实践。
在打完各项评分后,通过权重求和计算得出每个样本的总分,便可评价问答对的质量。
(2) NASL 语言沙箱
上文中的打分点前 3 点侧重于对问题质量的评价,以人工打分为主;后 4 点侧重于对代码答案质量的评价,不仅可用于对样本的评价,也可用于对大模型生成结果的评价。
为了自动化高效地验证代码各方面的正确性,考虑到 CodeWave 真实环境编译时间过长、需要与之隔离等问题,CodeWave 编程语言实验室实现了一套轻量级 NASL 语言沙箱,在一台训练机器上就可以部署大量进程,主要用于检查 NASL 代码语法和语义的正确性、在隔离环境安全地执行代码、将代码执行的输出结果与测试用例的预期结果进行比较和汇总。
NASL 沙箱具体包含以下几个部分:
语言编译器:解析器: 将 NASL 文本解析成 NASL AST,并同时判断语法正确性语言服务: 对语言进行静态检查,主要包括类型检查、重名校验、参数范围等最佳实践检查: 静态分析代码是否符合最佳实践,比如是否用了更合适的内置函数,循环中是否用了数据查询等代码执行引擎:环境隔离: 为了安全执行代码,与部署机器隔离并行执行: 能够并行执行多个测试用例、多个代码测试请求、多套上下文环境资源分配和超时机制: 针对超时的执行进程能够及时释放,比如死循环代码引发的超时等问题系统和浏览器环境模拟: 支持对当前日期时间、域名、浏览器设备信息进行模拟数据库环境模拟:NASL 运行时的测试经常需要数据库中有合适的数据,沙箱支持创建轻量级数据库,并且快速建表和填充数据资产的接入和模拟: 支持依赖库、组件库、接口、连接器等资产接入,可以模拟接口、连接器的实现等结果分析器:结果比较: 将代码执行的输出结果与测试用例的预期结果进行比较,对嵌套结构会进行深度比较报告汇总: 汇总生成测试用例成功和失败的详细报告
(3) 多轮反馈机制的答案合成
开源代码数据集中包含大量自然语言指令,但代码答案是通用编程语言的,所以需要用通用大模型 + 自然语言指令提示词的方式合成 NASL 代码。但由于各家大模型均不了解 NASL,即使输入 NASL 语言的完整说明书,大模型也很难生成语法语义正确的 NASL 代码。
因此我们引入了多轮反馈机制,将沙箱编译和运行时的报错信息即时反馈给大模型,让大模型对生成的代码进行修改,反复执行这个过程,直到生成的结果正确或者达到预定的最大修改轮数(比如 5 轮)。
刚开始,主要使用 gpt-4o/4o-mini 作为数据合成的核心 LLM。当指令比较简单时,比如简单算法、简单数据查询,经过几轮局部的细节修改,基本可以生成完全正确的 NASL 代码,比如:
// 用户指令:根据申请状态查询请假申请记录,支持分页,按申请时间升序排列\\n// 第 1 次生成\\nlogic queryLeaveRequests(applyStatus: app.enums.ApplyStatus, page: Integer, size: Integer) => result {\\n result = for LeaveRequest in app.dataSources.defaultDS.entities.LeaveRequestEntity\\n where LeaveRequest.applyStatus == applyStatus\\n order by LeaveRequest.createdTime asc;\\n result = Paginate(result, page, size);\\n end;\\n}\\n// NASL 沙箱解析器报错:缺少 select 语句\\n\\n// 第 2 次生成\\nlogic queryLeaveRequests(applyStatus: app.enums.ApplyStatus, page: Integer, size: Integer) => result {\\n result = for LeaveRequest in app.dataSources.defaultDS.entities.LeaveRequestEntity\\n where LeaveRequest.applyStatus == applyStatus\\n order by LeaveRequest.createdTime asc\\n select {\\n leaveRequest: LeaveRequest\\n };\\n result = Paginate(result, page, size);\\n end;\\n}\\n// NASL 沙箱最佳实践报错:语句顺序不是最佳实践,期望的调用顺序为 for -> join -> where -> group by -> select/aggr select -> having -> order by -> paginate\\n\\n// 第 3 次生成\\nlogic queryLeaveRequests(applyStatus: app.enums.ApplyStatus, page: Integer, size: Integer) => result {\\n result = for LeaveRequest in app.dataSources.defaultDS.entities.LeaveRequestEntity\\n where LeaveRequest.applyStatus == applyStatus\\n select {\\n leaveRequest: LeaveRequest\\n }\\n order by LeaveRequest.createdTime asc;\\n result = Paginate(result, page, size);\\n end;\\n}\\n// NASL 沙箱类型检查报错:赋值:类型不一致!右边类型:{ list: List<{ leaveRequest: LeaveRequest; }>; total: 整数 ; },左边类型:List<{ leaveRequest: LeaveRequest; }>。result = paginate(result, page, size)\\n\\n// 第 4 次生成\\nlogic queryLeaveRequests(applyStatus: app.enums.ApplyStatus, page: Integer, size: Integer) => result: {\\n list: List<{ leaveRequest: app.dataSources.defaultDS.entities.LeaveRequest }>;\\n total: Integer;\\n} {\\n result = for LeaveRequest in app.dataSources.defaultDS.entities.LeaveRequestEntity\\n where LeaveRequest.applyStatus == applyStatus\\n select {\\n leaveRequest: LeaveRequest\\n }\\n order by LeaveRequest.createdTime asc\\n paginate page, size;\\n end;\\n}\\n// NASL 沙箱编译成功,类型检查成功,合成结束。\\n
(4) 采用深度思考的 DeepSeek-R1 模型合成答案收益显著
但当指令稍微复杂一些,比如既要做数据查询又要基于查询结果做逻辑处理的情况,采用非推理类模型,模型无法充分理解和遵循 NASL 语法语义的所有要求,基本都无法生成正确的结果。往往是在修复一个问题的同时又引入了其它问题,严重降低了数据合成的成功率和效率。
在这种情况下,我们引入了 DeepSeek-R1 模型,经过思考的过程,让模型充分注意到语法中的各项要求。并且在收到错误反馈后,也更善于从整体实现的角度去进行修复,显著提升代码生成的成功率。在合成数据的对比中,相比非深度思考模型有着显著的收益:
下面通过一个例子来对比 DeepSeek-R1 模型和原模型的效果差异。原来使用 gpt-4o-mini 经过 5 轮修复后,编译或运行仍然有问题:
// 用户指令:根据是否显示的标志查询咖啡信息,并返回 CoffeeOrderItem 列表\\n// 已知 CoffeeOrderItem 如下:\\nstruct CoffeeOrderItem {\\n /* 咖啡 */\\n coffee: app.dataSources.defaultDS.entities.Coffee;\\n /* 下单数量 */\\n count: Integer;\\n}\\n\\n// gpt-4o-mini 经过 5 轮修复后的结果,但编译仍然有问题\\nlogic loadCoffeeByIsDisplay() => coffeeList: List {\\n coffeeList = for Coffee in app.dataSources.defaultDS.entities.CoffeeEntity\\n where Coffee.isDisplay == true\\n select {\\n coffee: Coffee,\\n count: COUNT(Coffee.id) // 这里假设数量是根据咖啡 ID 的数量来计算的\\n }\\n );\\n end;\\n}\\n
错误原因是这里 CoffeeOrderItem 中 count 属性只是用于前端下单时的数据占位。但 gpt-4o-mini 无法理解这点,习惯性当作聚合函数 COUNT 的语义来返回。即使 NASL 沙箱给出提示,gpt-4o-mini 依旧无法给出正确的代码。DeepSeek-R1 只要单轮就能生成正确结果。R1 的输出结果如下,可以看出, R1 一开始也考虑使用 COUNT 聚合函数,但它经过自我反问,很快意识到这一点不符合要求,随后推理出只能在数据查询之后用逻辑来进行处理。
/** \\nr1 的思考过程:\\n好的,我需要根据用户提供的 NASL 语言定义和项目上下文,编写一个函数来查询咖啡信息并返回 CoffeeOrderItem 列表。首先,用户的需求是根据是否显示的标志查询咖啡信息,所以需要用到数据库查询。\\n根据 NASL 的限制,必须使用 FROM 函数来构建查询链。项目上下文中,Coffee 实体有一个 isDisplay 字段,而 CoffeeOrderItem 需要包含 Coffee 实体和下单数量 count。但用户指令中没有提到数量的来源,可能需要进一步确认,但假设 count 可能是一个聚合值、固定值或需要其他处理,但根据结构体定义,可能需要从查询结果中构造。\\n接下来,我需要使用 FROM 函数,传入 CoffeeEntity,并在回调中构建查询链。WHERE 条件应该是 Coffee.isDisplay 等于传入的参数,但用户函数头没有参数,可能需要调整。不过根据指令,可能 isDisplay 是作为过滤条件,但函数没有参数,可能默认查询 isDisplay 为 true 的记录?\\n然后,在 SELECT 部分,需要构造 CoffeeOrderItem 的结构,即 coffee 字段和 count 字段。但 count 的来源不明确,可能需要设置为 0 或其他值,或者可能有其他逻辑。但根据结构体定义,count 是 Integer 类型,可能需要从查询结果中获取,但当前上下文中没有相关数据,可能需要默认值,比如每个咖啡记录 count 设为 0。\\n此外,需要注意 SELECT 的命名规范,转换表名和字段名的首字母小写。例如,Coffee 实体在 SELECT 中应转换为 coffee,结构体字段名保持不变。\\n最后,将查询结果转换为 CoffeeOrderItem 列表。可能需要使用 ListTransform 来处理查询结果,添加 count 字段。或者,在 SELECT 中直接构造结构体,但需要确保字段匹配。\\n检查 NASL 的限制,确保不使用禁止的语法,如循环,而是使用内置函数。同时,确保正确使用实体和结构体,避免类型错误。\\n*/\\nlogic loadCoffeeByIsDisplay() {\\n // 查询所有 isDisplay 为 true 的咖啡信息\\n let coffeeList = for Coffee in app.dataSources.defaultDS.entities.CoffeeEntity\\n where Coffee.isDisplay == true\\n select {\\n coffee: Coffee,\\n }\\n );\\n\\n // 转换为 CoffeeOrderItem 列表并设置数量为 0\\n result = ListTransform(coffeeList, { item => new app.structures.CoffeeStructure({\\n coffee: item.coffee,\\n count: 0\\n }) });\\n end;\\n}\\n
(5) 数据后处理
数据后处理是一个规则模块,根据模型评测中发现的代码和数据问题,设计进一步的过滤和组装策略。
过滤模块: 总结分析模型评测过程中发现的问题,定位到训练集中的错误数据样本,设计使用规则对其快速过滤,提升训练集质量。组装模块: 根据实际使用的场景,对已有数据进行重新组装,保证输入的数据与线上真实场景的上下文环境保持一致。
我们采用了从粗到细的多阶段训练方案,先使用初始构造的数据集训练得到初始模型,再基于训练后的模型做拒绝采样,利用 NASL 沙箱对采样代码进行验证,将验证通过的数据回流到数据集中,以此丰富数据集的多样性并提升数据质量。
另外在不同阶段对模型效果进行分析评测,针对分析结果进一步调整数据配比和数据质量。重复以上过程,直至达到比较稳定的效果。在 NASL 模型微调中,所有参数优化均采用 LORA 方案。
本阶段在 SFT 模型的基础上,通过提供明确的负反馈信息,来强化模型输出与人类偏好的对齐程度,采用 DPO(Direct Preference Optimization)的算法方案。
对微调后的模型进行采样,根据 NASL 沙箱反馈作为正负样本划分依据,构造<问题, 正确代码, 错误代码>三元组数据,用于离线强化学习的训练。
目前 NASL 大模型在多领域多场景的训练过程中,基座模型的选择与数据准备的合成阶段根据评测效果按需采用 DeepSeek 模型。比如代码补全重在体验的即时性,对模型的规模有限制要求,因此目前 NASL 代码补全的模型基座选择的是 DeepSeek-Coder-1.3B-Base。而在数据准备的指令和答案合成阶段深度使用了 DeepSeek R1 模型,特别是答案合成,在切换用深度思考的 DeepSeek-R1 模型之后,收益显著。
最后,CodeWave 团队针对产品中各项 AI 功能,正在对接 DeepSeek R1 的满血版和残血版进行全面评测。也在持续关注和跟踪 DeepSeek 深度思考、Coder、多模态等各类模型的后续发展。
","description":"作者 | 刘东、韩其琛、赵雨森 大模型时代下新语言训练的挑战\\n\\n在网易 CodeWave 智能开发平台中,NASL(NetEase Application Specific Language)可视化编程语言 作为产品核心,主要有以下三大作用:\\n\\n承载完整应用不同粒度、多种领域的可视化编程结构的精确描述。 大到一个页面节点、一个流程节点,小到一个表达式、一个运算符。有通用的 基础语言部分,也有 Web 应用常见的特定领域(如数据定义、数据查询、页面、流程、权限等)子语言部分。统一前后端各子领域的表达方式,降低学习门槛。NASL 统一了数据库、服务端逻辑、接口定义…","guid":"https://www.infoq.cn/article/eQ3T5A2xrBpfvZmJQXMW","author":"刘东阳,韩其琛,刘东","authorUrl":null,"authorAvatar":null,"publishedAt":"2025-03-20T07:24:52.908Z","media":[{"url":"https://static001.geekbang.org/wechat/images/1d/1dd3e62d8790d1283a7505a872b906a1.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/wechat/images/b3/b3f577cacfe4d9d067e18c3dd8be9a28.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/wechat/images/ec/ecec6e4e1d5e73bd86b24a04ae7ec06c.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/wechat/images/a5/a55ccfc0cd595d7c43e28dea2b978a15.png","type":"photo","width":0,"height":0,"blurhash":""}],"categories":["AI&大模型","编程语言"],"attachments":null,"extra":null,"language":null},{"title":"当大模型接管编程:NASA 疯狂的“反人类”编程要求,为何仍被奉为行业圣典?","url":"https://www.infoq.cn/article/MmfUCdZGpWaW8xoP5juV","content":"整理 | 华卫
在软件工程领域,有些 “老派” 的方法和理念,是经过时间检验的真理,值得我们重新审视和学习。
大多数大型软件开发项目都会使用编码规范,旨在规定编写软件的基本规则:代码应如何构建,以及应该使用和避免哪些语言特性,尤其是在代码的正确性会对设备产生决定性影响的领域,如潜水艇、飞机、将宇航员送上同步轨道的航天器,以及距离居民区仅几公里之外的核电站等设施运行的控制代码等。
在众多编码规范中,NASA 的编码规则以其严苛性和有效性反复被提起。近期,油管博主 ThePrime Time 发布的解读 NASA 安全编码规则的视频,甚至短时间内引发了超百万观看。
特别是在 AI 编程和“氛围编程”流行的当下,重新审视严谨、可验证的编程规范,是对软件工程本质的回归。
有声音说,“老派的 NASA 编码方式是最好的方式。”也有人评价,“在 C 语言中使用这些标准的编码人员是真正的战士。”
NASA 程序员在编写航天设备运行代码时都遵守一套严格的规则,这套编码规则由 NASA 喷气推进实验室(JPL)首席科学家 Gerard J. Holzmann 所提出,名为《The Power of Ten – Rules for Developing Safety Critical Code1》(十倍力量:安全关键代码开发规则)。
其在开头指出,“大多数现有的规范包含远远超过 100 条规则,而且有些规则的合理性存疑。有些规则,特别是那些试图规定程序中空白使用方式的规则(提到了 Python),可能是出于个人偏好而制定的。其他一些规则则是为了防止同一组织早期编码工作中出现的非常特定且不太可能发生的错误类型。毫不奇怪,现有编码规范对开发人员实际编写代码的行为影响甚微。许多规范最致命的方面是它们很少允许进行全面的基于工具的合规性检查。基于工具的检查很重要,因为对于大型应用程序编写的数十万行代码,手动审查通常是不可行的。”
ThePrime Time 对此表达了强烈地赞同,称“确实有很多个人偏好被写入了代码规范中。我认同目前提到的所有内容,代码就应该可靠。自动化和工具的使用应该杜绝个人偏好。”
NASA 的编码规则主要针对 C 语言,力求优化更全面检查用 C 语言编写的关键应用程序可靠性的能力。原因是,“在包括 JPL 在内的许多组织中,关键代码都是用 C 语言编写的。由于其悠久的历史,这种语言有广泛的工具支持,包括强大的源代码分析器、逻辑模型提取器、度量工具、调试器、测试支持工具,以及成熟稳定的编译器选择。因此,C 语言也是大多数已开发的编码规范的目标。”
ThePrime Time 表示,“我知道现在有很多软件开发人员,一听到用 C 语言编写安全关键代码,可能就会想‘怎么又是这个’ 。你们可没有像 ‘旅行者号’ (NASA 研制的太空探测器)那样的项目,你们还不是顶尖开发者。”
此外,Holzmann 认为,“为了有效,规则集必须很小,并且必须足够清晰,以便于理解和记忆。规则必须足够具体,以便可以机械地进行检查。当然,这么小的规则集不可能涵盖所有情况,但它可以为我们提供一个立足点,对软件的可靠性和可验证性产生可衡量的影响。”因此,他将 NASA 的编码规则限制在十条。
这十条规则正在 NASA 喷气推进实验室用于关键任务软件的编写实验,取得了令人鼓舞的成果。据 Holzmann 介绍,一开始,NASA 的开发人员对遵守如此严格的限制存在合理的抵触情绪,但克服之后,他们常常发现,遵守这些规则确实有助于提高代码的清晰度、可分析性和安全性。这些规则减轻了开发人员和测试人员通过其他方式确定代码关键属性(例如终止性、有界性、内存和栈的安全使用等)的负担。“这些规则就像汽车上的安全带,起初可能有点让人不舒服,但过一段时间后,使用它们会成为习惯,不使用反而难以想象。”
ThePrime Time 最后对 NASA 编码规则给出的整体评价是,“我喜欢这份文档,即便我并非完全认同其中所有的规则。我只是很惊讶,政府机构编写的内容竟如此条理清晰。这是一份极其连贯的文档,似乎出自一位追求务实的人之手。”
不少与 NASA 工程师共事过的开发者们,都对这则 NASA 十大编码规则的解读视频深有感触:“他们的编码指南并不‘疯狂’,反而实际上相当理智。我们没有以这种方式编程才是疯狂的”,并分享了许多个人的相关经历。
“在学习 C 语言的时候,我的教授曾为卫星编写 C 程序 / 代码。他把自己的方法教给了我们,这种方法要求我们在电脑上编程之前,先把所有内容都写在纸上。这种方式迫使我们准确理解自己正在编写的内容、内存分配等知识,还能编写出更高效的代码,并掌握相关知识。我很庆幸自己是通过这种方式学习的,因为在面试时,我能轻松地在白板上编写代码。”一名工程师说。
另一位与前 NASA 工程师共同开发过游戏的程序员透露,“他的代码是我见过的最整洁、最易读的。当时我还是一名初级程序员,仅仅通过和他一起编写代码,我就学到了很多东西。我们使用的是 C++ 语言,但他的编程风格更像是带有类的 C 语言。他的代码本身就很易于理解(具有自解释性),不过他仍然对自己的代码进行了注释(既有代码中的注释,也有实际的文档说明)。”
还有一位自述“和 NASA 一位级别很高的程序员关系非常密切”的开发者表示,“我听过很多故事,这些故事都能说明制定所有这些标准的合理性。客观来讲,从 Java 1.5 升级到 1.7 的成本,比从零开始重建任务控制中心(MCC)还要高。而重建任务控制中心是用 C 语言完成的,其中另一位首席工程师曾是 C++ 专家,他认定最初的 C 语言更可靠。”
同时有前 NASA 工程师出来现身说法道,“曾参与构建云基础设施,他们的指导原则可不是闹着玩的,代码审查简直是人间炼狱。‘严苛’这个词用来形容再贴切不过了。不过,相比我之前在电信、金融科技领域的工作经历,以及后来在其他科技公司的工作,我在 NASA 工作期间对可靠性方面的了解要多得多。”
对于这十条规则,Holzmann 已经声明,“为了支持强大的审查,这些规则有些严格,甚至可以说严苛。但这种权衡是有道理的。在关键时候,尤其是开发安全关键代码时,多费些功夫,遵守更严格的限制是值得的。这样我们就能更有力地证明关键软件能按预期运行。”并且,每条规则之后都附了其被纳入的简短理由。
ThePrime Time 对这些编码规则及理由一一进行了评价和分析,以下是经不改变原意的翻译和编辑后整理出来的解读内容。
将所有代码限制在非常简单的控制流结构中,不要使用 goto 语句、setjmp 或 longjmp 结构以及直接或间接递归。
理由:更简单的控制流意味着更强的验证能力,并且通常能提高代码的清晰度。禁止递归可能是这里最让人意外的一点。不过,如果没有递归,我们就能保证有一个无环的函数调用图,这能被代码分析器利用,还能直接帮助证明所有本应有限的执行实际上都是有限的。(注意,这条规则并不要求所有函数都有一个单一的返回点——尽管这通常也会简化控制流。不过,有很多情况下,提前返回错误是更简单的解决方案。)
ThePrime Time: 我不知道间接递归是什么意思。间接递归是指两个函数相互调用吗?在实际情况中,这种情况确实会发生,而且发生过很多次。比如有一个函数需要调用另一个函数去做某些事情并进行一些检查,然后再通过某种不受你控制的方式返回结果。特别是在那些没有异步 / 等待(async/await)机制的语言里,我猜你只能阻塞线程了,对吧?规则是说如果没有异步机制,就只能阻塞线程,然后在一个while循环里处理,是这样吗?我得想想我自己使用间接递归的场景。实际上,我在处理套接字重连时就用到了间接递归。具体来说,当我打开一个套接字(就像这样,打开这个套接字),重连机制会调用一个私有函数来重置状态,然后调用reconnect函数,reconnect函数会调用connect函数,当连接断开时,connect函数又会再次调用自己。从技术上讲,这就是一种间接递归。我在想,也许我可以把它改成用while循环加上等待机制,这样会不会更简单呢?现在真的让我开始思考这个问题了,这可能只是一种替代方案。
哎呀,我已经违反规则一了。不过间接递归确实是一种非常强大的无限问题解决机制,但我可以尝试不用它,对吧?我完全不介意尝试新的做法。理由很简单,“更简单的控制流意味着更强的验证能力,并且通常能提高代码的清晰度。”我认同这一点,确实看到代码里有类似这样的逻辑时会觉得有点绕。比如在一个 close 函数中调用 reconnect,然后在 reconnect 中检查是否已经启动,如果没有完成,就返回。这些语句的顺序会导致问题,所以我可以理解为什么会出现这种情况。我甚至可以说服自己接受这一点。
说实话,这是一个非常务实的观点,解释了为什么不应该使用递归。而且说句公道话,我大学三四年级的时候(不对,其实是大二),老师让我们用非递归的方式实现 AVL 树。如果你不熟悉 AVL 树,这是一种使用旋转的自平衡二叉搜索树,有四种不同的旋转:右旋、左旋、先右后左旋和先左后右旋。做起来其实很有趣,假设我们有一个二叉树,像这样:a(根节点),b 是左子节点,c 是右子节点。我们想重新组织成 b 作为根节点,a 作为左子节点,c 作为右子节点。如果你有一棵二叉树,看起来像 “a b c”,你就把它重组为 “a c b”,然后进行旋转。很简单直接,对吧?老师说我们要实现这个程序,但不能用递归。这对我来说是一次很棒的学习经历。
所有循环必须有固定的上限。检查工具必须能够轻易地静态证明循环的预设迭代上限不会被突破。如果无法静态证明循环的上限,就视为违反规则。
理由:没有递归且存在循环上限可以防止代码失控。当然,这条规则不适用于那些本就不打算终止的迭代(例如在进程调度器中)。在这些特殊情况下,适用相反的规则:必须能静态证明迭代不会终止。支持这条规则的一种方法是,给所有迭代次数可变的循环添加明确的上限(比如遍历链表的代码)。当超过上限时,会触发断言失败,包含失败迭代的函数将返回错误。(关于断言的使用,请参见规则 5)
ThePrime Time: 这是不是意味着不能使用像数组的forEach这样的方法呢?因为从技术上讲,其上限是根据数组动态变化的,没有固定值。还是说不能使用while (true)这种循环呢?这是一条有趣的规则。
初始化后不要使用动态内存分配。
理由:这条规则在安全关键软件中很常见,并且出现在大多数编码规范里。原因很简单:像 malloc 这样的内存分配器和垃圾回收器,其行为往往不可预测,可能会对性能产生重大影响。一类显著的编码错误也源于对内存分配和释放例程的不当处理,比如忘记释放内存、释放后继续使用内存、试图分配超过实际可用的内存,以及越界访问已分配的内存等等。强制所有应用程序在固定的、预先分配好的内存区域内运行,可以避免很多这类问题,也更容易验证内存的使用情况。需要注意的是,在不使用堆内存分配的情况下,动态申请内存的唯一方法是使用栈内存。在没有递归的情况下(规则 1),可以静态推导出栈内存使用的上限,从而可以证明应用程序将始终在其预先分配的内存范围内运行。
ThePrime Time: 这么一来,JavaScript 和 Go 语言可就有点麻烦了。不过说实在的,其实在 JavaScript 和 Go 里也能做到这一点。显然,在大多数情况下是可以的。但我敢肯定,只要调用类似G Funk(这里可能是随意提及的某个函数)这样的函数,它背地里肯定会分配一些你不知道的内存。当然,不是所有解释型语言都这样,这么说不太准确,不是所有解释型语言都有这个问题。
我猜这条规则意味着不能使用闭包,对吧?因为闭包会涉及到内存分配。准确地说,你得使用内存池(Arena)进行内存分配。也就是说,不能随意使用列表或字符串吗?也不是,其实可以使用列表和字符串,只是意味着所有内存分配都必须在程序开始时完成。我猜这里说的是堆内存,而不是栈内存。另外,我是这么理解的,比如说你从服务器获取一系列响应数据,你得事先分配一块足够大的内存区域,用来存储所有可能的响应数据,然后像使用环形缓冲区一样循环利用这块内存,这样就不会有额外的内存分配操作了,所有可能用到的数据都已经预先分配好了。所以一开始你就应该拥有所需的所有内存,这意味着可以使用字符串,只是得预先定义好字符串占用内存的大小。天呐,这得好好琢磨琢磨,确实很费脑筋,不过环形缓冲区的概念真的很有意思。
“在不使用堆内存分配的情况下,动态申请内存的唯一方式是使用栈内存。根据规则一,在没有递归的情况下,可以静态推导出栈内存使用的上限,这样就能证明应用程序始终在其预先分配的内存范围内运行。”这听起来有点疯狂,但其实挺酷的,仔细想想还挺有道理。
我听说在游戏开发里有这样一种做法,如果我说错了也请大家指正。在游戏开发中,每个子团队会有各自的资源预算,包括内存和 CPU 时间。在你负责的程序部分,你只能使用分配给你的那部分资源。一旦超出预算,就会有类似这样的提示:“嘿,物理模拟团队,你们用的时间太多了,能不能想想办法?” 我觉得这听起来挺不错的。我知道有这么回事,我举的这个例子是希望普通的游戏开发者也能理解。就好比今年两家小的游戏工作室因为资源超支没拿到奖金,大致就是这么个情况。宽泛来讲,实际情况比在 Twitch 聊天里说的要复杂一些,但差不多就是这样。我只是以一个普通游戏开发者的角度来解释这个规则,我开发过一些小游戏,但我也知道自己还算不上专业的游戏开发者。
任何函数的长度都不应超过以标准参考格式打印在一张纸上的长度,即每行写一条语句、每行写一个声明。通常情况下,这意味着每个函数的代码行数不应超过 60 行。
理由:每个函数都应该是代码中的一个逻辑单元,可以作为一个单元来理解和验证。跨越计算机显示器多个屏幕或打印时多页的逻辑单元要难得多。过长的函数往往是代码结构不佳的表现。
ThePrime Time: 好的,这挺合理的。60 行代码的空间足够你把事情弄清楚了。鲍勃大叔(Uncle Bob ,著名编程大师 Robert C. Martin)规定每个函数一般只能有三到五行代码,相比之下 60 行代码算很多了。不过这里说的是打印在一张纸上,对吧?就是说代码打印在单张纸上,大概就是这个意思。注意,这其实也不算特别严格的硬性规定,但从能打印在纸上这个角度来说,它又算是个硬性规定。我觉得 60 行代码能表达很多内容,肯定有办法打破这个规则,但我感觉自己通常能轻松写出最多 60 行代码的函数,我觉得这一点都不难。没错,Ghost 标准库有数千行代码,但我不会把 Ghost 标准库当作史上最整洁、最出色的代码之一。老实说,我个人觉得 Ghost 标准库读起来真的很糟糕。
这条规则的理由是,每个函数都应该是代码中的一个逻辑单元,能够作为一个整体被理解和验证。如果一个逻辑单元跨越计算机显示器的多个屏幕,或者打印出来有好多页,理解起来就困难得多。过长的函数往往意味着代码结构不佳。我基本上同意这个观点,我觉得实际上很少能见到超过 60 行代码的函数。而且一般来说,当你遇到这样的函数时,要么是因为功能本身非常复杂,由于行为的关联性必须写在一起;要么这个函数写得很糟糕。除非你写 React 代码,我觉得我说的这些还是适用的。
代码的断言密度平均每个函数至少应有两个断言。断言用于检查在实际执行中不应发生的异常情况。断言必须始终无副作用,并且应定义为布尔测试。当断言失败时,必须采取明确的恢复措施,例如,向执行失败断言的函数的调用者返回错误条件。任何静态检查工具能够证明永远不会失败或永远不会成立的断言都违反此规则。(也就是说,不能通过添加无用的 “assert (true)” 语句来满足该规则。)
理由:工业编码工作的统计数据表明,单元测试通常每编写 10 到 100 行代码就能发现至少一个缺陷。断言密度越高,拦截缺陷的几率就越大。断言的使用通常也被推荐作为强防御性编码策略的一部分。断言可用于验证函数的前置和后置条件、参数值、函数返回值以及循环不变式。由于断言无副作用,因此在测试后,可以在对性能关键的代码中有选择地禁用它们。
ThePrime Time: 我很喜欢这条规则。我觉得它有很多优点,而且我觉得自己需要更多地实践这条规则。我还得继续坚持,因为就像我之前说的,我的代码库里已经有不少断言了。我确实经常使用断言,但目前我代码里的断言一旦触发,程序就会直接崩溃。比如说,当程序内部生成的消息与我预期的不一致时,我就会认为自己犯了严重错误,觉得整个程序都得“炸掉” ,结果整个程序就会受到影响。有一点很棒,如果你能想出某种模糊测试策略,就能测试你的程序。你可以往程序里输入一堆随机数据,而程序里应该有防御性的语句,以确保不会触发更多的断言。这样一来,你甚至可以减少很多针对模糊测试的特定单元测试,这是不是很神奇?
下面是一个典型的断言使用示例:如果条件 C 成立,且断言 p 大于等于为真,就返回错误。假设断言定义如下:定义一个名为c_assert的断言,用于调试,当断言失败时,输出文件和行号等信息,这里设置为false 。在这个定义中,file和line由宏预处理器预先定义,用于输出失败断言所在的文件名和行号。语法#e会将断言条件e转换为字符串,作为错误消息的一部分打印出来。在嵌入式程序代码中,通常没有地方打印错误消息,在这种情况下,对测试调试的调用会变成空操作,断言就变成了纯粹的布尔测试。这有助于从异常行为中恢复错误。
我开始接触这 “十条规则” 的契机是,有个来自 Tiger Beetle(一个项目)的人加入了我们。他们在 Tiger Beetle 项目中对断言的使用非常严格。他可以往 Tiger Beetle 里输入任何数据,而程序始终能正常运行。他们每天在每次构建时,都会进行相当于 200 年查询量的测试,程序不断接受大量测试,而且运行得非常稳定。这真是个超酷的项目。
数据对象必须在尽可能小的作用域级别声明。
理由:这条规则支持数据隐藏的基本原则。显然,如果一个对象不在作用域内,其值就不能被引用或破坏。同样,如果必须诊断一个对象的错误值,可能分配该值的语句越少,诊断问题就越容易。该规则不鼓励将变量重复用于多个不兼容的目的,这可能会使故障诊断复杂化。
ThePrime Time: 有人说这只是因为 C 语言没有恰当的错误处理和语法特性,我强烈反对这种说法。实际上,断言非常有用。比如说,Tiger Beetle 项目是用 Zig 语言编写的,Zig 有恰当的错误处理工具,它有结果对象,而且其自身的错误处理结果对象能提供比标准错误更好的堆栈跟踪信息,这真的很酷。我记得在采访时,他说当时 Tiger Beetle 项目里有 8000 个断言。
没错,断言不是错误处理机制,实际上断言不是用于处理错误的,它是一种不变式,可以说是硬性终止条件。我们来看看,这和在 Zig 语言里直接返回错误有什么不同呢?在 Zig 里,你可以返回一个错误或者一个值,但这就是一种错误处理方式。Zig 里不会硬性终止程序,它必须有恢复机制。我觉得这样也挺好,无论是硬性终止,还是软性终止并搭配某种错误恢复机制,都需要构建相应的错误恢复机制。
我其实并没有完全理解规则六,除了感觉好像是说在使用变量的地方定义它,这样作用域就是最小的,是这个意思吗?听起来好像是这样,这里是在说封装的概念吗?
非 void 函数的返回值必须由每个调用函数检查,并且每个函数内部必须检查参数的有效性。
理由:这可能是最常被违反的规则,因此作为一般规则有些可疑。从严格意义上讲,这条规则意味着即使是 printf 语句和文件关闭语句的返回值也必须被检查。不过也有观点认为,如果对错误的响应与对成功的响应没有区别,那么显式检查返回值就没什么意义。这通常是调用 printf 和 close 的情况。在这种情况下,可以接受将函数返回值显式转换为 (void)—— 这表明程序员是有意忽略返回值,而非不小心遗漏。在更可疑的情况下,应该有注释解释为什么返回值无关紧要。不过,在大多数情况下,函数的返回值不应被忽略,尤其是在必须将错误返回值沿函数调用链向上传播的情况下。标准库因违反此规则而臭名昭著,并可能导致严重后果。例如,如果不小心执行 strlen (0),或者使用标准 C 字符串库执行 strcat (s1, s2, -1)—— 结果就很糟糕。遵循这条通用规则,我们可以确保例外情况必须有合理的解释,并且机械检查器会标记违规行为。通常,遵守这条规则比解释为什么不符合规则更容易。
ThePrime Time: 这实际上是我非常喜欢 Zig 的一个原因。我想 Rust 语言也有类似的情况,只不过当你忽略返回的结果或异步操作的返回值时,Rust 只是给出警告。我喜欢这条规则,我觉得这是一条很棒的规则。这是一条普遍适用的好规则。要知道,编程的很大一部分就是学习这些技巧,避免自己给自己挖坑。
预处理器的使用必须仅限于包含头文件和简单的宏定义。不允许使用令牌粘贴、可变参数列表(省略号)和递归宏调用。所有宏必须展开为完整的语法单元。条件编译指令的使用通常也值得怀疑,但并非总是可以避免。这意味着,即使在大型软件开发项目中,除了避免同一头文件多次包含的标准样板代码外,也很少有理由使用超过一两个条件编译指令。每次此类使用都应通过基于工具的检查器标记,并在代码中说明理由。
理由:C 预处理器是一个强大的混淆工具,可能会破坏代码的清晰度,并使许多基于文本的检查器感到困惑。即使手头有正式的语言定义,不受限制的预处理器代码中的构造的效果也可能极其难以破译。在 C 预处理器的新实现中,开发人员通常不得不求助于使用早期实现作为解释 C 标准中复杂定义语言的裁判。对条件编译持谨慎态度的理由同样重要。请注意,仅使用十个条件编译指令,就可能有多达 2 的 10 次方种可能的代码版本,每种版本都必须进行测试 —— 导致所需的测试工作量大幅增加。
ThePrime Time: 我认为对预处理宏保持谨慎肯定没错。我理解代码时遇到的困难,没有比处理预处理宏更多的了。预处理宏真的是最难懂的部分之一。这条规则实际上会让我们的开发工作变得更加复杂,我一点都不喜欢。有意思的是,总体来说我不喜欢预处理器。我能理解预处理器肯定会引发一堆问题,人们通常把它们叫做宏。一般来说,宏可能很有用,但它们通常也非常难以理解,理解起来特别费劲。谢天谢地 C 语言没有宏(这里表述有误,C 语言有宏,作者可能想表达宏的复杂性让人头疼 )。宏是一种强大的工具,但就像所有强大的工具一样,它们非常危险。预处理器是一个强大的混淆工具,会破坏代码的清晰度,让许多基于文本的检查器感到困惑。即使手头有正式的语言定义,不受限制的预处理代码中的结构效果也极难解读。在 C 预处理器的新实现中,开发人员常常不得不借助早期的实现来解读 C 标准中的复杂定义语言。
对条件编译保持谨慎的理由同样重要。要知道,仅仅 10 个条件编译指令就可能产生多达 2 的 10 次方种代码版本,每个版本都必须进行测试,这会大幅增加所需的测试工作量。我是说,这一点非常关键。一般来说,条件编译就是一场噩梦,尽管有时又不得不使用它。我觉得这条规则务实的地方在于,它认识到虽然无法避免使用条件编译,但条件编译确实非常困难且麻烦。
没错,我猜 Rust 语言的 cargo 特性主要是因为 Rust 编译速度慢才存在的。我认识的大多数人对 Rust 二进制文件不太感兴趣,更多的是担心编译时间太慢。我敢肯定,最终 Rust 二进制文件非常重要,但就我所知,很多时候问题就出在编译速度上。正是因为编译慢,才引出了一系列问题,比如我总是会遇到这样的情况,使用 clap 时忘记添加 feature derive,然后又得去添加;使用 request 时又忘记添加 request feature 之类的,情况越来越糟。你们看过 AutoSAR 的 C 代码吗?我敢肯定那代码很糟糕。
指针的使用应受到限制。具体来说,允许的解引用级别不超过一级。指针解引用操作不得隐藏在宏定义或 typedef 声明中。不允许使用函数指针。
理由:即使是经验丰富的程序员也容易误用指针。它们可能使程序中的数据流难以跟踪或分析,尤其是对于基于工具的静态分析器。同样,函数指针可能会严重限制静态分析器可以执行的检查类型,只有在有充分理由使用它们的情况下才应使用,并且理想情况下应提供替代方法来帮助基于工具的检查器确定控制流和函数调用层次结构。例如,如果使用函数指针,工具可能无法证明没有递归,因此必须提供替代保证来弥补分析能力的损失。
ThePrime Time: 比如说,怎么处理异步相关的操作和中断呢?我觉得他们可能不处理异步操作,但我又确定他们肯定会处理。处理异步操作肯定得使用某种互斥锁,对吧?比如使用信号量互斥锁,然后还得涉及对内存的引用。异步操作具有不确定性,所以不太好处理。其实也不是完全不确定,只是你得在一定程度上进行处理。想象一下,你有一个探测器,上面有个小摄像头正在拍照。在某个时刻你拍了照,照片进行处理后存储到内存中,处理完成后会有提示。然后某些代码需要被唤醒,这不也在一定程度上涉及到函数指针吗?我猜得用互斥锁,对吧?所以我猜你会有一段代码,比如说处理拍照的代码。你得在这里进行一些操作,比如获取信号量,在 C 语言里信号量的值为 1,具体是用 lock unlock(锁定解锁 )还是 lock acquire(获取锁 )我记不清了。代码就停在这里等待,当照片数据传入后,代码开始处理,处理完之后再回到等待状态。
我理解这个,不过这条规则感觉更难落实。
所有代码从开发的第一天起,就必须在编译器最严格的设置下启用所有编译器警告进行编译。所有代码必须在此设置下编译且不发出任何警告。所有代码必须每天至少使用一个,但最好是多个最先进的静态源代码分析器进行检查,并且应以零警告通过分析。
理由:如今市场上有几种非常有效的静态源代码分析器,还有相当多的免费工具。任何软件开发工作都没有理由不使用这种现成的技术。即使对于非关键代码的开发,也应将其视为常规做法。零警告规则甚至适用于编译器或静态分析器给出错误警告的情况:如果编译器或静态分析器感到困惑,应重写导致困惑的代码,使其更简单有效。很多开发者一开始认为某个警告肯定是无效的,结果后来才意识到,由于一些不那么明显的原因,该警告实际上是合理的。早期的静态分析器,比如 lint,大多会给出无效的提示信息,这让静态分析器的名声有些不好,但现在情况已经不同了。当今最好的静态分析器速度快,并且会生成有针对性且准确的提示消息。在任何一个严肃的软件项目中,它们的使用都不应有商量余地。
ThePrime Time: 说实话,我觉得这挺合理的。尤其是对于新手而言,如果你刚开始接触软件开发,就应该能够做到这一点。公平地说,我不算专业的软件开发人员,所以我能理解这一点。我觉得这真的很棒,规则 10 简直太实用了。
不过,要把这条规则应用到很多项目中可能会很困难。比如说在 JavaScript 开发中,大家都知道 JavaScript 的 lint 工具体验很差,大多数 ESLint 规则纯粹是些主观的好坏评判标准。比如在处理 Promise 时,使用re和reject作为参数实际上是不好的做法,对吧?
参考链接:
https://www.youtube.com/watch?v=JWKadu0ks20\\"
声明:本文为 InfoQ 整理,不代表平台观点,未经许可禁止转载。
","description":"整理 | 华卫 在软件工程领域,有些 “老派” 的方法和理念,是经过时间检验的真理,值得我们重新审视和学习。\\n\\n大多数大型软件开发项目都会使用编码规范,旨在规定编写软件的基本规则:代码应如何构建,以及应该使用和避免哪些语言特性,尤其是在代码的正确性会对设备产生决定性影响的领域,如潜水艇、飞机、将宇航员送上同步轨道的航天器,以及距离居民区仅几公里之外的核电站等设施运行的控制代码等。\\n\\n在众多编码规范中,NASA 的编码规则以其严苛性和有效性反复被提起。近期,油管博主 ThePrime Time 发布的解读 NASA 安全编码规则的视频,甚至短时间内引发了超百万观看。…","guid":"https://www.infoq.cn/article/MmfUCdZGpWaW8xoP5juV","author":"华卫","authorUrl":null,"authorAvatar":null,"publishedAt":"2025-03-19T10:36:47.271Z","media":[{"url":"https://static001.geekbang.org/wechat/images/00/003439c1289c033d5a8e2083e3d8c125.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/wechat/images/20/20d668f695f36b9b9a1a85fe14fdb941.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/wechat/images/e7/e7a0e9100c478a92b1dccee188f539c1.png","type":"photo","width":0,"height":0,"blurhash":""}],"categories":["编程语言"],"attachments":null,"extra":null,"language":null},{"title":"Uber 的云旅程:在 x86 世界中拥抱 ARM","url":"https://www.infoq.cn/article/sRh1LtfFD2k2cWqahMM2","content":"2023 年 2 月,Uber 开始从本地数据中心战略性地迁移到 Oracle 云基础设施(OCI)和 Google 云平台。此次迁移的一个关键环节是将基于 ARM 的计算机集成到以 x86 为主的集群中,以降低成本、提高性价比,并在供应链不稳定的情况下确保硬件灵活性。
x86 和 ARM 架构代表了处理器设计中的两种完全不同的理念,它们的区别奠定了数十年来的计算产业格局。x86 处理器通常为计算密集型任务提供更高的峰值性能,但消耗更多电量,这使得它们在电源插座随时可用的台式机和服务器领域占据主导地位;与此同时,ARM 处理器在能效方面表现出色,提供更好的每瓦性能比,使其成为移动设备、嵌入式系统以及日益注重功耗的数据中心的首选架构。
多架构集成面临的挑战不仅在于部署新的硬件。对于 Uber 的基础设施团队来说,这意味着重新看待多年来完全基于 x86 的基础系统。这一历程也显示出架构假设可以深度渗透到技术栈的每一层中。
此次转变的基础是 Oracle Cloud Infrastructure 对 Ampere Computing 的 ARM 处理器的战略性引入。这些芯片提供了卓越的能效——这是 ARM 在移动领域的最显著优势,现已扩展到数据中心环境。对于云提供商来说,这意味着大幅节省电力和提高计算密度,从而降低能源成本和物理占用空间要求。
对于 Uber 来说,这些优势与其可持续发展目标完美契合。随着公司努力实现零排放,采用节能计算基础设施是在减少环境影响的同时改善成本结构的重要一步。
整个转换过程从主机级的准备工作开始——创建包含操作系统、内核和基本基础设施组件的 ARM 兼容镜像。主机启动后,团队开始着手构建各种管道,找出了复杂的 Web 依赖关系。Uber 的容器系统依赖于 Makisu,这是一种针对 x86 优化的工具,无法针对 ARM 进行交叉编译。
为容器镜像构建管道
团队没有重写 5,000 多个服务构建流程,而是采用了一种巧妙的引导方法。他们利用 Google Bazel 构建了 Makisu 本身的 ARM 版本,然后就可以原生构建其他服务了。这个看似简单的任务暴露了一种循环依赖关系:Makisu 在 Buildkite 上运行,而 Buildkite 在 Uber 的 Odin 平台上运行,Odin 平台又依赖主机代理——所有这些都是用 Makisu 构建的。
打破这种循环依赖关系需要使用 Bazel 的多架构特性有条不紊地重建每一层。团队从主机代理开始,然后重建 Odin 的组件,接着是 Buildkite,最后是 Makisu。这个基础启用了分布式构建管道,可以生成统一的多架构容器镜像。
虽然这种方法使构建成本翻倍(每周有超过 400,000 个容器构建),但从经济角度来看,采用 ARM 仍然是有利可图的。分布式构建系统还提供了一个关键优势:它支持逐步、受控的迁移,而不是全有或全无的方法。
部署系统需要类似的增强。Uber 实施了针对架构的放置约束和自动回退机制,如果出现兼容性问题,这些机制将恢复到 x86。这些保护措施让团队可以逐步迁移服务,同时保持生产可靠性。
成功部署他们的第一批基于 ARM 的服务标志着一个技术里程碑,证明了多架构基础设施可以在 Uber 的规模下正常工作。然而,从最初的成功到迁移数千个服务的过程还需要额外的策略和工具。
随着云提供商扩展其处理器架构选项,Uber 和 Bitmovin 等组织展示了将各种计算架构整合到大型基础设施系统中的挑战和潜在好处。Bitmovin 将其编码服务完全迁移到 ARM 处理器的历程,以及 Uber 的经验,为企业如何在大规模范围内应对架构异构性提供了宝贵的见解。
原文链接:
Uber\'s Cloud Journey: Embracing ARM in an x86 World(https://www.infoq.com/news/2025/02/uber-arm-cloud/)
","description":"2023 年 2 月,Uber 开始从本地数据中心战略性地迁移到 Oracle 云基础设施(OCI)和 Google 云平台。此次迁移的一个关键环节是将基于 ARM 的计算机集成到以 x86 为主的集群中,以降低成本、提高性价比,并在供应链不稳定的情况下确保硬件灵活性。 x86 和 ARM 架构代表了处理器设计中的两种完全不同的理念,它们的区别奠定了数十年来的计算产业格局。x86 处理器通常为计算密集型任务提供更高的峰值性能,但消耗更多电量,这使得它们在电源插座随时可用的台式机和服务器领域占据主导地位;与此同时,ARM 处理器在能效方面表现出色…","guid":"https://www.infoq.cn/article/sRh1LtfFD2k2cWqahMM2","author":"作者:Claudio Masolo","authorUrl":null,"authorAvatar":null,"publishedAt":"2025-03-19T06:00:00.480Z","media":[{"url":"https://static001.geekbang.org/infoq/6d/6d29123cc6941b308a7b4e2444857f89.webp","type":"photo","width":0,"height":0,"blurhash":""}],"categories":["编程语言"],"attachments":null,"extra":null,"language":null},{"title":"云原生时代的架构革新,Apache Doris 存算分离如何实现弹性与性能双重提升","url":"https://www.infoq.cn/article/zaUGz5EB7W3375ZDBPgm","content":"导读: 随着云基础设施的成熟,Apache Doris 3.0 正式支持了存算分离全新模式。基于这一架构,能够实现更低成本、极致弹性以及负载隔离。本文将介绍存算分离架构及其优势,并通过导入性能、查询性能、资源成本的测试,直观展现存算分离架构下的性能表现,为读者提供具体场景下的使用参考。
在数据驱动决策的时代,数据规模增长加快、分析需求不断变化。数据从多种渠道(如应用日志、网络交互、移动设备等)源源不断地流入,包含结构化、半结构化、非格式化等多种数据格式,这对数据的存储和分析提出了很高的挑战。与此同时,企业对实时分析、探索性查询的需求激增,要求系统在保证毫秒级响应能力的同时,兼具极致的成本效益与弹性扩展能力。
Apache Doris 诞生于存算一体的分布式时代,是典型的 Shared Nothing 架构:BE 节点上存储与计算紧密耦合、多 BE 节点采用 MPP 分布式计算架构,这种架构带来了高可用、极简部署、横向可扩展以及强大的实时分析性能等一系列核心特色。在实时分析、小规模数据处理等场景中,凭借可预期的稳定低延迟表现,具有不可替代的优势。但在面对大规模数据处理时面临一些挑战,主要体现在:
成本高且弹性不足: 合理平衡存储和计算资源较为困难。存储方面,集群必须足够大以容纳所有数据;因此计算资源的分配既要满足查询请求,又要避免浪费。然而,调整集群规模通常耗时较长,企业往往选择过度配置集群以简化运维操作,这就导致资源浪费和成本增加。受限的负载隔离: Apache Doris 2.0 开始支持 Workload Group 实现软限隔离,也支持 Resource Group 实现一定程度的硬限隔离,但是这两种方式都无法达到彻底的物理隔离。运维难度较大: OLAP 系统内置分布式存储系统,不仅需要运维计算节点,还需有效管理存储系统。而存储系统的管理要求非常高,任何不当操作都可能导致数据丢失。
即使如此,在没有稳定且大规模存储支持的情况下,存算一体架构依然是最好的选择。
随着云基础设施的成熟,越来越多的企业都希望 Apache Doris 能更深度地适应公有云、私有云和 K8s 容器平台,以提供更灵活的弹性能力。公有云提供无需预置空间的成熟对象存储和计算资源按需购买,私有云则通过 K8s、MinIO 等技术构建资源平台。云基础设施的成熟,也推动了 Apache Doris 存算分离架构的实现,使更低成本、极致弹性、负载隔离成为可能。
飞轮科技基于 Apache Doris 内核研发全托管企业级云数仓产品(即 SelectDB Cloud\\")过程中,设计并实现了全新的云原生存算分离架构,并将这一架构的实现贡献至 Apache Doris 社区。Apache Doris 在 3.0 版本中正式支持存算分离这一模式。
SelectDB Cloud 是飞轮科技基于 Apache Doris 内核构建,能够为 Apache Doris 提供原生的存算分离架构云托管服务,并在线下稳定运行近 3 年,获得客户广泛认可。 它支持全球主流云平台,推出开箱即用的 SaaS 部署模式和更符合客户合规需求的 BYOC 部署模式,为企业提供多云一致的使用体验。此外,飞轮科技与阿里云共同打造阿里云一级产品——阿里云瑶池数据库 SelectDB 版,能够为用户提供阿里云上的全托管服务。目前,SelectDB Cloud 及 阿里云瑶池数据库 SelectDB 版已为点点互动、华瓴科技、名创优品、趣丸、波司登、MiniMax、新东方等数百家知名企业提供服务,帮助这些企业实现查询性能、成本效益、整体性价比的综合提升。
在存算分离模式下,Apache Doris 整体架构由共享存储层、计算层和元数据层三部分构成:
共享存储层: 数据持久化到共享存储层,计算节点可以共享数据,这为计算节点的灵活性提供了基础。成熟稳定的共享存储为系统带来极低的存储成本和极高的数据可靠性,同时,公有云对象存储或者企业内部专业团队运维的共享存储可以大幅降低 Doris 的运维负担。
计算层: 计算层由任意数目的计算组构成,负责执行查询计划,每个查询仅在一个计算组内执行。计算节点无状态,本地配置本地磁盘作为高速缓存以加速查询,共享同一份数据和元数据服务,一个或者多个计算节点组成一个计算组。计算组之间是物理隔离的,可以独立扩缩容,计算节点的本地高速缓存都是隔离的,这样尽可能地保证较好的隔离性。
元数据层: 提供系统的元数据管理服务,包括数据库、表、Schema、rowset 元数据、事务信息等,支持横向扩展。未来 Apache Doris 存算分离模式下的 FE 节点也将实现无状态化,内存占用不再与集群规模相关,仅需极少的内存即可正常运行,消除 FE 内存瓶颈问题。
对于存算分离架构来说,写入性能和小文件数量是影响架构稳定性和效率的关键因素。而业内常见的存算分离方案,将数据和元数据存储在共享存储中,其事务能力依赖于 FE 单点,通常面临以下挑战:
写入性能差:FE Master 驱动的两阶段提交导致高延迟和低吞吐。小文件问题:频繁写入元数据生成大量小文件,影响系统稳定性并增加成本。扩展性差:FE 内存存储元数据,随着 Tablet 数量的增加,内存压力增大,导致写入瓶颈。数据删除风险:通过差集计算删除数据,依赖超时机制,难以避免写入和删除的冲突,存在误删除的风险。
相比之下,Apache Doris 通过共享元数据服务有效解决了这些问题:
实时写入:元数据服务提供全局一致的视图,支持低延迟和高吞吐的写入。经测试,Doris 存算分离模式在 50 并发下是其他方案的 100 倍;在 500 并发下是其他方案的 11 倍。小文件控制:数据写入共享存储,元数据写入服务,可有效控制小文件数量。经测试发现,Doris 存算分离模式下的写入文件数仅是业内其它存算分离方案的 1/2。扩展性提升:未来计划将 FE 的元数据迁移至元数据服务,消除集群规模的限制。数据删除保障:Doris 采用正向删除,基于全局一致视图,确保写入和删除互斥,避免误删除数据的风险。
Apache Doris 存算分离架构,主要提供了提更低成本、极致弹性以及负载隔离这三大优势:
更低成本:与存算一体架构相比,存算分离架构综合成本降低超 90%。
按需付费:相较于存算一体,无需再预置计算和存储资源,存储可按实际使用付费,计算资源则可以灵活弹性扩展。单副本存储:数据仅需在低成本的对象存储中存储一份副本,而不再在高成本的块存储中存储三个副本。热数据则缓存于块存储中,这不仅降低了存储量和硬件资源需求,还显著降低了存储成本(例如,AWS 上的 EBS 价格是 S3 的 2 到 4 倍),同时保证了查询性能。资源消耗降低:Compaction 操作所消耗的资源和副本数量成正比,在存算分离模式下只需要处理单一数据副本,资源消耗大幅减少。
极致弹性:得益于无状态的计算节点设计,能够更加灵活地应对不断变化的业务需求,提供高效、弹性的计算资源管理。
弹性扩缩容:支持灵活调整计算资源,更好应对业务高峰或波动。当系统负载增加时,计算节点可以迅速扩容;而在需求减少时,计算资源又可以灵活缩减,从而避免不必要的资源浪费。计算节点按需分配:支持将不同配置的计算节点灵活分配到各计算组中,根据任务需求精确分配资源。例如,高性能计算节点被用于复杂查询或高并发场景,而标准配置节点分配于简单查询或低频请求。
负载隔离:提供高效的资源管理和负载隔离,为不同业务需求提供精细化的计算资源调度。
业务间负载隔离:针对不同业务需求,可为每业务配置独立计算组,并实现物理隔离。确保各业务计算任务在专用资源上运行,减少相互干扰,保障系统的稳定性和高效性。离线负载隔离:对于大规模离线数据处理任务,可将其分配到特定的计算组,使用低成本的资源进行批量数据处理,而不影响实时业务的计算性能。读写隔离:可分别为读、写操作创建计算组和用户。写计算组专门处理数据写入(插入、更新等),而读计算组专门处理查询请求,确保在线业务的查询延迟稳定。
接下来,我们将从导入、查询、资源成本等多个维度对 Doris 存算分离模式进行对比测试,以更直观地展示其性能表现。
在相同计算资源下,针对 Doris 存算分离、Doris 存算一体、业内常见存算分离方案,进行两组实时导入性能对比测试:
50 并发:写入 250 个 20000 行的数据文件500 并发:写入 10000 个 500 行的数据文件
测试结果如下:
在 50 并发下,Doris 存算分离与存算一体的写入性能基本相当,是业内其他存算分离方案的 100 倍。在 500 并发下,虽然 Doris 存算分离相比存算一体写入性能稍有损耗,但比业内其他存算分离方案仍有超 11 倍的性能优势。
在批量数据导入场景,分别基于 Doris 存算分离、Doris 存算一体进行导入 TPC-H 1TB 和 TPC-DS 1TB 测试数据集,观察其性能表现。
导入方式: 采用 S3 Load 导入方式,在默认配置下,对多张表的数据进行串行导入,对导入总时间进行对比。
硬件配置如下:
机器数量: 4 台阿里云主机(1 FE,3 BE)CPU:48 核内存:192G网络带宽:21Gbps磁盘:阿里云 ESSD
经测试,在存算一体模式同样采用单副本的情况下,存算分离模式批量数据写入性能较存算一体模式分别提升了 20.05% 和 27.98%。(实际部署中存算一体模式一般会采用三副本,那么存算分离模式的写入性能优势会更加明显。)
在存算分离模式下,Apache Doris 通过多层缓存机制加速查询,这些缓存层级有效地提升数据访问速度,减少对共享存储的访问,提升查询效率。具体层次如下:
Doris Page Cache:使用内存缓存解压后的数据Linux Page Cache:使用内存缓存压缩后的数据本地磁盘 Cache:缓存压缩数据
硬件配置如下:
机器数量: 4 台阿里云主机(1 FE,3 BE)CPU:48 核内存:192G网络带宽:21Gbps磁盘:阿里云 ESSD
我们对存算一体和存算分离模式进行了不同缓存下的性能测试。以 TPC-DS 1TB 测试集为例,测试结果如下:
完全命中缓存时,即跑两遍取第二遍的完成时间,第一遍把所有数据均加载进缓存中,存算分离与存算一体模式查询性能完全持平;部分命中缓存时,即测试开始前清空所有缓存,取第一遍的完成时间,测试过程中数据被逐渐加载进缓存中。与存算一体相比,查询性能基本相当,总体性能损耗约 10% ,这一测试场景也与用户实际应用最为接近。完全未命中缓存时,即在每个 SQL 执行前,清理所有缓存。与存算一体相比,性能损耗约 35%。
我们以某企业在线业务为例,对比基于 Doris 存算一体与存算分离模式下的成本差异:
存算一体: 保存于 Doris 中的单副本数据是 100T,三副本后的总数据量是 300T。考虑到避免频繁扩缩容影响业务,磁盘使用率平常保持在 50% 左右。整体的成本如下表所示,每月资源成本支出为 36962.7 美金。
存算分离: 同样的数据规模,使用存算分离模式后,仅需要存储单副本存储在对象存储,热数据在本地磁盘上 cache 一份。如下表所示,每月资源成本支出下降到 22212.65 美金,相较存算一体模式节省了 40% 成本支出。
以 200TB 的历史数据为例,存算一体和存算分离模式下的资源占用如下表。存算一体的资源成本为 48851.1 美金/月,而存算分离的成本仅为 4502.4 美金/月,成本可以降低 90% 以上。
“网易 163 邮箱使用 Apache Doris 替换了原先 Clickhouse、Elasticsearch、Starrocks 等多技术栈。凭借其存算分离架构、湖仓一体、倒排索引能力,支撑了亿级数据实时写入与秒级查询响应,并实现存储成本降低 10 倍、日志检索性能提升 10 倍的成效。” ——— 网易 163 邮箱
“波司登集团基于阿里云数据库 SelectDB 版作为数仓升级方案,借助阿里云 SelectDB 云原生存算分离架构,实现资源隔离、弹性扩缩容,并取得查询性能提升 2-5 倍、总体成本降低 30% 以上、效率提升 30% 的可观收益。” ——— 波司登集团
“阿里云数据库 SelectDB 版作为 MiniMax 日志存储服务的核心支撑,为在线和离线业务提供了高效、稳定的查询与聚合分析能力。其存算分离的弹性架构,以及对实时物化视图、租户资源隔离及冷热分离等企业级特性的支持,不仅有效解决了日志场景下 PB 级别数据查询的性能瓶颈,还通过智能化的资源调度与存储优化,实现了成本与效率的最佳平衡,为业务的高效运转提供了坚实保障。” ——— MiniMax infra 团队
“阿里云数据库 SelectDB 版为新东方多个核心场景提供了强有力的技术支撑。在湖仓一体实践中,它作为 Paimon 的高性能查询分析引擎,为湖上数据提供了强大的加速分析能力,实现 3-5 倍的性能提升。在半结构化数据处理场景中,依托存算分离架构、Variant 类型高压缩率、倒排索引以及 OSS 低成本存储方案,快速实现海量日志的检索分析,与 Elasticsearc 相比,查询分析性能提升 3-倍,存储成本降低 5 倍,极大优化了资源利用率。” ———新东方
“高途教育使用 SelectDB 应用在 BI 报表类高并发低延迟的场景,解决了需要根据数据选择引擎的难题。其存算分离架构和快速扩容的特性,保障了高峰场景数据的秒级产出;多租户的资源隔离方案为成本控制和资源分摊等提供了坚实的基础。期待未来在数据湖和动态扩容方面的进一步建设,加深双方合作。” ———高途教育
以上就是对 Apache Doris 存算分离核心特性及使用方案的完整介绍。存算分离架构的引入,带来更低成本、极致弹性、负载隔离等显著优势。在这一架构的加持下,Doris 凭借其强大的实时数据分析、湖仓融合分析及半结构化数据处理能力,已然成为搭建现代化数据平台的理想选择,能够有效简化当前纷繁复杂的数据分析技术栈。
未来,Apache Doris 将持续增强存算分离模式的功能,包括支持存算分离的快照、时间旅行以及 CCR,提升系统的稳定性和易用性,比如 FE 无状态。为使用者提供更加弹性、高效、稳定、流畅的使用体验。
","description":"导读: 随着云基础设施的成熟,Apache Doris 3.0 正式支持了存算分离全新模式。基于这一架构,能够实现更低成本、极致弹性以及负载隔离。本文将介绍存算分离架构及其优势,并通过导入性能、查询性能、资源成本的测试,直观展现存算分离架构下的性能表现,为读者提供具体场景下的使用参考。 在数据驱动决策的时代,数据规模增长加快、分析需求不断变化。数据从多种渠道(如应用日志、网络交互、移动设备等)源源不断地流入,包含结构化、半结构化、非格式化等多种数据格式,这对数据的存储和分析提出了很高的挑战。与此同时,企业对实时分析、探索性查询的需求激增…","guid":"https://www.infoq.cn/article/zaUGz5EB7W3375ZDBPgm","author":"SelectDB","authorUrl":null,"authorAvatar":null,"publishedAt":"2025-03-18T09:14:10.507Z","media":[{"url":"https://static001.geekbang.org/infoq/30/309734c587eb85c96f3b6a4d4a369a4b.jpeg","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/b9/b9e9398790646181a01122bd3910abfe.jpeg","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/06/06e8d93248ab682b458097eb52acb5e9.jpeg","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/cd/cda789e5b3c31984cbef83967121325a.jpeg","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/81/8156445848f2f86b39c933bca913db2e.jpeg","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/25/2579cb0d51b55ebba300ab9f606cf3e9.jpeg","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/aa/aa50a5181b3cf4a5c5e6e5cf05fea4dd.jpeg","type":"photo","width":0,"height":0,"blurhash":""}],"categories":["数据库"],"attachments":null,"extra":null,"language":null},{"title":"Spring近期新闻:Boot、Security、Auth Server、Integration、AI和AMQP发布里程碑版本","url":"https://www.infoq.cn/article/XDaKmQKcTjRMB1vWwHbH","content":"最近,Spring生态社区活动较为活跃,重点发布了如下产品的里程碑版本:Spring Boot、Spring Security、Spring Authorization Server、Spring Integration、Spring AI和Spring AMQP。
很多版本已经包含在了Spring Boot 3.5.0-M2、3.4.3和3.3.9中。
Spring Boot\\" 3.5.0的第二个里程碑版本\\"提供了缺陷修复、文档改进、依赖关系升级和新功能,比如,通过actuator端点按需触发Quartz job的能力;通过更新PrometheusPushGatewayManager类以支持Prometheus Client\\"。关于此版本的更多详情,请参阅发布说明\\"。
同样,Spring Boot的3.4.3和3.3.9版本也已发布(发布新闻分别参见此处\\"和此处\\"),其中包括缺陷修复、文档改进、依赖关系升级以及在JavaVersion枚举类中添加了TWENTY_FOUR。关于这些版本的更多详细信息,请分别参见3.4.3版本\\"和3.3.9版本\\"的发布说明。
Spring Security\\" 6.5.0的第二个里程碑版本提供了缺陷修复、依赖关系升级和新特性,比如,新的HttpStatusAccessDeniedHandler类可将HTTP状态码设置为响应;新接口GenerateOneTimeTokenRequestResolver和ServerGenerateOneTimeTokenRequestResolver,能够分别解析来自Jakarta Servlet HttpServletRequest和Spring Framework ServerWebExchange接口的GenerateOneTimeTokenRequest类实例的策略。关于此版本的更多详细信息,请参阅发布说明\\"。
同样,Spring Security的6.4.3版本和6.3.7版本也发布了缺陷修复、依赖关系升级和新特性,比如,重构了s101 Gradle任务,现在它依赖于assemble任务而不是check任务,以提高稳定性;在WebAuthnDsl类中添加了disableDefaultRegistrationPage布尔型字段,以禁用默认的WebAuthn注册页面。有关这些版本的更多详细信息,请参见6.4.3\\"版本和6.3.7版本\\"的发布说明。
Spring Authorization Server\\" 1.5.0的首个里程碑式版本\\"进行了依赖关系升级,并支持互联网工程任务组(Internet Engineering Task Force,IETF)的RFC 9449,即OAuth 2.0展示持有证明(OAuth 2.0 Demonstrating Proof of Possession,DPoP)\\",这是一种 “通过应用层上的持有证明机制来限制OAuth 2.0令牌的发送方”的机制。有关此版本的更多详细信息,请参阅发布说明\\"。
同样,Spring Authorization Server的1.4.2和1.3.5版本已发布\\",包含缺陷修复、依赖关系升级和1.4.2版本中的新特性,比如,在许多与OAuth2、OIDC和JWT相关的类中添加了Java的@Override注解;在AuthorizationServerContextFilter类中用首选的fromUriString()方法替换了Spring框架UriComponentsBuilder类中定义的过时的fromHttpUrl()方法。关于这些版本的更多详细信息,请参见1.4.2版本\\"和1.3.5版本\\"的发布说明。
Spring for GraphQL\\" 1.3.4版本发布\\",包含了缺陷修复、文档改进、依赖关系升级和新功能,例如,Spring Framework WebSocketHandler 接口的实现现在可记录未处理的错误;BearerTokenAuthenticationExtractor 类中的授权密钥的查找应区分大小写。关于该版本的更多详细信息,请参阅发布说明\\"。
Spring Session\\"的3.4.2和3.3.6版本发布,其中包括值得关注的依赖关系升级,如Spring Boot 3.3.8、Spring Framework 6.2.3和Project Reactor 2023.0.15。关于这些版本的更多详细信息,请参阅3.4.2版本\\"和3.3.6版本\\"的发布说明。
Spring Integration\\" 6.5.0 的第二个里程碑版本\\"提供了缺陷修复、依赖关系升级和新功能,例如,一旦资源关闭,StreamTransformer类的实例必须从输出消息中移除IntegrationMessageHeaderAccessor类中定义的CLOSEABLE_RESOURCE头信息;Apache Kafka的入站通道适配器现在默认生成Spring Framework MessageHeaders类中定义的ID和TIMESTAMP头信息,以便与Spring Integration其他类似通道适配器保持一致。关于此版本的更多详细信息,请参阅发布说明\\"。
同样,Spring Integration的6.4.2和6.3.8版本发布,其中包括依赖关系升级和一些值得关注的问题的解决,例如,使用DelayerEndpointSpec类中定义的taskScheduler()方法无法指定自定义任务调度器;如果目录路径是符号链接,SftpInboundFileSynchronizer的实例无法同步文件。关于这些版本的更多详细信息,请参阅6.4.2版本\\"和6.3.8版本\\"的发布说明。
Spring AI\\" 1.0.0的第六个里程碑版本\\"聚焦于继续“从设计角度审查代码库”。新特性包括:利用新注解@Tool和@ToolParam以及新类 MethodToolCallback和FunctionToolCallback实现声明式、编程式和函数式定义工具的能力;集成新的模型上下文协议(Model Context Protocol)Java SDK\\";增强\\"了Vector Store API\\"。有关此版本的更多详细信息,包括破坏性变更,请参见升级说明\\"。
Spring AMQP\\" 4.0.0的第一个里程碑版本\\"提供了缺陷修复、文档改进、依赖关系升级和新功能,例如,使用JSpecify\\"和NullAway\\"实现了全面的空安全性迁移;改进了AbstractMessageListenerContainer类,将getMessageAckListener()从protected变为public(与对应的setMessageAckListener()方法保持一致),并增加了一个缺失的getErrorHandler()方法。有关该版本的更多详细信息,请参阅发布说明\\"。
同样,Spring AMQP的3.2.3和3.1.9版本发布,提供了缺陷修复、依赖关系升级以及对上述AbstractMessageListenerContainer类改进的回传。有关这些版本的更多详细信息,请参阅3.2.3版本\\"和3.1.9版本\\"的发布说明。
Spring for Apache Kafka\\"发布3.3.3和3.2.7版本\\",提供了缺陷修复、依赖关系升级以及对MessagingMessageListenerAdapter类的优化,该类在DelegatingInvocableHandler类中定义的invoke()方法中会返回null。关于这些版本的更多详细信息,请参阅3.3.3版本\\"和3.2.7版本\\"的发布说明。
Spring for Apache Pulsar\\"的1.2.3和1.1.9版本已发布\\",分别升级了对Spring Framework 6.2.3和6.1.17、Micrometer 1.14.4和1.13.11、Micrometer Tracing1.4.3和1.3.9以及Project Reactor 2024.0.3和2023.0.15的依赖关系。关于这些版本的更多详细信息,请参阅1.2.3版本\\"和1.1.9版本\\"的发布说明。
原文链接:
Spring News Roundup: Milestone Releases of Boot, Security, Auth Server, Integration, AI and AMQP\\"
","description":"最近,Spring生态社区活动较为活跃,重点发布了如下产品的里程碑版本:Spring Boot、Spring Security、Spring Authorization Server、Spring Integration、Spring AI和Spring AMQP。 \\n\\n很多版本已经包含在了Spring Boot 3.5.0-M2、3.4.3和3.3.9中。\\n\\nSpring Boot\\n\\nSpring Boot\\" 3.5.0的第二个里程碑版本\\"提供了缺陷修复、文档改进、依赖关系升级和新功能,比如,通过actuator端点按需触发Quartz job的能力…","guid":"https://www.infoq.cn/article/XDaKmQKcTjRMB1vWwHbH","author":"Michael Redlich","authorUrl":null,"authorAvatar":null,"publishedAt":"2025-03-17T02:44:58.208Z","media":null,"categories":["编程语言"],"attachments":null,"extra":null,"language":null},{"title":"Java 社区的一次十亿行数据编程挑战","url":"https://www.infoq.cn/article/YPVbb8PFstQmgfViY5Ii","content":"Gunnar Morling 是一位软件工程师和开源爱好者,目前在 Decodable 从事基于 Apache Flink 的流处理工作。之前他在 Redhat 领导了 Debezium 项目。他是 Java Champion,创立了多个开源项目,如 JfrUnit、kcctl 和 MapStruct。Gunnar 曾在 QCon、Java One 和 Devoxx 等各种会议上发表过演讲。本文中,Gunnar Morling 讨论了应对一个包含十亿行数据的文件时,速度最快的解决方案所采用的一些技巧,这些技巧通过并行化和高效的内存访问在不到两秒的时间内就能处理 13 GB 的输入文件。
我想谈谈我之前参加的一个病毒式编程挑战,名为“十亿行挑战”(1 Billion Row Challenge,1BRC)。
我在一家名为 Decodable 的公司担任软件工程师。我们基于 Apache Flink 构建了一个用于流处理的托管平台。这件事对我来说完全是副业,但 Decodable 支持我这样做。
之所以举办这项挑战是因为我想学点新东西。每六个月就会有新的 Java 版本出现,带有新的 API 和新功能。要跟踪所有这些开发成果并非易事。我想知道这些新 Java 版本中有哪些新东西,我能用它们做什么?同时我也想为社区提供一个渠道让大家都能学到新东西。在这个挑战中,你可以从其他人的实现里汲取灵感。另外我还想要纠正一个偏见,那就是很多人认为 Java 很慢。但如果你看看现代版本及其特性,你会发现这完全是错误的。
我们先来深入研究一下挑战的细节。
我们的想法是,有一个包含温度测量值的文件,本质上就像一个 CSV,但它不是以逗号,而是以分号作为分隔符。内容有两列,还有一个车站名称,如汉堡或慕尼黑等。与之关联的温度测量值是随机值。
挑战任务是处理该文件,汇总文件中的值,并为每个站点确定最小值、最大值和平均温度值,很简单。唯一的警告是,正如挑战的名称所示,它有 10 亿行,生成文件的大小约为 13 GB,相当大。然后你必须打印出结果,如上图。
关于规则再多说一点。首先,这主要针对 Java。为什么?因为这是我最了解的平台,我想支持它,想传播关于它的知识。然后,你可以选择任何版本,新版本、预览版本、所有类型的发行版,如 GraalVM,或各种各样的 JDK 提供程序都可以。你可以使用一个名为 SDKMAN 的工具进行管理。这是一个非常好的工具,可以管理很多 Java 版本,并在不同版本之间来回切换。
仅限 Java,没有依赖项。引入一些库为你完成任务没什么意义,你应该自己编程。各次运行之间没有缓存。我对每个实现都运行了五次。然后我丢弃了最快和最慢的那个,并从剩下的三次运行结果中取平均值。可以缓存的话,你只需执行一次任务,将结果保存在文件中,然后将其读回,这样就会非常快。这没有多大意义。你也可以从他人那里获得灵感。
关于我的运行环境:
我的公司花了 100 欧元购买了这台机器,有 32 个内核,其中我主要只使用 8 个内核。有相当多的 RAM。实际上文件总是从 RAM 盘读取。我想确保磁盘 I/O 不至于影响性能,因为它的可预测性要差得多。这里只有一个纯粹的 CPU 绑定问题。
上面是我的基本实现。我使用这个 Java Streams API、这个 files.lines 方法,它为我提供了一个包含文件行的流。我从磁盘读取该文件,然后使用 split 方法将每行映射到那里。我想将站名与值分开。然后我将结果(行)收集到这个分组收集器中。我按站名对其分组。
然后,对于我的每个站,我需要聚合这些值,在我的聚合器实现中处理。每当新值添加到现有聚合器对象时,我都会跟踪最小值和最大值。为了计算平均值,我会跟踪值的总和和计数。非常简单。然后,如果我并行运行这个操作,我需要合并两个聚合器,同样非常简单。最后,如果我完成了,需要减少处理结果,然后通过对象发出这样的结果,其中包含最小值和最大值。对于平均值,我只需将总数除以计数,然后将其打印出来。在这台机器上这大约需要五分钟,不算超级快,但也不是很糟糕。编写这段代码花了我半个小时不到,还不错。如果你在工作中解决这个问题,到这里你可能会收工回家,喝杯咖啡,就完事了。当然,为了这次挑战的目的,我们希望速度更快,看看我们能在这里取得多大的进展。
这项挑战重要的是必须有人来参与。一位来自荷兰的 Java 冠军 Roy Van Rijn 立刻对此产生了兴趣,在我发布帖子后大约一小时,他创建了自己的第一个实现,不是很花哨或很复杂。只要第一个人出现,其他人也会来参与。
我们深入了解一下如何加快这个程序的速度。人们花了整个一月份的时间来研究这个问题,他们探索到了一个非常深的层次,基本上是计算 CPU 指令。
首先我们谈谈并行化,因为我们有很多 CPU 核心。在我用来评估它的服务器上有 32 个核心,64 个线程。我们想利用这一点,只使用一个核心会有点浪费。我们该怎么做呢?回到我简单的基线实现,我能做的第一件事就是添加这个并行调用,也就是 Java Streams API 的这一部分。
现在它将并行处理这个管道,或者说这个流管道的一部分。只需添加这个单一方法调用,就可以将时间缩短到 71 秒,非常轻松的胜利。
如果你仔细想想,是的,它让我们的速度加快了不少,但并没有达到八倍的水平。可我们有 8 个 CPU 核心,为什么它没有八倍的速度?因为这个并行运算符适用于处理逻辑。所有这些聚合和分组逻辑都是并行发生的,但从内存中读取文件仍然是按顺序发生的。读取部分是按顺序进行,其他 CPU 核心依旧处于空闲状态,所以我们也想将其并行化。
新的 Java 版本都带有新的 API、JEP、Java 增强提案。其中之一是最近添加的外部函数和内存 API。
本质上它是一个 Java API,允许你使用原生方法。它比旧的 JNI API 更易用,还允许你使用本机内存。你可以管理自己的内存部分(如堆外内存),而不是由 JVM 管理的堆,并且你将负责维护它、释放它,等等。我们想在这里使用它,因为我们可以内存映射这个文件,然后在那里并行处理它。
首先我们确定并行度。我们的例子中是八个核心,这就是我们的并行度。接下来我们要对这个文件进行内存映射。在早期的 Java 版本中,你也可以使用内存映射文件,但你有大小之类的限制,你无法一次对整个 13 GB 的文件进行内存映射。而现在有了新的外部内存 API,我们就可以做到这一点。你映射文件。我们有这个 Arena 对象。这本质上是我们对这个内存的表示。有不同类型的 Arena,这里我只是使用这个全局 Arena,它可以从我的应用程序中的任何位置访问。现在我可以使用多个线程并行访问整个内存部分。
为了做到这一点,我们需要分割文件和内存表示。首先,我们将其大致分成八个相等的块。我们将整个大小除以八。当然,很有可能我们会分割到某一行的中间,而理想情况下,我们希望我们的工作进程能够处理整行。这里发生的事情是,我们转到了文件的大约八分之一,然后继续转到下一个行结束符。那么这里就是这个块的结尾,也是下一个块的起点。然后我们处理这些块,我们启动线程,然后将它们连接起来。现在我们真正在整个周期内都利用了所有 8 个内核,进行 I/O 时也一样。
有一个警告。从本质上讲,其中一个 CPU 核心总是最慢的。在某个时候,其他七个核心都会等待最后一个核心完成,因为数据的分布有点不均匀。人们最终的做法是不再使用 8 个块,而是将这个文件分成更小的块。本质上,他们积压了这些块。每当其中一个工作线程处理完当前块时,它就会去处理下一个块。通过这种方式,你可以确保所有 8 个线程始终得到平等利用。事实证明,理想的块大小是 2 兆字节。为什么是 2 兆字节?我使用的这台机器上的这个 CPU 有 16 兆字节的二级缓存,8 个线程每次处理 2 兆字节。这个数值在预测 I/O 等方面是最好的。这也表明,我们确实深入到了具体的 CPU 和架构的层面来真正优化该问题。
我们更深入地分析一下。我们已经了解了如何利用多个 CPU 核心,但具体处理每一行时究竟发生了什么?我们仔细看看。
我们想摆脱最初的使用正则表达式等分割文件的做法,那样效率并不高。我能想到的办法是,只需逐个字符地处理这些输入行即可。
这里差不多是一个状态机。我们读取字符,继续读取行,直到没有字符。然后我们使用将站点名称与温度值分隔开的分号字符来切换这些状态。根据我们所处的状态,我们是读取组成站点名称的字节,还是读取组成测量值的字节?我们需要将它们添加到某个构建器或缓冲区中,以聚合这些值。
然后,如果我们在一行的末尾,也就是说我们找到了行结束符,那么我们需要使用建立的这两个缓冲区来记录站点和测量值。对于测量值,我们需要了解如何将其转换为整数值,这也是人们想出的办法。这个问题被描述为双精度或浮点运算,因此值是 21.7 度,但同样,我总是只遇到一个小数位。人们意识到,这个数据实际上总是只有一个小数位。我们可以利用这一点,只需将数字乘以 100 即可将其视为整数问题,作为计算方法。然后在最后,将其除以 100 或 10。这是人们经常做的事情,我低估了他们会在多大程度上利用该数据集的特定特性。
所以我们处理或使用这些值。如果我们看到减号就取反这个值。如果我们看到两位数字中的第一个,就把它乘以 100 或 10。这样做,我们可以把时间缩短到 20 秒,已经比最初的基线实现快了一个数量级。
到目前为止没有什么真正神奇的事情。你也应该得到一个启示,继续做这样的事情有多大意义?如果这是你在日常工作中面临的问题,也许就此打住吧。它可读性好,可维护性好。它比原生基线实现快了一个数量级,所以这相当不错。
当然,为了应对这一挑战,我们可能需要走得更远。我们还能做什么?我们可以再次回到并行的概念,尝试一次处理多个值,现在我们有了不同的并行方法。我们已经看到了如何充分利用所有 CPU 核心。这是并行度的一方面。我们还可以考虑扩展到多个计算节点,这通常是我们对大规模数据存储所做的事情。对于这个问题它并不那么重要,我们必须拆分该文件并将其分发到网络中。也许不是那么理想,但那将是另一个极端。而我们也可以朝另一个方向发展,在特定的 CPU 指令内作并行化。这就是 SIMD(单指令多数据)所做的事情。
基本上所有这些 CPU 都有扩展指令,允许你一次将相同类型的操作应用于多个值。例如,在这里我们想找到行尾字符。现在我们不再逐字节对比,而是可以使用这样的 SIMD 指令将其应用于 8 个或 16 个甚至更多字节,当然这会大大加快速度。问题是,在 Java 中,你没有很好的方法来利用这些 SIMD 指令,因为它是一种可移植的抽象语言,它不允许你降低到这种级别的 CPU 底层上。
好消息是我们可以用上面这个向量 API,它仍在孵化中,在第八个孵化版本左右。这个 API 现在允许你在扩展中使用这些向量化指令。你可以使用这个相等运算符进行类似这样的比较调用,然后它将被转换为底层架构的正确 SIMD 指令,转换为 Intel 或 AMD64 扩展。对于 Arm,它也会这样做。如果你的机器没有任何向量扩展,它将回退到标量执行。这是指令级别的并行化。我对此作了另一次演讲(https://speakerdeck.com/gunnarmorling/to-the-moon-and-beyond-with-java-17-apis\\"),其中向你展示了如何使用 SIMD 解决 FizzBuzz。
这种模式可以一次将相同的操作应用于多个值,此外我们还可以执行所谓的 SWAR,即寄存器内的 SIMD。
这里的想法是,做同样的事情,比如一次处理多个值的相等操作,我们也可以在单个变量中执行此操作。如果你有 8 个字节,我们也可以看到一个 long,那是 64 位,那也是 8 个字节。我们可以将正确级别的位级魔法应用于 long 值,然后将此操作应用于所有 8 个字节。这里会有位级屏蔽和移位等等事情。Richard Startin 有一篇非常好的博客文章,一步一步地向你展示了如何做到这一点,或者如何使用它来查找字符串中的第一个零字节。
我把数学公式放在右边,你会看到,这实际上给了你一个长整型的第一个零字节。这就是寄存器内的 SIMD,SWAR。现在有趣的是,如果你看一下这段代码,会发现这里缺少了一些东西。有人意识到我们这里缺了什么吗?这段代码中没有 if、没有条件、没有分支。这实际上非常重要,因为我们需要记住 CPU 实际上是如何工作的。如果你看看 CPU 如何获取和执行我们的代码,会发现它总是采用这种流水线方法。每条指令都有这个阶段,它将从内存中获取,解码,执行,最后写回结果。现在这些事情中的多个操作是并行发生的。当我们解码一条指令时,CPU 已经去获取下一条指令了。这是一种流水线并行化方法。
当然,CPU 实际上需要知道下一条指令是什么,否则我们就不知道要获取什么。为了让它知道,我们实际上不能有任何 if,因为那样我们就不知道要往哪个方向走。如果你有一种用这种无分支方式表达这个问题的方法(就像我们之前看到的那样),那么这对 CPU 中分支预测器来说非常有益,这样它就总能知道下一条指令是什么。我们从来没有遇到过一种情况,就是实际上需要刷新这个管道,只因为我们在这个预测执行中走了一条错误的路径。
人们经常使用的资源之一是这本书《黑客的喜悦》。如果你对此感兴趣,我建议每个人都去买这本书。比如这个问题,比如在字符串中找到第一个零字节,所有这些算法、例程都在这本书中描述过了。如果这件事让你兴奋,一定要看看这本书买下来。
有一天我醒来,突然间所有这些结果都不一样了。它比以前快了两倍。我运行了前一天运行过的一个实现,突然间速度快了很多。我在想发生了什么事?
其实这个负载最初是在虚拟服务器上跑的。我得到了专用的虚拟 CPU 核心,这样我就不会在那台机器上有任何吵闹的邻居了。我没想到的是他们会直接把这个负载转移到另一台机器上。我不知道为什么会这样。也许原因是随机的。也许他们看到了那台机器上有很多负载。无论如何,它只是被转移到了另一台比以前更快的主机上。这当然对我来说是一个大问题,因为到目前为止我所做的所有对比都是错误的,不再具有可比性。我意识到自己需要一台专用服务器,正如我提到的,我的雇主 Decodable 挺身而出赞助了它。
当然我还需要维护方面的帮助,因为我不是运维方面的专家。例如,你可能想关闭超线程,或者你想关闭核心加速功能以获得稳定的结果。我并不擅长做这些事情,但社区的 René 来帮忙了。他主动提出帮助设置这个东西。有很多这样的人都来帮忙,然后人们实际上构建了一个 TCK,一个测试套件。
它实际上是一个你必须通过的测试套件。你不仅想要快,还想要正确。人们构建了这个测试套件,它实际上随着时间的推移而增长。然后,每当有新的提交、新的条目进来时,它首先必须通过这些测试。然后如果它有效,那么我会去评估它并运行实现。这就是它的样子。
它有带有测量值的示例文件和一个预期文件,然后测试运行器将针对该组文件处理实现,并确保结果正确。另一件事也非常重要,我必须在那台机器上运行所有这些程序。有很多事情与此相关,例如确保机器配置正确。对所有程序我都会运行五次,丢弃最快和最慢的结果。
然我们再谈一件事,也是非常重要的,就是簿记。回到我展示的初始代码,里面有一个 Java Streams 实现,我使用这个收集器将值分组到不同的存储桶中,每个气象站名称都是如此。人们意识到,这里也是可以做大量优化的。凭直觉,你会为此使用 HashMap。你将使用气象站名称作为该 HashMap 中的键。Java HashMap 是一种通用结构,适用于一系列用例。然后,如果我们想为一个特定用例获得最佳性能,那么我们最好自己实现一个定制的数据结构。
这就是我们在这里看到的,它比较简单。这里我们想跟踪每个气象站名称的测量值。它就像一张地图,由一个数组支持。
现在的想法是,我们获取车站名称的哈希键,并将其用作该数组中的索引,在数组中的特定位置,我们将管理特定车站名称的聚合器对象。我们获取哈希码,并希望不会溢出。这就是为什么我们将其与数组大小的逻辑结尾一起获取。我们始终在数组中对其进行良好的索引。然后我们需要检查,在数组中的特定位置是否已经存在某些内容?如果没有,则意味着我们手中有特定车站的第一个实例,因此是汉堡市的第一个值或慕尼黑的第一个值。我们只需在那里创建这个聚合器对象并将其存储在数组中的特定偏移量处。当然另一种情况是,我们转到数组中的特定索引,并且那里很可能已经存在某些内容。如果你有同一车站的另一个值,则那里已经存在某些内容。
问题是我们还不知道,这实际上是我们手中的特定键的聚合器对象,还是其他东西?因为多个站名可能具有相同的键。这意味着,在这种情况下,如果某个东西已经存在于这个特定的数组槽中,则需要回退并对比实际名称。只有当传入的名称也是该槽中聚合对象的名称时,我们才能将值添加到该名称中。这就是为什么它被称为线性探测。否则,我们将继续在该数组中迭代,直到我们找到一个空闲的槽,然后我们可以在那里安装它,或者我们找到了我们手中的键的槽。对于这个案例,它的性能实际上比我们仅使用 Java HashMap 所能获得的性能要好得多。
当然,这在很大程度上取决于我们用来查找该索引的特定哈希函数。这可以追溯到人们真正针对特定数据集进行了大量优化的工作上,他们使用了对特定数据集无冲突的哈希函数。这有点违背我的想法,因为问题在于这个文件,正如我提到的,它的大小为 13 GB,而我没有很好的方法将 13 GB 分发给大家,所以他们必须自己生成它。我有数据生成器,每个人都可以使用这个生成器为自己创建文件,然后将其用于自己的测试目的。问题是在这个数据生成器中,我有一个特定的密钥集。我有大约 400 个不同的车站名称,这只是一个例子,但人们非常字面地理解了它,然后他们针对这 400 个车站名称进行了大量优化。他们对这 400 个名称使用了不会发生任何冲突的哈希函数。人们会利用他们能利用的一切。
所有这些的问题在于它也给我带来了很多工作,因为你无法真正证明没有哈希冲突。实际上,每当有人提交他们的实现时,我都必须去检查他们是否真的处理过这种情况,即两个站会创建相同的密钥,他们是否相应地处理了这些冲突?因为如果你不这样做,就会回到缓慢的时代,你会非常快,但你会不正确,因为你没有正确处理所有可能的名称。这是我为自己设置的一个小陷阱,这意味着我总是必须检查这一点,并在拉取请求模板中询问人们,如果你有一个自定义映射实现,你在哪里处理冲突?
上面提到了三件大事,并行化,然后是使用 SIMD 和 SWAR 处理所有这些解析,以及用于簿记的自定义哈希映射。然后还有更具体的技巧,我会提到其中的几个,想给你一些现成的灵感。
现有的一个工具是 Epsilon 垃圾收集器,这是一个非常有趣的垃圾收集器,因为它不收集任何垃圾。这是一个无操作实现。如果你有常规的 Java 应用程序,它不会是一个好主意。因为你会不断分配对象,如果你不执行任何 GC,就将在某个时候耗尽堆空间。在这个挑战中人们意识到,我们实际上可以以一种在处理循环中不进行任何分配的方式来实现这一点。我们最初在引导程序时会做一些分配,但稍后不会再创建任何对象。我们只有可以重用的数组,就像可变结构一样,我们可以更新它们。
然后我们就不需要任何垃圾收集了,也不需要任何 CPU 周期花在垃圾收集上,这意味着我们可以更快一点。我认为这是一件有趣的事情。另一件事,你可以看到这里人们使用了很多 GraalVM。GraalVM 实际上有两个作用。它是一个提前编译器,因此它会获取你的 Java 程序并从中发出原生二进制文件。这有两个优点。首先它占用更少的内存。其次它启动速度非常快,因为它不必进行类加载和编译等所有操作,这一切都发生在构建时。如果你有这个原生二进制文件,它启动速度很快。
一开始我认为在启动时节省几百毫秒对处理 13 GB 的文件不会有什么影响,但实际上它确实有影响。AOT 编译器和大多数最快的实现实际上都使用了带有 GraalVM 的 AOT 编译器。也可以使用它来替代 JVM 中的即时编译器。你可以将其用作 C2 编译器的替代品。我并不是说你应该总是这样做。这有点取决于你的特定工作量和你做的事情。而这个问题非常适合这样做。人们只需使用 GraalVM 作为 JVM 中的 JIT 编译器,就可以获得大约 5% 的良好改进。我推荐你尝试一下,因为它基本上是免费的。你只需要确保你使用的 JVM 或 Java 发行版有 GraalVM 作为 C2 编译器的替代品。
还有其他一些东西,比如不安全。我发现上图右边的构造很有趣,如果你看一下,这是我们的内部处理循环。我们有一个 scanner 对象。我们尝试获取下一个值,尝试处理它们,等等。这里看到的是,我们在以顺序方式编写的程序中有三次相同的循环。你会说这三个循环是一个接一个地运行。实际发生的情况是,由于 CPU 有多个执行单元,编译器会发现这实际上可以并行化,因为这些循环之间没有数据依赖关系。我们可以采用这些循环并同时运行它们。我发现这很有趣。为什么是三次?因为是经验决定的。想出这个主意的 Thomas 网友尝试了两次、四次,结果发现三次循环是该机器上最快的。在其他机器上可能会有所不同。
那么你一定很好奇,我们最后能跑多快?
这是我一开始的 8 个 CPU 核心的排行榜。当我转移到自己的本地机器时,试图保持相同的速度。利用了这 8 个核心后,我们缩短到了 1.5 秒。我没想到 Java 能跑得这么快,在 1.5 秒内就能处理 13 GB 的输入。我觉得这相当令人印象深刻。
情况会变得更好,因为我有了一台强大的服务器,有 32 个核心和 64 个线程,还有超线程。当然,我想看看我们能跑多快?然后我们缩短到了 300 毫秒。
对我来说这简直令人难以置信,超级令人印象深刻。此外,正如我所提到的,人们在其他语言、其他平台上也做到了这一点,而 Java 确实处于领先地位,所以在其他平台上你不会有太大的优势。
还有另一项评估,因为我提到我有一个包含 400 多个站名的数据生成器,人们通过选择特定的哈希函数等对其进行了大量优化。有些人意识到这实际上不是我的本意。我想看看这一般来说能有多快?于是我们有了另一个排行榜,其中实际上有 10k 个不同的站名。
正如你看到的,它实际上有点慢,因为你真的无法针对该数据集进行那么多优化。此外,这里排名靠前的人也不一样了。
人们为此工作了很长时间,挑战持续了整个 1 月。当人们想出某种技巧时,其他人也会很快将其采纳到自己的实现中。这是一段漫长的旅程。
上面是 Roy Van Rijn 的实现,他保存了非常好的日志,你可以看到他随着时间的推移是如何进步的。如果你往下看,你会看到他开始有点挣扎,因为他做了一些改变,实际上它们比以前慢了。问题是他跑在了他的 Arm MacBook 上,这显然与我运行它的机器有不同的 CPU 和不同的特性。他看到了一些本地改进,但实际上在评估机器上速度更快。你可以在底部看到,他尝试购买一台 Intel MacBook,以便有更好的机会在本地执行某些操作,并且该操作在那台机器上的性能也会更好。我发现 Java 中也发生了这种情况,这真的很令人惊讶。这个层面如此深入,特定的 CPU 甚至它具体是哪一代都会在这里产生影响。
你应该做这些优化工作吗?这要视情况而定。如果你在开发企业应用程序,我知道你大多数时候都在处理数据库 I/O。达到那个级别并试图避免业务代码中的 CPU 周期可能会很浪费时间。而如果你要应对这样的挑战,那么这可能是一件有趣的事情。我建议的是,例如某个实现比我的基线快一个数量级。它仍然非常易读,你在这方面没有任何陷阱。这种优化就很不错,你应该非常清楚你是否想这样做。
或者如果你想加入 GraalVM 团队,也可以尝试一下极限优化。我前几天才知道,在比赛中一位名叫 Mary Kitty 的选手被 Oracle 的 GraalVM 编译器团队聘用了。
这场挑战不仅影响了 Java 社区,还影响了其他生态系统。在 Snowflake 中,他们发起了一项“一万亿行挑战”。
GitHub 存储库中有这个挑战的展示和说明。你可以去那里看看 Rust 和 OCaml 中的所有实现,以及我从未听说过的所有好东西,看看他们以非常友好、有竞争力的方式做了些什么事情。
上面是一些统计数据。
从经验教训来看,如果我想再来一次,我必须在规则方面真正规范化,实现更多自动化,并与社区合作。Java 语言慢吗?我认为我们已经揭穿了这一谎言。明年我会再做一次吗?我们拭目以待。
原文链接:https://www.infoq.com/presentations/1brc/#idp_register/\\"
","description":"Gunnar Morling 是一位软件工程师和开源爱好者,目前在 Decodable 从事基于 Apache Flink 的流处理工作。之前他在 Redhat 领导了 Debezium 项目。他是 Java Champion,创立了多个开源项目,如 JfrUnit、kcctl 和 MapStruct。Gunnar 曾在 QCon、Java One 和 Devoxx 等各种会议上发表过演讲。本文中,Gunnar Morling 讨论了应对一个包含十亿行数据的文件时,速度最快的解决方案所采用的一些技巧…","guid":"https://www.infoq.cn/article/YPVbb8PFstQmgfViY5Ii","author":"Gunnar Morling","authorUrl":null,"authorAvatar":null,"publishedAt":"2025-03-13T10:43:34.473Z","media":[{"url":"https://static001.geekbang.org/infoq/6f/6fc2f2d008279a4152e1f7c9498fb728.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/5d/5d9199fb8aa59235960691fd12d71e3d.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/5d/5d911b52c466705c0b1cdbb9c137b857.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/cd/cd51bdcd1b03bf517241e65646736ea3.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/ab/ab728d538a4a44dd18541ae8bb7925db.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/40/40632481b4740b08d557615bc82a39a5.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/bc/bc30b0f25d2a365348c636696468b5d9.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/2d/2d38ab004a445adecc1274d19e7161be.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/a4/a40bf894a92c8326cf832ba7430e6410.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/17/175ca23b95a7c69a929c5b6cb064ee66.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/1c/1c53987edb5989cfd5a0c5042cc78665.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/a5/a5eb78c457736e194501321629acaa96.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/64/64c74112f6462573187e464027fcb7fa.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/44/449a8c6c7578139c3c168ea513c11c72.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/5f/5fdb8605b1fa232327f40dca5b65605e.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/a9/a9e394031df4798e8ad7fed441524241.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/5c/5cd5397a98239c4271c889d4b5492249.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/aa/aaa1d49ac4e09835bb02ed341686223a.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/f0/f028cadc5d2de894cd33fb01cf5192ff.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/d7/d7cc69a8d11c403e4df2af3042c5ebf1.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/31/31079d3c7fd11dc74b69c9dd0aa99f5d.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/f8/f8eebebc9209321ed869dff18b3dd4dc.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/8c/8c539f5987b93c77eec022ac9b914b13.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/d7/d7eef1b212b549389471ec492b5a88b7.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/07/074e28ba197baf4cb532cf69102e773f.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/1c/1c4404b579c1692f277acfcca53c4be4.png","type":"photo","width":0,"height":0,"blurhash":""}],"categories":["编程语言"],"attachments":null,"extra":null,"language":null},{"title":"GitHub Copilot两期连看:开发流程全览及 Copilot 在 SQL 开发中的妙用","url":"https://www.infoq.cn/article/Ji8lek7OYX4aX9sMrZDs","content":"GitHub Copilot,这款备受瞩目的 AI 开发助手,正以前所未有的姿态重塑开发流程。而现在,专为开发者和技术团队精心打造的 GitHub Copilot Fridays 系列课程,正持续为大家解锁 Copilot 的无限潜能。今天,我们迎来了第五期和第六期课程,这将是两场不容错过的技术盛宴,深度探索Copilot 在更多复杂场景、特定角色工作流中的卓越应用,准备好与我们一同深入挖掘其中的奥秘了吗?
本期课程将为您介绍:从GitHub 项目开始,开发人员可以在其中组织和跟踪他们的工作;然后,开发人员继续处理 GitHub Issues,高效管理任务、错误和功能请求;接下来,将展示 GitHubCodespaces,这是一个基于云的开发环境,允许开发人员无需任何设置即可立即开始编码。开发人员可以利用GitHub Copilot来获取代码建议和完整功能,还可以使用 Copilot Chat 以对话方式与 Copilot 进行交互,以获取编码帮助。
课程将重点介绍创建和审查Pull 请求的过程,这是协作开发的重要组成部分。它使用 GitHub Actions 深入研究 CI/CD,实现工作流程自动化并确保持续集成和交付。开发人员还可以利用 GitHub 高级安全功能,包括用于依赖项更新的Dependabot、用于识别漏洞的代码扫描、用于防止敏感数据泄露的秘密扫描以及用于全面安全状态的安全概述。
点击此处\\",观看课程,掌握迅速上手新项目的秘笈。
本次课程将为您全面概述如何在SQL 数据库开发人员的日常工作环境中,以及在以 SQL 脚本、存储过程或内部函数的形式开发的 ETL 集成中,充分利用 GitHub Copilot 这一强大工具。
通过本课程的学习,您将深入了解GitHub Copilot 如何与 SQL 开发紧密结合,它能够如何帮助您更快速、准确地编写 SQL 代码,减少错误并提高代码质量。您将学会如何借助 Copilot 的智能提示和自动完成功能,加速 SQL 脚本的编写过程,无论是复杂的查询语句还是存储过程的开发。
点击此处\\",观看课程,探索GitHub Copilot 在 SQL 数据库开发中的无限潜力。
在接下来的时间里,GitHub Copilot Fridays还将为您带来一系列精彩纷呈的主题:
完美组合:GitHub Copilot与GitHub Actions
深度解析Copilot与GitHub Actions的协作,推动开发自动化。
从热点到生产力:Copilot的关键指标(第1部分)
探讨如何通过数据衡量Copilot的实际生产力提升效果。
这不仅是学习新知识的旅程,更是为您的开发工作注入高效动力的关键一步。立即锁定我们的系列视频,跟随专家的脚步,将GitHub Copilot 的优势融入到您的日常开发流程中,开启属于您的高效开发新篇章。
","description":"GitHub Copilot,这款备受瞩目的 AI 开发助手,正以前所未有的姿态重塑开发流程。而现在,专为开发者和技术团队精心打造的 GitHub Copilot Fridays 系列课程,正持续为大家解锁 Copilot 的无限潜能。今天,我们迎来了第五期和第六期课程,这将是两场不容错过的技术盛宴,深度探索Copilot 在更多复杂场景、特定角色工作流中的卓越应用,准备好与我们一同深入挖掘其中的奥秘了吗? \\n\\n \\n\\n第五期课程:通过GitHub Copilot加速开发者入职\\n\\n本期课程将为您介绍:从GitHub 项目开始,开发人员可以在其中组织和跟踪他们的工作…","guid":"https://www.infoq.cn/article/Ji8lek7OYX4aX9sMrZDs","author":"微软中国MSDN","authorUrl":null,"authorAvatar":null,"publishedAt":"2025-03-13T09:44:44.511Z","media":null,"categories":["微软","AI&大模型","数据库"],"attachments":null,"extra":null,"language":null},{"title":"Go 1.24 带来泛型类型别名、弱指针,并改进了终结器","url":"https://www.infoq.cn/article/yGilcS0ZvVBl9ZSpqB59","content":"Go 语言在最新版本 1.24 中引入了几个重要的特性,包括泛型类型别名、弱指针,并改进了终结器等。它还增强了 map 默认实现、小对象分配以及互斥锁处理的运行时性能。
Go 语言的类型别名为现有类型提供了一个同义词,这非常有助于提高可读性和简洁性。现在,Go 1.24 允许为泛型类型创建类型别名。也就是说,类型别名可以指定一个类型参数。
type ComparableVector[T comparable] = Vector[T]\\ntype ComparableVectorOfInts = ComparableVector[int]\\ntype ThisWouldBeAnError = ComparableVector[[]int]
这里有必要回顾一下,Go 提供了一种类似的语法,用于在现有类型的基础上定义新类型,例如 type NewInt int。尽管语法的差别只是少了=,但由于 NewInt 不能代替 int,所以影响还是很大的。
有趣的是,对于是否引入泛型类型别名及其对语言的影响,有关讨论已经持续了三年多。
弱指针不会增加对象的引用计数。当一个对象只被弱指针引用时,垃圾回收器就可以释放它。因此,在尝试使用弱指针的值之前,应检查它是否为 nil:
var strongInt int = 5\\nvar weakInt *int\\nweakInt = &strongInt\\n...\\nweakInt.Value()
在实现对象缓存等功能时,弱指针可能很有用,因为它可以避免对象仅仅因为包含在缓存中而被保留下来。
Go 终结器的作用是在对象被垃圾回收时进行清理。在 Go 1.24 之前,这项工作可以使用 [runtime.SetFinalizer](https://tip.golang.org/pkg/runtime#SetFinalizer)来完成,但有几个需要注意的事项,包括:无法在同一个对象上定义多个终结器;终结器对涉及引用循环的对象不起作用,等等。为了克服这些限制,Go 1.24 提供了一个新的运行时函数 AddCleanup,用于为对象注册清理函数:
runtime.AddCleanup(objPointer, cleanupFunc, resourceToCleanUp)\\n...\\nfunc cleanupFunc(resourceToCleanUp CleanUpArgType) {\\n ...\\n}
该清理机制解决了上述终结器问题。此外,它还能确保所有的清理函数都在单独的 goroutine 中顺序调用。
如前所述,Go 1.24 改进了 map 的运行时性能。特别是,它采用 SwissTable 作为实现 map的基础,并使用并发 hash-trie 来实现 sync.Map。
使用 SwissTable,大型 map 的访问和分配速度提高了 30%,预设大小 map 的分配速度提高了 35%,迭代速度提高了 10% 到 60%,具体取决于 map 中数据项的多少和大小。
同样,采用并发 hash-trie 后,在几乎所有基准测试中,新的 sync.Map 实现都击败了旧实现。
Go 1.24 包含的改进和更改远不止这些,其中还包括:字节包和字符串包中新增的函数、ommitzero json 标签、目录受限的文件系统访问等。虽然发布说明一如既往地简洁,但你可以观看 Reddit 用户 GreenTowel3732 发布在 YouTube 上的精彩视频概述。
原文链接:
https://www.infoq.com/news/2025/02/go-1-24-generic-aliases/\\"
","description":"Go 语言在最新版本 1.24 中引入了几个重要的特性,包括泛型类型别名、弱指针,并改进了终结器等。它还增强了 map 默认实现、小对象分配以及互斥锁处理的运行时性能。 Go 语言的类型别名为现有类型提供了一个同义词,这非常有助于提高可读性和简洁性。现在,Go 1.24 允许为泛型类型创建类型别名。也就是说,类型别名可以指定一个类型参数。\\n\\ntype ComparableVector[T comparable] = Vector[T] type ComparableVectorOfInts = ComparableVector[int] type…","guid":"https://www.infoq.cn/article/yGilcS0ZvVBl9ZSpqB59","author":"作者:Sergio De Simone","authorUrl":null,"authorAvatar":null,"publishedAt":"2025-03-12T03:49:43.175Z","media":null,"categories":["编程语言"],"attachments":null,"extra":null,"language":null},{"title":"Java近期新闻:JDK 24 RC1、JDK Mission Control、Spring、Hibernate、Vert.x、JHipster、Gradle","url":"https://www.infoq.cn/article/sYbvJRpEIL7fgwh7dzbN","content":"JDK Mission Control 9.1.0\\" 发布,包含了错误修复和改进,例如:在 JFR Writer API 中使用自定义 JFR 事件类型(即扩展 Java Event\\" 类)并注册这些类型的能力;在转换器中使用原始类型的能力。更多关于此版本的详细信息可以在问题列表\\"中找到。
JDK 24 早期访问构建\\"的当前版本仍然是 Build 36\\"。更多详细信息可以在发布说明\\"中找到。
根据 JDK 24 的 发布计划\\",Oracle Java 平台团队首席架构师 Mark Reinhold\\" 正式宣布\\" JDK 24 进入第一个发布候选\\"阶段,因为 Build 36 中没有未解决的 P1 级错误。预计的普遍可用性(GA)发布时间为 2025 年 3 月 18 日,将包含 24 个最终确定的功能。更多关于这些功能的详细信息以及 JDK 25 的预测可以在 InfoQ 的新闻报道\\"中找到。
JDK 25 早期访问构建版本\\"的 Build 10\\" 也已发布,包含从 Build 9 以来的更新\\",修复了各种问题\\"。更多关于此版本的详细信息可以在发布说明\\"中找到。
对于 JDK 24\\" 和 JDK 25\\",开发者可以通过 Java Bug 数据库\\"报告错误。
Spring Framework\\" 7.0.0 的第二个里程碑版本\\"发布,包含一些新功能,例如:改进 AnnotatedMethod\\" 类中定义的 equals() 方法和 HandlerMethod\\",解决跨域资源共享(CORS)配置查找失败的问题;改进 GenericApplicationContext\\" 类,通过 JSpecify 的 @Nullable\\" 注解为 registerBean() 方法的 constructorArgs 参数添加了空值支持。更多关于此版本的详细信息可以在发布说明\\"中找到。
类似的,Spring Framework 6.2.3 和 6.1.17 也已发布,包含新功能,例如:改进了 MVC XML 配置,解决了使用 AntPathMatcher\\" 类的处理器映射问题,改为使用 PathPatternParser\\" 类;改进 ProblemDetails\\" 类,实现 Java Serializable\\" 接口,以便在分布式环境中使用。这些版本将分别包含在即将到来的 Spring Boot 3.4.3(和 3.5.0-M2)以及 3.3.9 的发布中。更多关于此版本的详细信息可以在 6.2.3 版本的发布说明\\" 和 6.1.17 版本的发布说明\\" 中找到。
Spring Data\\" 2025.0.0 的第一个里程碑版本\\"发布,包含新功能,例如:通过 MongoDB Atlas\\" 和 Cassandra Vector Search\\" 为 MongoDB 和 Cassandra 提供向量搜索支持;增加新的 Vector 数据类型,允许在领域模型中抽象底层值,简化声明、可移植性和默认存储选项。更多关于此版本的详细信息可以在发布说明\\"中找到。
类似的,Spring Data 2024.1.3 和 2024.0.9(均为服务版本\\")也已发布,包含错误修复、依赖项升级和对子项目的依赖项升级,例如:Spring Data Commons 3.4.3 和 3.3.9;Spring Data MongoDB 4.4.3 和 4.3.9;Spring Data Elasticsearch 5.4.3 和 5.3.9;以及 Spring Data Neo4j 7.4.3 和 7.3.9。这些版本将分别包含在即将到来的 Spring Boot 3.4.3 和 3.3.9 中。
Spring Tools\\" 4.28.1 发布\\",变化包括:为 Windows 提供经过正确签名的 Eclipse 基金会发行版;解决在 Windows 11 上打开 Spring Tool Suite 可执行文件时出现的未知发布者错误。更多关于此版本的详细信息可以在发布说明\\"中找到。
IBM 发布 Open Liberty 25.0.0.2-beta\\",支持配置 MicroProfile Telemetry 2.0(mpTelemetry-2.0),将 Liberty 审计日志发送到 OpenTelemetry 收集器。这样,审计日志就可以与 Liberty 的其他日志源一起使用相同的解决方案进行管理。
Micronaut 基金会发布 Micronaut Framework 4.7.6\\",包含 Micronaut Core 4.7.14\\"、错误修复以及对 Micronaut Oracle Cloud\\" 模块的补丁更新。此版本还升级了 Netty 4.1.118\\",这是一个修复了CVE-2025-24970\\" 的补丁版本,该漏洞影响 Netty 4.1.91.Final 至 4.1.117.Final 版本,当通过 SslHandler\\" 类实例接收特别构造的数据包时,会发生崩溃。更多关于此版本的详细信息可以在发布说明\\"中找到。
Hibernate ORM\\" 7.0.0 的第四个 Beta 版本\\"发布,包含以下功能:迁移到 Jakarta Persistence 3.2\\" 规范(这是针对 Jakarta EE 11 的最新版本);以 JDK 17 为基线;改进领域模型验证;从 Hibernate Commons Annotations\\"(HCANN)迁移到新的 Hibernate Models\\" 项目,用于处理应用程序底层领域模型。更多关于此版本的详细信息可以在发布说明\\"和迁移指南\\"中找到。
Hibernate Reactive\\" 2.4.5.Final 发布\\",与 Hibernate ORM 6.6.7.Final 兼容,并解决了以下问题:在 Hibernate Reactive with Panache 中,通过 Session\\" 接口的 persist() 方法创建具有双向一对一关系的新对象时抛出 Hibernate ORM PropertyAccessException\\";ReactiveUpdateRowsCoordinatorOneToMany\\" 类的 doReactiveUpdate() 方法忽略了 deleteRows() 方法的返回值。更多关于此版本的详细信息可以在发布说明\\"中找到。
Eclipse Vert.x\\" 5.0 的第五个候选版本\\"发布,包含了一些显著的变化,例如:移除已废弃的类——ServiceAuthInterceptor 和 ProxyHelper,以及在 ServiceBinder 类中定义的两个重载的 addInterceptor() 方法;支持 Java 平台模块系统(JPMS)。更多关于此版本的详细信息可以在发布说明\\"以及弃用和重大变更清单\\"中找到。
Micrometer Metrics\\" 1.15.0 的第二个里程碑版本发布,包含了错误修复、文档改进、依赖项升级和新功能,例如:移除对 OkHttp\\" 客户端工具中 HTTP 状态码 404(Not Found\\")和 301(Moved Permanently\\")的特殊处理;弃用 SignalFxMeterRegistry\\" 类(步进计数器),推荐使用 OtlpMeterRegistry\\" 类(推送计数器)。更多关于此版本的详细信息可以在发布说明\\"中找到。
Micrometer Tracing\\" 1.5.0 的第二个里程碑版本发布,包含了依赖项升级,并弃用 ArrayListSpanProcessor\\" 类,推荐使用 Open Telemetry 的 InMemorySpanExporter\\" 类。更多关于此版本的详细信息可以在发布说明\\"中找到。
Piranha\\" 25.2.0 发布\\",包含了许多依赖项升级、文档改进和一些显著的变化,例如:移除 GlassFish 7.x 和 Tomcat 10.x 的兼容性扩展;在 FileUploadExtension\\"、FileUploadMultiPart\\"、FileUploadMultiPartInitializer\\" 和 FileUploadMultiPartManager\\" 类中增加文件上传大小设置功能。更多关于此版本的详细信息可以在发布说明\\"、文档\\"和问题追踪器\\"中找到。
Project Reactor\\" 2024.0.3 发布\\",这是第三个维护版本,包含了以下依赖项升级:reactor-core 3.7.3、reactor-netty 1.2.3 和 reactor-pool 1.1.2。此外,reactor-addons 3.5.2、reactor-kotlin-extensions 1.2.3 和 reactor-kafka 1.3.23 的版本保持不变。更多关于此版本的详细信息可以在变更日志\\"中找到。
类似的,Project Reactor 2023.0.15 发布,这是第十五个维护版本\\",包含了以下依赖项升级:reactor-core 3.6.14、reactor-netty 1.1.27 和 reactor-pool 1.0.10。此外,reactor-addons 3.5.2、reactor-kotlin-extensions 1.2.3 和 reactor-kafka 1.3.23 的版本保持不变。更多关于此版本的详细信息可以在变更日志\\"中找到。
JHipster\\" 8.9.0 发布\\",包含以下功能:依赖项升级到 Spring Boot 3.4.2、Node 22.13.1、Gradle 8.12.1、Angular 19.0.6 和 Typescript 5.7.3;对 JHipster 领域语言\\"(JDL)中纯时间字段(Java LocalTime\\" 类)的支持,该字段不再与日期绑定。更多关于此版本的详细信息可以在发布说明\\"中找到。
Gradle 8.13.0 的第一个候选版本\\"发布,引入了一个新的自动配置\\"工具,该工具可以自动下载 Gradle 守护进程\\" 所需的 JVM。其他显著改进包括:为 Scala 插件\\"提供显式的 Scala 版本配置,可以自动解析所需的 Scala 工具链依赖项;在 JUnit XML 测试事件时间戳中改进了毫秒级精度。更多关于此版本的详细信息可以在发布说明\\"中找到。
原文链接:
https://www.infoq.com/news/2025/02/java-news-roundup-feb10-2025/\\"
","description":"OpenJDK JDK Mission Control 9.1.0\\" 发布,包含了错误修复和改进,例如:在 JFR Writer API 中使用自定义 JFR 事件类型(即扩展 Java Event\\" 类)并注册这些类型的能力;在转换器中使用原始类型的能力。更多关于此版本的详细信息可以在问题列表\\"中找到。\\n\\nJDK 24\\n\\nJDK 24 早期访问构建\\"的当前版本仍然是 Build 36\\"。更多详细信息可以在发布说明\\"中找到。\\n\\n根据 JDK 24 的 发布计划\\",Oracle Java 平台团队首席架构师 Mark Reinhold\\" 正式宣布\\" JDK 24…","guid":"https://www.infoq.cn/article/sYbvJRpEIL7fgwh7dzbN","author":"Michael Redlich","authorUrl":null,"authorAvatar":null,"publishedAt":"2025-03-10T08:11:15.099Z","media":null,"categories":["编程语言"],"attachments":null,"extra":null,"language":null},{"title":"MongoDB 的开源替代方案 FerretDB 发布 2.0 版本","url":"https://www.infoq.cn/article/lxS9XOU83JfAk7ur8kch","content":"近日 FerretDB 宣布推出 2.0 版本的首个候选发布版。FerretDB 由新近发布的 DocumentDB 驱动,作为 MongoDB 的开源替代方案,它带来了显著的性能提升、更强的功能兼容性、向量搜索能力以及复制支持。
正如 InfoQ 此前报道,FerretDB 最初在三年前以 MangoDB 的名称推出,并于去年正式发布。FerretDB 的联合创始人兼首席执行官 Peter Farkas 写道:
“FerretDB 2.0 在性能和兼容性方面实现了巨大飞跃。由于底层的改进,FerretDB 在处理某些工作负载时速度提升了 20 倍,性能与市场上的领先竞品相当。之前版本中可能遇到兼容性问题的用户会惊喜地发现,FerretDB 现在支持更广泛的应用程序,能让更多应用无缝运行。”
FerretDB 基于 Apache 2.0 许可发布,通常与 MongoDB 的驱动程序和工具兼容。对于许多倾向于避开 SSPL 许可(一种 copyleft 开源软件许可)的开源项目和早期商业项目而言,它被设计为 MongoDB 5.0 及以上版本的直接替代品。
FerretDB 2.x 利用了微软的 DocumentDB PostgreSQL 扩展。这个基于 MIT 许可的开源扩展为 PostgreSQL 引入了 BSON 数据类型及相关操作。该解决方案包含两个 PostgreSQL 扩展:用于 BSON 优化的 pg_documentdb_core 和用于数据操作的 pg_documentdb_api。
FerretDB 团队表示,保持 DocumentDB 与 FerretDB 之间的兼容性,能让用户在 Postgres 上运行文档数据库工作负载时获得更好的性能,并且对现有应用程序有更好的支持。Azure 的首席产品经理 Abinav Rameesh 在描述基于 vCore 的 Azure Cosmos DB for MongoDB 背后的引擎时解释道:
“寻找即用型 NoSQL 数据库的用户可以借助 FerretDB 中的现有解决方案……用户可以通过 Postgres 与 DocumentDB 进行交互,而 FerretDB 2.0 则提供了符合文档数据库协议的接口。”
Farkas 在领英(LinkedIn)上评论补充道:
“随着微软开源 DocumentDB,我们比以往任何时候都更接近,能真正在行业内开展协作共同创建文档数据库的开放标准。”
在另一篇文章中,Farkas 解释了为什么他认为文档数据库除了做到 “与 MongoDB 兼容” 之外,还需要标准化。FerretDB 列出了与 MongoDB 的 已知差异,并指出虽然它使用相同的协议错误名称和代码,但在某些情况下,确切的错误消息可能有所不同。尽管与 DocumentDB 集成提升了性能,但与 FerretDB 1.0 相比,这代表了重大转变并引入了回归限制。Farkas 写道:
“随着 FerretDB 2.0 的发布,我们现在专注于利用 DocumentDB 支持 PostgreSQL 数据库(……)不过,对于那些依赖早期版本和后端的用户,FerretDB 1.x 版本仍可在我们的 GitHub 仓库中获取,我们鼓励社区继续为其开发作出贡献,或者自行进行分支和扩展。”
作为 FerretDB 2.0 发布的一部分,FerretDB Cloud 正在开发中。这个托管数据库即服务选项最初将在 AWS 和 GCP 上提供,后续还计划支持微软 Azure。FerretDB 项目的高级路线图可在 GitHub 上查看 。
Renato Losio,Renato 作为云架构师、技术主管和云服务专家,拥有丰富的经验。目前,他居住在柏林,担任首席云架构师开展远程工作。他主要感兴趣的领域包括云服务和关系型数据库。他是 InfoQ 的编辑,也是经过认证的 AWS Data Hero。
原文链接:
https://www.infoq.com/news/2025/02/ferretdb-documentdb/\\"
","description":"近日 FerretDB 宣布推出 2.0 版本的首个候选发布版。FerretDB 由新近发布的 DocumentDB 驱动,作为 MongoDB 的开源替代方案,它带来了显著的性能提升、更强的功能兼容性、向量搜索能力以及复制支持。 正如 InfoQ 此前报道,FerretDB 最初在三年前以 MangoDB 的名称推出,并于去年正式发布。FerretDB 的联合创始人兼首席执行官 Peter Farkas 写道:\\n\\n“FerretDB 2.0 在性能和兼容性方面实现了巨大飞跃。由于底层的改进,FerretDB 在处理某些工作负载时速度提升了 20 倍…","guid":"https://www.infoq.cn/article/lxS9XOU83JfAk7ur8kch","author":"作者:Renato Losio","authorUrl":null,"authorAvatar":null,"publishedAt":"2025-03-06T03:00:00.957Z","media":null,"categories":["数据库"],"attachments":null,"extra":null,"language":null},{"title":"Curl 之父:我是如何枕着18万行C代码还能安稳入睡的","url":"https://www.infoq.cn/article/GhrCANJrVBOLv7pVJIoI","content":"Curl 作为一个安装量超过 200 亿次的开源项目,承载着极高的安全性和稳定性要求。其作者 Daniel Stenberg 通过严格的代码规范、工具化的错误预防、海量的测试体系,以及高效的漏洞修复流程,确保项目的可靠性。面对“是否用 Rust 重写 Curl”的讨论,他明确表示,Curl 不会被重写,而是通过持续迭代和精细打磨来提升安全性。项目团队不仅采用多层次的测试方法,还通过安全审计、漏洞赏金计划等手段,不断优化代码质量。这种对细节的极致追求,为开源软件的长期维护和安全保障提供了宝贵的经验。
在本年度的 FOSDEM 开源大会上,Curl 作者 Daniel Stenberg 分享了“如何在你的 C 语言代码安装量达到 200 亿次时依然能睡得安稳”的秘诀。
Stenberg 认为,全球的 Curl 安装量达到 200 亿次可能还只是一个保守的估计。
这个数字无疑让这个由他独立开发的开源数据传输工具项目承担起了“一点点”责任。
“当然,我们用的是最安全的编程语言。”他说道,这引得观众们一阵笑声——因为 Curl 是用 C 语言编写的。
他的演讲既有趣又干货满满,令人信心倍增。
它还提供了一个鼓舞人心的例子,展示了当一个项目专注于更高层次的安全性时会发生什么,以及这种承诺如何转化为实际行动——尤其是在风险异常高的情况下。
在演讲的最后,Stenberg 展示了一张有趣的幻灯片,模仿 O\'Reilly 出版社的书皮,书名是《用 Rust 重写 Curl,一个副业项目》(书皮上方还加了一句标语:“与其亲自动手,不如告诉别人怎么做”)。
“这本书非常受欢迎。”Stenberg 说道,并尖锐地指出,“但没有人真正实现过。”
Curl 包含 18 万行 C 语言代码,相当于《战争与和平》这部小说长度的 1.14 倍。Stenberg 说:“对于它的功能来说,这些代码算相当多了……它只是一个用来传输数据的工具。我们不会用 Rust 重写 Curl,也不会用任何其他语言——我们不会重写它。它已经在那里了。”Stenberg 承认 Rust “可能是一种很棒的语言”,并表示第三方依赖项可以用 Rust 编写,他预测未来在 Curl 项目中会有更多这样的情况。
但目前 Curl 的代码库仍然用 C 语言编写,“我们只是耐心地迭代和打磨,随着时间的推移不断完善。不会有任何重写。”
因此,他在演讲中展示的其实是他在保持 Curl 安全性方面所做的工作。
虽然他们用 C 语言编写代码,但 Stenberg 表示,他们已经禁止使用“一些容易出错的函数”。
在演讲结束时,有人要求举例,Stenberg 首先提到了 gets()(Stack Overflow 上有评论者称其为“制造缓冲区溢出的恶魔工具”),还有 scanf()、strcopy() 和 sprintf()。
“不管你经验有多丰富——C 标准库中的一些函数真的不建议在代码中使用。我们用工具检查并禁止使用它们,这样就不会不小心让它们混进去了。”
他们还有一种特殊的“折磨测试”,在调试构建过程中,每个可能发生内存分配失败的函数(如 malloc 或 calloc)都有一个包装器,让他们可以反复调用这些函数——一直调用直到失败。Stenberg 解释说:“它们应该是优雅地失败——没有内存泄漏,没有崩溃,只以错误码的形式退出。这是测试退出路径的绝佳方式,确保我们在退出时总是释放和清理了资源。”
开发团队并不会测试所有东西。他笑着说:“这可不是一个快速的过程。”因此,他们设计了一个系统,随机测试一个较小的子集。他们还使用了持续集成,每一个拉取请求和代码提交都会运行 40 多万个测试。“我记得大概一年前运行这些测试需要花费数小时,”他回忆道,但在对测试进行了优化之后,现在只需要 30 分钟。“快速运行测试让我们能够立即了解代码变更的最新状态。”
你可能听说过“ CPU 秒”这个词,即全功率使用服务器级 CPU 一秒钟—— 86400 个 CPU 秒加起来就是一整天的 CPU 时间。Stenberg 表示,目前“我们每天在 CI 上平均花费大约 10 个 CPU 天。”
为了确保整个项目的安全性,Stenberg 还提到了其他各种各样的测试——甚至有一个是测试“代码风格是否正确,以及代码中的缩进和拼写是否准确”。他们还有一个 CI 任务,用于确保代码中没有任何二进制代码块。
还有单元测试、库测试、工具测试,“当然,我们还有一直在检查代码的分析器”——包括静态和动态分析器。Curl 还是谷歌 OSS-Fuzz 项目的一部分。
“我们希望确保这 200 亿次安装都能正常运行。”
谈到漏洞时,Stenberg 表示:“我们会尽快修复漏洞,按规定通知发行版,并非常详细地记录所有信息,包括以 JSON 格式列出受影响的 Curl 版本。”这些信息也会发布在 Curl 的官方网站上。Curl 项目现在也是一个官方的 CVE 编号机构,“这样我们可以更好地管理我们自己的 CVE。”
他们非常重视发现漏洞,Stenberg 补充说:“我们进行了多次审计。”
Stenberg 回忆说,他们在 2016 年的第一次审计“发现了 7 个 CVE”,2022 年的审计又发现了 2 个 CVE。但他自豪地表示,2024 年的一次更严格的审计结果是 0 个 CVE——这是一个令人振奋的趋势。审计是一项艰巨的任务。“有人会花大量工时来查看代码……对于一个小型开源项目来说,这不是一件容易做好的事情。你需要有足够的资金支持,才能让这一切成为可能。”
他指出,审计的成本“比我们多年的漏洞赏金计划的总成本还要高”——尽管漏洞赏金计划最终发现了更多的 CVE。
这个漏洞赏金计划与 HackerOne 和互联网漏洞赏金计划(Internet Bug Bounty Program)合作开展。Stenberg 表示,自 2019 年 4 月启动计划的六年来,他们已经支付了超过 85000 美元。在 500 份漏洞报告中,有 76% 导致了 CVE(有 19% 是非 CVE 级别的漏洞)。“其他的报告并不都是无效的,”Stenberg 说,“但也确实有不少……我们会公开所有报告的后续讨论,方便大家跟进……”
尽管“漏洞赏金”幻灯片上的最后一项只是提到“AI 垃圾报告越来越多”。
“实际上,目前我们收到的有效报告和‘AI 垃圾报告’的比例差不多,”Stenberg 表示——大约有 10% 到 15% !
该项目致力于实现最高级别的安全性,这种承诺似乎渗透到了每一个层面。
所有提交的代码都经过仔细评审——既有人工评审,也有机器评审。Stenberg 说:“现在我们有一个非常严格的代码风格”,这让整个 18 万行的代码库看起来像是由一个作者编写的(这种一致性使得代码更容易阅读和调试)。
“我们有大量的文档,涵盖了源代码、内部 API 和所有相关内容。”后来 Stenberg 解释说,甚至还有文档检查工具,不仅限于检查拼写和语法。“例如,我们会尽量避免在文档中使用英语缩写,像“isn\'t”这样的表达是不被允许的……诸如此类……”
该项目的开发团队在访问托管在 GitHub 上的源代码时都使用双因子认证……
GitHub 为他们提供了额外的测试资源,导致在 Mastodon 上引发了一些有趣的讨论,例如,其他开源项目是否也应该从一开始就采用最严格的安全措施。
“我认为大多数开源项目都是从‘小’和‘简单’起步的,”Stenberg 回应说,并补充道,“从一开始就做到尽善尽美,确保一切严格无误,甚至是在还不确定项目是否能成功之前,可能并不明智。我认为很少有项目能做到……我们开始时几乎每个环节都很松散……”
在后续的讨论中,Curl 开发者 Stefan Eissing 开玩笑说,有时候感觉风险巨大。“我们有一些开源项目,‘感觉如果搞砸了,几个星球的文明就会终结’。这可不是文明该有的运作方式。”
Stenberg 对 GitHub 给予他们的帮助心存感激,也许他希望这种水平的支持能够延伸到更多正在努力解决自身问题的开源代码库上。
“放眼世界,许多项目仍然需要得到一些帮助……”
原文链接:
https://thenewstack.io/curls-daniel-stenberg-on-securing-180000-lines-of-c-code/
声明:本文为 InfoQ 整理,不代表平台观点,未经许可禁止转载。
","description":"Curl 作为一个安装量超过 200 亿次的开源项目,承载着极高的安全性和稳定性要求。其作者 Daniel Stenberg 通过严格的代码规范、工具化的错误预防、海量的测试体系,以及高效的漏洞修复流程,确保项目的可靠性。面对“是否用 Rust 重写 Curl”的讨论,他明确表示,Curl 不会被重写,而是通过持续迭代和精细打磨来提升安全性。项目团队不仅采用多层次的测试方法,还通过安全审计、漏洞赏金计划等手段,不断优化代码质量。这种对细节的极致追求,为开源软件的长期维护和安全保障提供了宝贵的经验。 在本年度的 FOSDEM 开源大会上,Curl 作者…","guid":"https://www.infoq.cn/article/GhrCANJrVBOLv7pVJIoI","author":"David Cassel","authorUrl":null,"authorAvatar":null,"publishedAt":"2025-03-05T10:48:03.811Z","media":[{"url":"https://static001.geekbang.org/infoq/9a/9ac5885f48bbce2a371582b6de608267.jpeg","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/df/dfe77ea4a6cddca0ef04d245e7d20670.jpeg","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/20/203871855beb772996fdaeb23539b61e.jpeg","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/73/73b75d2a882ee9ec90b5612dce992ad3.jpeg","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/b7/b757668af5b4fa2797ea8cd679be1226.jpeg","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/94/94130ad7681a170fd55768c3b42da102.jpeg","type":"photo","width":0,"height":0,"blurhash":""}],"categories":["编程语言"],"attachments":null,"extra":null,"language":null},{"title":"Rust 1.84 已发布,包括可能会破坏工具链的 WASI 目标更名","url":"https://www.infoq.cn/article/YmDqiModtzBpO1p4p8TF","content":"本文最初发布于DEV CLASS。
Rust 团队发布了 1.84.0 稳定版,带来下一代 trait 求解器和依赖版本检查改进方面的进展。不过,如果开发人员尚未进行必要的更新,那么 WebAssembly 系统接口(WASI)目标名称的变更可能会破坏工具链。
新版 Rust 主要有三个特性\\"。首先是 Cargo 解析器可以感知支持的最小 Rust 版本(MRSV)。虽然该特性在默认情况下并未启用,但现在已经稳定。Cargo 是 Rust 官方的软件包管理器。如果升级后的软件包需要新一些的 Rust 版本,那么 Cargo 现在可以自动忽略它。在软件包清单中,MSRV 使用了可选的 rust-version 字段。
接下来是下一代 trait 求解器的进展。新的 trait 求解器是 Rust 类型系统的一部分,用于确定类型是否以及如何实现 trait (类似于其他语言中的接口)。按照\\" Rust 类型团队的说法,新求解器“应能修复许多长期存在的(稳定性)Bug,赋能未来类型系统的改进,并改善编译时间”。新求解器尚未完成,但现在将用于一致性检查,确保任何给定类型的 trait 最多只有一种实现。
第三,Rust 正在添加用于对指针出处进行严格检查的 API,尤其是在将指针转换为整数和返回整数时。该团队解释说,这个问题本身就存在模糊性。新 API 将有利于 Miri\\" 等工具检测 Rust 代码中的未定义行为,也有利于证明 Rust 代码的形式正确性。
一些开发人员在升级 Rust 时会收到错误信息,因为目标 wasm32-wasi 已不再可用。这是因为该目标在 Rust 1.71 中已更名为 was32-wasip1 [zero point 1]。解决方法是升级前进行以下操作 :
rustup target remove wasm32-wasi
这背后的故事是,还有一个 wasm-wasip2 [zero point 2] 目标,与 WASI(WebAssembly 系统接口)的里程碑版本相匹配。将初始目标命名为 wasm32-wasi(当时它还是早期预览版)是个错误,这掩盖了它还是一个正在开发中的接口这一事实。去年 4 月,开发人员收到了有关更改的预警,并有 8 个月的过渡期在项目中改用新的目标名称。不可避免的是,有些开发者还没有这样做,wasm32-wasi 的消失会造成一些麻烦,不过这也可能促使开发者在可能的情况下转向更新的 warm-wasip2 目标。
声明:本文为InfoQ翻译,未经许可禁止转载。
","description":"本文最初发布于DEV CLASS。 Rust 团队发布了 1.84.0 稳定版,带来下一代 trait 求解器和依赖版本检查改进方面的进展。不过,如果开发人员尚未进行必要的更新,那么 WebAssembly 系统接口(WASI)目标名称的变更可能会破坏工具链。\\n\\n \\n\\n新版 Rust 主要有三个特性\\"。首先是 Cargo 解析器可以感知支持的最小 Rust 版本(MRSV)。虽然该特性在默认情况下并未启用,但现在已经稳定。Cargo 是 Rust 官方的软件包管理器。如果升级后的软件包需要新一些的 Rust 版本,那么 Cargo 现在可以自动忽略它…","guid":"https://www.infoq.cn/article/YmDqiModtzBpO1p4p8TF","author":"Tim Anderson","authorUrl":null,"authorAvatar":null,"publishedAt":"2025-03-05T09:52:14.017Z","media":[{"url":"https://static001.geekbang.org/infoq/fc/fc17abca6f8d5755b00cda223441404d.png","type":"photo","width":0,"height":0,"blurhash":""}],"categories":["编程语言"],"attachments":null,"extra":null,"language":null},{"title":"JDK 24 和 JDK 25:最新进展全知晓","url":"https://www.infoq.cn/article/eSp14PeS2JYsBP4rwaVG","content":"
JDK 24 是自 JDK 21 以来的第三个非长期支持版本。甲骨文公司 Java 平台组首席架构师 Mark Reinhold 宣布,JDK 24 已进入首个候选发布阶段。2024 年 12 月初,主线源代码仓库分支到 JDK 稳定版本仓库(Rampdown 第一阶段),这确定了 JDK 24 的功能集。对于关键漏洞,比如回归问题或严重的功能缺陷,可能会进行修复,但必须通过修复请求流程获得批准。按照发布计划,JDK 24 将于 2025 年 3 月 18 日正式发布 。以 JEP(Java 增强提案)形式呈现的最终 24 项新特性,可分为五大类:核心 Java 库、Java 语言规范、安全库、HotSpot 和 Java 工具。
核心 Java 库(7 项新特性):
JEP 472:为限制 JNI 的使用做准备;JEP 484:类文件 API;JEP 485:流收集器;JEP 487:作用域值(第四次预览);JEP 489:向量 API(第九次孵化);JEP 498:使用 sun.misc.Unsafe 中的内存访问方法时发出警告;JEP 499:结构化并发(第四次预览)。
Java 语言规范(4 项新特性):
JEP 488:模式、instanceof 和 switch 中的原始类型(第二次预览);JEP 492:灵活的构造函数体(第三次预览);JEP 494:模块导入声明(第二次预览);JEP 495:简单源文件和实例主方法(第四次预览)。
安全库(4 项新特性):
JEP 478:密钥派生函数 API(预览);JEP 486:永久禁用安全管理器;JEP 496:基于模块格的抗量子密钥封装机制;JEP 497:基于模块格的抗量子数字签名算法。
HotSpot(8 项新特性):
JEP 404:分代 Shenandoah(实验性);JEP 450:紧凑对象头(实验性);JEP 475:G1 的后期屏障扩展;JEP 479:移除 Windows 32 位 x86 端口;JEP 483:提前类加载和链接;JEP 490:ZGC:移除非分代模式;JEP 491:无需固定即可同步虚拟线程;JEP 501:弃用 32 位 x86 端口以便后续移除。
Java 工具(1 项新特性):
JEP 493:不使用 JMODs 链接运行时镜像。
我们来审视其中一些新特性,并了解它们在主要 Java 项目(Amber、Loom、Panama、Valhalla 和 Leyden)中的归属。这些项目旨在孵化一系列组件,最终通过精心策划的合并纳入 JDK。
JEP 495:简单源文件和实例主方法(第四次预览),在经过前三轮预览后,此次发布第四次预览且内容无变化(仅第二次更改了名称)。此前三轮预览分别是:JDK 23 中的 JEP 477“隐式声明类和实例主方法(第三次预览)”;JDK 22 中的 JEP 463“隐式声明类和实例主方法(第二次预览)”;JDK 21 中的 JEP 445“匿名类和实例主方法(预览)”。该特性旨在“改进 Java 语言,让初学者编写第一个程序时,无需理解为大型程序设计的语言特性”。这一 JEP 提案推进了甲骨文公司 Java 语言架构师 Brian Goetz2022 年 9 月发表的博客文章《 Paving the on-ramp》。甲骨文公司技术人员咨询成员 Gavin Bierman 已发布规范文档初稿,供 Java 社区审核。更多关于 JEP 445 的详细信息,可查看[InfoQ 新闻报道](https://www.infoq.com/news/2025/02/java-24-so-far/\\")。
JEP 487:作用域值(第四次预览),原名为“扩展本地变量(孵化)”。经过一轮孵化和三轮预览后,此次推出第四次预览且有一处变动。此前的预览版本分别是:JDK 23 中的 JEP 481“作用域值(第三次预览)”;JDK 22 中的 JEP 464“作用域值(第二次预览)”;JDK 21 中的 JEP 446“作用域值(预览)”;JDK 20 中的 JEP 429“作用域值(孵化)”。该特性支持在线程内部和线程之间共享不可变数据,与线程局部变量相比更具优势,尤其在使用大量虚拟线程时。与上一版预览相比,唯一的变动是从`ScopedValue`类中移除了`callWhere()`和`runWhere()`方法,以使 API 更加流畅。通过`ScopedValue.Carrier`类中定义的`call()`和`run()`方法,可实现使用一个或多个绑定的作用域值的功能。
在完成评审后,JEP 489:向量 API(第九次孵化)根据前八轮孵化的反馈意见进行了改进。此前的孵化版本分别是:JDK 23 中的 JEP 469“向量 API(第八次孵化)”;JDK 22 中的 JEP 460“向量 API(第七次孵化)”;JDK 21 中的 JEP 448“向量 API(第六次孵化)”;JDK 20 中的 JEP 438“向量 API(第五次孵化)”;JDK 19 中的 JEP 426“向量 API(第四次孵化)”;JDK 18 中的 JEP 417“向量 API(第三次孵化)”;JDK 17 中的 JEP 414“向量 API(第二次孵化)”;JDK 16 中作为孵化模块发布的 JEP 338“向量 API(孵化)”。原本计划复用最初的孵化状态进行重新孵化,最终决定继续按顺序编号。向量 API 将持续处于孵化阶段,直到 Valhalla 项目 的必要特性作为预览特性推出。届时,向量 API 团队将对向量 API 及其实现进行调整以使用这些特性,并将向量 API 从孵化阶段推进到预览阶段。
JEP 483 提前类加载和链接旨在“通过让应用程序的类在 HotSpot Java 虚拟机启动时,以加载和链接状态即时可用,从而缩短启动时间”。这可以通过在一次运行过程中监控应用程序,并将所有类的加载和链接形式存储在缓存中,以供后续运行使用来实现。该特性将为未来缩短启动时间和预热时间奠定基础。
JEP 497 基于模块格的抗量子数字签名算法旨在“通过提供符合 FIPS 204 标准的基于模块格的抗量子数字签名算法(ML-DSA)实现,增强 Java 应用程序的安全性”。这将通过实现 Java 的`KeyPairGenerator`、`Signature`和`KeyFactory`类来达成。
受 Lilliput 项目 启发,JEP 450 紧凑对象头(实验性)提议“在 64 位架构下,将 HotSpot JVM 中对象头的大小从 96 到 128 位缩减至 64 位”。由于该特性被视为实验性的,默认处于禁用状态,若开发者启用可能会导致意外后果。更多关于 JEP 450 的详细信息,可查看 InfoQ 新闻报道_(__https://www.infoq.com/news/2025/02/java-24-so-far/)_。
JEP 404 分代 Shenandoah(实验性)提议提供一种实验性的分代模式,同时不影响非分代的 Shenandoah 垃圾回收器,目标是在未来的 JDK 版本中将分代模式设为默认选项。该 JEP 最初计划用于 JDK 21,但由于“评审过程中发现的风险,以及对如此大量代码贡献进行全面评审的时间不足”,最终从 JDK 21 的最终特性集中移除。当时,Shenandoah 团队决定将目标设定为未来的 JDK 版本,以“尽可能提供最佳的分代 Shenandoah”。#### JDK 25
JDK 25 计划于 2025 年 9 月发布正式版,目前尚无针对 JDK 25 的 JEP 提案。不过,基于一些 JEP 候选提案和草案,尤其是已提交的那些,我们可以推测哪些 JEP 有可能被纳入 JDK 25。甲骨文公司技术人员咨询成员 Gavin Bierman 在给 Java 社区的一封邮件中宣布,他计划在 2025 年 9 月 JDK 25 发布时,敲定 JEP 495“简单源文件和实例主方法(第四次预览)”中所谓的“入门匝道(on-ramp)”特性。截至目前,相关草案尚未创建,但预计很快会有变动。
JEP 502“稳定值(预览)”,原名为“计算常量(预览)”,引入了计算常量的概念,即最多初始化一次的不可变值持有者。它兼具`final`字段的性能和安全优势,同时在初始化时机上更具灵活性。
JEP 草案 8340343“结构化并发(第五次预览)”提议进行第五次预览,对 API 做出几处修改,以从前四轮预览中获取更多反馈。此前的预览版本分别是:即将在 JDK 24 正式版中发布的 JEP 499“结构化并发(第四次预览)”;JDK 23 中的 JEP 480“结构化并发(第三次预览)”;JDK 22 中的 JEP 462“结构化并发(第二次预览)”;JDK 21 中的 JEP 453“结构化并发(预览)”。该特性引入结构化并发,将“在不同线程中运行的相关任务组视为单个工作单元,从而简化错误处理和取消操作,提高可靠性并增强可观测性”,进而简化并发编程。其中一项 API 修改提议是,通过静态工厂方法而非公共构造函数来打开`StructuredTaskScope`接口。
JEP 草案 8326035“CDS 对象流”提议在 Z 垃圾回收器(ZGC)中为类数据共享(CDS)添加对象归档机制,并采用统一的 CDS 对象归档格式和加载器。该特性将把 GC 的实现细节和策略与 CDS 归档对象流机制分开。
JEP 草案 8300911“PEM API(预览)”引入了一种简单直观的 API,用于对隐私增强邮件(PEM)格式进行编码和解码,描述最多可更改一次的值持有者。PEM 格式将用于存储和发送加密密钥及证书。
JEP 草案 8291976“在 HttpClient 中支持 HTTP/3” 提议更新 JDK 11 中发布的 JEP 321“HTTP 客户端”,以支持 HTTP/3 协议。这将使应用程序和库能够与 HTTP/3 服务器交互,并通过最少的代码更改获得 HTTP/3 带来的优势。我们预计甲骨文公司很快就会确定针对 JDK 25 的 JEP。
Michael Redlich,在过去 25 年里,Michael Redlich 始终是 Java 社区的活跃成员。2001 年,他创立了花园州 Java 用户组(前身为 ACGNJ Java 用户组),这个用户组至今仍在持续运营。
从 2016 年开始,Mike(Michael 的昵称)担任 InfoQ 的 Java 社区新闻编辑。在此期间,他每月撰写新闻报道,进行技术内容创作,还参与技术评审工作,为社区贡献颇丰。他曾在诸多重要场合发表演讲,比如甲骨文 Code One 大会、企业新兴技术大会、Trenton 计算机节(TCF)、TCF IT 专业人员大会,以及众多 Java 用户组活动。
在技术规范制定领域,Mike 是 Jakarta NoSQL 和 Jakarta Data 规范的贡献者,积极推动相关技术的发展。同时,他还参与了 Jakarta EE 大使领导委员会,为该技术生态的发展出谋划策。2023 年 4 月,他荣获 Java Champion 称号,这无疑是对他在 Java 领域卓越贡献的高度认可。
Mike 在新泽西州克林顿市的埃克森美孚技术与工程公司工作了长达 33 年半之久,最近刚刚退休。在那里,他积累了丰富的科学实验室和网络应用程序定制化开发经验。此前,他还在 Ai-Logix 公司(现 AudioCodes)担任技术支持工程师,不仅为客户提供专业的技术支持,还负责开发电话应用程序。
原文链接:
https://www.infoq.com/news/2025/02/java-24-so-far/\\"
","description":"JDK 24 是自 JDK 21 以来的第三个非长期支持版本。甲骨文公司 Java 平台组首席架构师 Mark Reinhold 宣布,JDK 24 已进入首个候选发布阶段。2024 年 12 月初,主线源代码仓库分支到 JDK 稳定版本仓库(Rampdown 第一阶段),这确定了 JDK 24 的功能集。对于关键漏洞,比如回归问题或严重的功能缺陷,可能会进行修复,但必须通过修复请求流程获得批准。按照发布计划,JDK 24 将于 2025 年 3 月 18 日正式发布 。以 JEP(Java 增强提案)形式呈现的最终 24 项新特性,可分为五大类:核心…","guid":"https://www.infoq.cn/article/eSp14PeS2JYsBP4rwaVG","author":"作者:Michael Redlich","authorUrl":null,"authorAvatar":null,"publishedAt":"2025-03-04T06:00:00.414Z","media":null,"categories":["编程语言"],"attachments":null,"extra":null,"language":null},{"title":"数据无界、湖仓无界, Apache Doris 湖仓一体解决方案全面解读","url":"https://www.infoq.cn/article/8B2hhzuGoe7zHgkxhVKH","content":"导读:湖仓一体架构融合了数据湖的低成本、高扩展性,以及数据仓库的高性能、强数据治理能力,高效应对大数据时代的挑战。为助力企业实现湖仓一体的建设,Apache Doris\\" 提出了数据无界和湖仓无界核心理念,并结合自身特性,助力企业加速从 0 到 1 构建湖仓体系,降低转型过程中的风险和成本。本文将对湖仓一体演进及 Apache Doris 湖仓一体方案进行介绍。
在过去的数年间,数据分析技术栈经历了许多重要变革,从最初数据仓库概念的诞生,到数据湖的兴起,进而演进到湖仓一体解决方案。这一技术路线的演进,反映出现代企业在数据分析领域对性能、实时性、一致性、开放性、统一管理方面的需求不断增强。
在企业信息化发展初期、业务流程数字化的不断推进下,积累的数据愈发繁杂。管理层亟需快速整理这些数据,清晰洞察业务状况以精准决策,在此背景下催生了数据仓库。
数据仓库的核心目标是助力商业智能(BI)决策,将分散于各业务系统的结构化数据抽取、转换、加载(ETL)至集中存储库。数据仓库的显著优势包括:
高效的结构化数据分析:严格的 Schema 设计确保数据高质量,为后续处理和分析奠定坚实基础;列式存储可以提高特定查询的效率;精心设计的专用数据格式,能够更好适应结构化数据的特点和分析需求;存算一体架构减少了数据传输的开销,提升了分析性能。成熟的 SQL 查询支持:基于关系模型的数据仓库完美适配 SQL 语言,相关人员可运用熟悉的查询语句,快速检索、统计、分析数据及生成各类报表,满足企业经营分析、销售趋势预测等方面的需求。数据一致性保障:通过集中式存储与管理,数据仓库在严格的事务处理机制下能够确保数据的准确性与一致性,避免冗余和不一致带来的分析误差,为企业提供可靠的数据依据。
伴随互联网普及、物联网兴起,非结构化数据(如时序数据、图片、视频、文档)大量涌现,传统数据仓库无论从扩展性、成本,还是对非结构化数据的支持方面都难以承载新的需求,企业迫切寻求更高性价比的存储分析方案。同时,数据科学与机器学习的蓬勃发展推动了探索式分析需求,催生了数据湖技术的出现。
Google 在大数据领域的开创性研究成果 —— Google 文件系统(GFS)、MapReduce 和 BigTable,犹如灯塔般引领了全球大数据技术的蓬勃发展之路,基于 Hadoop 的技术架构和生态系统自此诞生,催生了数据湖这一概念。Hadoop 使得在低成本的商用服务器上进行大数据处理成为可能,它能够很好支持以下应用场景:
超大规模数据处理:通过分布式存储和并行计算技术,可以在通用计算节点上进行高效地大规模数据处理,避免了依赖特殊硬件带来的高昂成本。多模态数据支持与低成本存储:不同于传统数仓需要严格的表模式定义,数据湖能够以原始格式存储任意数量和类型的数据。通过 Schema-on-Read 机制,可在读取时再进行模式定义,最大限度地保留数据价值。这种灵活性尤其适用于图像、音视频和日志等信息,提供了更为敏捷的探索性分析能力。此外,依托于对象存储,不仅降低了存储成本,还实现了极高的可扩展性。多模态计算:利用不同的计算引擎,在同一份数据集上执行包括 SQL 查询、机器学习、AI 训练等不同计算任务,满足多样化的数据处理需求。
“数据湖”这个名称生动诠释了企业数据状态:大量原始数据汇聚在一个统一的存储底座中形成“湖”,然后在湖上构建各类系统进行数据分析和处理。随着技术的发展,数据湖也逐渐形成了以存储、计算、元数据为主的三层架构,为后续的湖仓一体发展奠定了基础。
存储层: 数据湖通常使用分布式文件系统或者对象存储进行数据存储,比如 HDFS、AWS S3、Azure Blob Storage、阿里云 OSS、华为云 OBS、腾讯云 COS 等。它们提供几乎无限的存储容量,具备高可用性、低成本等优势,企业可按需使用。数据以原始格式存储,避免了传统数据仓库复杂的数据建模与结构化过程,为后续多样化的数据处理需求提供了灵活的基础。计算层: 存储的数据允许被不同计算引擎访问,多引擎相互合作可满足不同场景下的数据处理速度与灵活性要求,如 Hive 引入 HiveQL,通过 SQL 进行批量数据加工处理;Spark 支持批处理、流处理、机器学习等多种计算场景;Presto 则专注交互式查询,快速响应复杂的即席查询请求。元数据层: 以 Hive Metastore 为代表的元数据服务,记录了数据湖中的表结构、分区信息、数据存储位置等关键元数据,使得不同的计算引擎与工具能够基于统一的元数据理解数据,实现数据共享与协同处理,是维持数据湖有序运行的重要组件。
数据仓库和数据湖技术经过多年的发展,在各自领域都发挥的重要作用。这里简要总结了两类系统在不同技术方面的对比。随着企业对数据实时性、准确性、开放性等需求的日益增加,传统数据仓库和数据湖都各自面临来自不同方面的挑战:
传统数据仓库:
数据实时性匮乏:在电商大促和实时监控场景下,企业要求达到秒级甚至亚秒级的数据洞察能力。数据仓库基于静态的 ETL(Extract, Transform, Load)过程,难以处理持续变更的数据,无法满足实时决策的需求。例如,物流企业追踪货物的实时轨迹变更很难依靠传统的数据仓库来实现。半结构化与非结构化挑战:社交媒体、医疗影像等领域充斥半结构化、非结构化数据,数据仓库固定 Schema 管理无法灵活适配,存储、索引、访问效率低下,像医疗科研分析海量病历文本与影像时,传统仓库束手无策。
数据湖:
性能瓶颈:面对分析师即时查询、业务人员自助探索需求,Spark/Hive 批处理在交互式、低延迟分析上乏力。如金融风控人员需实时核验交易风险,数据湖分析引擎延迟阻碍及时决策,亟需高性能计算引擎(如基于内存优化、向量化执行)加速数据处理。事务性保证缺失:数据湖系统通常都会抛弃操作的事务性,以此来换取更为灵活的数据处理方式以及更好的扩展性。但由于缺乏事务性保证,数据的一致性和完整性可能会受到影响,在进行复杂的数据操作和处理时,可能会出现数据不一致或者数据丢失的情况。这对于一些对数据准确性要求较高的应用场景来说,可能会带来一定的风险和挑战。数据治理危机:数据湖开放写入的特性,易引入低质量、不一致数据,若缺乏有效治理,“数据湖” 将沦为 “数据沼泽”,企业难以基于可信数据洞察,如多源数据汇聚的数据湖,因格式、定义差异常出现数据冲突。
由于数据仓库和数据湖各自擅长的领域不同,因此大多数企业会同时维护数据仓库和数据湖两套系统,以满足不同的业务需求。但随之而来的是数据在两套系统中冗余存储、在不同系统间重复传输、使用体验不一、数据孤岛等诸多问题。在上述背景下,如何融合数据仓库和数据湖的优势,成为了现代数据栈的发展趋势。
湖仓一体是将数据湖和数据仓库的优势相结合的数据管理系统。为现代企业提供可扩展的存储和处理能力,避免处理不同工作负载的孤立系统,帮助企业建立单一数据源,消除冗余成本并确保数据新鲜度。随着近些年对湖仓融合的探索,湖仓一体架构也逐渐形成了以下结构范式,每一个层级都具有其独特的作用和价值,在融合数据仓库和数据湖的优势的同时,也解决了湖仓割裂的问题。
存储层:坚实基座 湖仓一体架构继承了数据湖时代分布式存储的优势,以 HDFS 或云对象存储为基础,确保数据的低成本、高可用存储。数据以原始格式或开放文件格式(如 Parquet、ORC)存入存储层,这些格式具备高效的压缩比与列存储特性,在数据读取时能够快速定位所需列数据,减少不必要的 I/O 开销,为后续数据处理提供高性能访问基础。开放数据格式:灵活互通 在湖仓一体架构下,Parquet、ORC 等开放文件格式广泛应用于数据存储,保障了数据在不同计算引擎间的通用性。同时,Iceberg、Hudi、Delta Lake 等开放表格式发挥关键作用,它们不仅支持数据的近实时更新、高效的快照管理,还兼容 SQL 标准,使得数据既可以像传统数据库表一样进行事务性操作,又能充分利用数据湖的分布式存储与弹性计算优势,实现数据在数据湖与数据仓库场景间的无缝切换,为实时数据处理与历史数据分析提供统一的数据基础。计算引擎:多元协同 计算层面整合了 Spark、Flink、Presto、Doris 等多样的计算引擎,各引擎各司其职。Spark 凭借其丰富的 API 与强大的批处理、机器学习,处理大规模数据复杂任务能力;Flink 聚焦实时流计算,保障数据实时性处理需求;Presto、Doris 针对交互式查询优化,快速响应用户即时的数据探索请求。通过统一的调度与资源管理,不同引擎可以共享存储资源,协同处理复杂的数据工作流,满足企业从实时监控到深度分析的全方位计算需求。元数据管理:统一中枢 从早期的 Hive Metastore 演进到如 Unity Catalog、Apache Gravitino 这样的新一代元数据管理系统,湖仓一体架构实现了元数据的大一统。统一元数据管理支持跨多云、多集群环境下的元数据集中管理,提供统一的命名空间、全局的数据目录,无论数据存储在何处,使用何种计算引擎,用户都能通过统一的 API 进行快速检索、理解与访问数据。同时,元数据服务也在权限管理、审计、数据血缘追踪方面不断加强,帮助企业完成高质量的数据资产管理。
湖仓一体架构的出现,融合了数据湖的低成本、高扩展性与数据仓库的高性能、强数据治理能力,从而实现对大数据时代各类数据的高效、安全、质量可控的存储和处理分析。同时,通过标准化的数据格式和元数据管理,统一了实时、历史数据,批处理和流处理,正在逐步成为企业大数据解决方案新的标准。
Apache Doris\\" 自 2.1 版本以来,Apache Doris 在湖仓一体场景的能力得到了显著提升与完善。
企业在推进湖仓一体化建设时,面临新系统选型、原有系统整合与升级等多重挑战。这一过程不仅涉及不同系统之间的选型困境,还包括数据格式转换、新接口适配、系统间的平滑切换,以及部门间的人力协调、权限移交与合规等问题。因此,企业亟需一个可操作的步骤,以逐步实现湖仓一体化。
为了更好的帮助企业完成湖仓一体的建设,Apache Doris 结合自身特性,提出了【数据无界】和【湖仓无界】核心理念,旨在帮助企业快速完成湖仓一体转型,降低转型过程中的风险和成本。
在构建湖仓一体化架构时,企业首先面临数据分析的统一接入难题。Apache Doris 作为高性能湖仓计算引擎,不仅提供统一的查询加速服务,还能有效简化系统架构,让数据价值触手可及。
Apache Doris 通过可扩展的连接器框架,支持主流数据系统和数据格式接入,并提供基于 SQL 的统一数据分析能力,用户能够在不改变现有数据架构的情况下,轻松实现跨平台的数据查询与分析。
数据源连接器:无论是 Hive、Iceberg\\"、Hudi\\" 、Paimon\\",还是支持 JDBC 协议的数据库系统,Doris 均能轻松连接并高效提取数据。对于湖仓系统,Apache Doris 可从元数据服务中获取数据表的结构和分布信息,进行合理的查询规划,并利用 MPP 架构扫描和计算分布式数据。Doris 支持的数据源及其对应的元数据管理和存储系统如下:
可扩展的连接器框架:Doris 提供良好的扩展性框架,帮助开发人员快速对接企业内部特有的数据源,实现数据快速互通。
Doris 定义了标准的数据目录(Catalog)、数据库(Database)、数据表(Table)三个层级,开发人员可以方便的映射到所需对接的数据源层级。Doris 同时提供标准的元数据服务和数据读取服务的接口,开发人员只需按照接口定义实现对应的访问逻辑,即可完成数据源的对接。Doris 兼容 Trino Connector 插件\\",可直接将 Trino 插件包部署到 Doris 集群,经过少量配置即可访问对应的数据源。Doris 目前已经完成了 Kudu、Bigquery、Delta Lake、Kafka、Redis 等数据源的对接。便捷的跨源数据处理:Doris 支持在运行时直接创建多个数据源连接器,可使用 SQL 对这些数据源进行联邦查询。比如用户可以将 Hive 中的事实表数据与 MySQL 中的维度表数据进行关联查询:
SELECT h.id, m.name\\n FROM hive.db.hive_table h JOIN mysql.db.mysql_table m\\n ON h.id = m.id;
结合 Doris 内置的作业调度能力,还可以创建定时任务,进一步简化系统复杂度。比如用户可以将上述查询的结果,设定为每小时执行一次的例行任务,并将每次的结果,写入一张 Iceberg 表:
CREATE JOB schedule_load\\n ON SCHEDULE EVERY 1 HOUR DO\\n INSERT INTO iceberg.db.ice_table\\n SELECT h.id, m.name\\n FROM hive.db.hive_table h JOIN mysql.db.mysql_table m\\n ON h.id = m.id;
企业在湖仓一体化转型过程中,对数据分析的性能需求是最根本且迫切的。Doris 作为分析型数据仓库,在数据处理和计算方面做了大量优化,并提供了丰富的查询加速功能:
执行引擎: Apache Doris 执行引擎基于 MPP 执行框架和 Pipeline 数据处理模型,能够很好的在多机多核的分布式环境下快速处理海量数据。同时,得益于完全的向量化执行算子,在计算性能方面 Apache Doris 在 TPC-DS 等标准评测数据集中处于领先地位。查询优化器: Apache Doris 能通过查询优化器自动优化和处理复杂的 SQL 请求。查询优化器针对多表关联、聚合、排序、分页等多种复杂 SQL 算子进行了深度优化,充分利用代价模型和关系代数变化,自动获取较优或最优的逻辑执行计划和物理执行计划,极大降低用户编写 SQL 的难度,提升易用性和性能。缓存加速与 IO 优化: 对外部数据源的访问,通常是网络访问,因此存在延迟高、稳定性差等问题。Apache Doris 提供了丰富的缓存机制,并在缓存的类型、时效性、策略方面都做了大量的优化,充分利用内存和本地高速磁盘,提升热点数据的分析性能。同时,针对网络 IO 高吞吐、低 IOPS、高延迟的特性,Doris 也进行了针对性的优化,可以提供媲美本地数据的外部数据源访问性能。物化视图与透明加速: Apache Doris 提供丰富的物化视图更新策略,支持全量和分区级别的增量刷新,以降低构建成本并提升时效性。除手动刷新外,Doris 还支持定时刷新和数据驱动刷新,进一步降低维护成本并提高数据一致性。物化视图还具备透明加速功能,查询优化器能够自动路由到合适的物化视图,实现无缝查询加速。此外,Doris 的物化视图采用高性能存储格式,通过列存、压缩和智能索引技术,提供高效的数据访问能力,能够作为数据缓存的替代方案,提升查询效率。
如下所示,在基于 Iceberg 表格式的 1TB 的 TPCDS 标准测试集上,Doris 执行 99 个查询的总体运行耗时仅为 Trino 的 1/3。
实际用户场景中,Doris 在使用一半资源的情况下,相比 Presto 平均查询延迟降低了 20%,95 分位延迟更是降低 50%。 在提升用户体验的同时,极大降低了资源成本。
在企业整合多个数据源并实现湖仓一体转型的过程中,迁移业务的 SQL 查询到 Doris 是一项挑战,因为不同系统的 SQL 方言在语法和函数支持上存在差异。若没有合适的迁移方案,业务侧可能需要进行大量改造以适应新系统的 SQL 语法。
为了解决这个问题,Doris 提供了 SQL 转换服务\\",允许用户直接使用其他系统的 SQL 方言进行数据查询。转换服务会将这些 SQL 方言转换为 Doris SQL,极大降低了用户的迁移成本。目前,Doris 支持 Presto/Trino、Hive、PostgreSQL 和 Clickhouse 等常见查询引擎的 SQL 方言转换,在某些实际用户场景中,兼容率可达到 99%以上。
面对多系统并存带来的挑战,湖仓一体化转型的第二步便是架构整合、以减少需维护的系统数量。 这不仅有利于降低架构复杂性,同时可解决数据一致性和管理一致性的问题。接下来我们从系统架构、功能等多维度介绍基于 Doris 的湖仓一体架构整合方案。
自 3.0 版本以来,Apache Doris 支持面向云原生的存算分离架构。这一架构凭借低成本和高弹性的特点,能够有效提高资源利用率,实现计算和存储的独立扩展。这对于湖仓一体化至关重要,为企业提供了灵活的资源管理方式,使其能够更高效地应对大规模数据分析需求。
上图是 Doris 存算分离的系统架构,对计算与存储进行了解耦,计算节点不再存储主数据,底层共享存储层(HDFS 与对象存储)作为统一的数据主存储空间,并支持计算资源和存储资源独立扩缩容。存算分离架构为湖仓一体解决方案带来了显著的优势:
低成本存储: 存储和计算资源可独立扩展,企业可以根据需要增加存储容量而不必增加计算资源。同时,通过使用云上的对象存储,企业可以享受更低的存储成本和更高的可用性,对于比例相对较低的热点数据,依然可以使用本地高速磁盘进行缓存。唯一可信来源: 所有数据都存储在统一的存储层中,同一份数据供不同的计算集群访问和处理,确保数据的一致性和完整性,也减少数据同步和重复存储的复杂性。负载多样性: 可以根据不同的工作负载需求动态调配计算资源,支持批处理、实时分析和机器学习等多种应用场景。通过分离存储和计算,企业可以更灵活地优化资源使用,确保在不同负载下的高效运行。
主流的数据湖格式,如 Iceberg 和 Hudi,通过标准化的数据表格式规范,为数据湖提供了灵活高效的存储和管理方式。Apache Doris 不仅支持这些主流湖格式,还具备自身的存储格式,能够满足相应的需求,并提供更丰富的功能和更高的性能。
半结构化数据支持: Doris 原生支持 JSON、Variant 等半结构化数据类型,提供 Schemaless 的数据管理体验,节省了用户转换、清洗数据的开销。用户可以直接导入任意 JSON 格式的数据,Doris 会自动解析并以高效的列格式存储,适应复杂的数据分析需求。数据更新的支持: Doris 提供近实时的数据更新能力,也支持对变更数据的高效分析。此外,基于部分列更新能力,用户也可以在 Doris 内完成多流合并宽表的操作,进一步简化数据链路。丰富的数据索引: Doris 可以通过前缀索引、倒排索引来快速命中数据,也可通过跳数索引、BloomFilter 索引进行快速数据跳过。在存算分离/湖仓场景下,能显著减少本地或网络 IO,是数据分析场景的查询加速利器。实时数据和批数据写入: Doris 支持通过微批方式进行高频数据写入,同时也可批量加载预先生成的数据。同时,通过 MVCC 的数据管理方式,可在同一份数据上存储和处理实时数据和历史数据。
数据湖的开放性对湖仓一体架构的重要性不言而喻。它是高效整合和管理数据的关键因素,也是影响湖仓一体架构性能和成本的主要因素之一。在【01 数据无界:打破数据便捷】章节中,已经介绍了 Doris 对开放表格式、文件格式等系统的支持。
此外, Apache Doris 自身存储的数据同样拥有良好的开放性。Doris 提供了开放存储 API,并基于 Arrow Flight SQL 协议实现了高速数据链路\\",具备 Arrow Flight 的速度优势以及 JDBC/ODBC 的易用性。 基于该接口,用户可以使用 Python/Java/Spark/Flink 的 ABDC 客户端访问 Doris 中存储的数据。
与开放文件格式相比,开放存储 API 屏蔽了底层的文件格式的具体实现,Doris 可以通过自身存储格式中的高级特性,如丰富的索引机制来加速数据访问。同时,上层的计算引擎无需对底层存储格式的变更或新特性进行适配,所有支持的该协议的计算引擎都可以同步享受到新特性带来的收益。
以上是对湖仓一体演进及 Apache Doris 湖仓一体方案的完整介绍\\"。在下一篇文章中,我们将以“湖仓分析加速”、“多源联邦分析”、“湖仓数据处理”这三个典型场景为例,分享 Apache Doris 湖仓一体方案的最佳实践。 结合实际问题,详细分享使用指南及带来的效果。
","description":"导读:湖仓一体架构融合了数据湖的低成本、高扩展性,以及数据仓库的高性能、强数据治理能力,高效应对大数据时代的挑战。为助力企业实现湖仓一体的建设,Apache Doris\\" 提出了数据无界和湖仓无界核心理念,并结合自身特性,助力企业加速从 0 到 1 构建湖仓体系,降低转型过程中的风险和成本。本文将对湖仓一体演进及 Apache Doris 湖仓一体方案进行介绍。 在过去的数年间,数据分析技术栈经历了许多重要变革,从最初数据仓库概念的诞生,到数据湖的兴起,进而演进到湖仓一体解决方案。这一技术路线的演进,反映出现代企业在数据分析领域对性能、实时性、一致性…","guid":"https://www.infoq.cn/article/8B2hhzuGoe7zHgkxhVKH","author":"SelectDB","authorUrl":null,"authorAvatar":null,"publishedAt":"2025-02-26T09:00:20.732Z","media":[{"url":"https://static001.geekbang.org/infoq/8e/8e5762aca44fed5ff3c850cec3a8f347.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/74/74a3863f207df6ceebcbf7c8381dc588.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/77/77fb2ad433231ebdcded413e0cff8677.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/be/bea5b0704f8f51596106c91b87bd3498.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/ea/ea68b5dde326d00d2090a9f0fc484c04.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/a5/a572b7df6d7ff1fb0b7818d2286feaef.png","type":"photo","width":0,"height":0,"blurhash":""}],"categories":["数据库"],"attachments":null,"extra":null,"language":null},{"title":"斥资2.2 亿美元,MongoDB又收购一家AI公司","url":"https://www.infoq.cn/article/DovQ4XQXmIPljcMjOloG","content":"当地时间2月24日,MongoDB 公司宣布斥资2.2亿美元收购了 Voyage AI公司,后者是一家嵌入模型和重新排序器提供商,可以构建更准确的AI应用程序。
Voyage AI 成立于2021年,由一群在机器学习和自然语言处理(NLP)领域具有深厚背景的专家创立。创始团队成员包括多位曾在谷歌、Meta、Uber、OpenAI等顶尖科技公司任职的资深工程师和数据科学家。公司旨在开发针对企业需求的变革性 AI 解决方案。
尽管Voyage AI是一家相对年轻的公司,但其技术已在多个垂直行业中展现出较大潜力。Voyager AI 为特定垂直行业提供 AI 模型,这些模型可以进一步定制,以加速构建用于整合法律和财务文件、图像、代码或整个知识库的 AI 应用程序,而无需每个开发团队重新发明相同的嵌入和重新排名工具。
MongoDB 产品高级副总裁 Andrew Davidson 表示,Voyage AI 的技术将与 MongoDB 的文档数据库和矢量数据库进行深度集成,预计在今年晚些时候推出。这一整合将使开发者能够更轻松地构建和部署AI应用程序,同时减少由大模型产生的“幻觉”。
Davidson 强调,Voyage AI 的嵌入模型和重新排序器能够从高度专业化的文本和非结构化数据中提取精确的含义,从而确保生成的数据与应用程序的用例高度一致。“这种技术提供了更高的保真度,使IT组织能够更自信地部署AI应用程序,”他补充道。
当前,生成式AI的广泛应用面临一个主要挑战:如何在正确的时间将正确的数据提供给正确的模型。MongoDB 通过其灵活的文档数据库和矢量数据库,为开发者提供了一个熟悉的抽象层,使他们能够更高效地管理数据并构建AI应用程序。这种集成不仅简化了开发流程,还减少了数据管理任务的时间和资源消耗。
随着企业对AI应用程序的需求不断增加,高层管理人员对数据管理问题的耐心正在迅速耗尽。许多企业领导者对AI的潜力充满期待,但由于缺乏对数据管理复杂性的理解,他们开始质疑现有IT团队是否能够应对当前的AI挑战。MongoDB 的收购和整合计划正是为了解决这一问题,帮助企业更快地实现AI的价值。
尽管Voyage AI的财务状况未完全公开,但作为一家快速成长的AI技术公司,其在嵌入模型和重新排序器领域的创新已吸引了多家大型科技公司的关注。此次被MongoDB收购,不仅为Voyage AI提供了更广阔的市场和资源,也标志着其在AI技术领域的重要地位。
","description":"当地时间2月24日,MongoDB 公司宣布斥资2.2亿美元收购了 Voyage AI公司,后者是一家嵌入模型和重新排序器提供商,可以构建更准确的AI应用程序。 \\n\\nVoyage AI 成立于2021年,由一群在机器学习和自然语言处理(NLP)领域具有深厚背景的专家创立。创始团队成员包括多位曾在谷歌、Meta、Uber、OpenAI等顶尖科技公司任职的资深工程师和数据科学家。公司旨在开发针对企业需求的变革性 AI 解决方案。\\n\\n \\n\\n尽管Voyage AI是一家相对年轻的公司,但其技术已在多个垂直行业中展现出较大潜力。Voyager AI 为特定垂直行业提供 AI…","guid":"https://www.infoq.cn/article/DovQ4XQXmIPljcMjOloG","author":"李冬梅","authorUrl":null,"authorAvatar":null,"publishedAt":"2025-02-25T06:59:13.931Z","media":null,"categories":["生成式 AI","数据库"],"attachments":null,"extra":null,"language":null},{"title":"Spring近期新闻:Boot、Framework、Data、Security、Integration和Modulith发布里程碑版本","url":"https://www.infoq.cn/article/aPPgLgFksHqUN92LueyC","content":"
最近,Spring生态系统的活动较为频繁,主要值得关注的是发布了如下项目的里程碑版本:Spring Boot、Spring Framework、Spring Data、Spring Security、Spring Integration和Spring Modulith。
Spring团队还宣布\\",他们开始将Spring项目的里程碑和候选版本发布到Maven中央仓库,并计划在2025年11月\\"发布GA版本。
Spring Boot\\" 3.5.0的第一个里程碑版本\\"提供了缺陷修复、文档改进、依赖关系升级和新特性,比如,支持Spring Framework TaskDecorator接口实现调度任务;使DataSourceBuilder类支持Vibur DBCP\\"连接池。关于该版本的更多详细信息,请参阅发布说明\\"。
Spring Boot的3.4.2和3.3.8版本发布(发布新闻分别参见此处\\"和此处\\"),它们提供了文档改进、依赖关系升级并解决了一些值得关注的问题,比如,当只声明logging.structured.gelf.host属性时,GraylogExtendedLogFormatProperties类的实例会抛出NullPointerException异常;增加了BindableRuntimeHintsRegistrar类中对TypeNotPresentException的处理。关于这些版本的详细信息,请参阅3.4.2版本\\"和3.3.8版本\\"的发布说明。
Spring Framework\\" 7.0.0的第一个里程碑版本提供了文档改进、依赖关系升级和新的特性,比如,重新定义并优化了KotlinDetector,包括移除不再有用的方法;允许ClientHttpRequestInterceptor接口的多次执行。这次版本发布还通过优化十多个模块和废弃org.springframework.lang包中定义的注解,借助JSpecify\\"提供了初步的null安全策略。关于该版本的更多信息,请参阅发布说明\\"。
Spring Data\\" 2025.1.0的第一个里程碑版本\\"提供了如下特性,将即将发布的Jakarta EE 11 GA(采用Hibernate ORM 7.0和Hibernate Validator 9.0作为兼容实现)和Kotlin 2.x作为最低的基线要求;Spring Data JPA的重要修订,包括使用Java Persistence Query Language\\"(JPQL)进行衍生查询。Spring Data团队预计在2025年11月发布GA版本。关于该版本的更多详细信息,请参阅发布说明\\"。
Spring Security\\" 6.5.0的第一个里程碑版本提供了缺陷修复、依赖关系升级和新特性,比如,通过添加@AuthenticationPrincipal和@CurrentSecurityContext注解支持表达式模板(Expression Template);在ClientRegistration类中新增了一个内部类ClientSettings,该类提供了一个boolean字段requireProofKey,用于启用 代码交换证明密钥(Proof Key for Code Exchange,PKCE)\\"。关于该版本的更多信息,请参阅发布说明\\"。
Spring Integration\\" 6.5.0的第一个里程碑版本\\"提供了一个缺陷的修复、依赖关系升级和新特性,例如,为AbstractMessageGroupStore类添加了锁定策略;为@Aggregator注解中定义的discardChannel元素添加了一个可选标记,以丢弃整组消息而不是单个消息。关于该版本的更多信息,请参阅发布说明\\"和新功能\\"页面。
Spring Modulith\\" 1.4.0的第一个里程碑版本\\"提供了缺陷修复、依赖关系升级和新特性,比如,支持Micrometer Observation API\\"的新DefaultModulithObservationConvention类;以编程方式探测NamedInterface类实例的新策略。关于该版本的更多详细信息,请参阅发布说明\\"。
Spring Modulith的1.3.2和1.2.8版本也已发布\\",分别升级了对Spring Boot 3.4.2和3.3.8的依赖关系,并解决了如下的问题:从RepositoryEntityController类的实例创建名为repositoryEntityController的bean时出现错误,从而导致了BeanCreationException;为Spring Framework @EventListener注解生成AsciiDoc时,如果没有参数的话,会抛出IllegalArgumentException。关于这些版本的更多详细信息,请分别参阅1.3.2版本\\"和1.2.8版本\\"的发布说明。
Spring AI MCP\\"团队发布\\"了0.6.0,该版本提供了如下新特性:MCP客户端与服务器之间的新协议版本协商;可配置的SSE端点,包括与默认/sse端点的向后兼容性。该版本弃用的内容包括:McpClient接口中定义的using(ClientMcpTransport)方法,取而代之的是sync(ClientMcpTransport)和async(ClientMcpTransport)方法;同样在McpClient接口中定义的Builder类,取代它的是新的构建器模式;McpAsyncClient类中定义的非反应式类型的构造函数。关于该版本的更多详细信息,请参阅发布说明\\"。
Spring AMQP\\" 3.2.2发布\\",提供了两个缺陷的修复、依赖关系升级和一项新特性,即移除被团队认为“虚假”的非公开RestTemplateHolder类,从而解决了RestTemplateNodeLocator类中的弃用警告问题,这个类是由公开的RestTemplateNodeLocator类意外暴露的。该类的逻辑也进行了重构,以直接暴露Spring Framework RestTemplate类的实例。关于该版本的更多详细信息,请参阅发布说明\\"。
Spring for Apache Kafka\\" 3.3.2发布\\",该版本提供了文档改进、依赖关系升级并解决了如下问题:因为Kafka观察对象上Micrometer DefaultLongTaskTimer类实例的活动任务数不断增加,从而导致spring.kafka.listener.active指标的内存泄漏,而这些任务从未被垃圾回收;由于KafkaMessageListenerContainer类实例的观察范围未在异常处理的catch子句中关闭,从而导致的异常。
该团队宣布,Apache Kafka 4.0.0的开发工作将会开始。它将基于即将发布的Kafka Client 4.0.0和Spring Framework 7.0.0,并兼容Spring Boot 4.0.0。关于该版本的更多详细信息,请参阅发布说明\\"。
Apache Pulsar的Spring 1.2.2和1.1.8版本发布,该版本提供了缺陷修复、依赖关系升级,并解决了如下问题:如果消息已发送到死信主题(Dead Letter Topic,DLT) 主题,监听器再次消费相同的消息时,会遇到PulsarBatchListenerFailedException。这些版本分别包含在 Spring Boot 3.4.2和3.3.8中。关于这些版本的更多详细信息,请分别参阅1.2.2版本\\"和1.1.8版本\\"的发布说明。
原文链接:
Spring News Roundup: Milestone Releases of Boot, Framework, Data, Security, Integration, Modulith\\"
","description":"最近,Spring生态系统的活动较为频繁,主要值得关注的是发布了如下项目的里程碑版本:Spring Boot、Spring Framework、Spring Data、Spring Security、Spring Integration和Spring Modulith。 \\n\\nSpring团队还宣布\\",他们开始将Spring项目的里程碑和候选版本发布到Maven中央仓库,并计划在2025年11月\\"发布GA版本。\\n\\nSpring Boot\\n\\nSpring Boot\\" 3.5.0的第一个里程碑版本\\"提供了缺陷修复、文档改进、依赖关系升级和新特性,比如,支持Spring…","guid":"https://www.infoq.cn/article/aPPgLgFksHqUN92LueyC","author":"Michael Redlich","authorUrl":null,"authorAvatar":null,"publishedAt":"2025-02-24T07:12:05.744Z","media":null,"categories":["编程语言"],"attachments":null,"extra":null,"language":null},{"title":"Linus 将不顾反对合并Rust代码?!内核维护者无奈强调:不能让“癌症”扩散!","url":"https://www.infoq.cn/article/y3hRPLwDSQAdImaClNCe","content":"自从 2022 年 Rust 代码首次被合并到 Linux 内核中,围绕它的争议就不断升温。Rust 因其在内存安全方面的优势而备受推崇,也被各国政府和安全专家认为能够有效减少由于内存安全漏洞导致的高危安全问题。
近段时间以来,围绕在 Linux 内核中引入 Rust 语言的讨论愈演愈烈。
本周,一直以来对 Rust 持质疑态度的 Linux 内核关键维护者 Christoph Hellwig 在 Linux 内核邮件列表上的一条讨论线程中无奈披露,Linus Torvalds 私下说过,他绝对会不顾维护者的反对,合并 Rust 代码。
Hellwig 直言:“所以从现在开始,作为一名 Linux 开发者或维护者,你想接受 Rust 也好,不想接受也罢,都必须去面对它。”
与此同时,Linux 核心内核开发者Greg Kroah-Hartman(下称Greg K-H) 也再次呼吁社区接纳那些愿意贡献 Rust 代码以改进内核的开发者。他本周三在邮件中写道:“没错,混合语言的代码库确实很棘手,也很难维护,但我们是内核开发者啊。我们维护和强化 Linux 的时间比任何人最初的预期都要长。”
Greg K-H 进一步表示,“我们把开发模式打磨成了精细运转的工程奇迹,创造了前所未有的成果。”“再添加一种新语言不应该成为问题。相比之下,我们过去克服过更棘手的挑战,现在更不应该让项目在未来 20 多年继续成功的道路上退缩。面对新的好想法,我们必须继续前进,并欢迎那些愿意一起真正投入工作、帮助我们共同成功的人。”
Hellwig 和 Greg K-H 发表这些内容的背景,源于上个月在社区中的多轮激烈争论。
当时 Rust for Linux(R4L)项目提交了一则补丁,允许使用 Rust 编写的设备驱动去调用主要用 C 语言编写的内核的核心 DMA API,却遭到 Linux 内核维护者 Christoph Hellwig 的质疑。Hellwig 将维护多语言代码库比作“癌症”,强调自己无意承担维护 Rust 设备驱动代码的负担。紧随其后的争论引发了时任 Asahi Linux 项目负责人的 Hector Martin 的不满。他要求 Linus Torvalds 表态,是否会将这个补丁合入内核。
最终, Linus 并没有给出补丁去留的明确裁定,而是批评 Martin 在社交媒体上就此事“作秀”,并为 Linux 社区的治理模式辩护。Hector Martin 称,这成为“压倒他的最后一根稻草”。随后,Martin 辞去了 Linux 维护者一职,并离开了 Asahi Linux 项目,不再负责 Linux 内核 Apple Silicon 代码的上游维护工作。
延展阅读:《Rust 补丁两年零通过,34年开发者煽动网友逼Linus表态,维护者激烈反击:Rust 就是 Linux 的“癌症”!》\\"
在最新的邮件中,Hellwig 再次表达了对在同一个代码库中混合使用 Rust 和 C 的担忧。他警告称,如果在没有明确政策和广泛讨论的前提下就把 Rust 代码大规模合并到内核的各个子系统里,会令后续维护者疲于奔命。这种“多语言混编”也会影响对旧代码的全局性改进。
“我曾在混合语言的代码库上工作过,那简直是我的噩梦:因为各种原因,会把部分代码从语言 A 重写成语言 B,然后又因为原因 Z 再转回 A,这种折腾不断。而这还没算上 Linux 社区平时常见的内斗纷争。”
Hellwig 强调,C 和 Rust 之间存在巨大语义鸿沟,给内核基础组件做互操作需要大量的“胶水”或绑定层。一旦绑定(bindings)分散到各个子系统,就像“癌症”一样随处扩散,最终造成对核心基础设施的重复改写与无法预期的复杂度。
为安抚内核开发者社区,目前 Rust for Linux 项目和 Linux 内核维护工作的贡献者 Miguel Ojeda 发布了所谓的 “Rust kernel policy”(Rust 内核策略),但并未将其纳入内核代码库。
Rust kernel policy:https://rust-for-linux.com/rust-kernel-policy\\"
Hellwig 质疑,这个文档只发布在网络上,而非放入内核代码树中,“所以我并不觉得这份‘政策’文档有什么实际价值。”“就我个人而言,我对 Rust 语言本身没问题,也能用它。我也很希望看到内核能更安全。但是,在一个无法控制的多语言代码库里工作,几乎可以肯定会让我把业余时间花在别的事情上。我听到有些人也在小声嘀咕类似的想法,只是大家没我这么直白而已。”
因此,Hellwig 强调,如果真正想解决内存安全问题,就应该在现有 C 代码上做更多防护、审查与修复,而不是把希望全部寄托在换语言上。他还提到,社区已经在做“编译器强制同步检查”或“整数溢出检查”等工作,但推进并不顺利,因为部分开发者或维护者对这类改动都尚有抵触,何况是引入另一种语言。
总之,Hellwig 认为,现在的现状是:Linus 想做什么就可以强行做什么(这毕竟是他的项目),但他觉得Linus 需要把这些事情说清楚——包括对贡献者的期望等等,都要讲得非常明白。
在 Hellwig 披露 Linus 态度的同时,另一位“重量级”内核维护者 Greg K-H 却持截然不同的观点。一直以来,Greg K-H 都倾向于支持引入 Rust ,本周他在邮件中也再次讨论了关于 Rust 和内存安全的争议。
“我们遇到的大多数(按数量而不是质量或严重程度来算)漏洞,都是源于 C 中那些愚蠢的小角落,而这些问题在 Rust 中完全不存在,”他写道。
“比如简单的内存越界写入(并不是说 Rust 能捕捉所有类似问题)、错误处理路径的清理、忘记检查错误返回值,以及使用已释放的资源等。这些正是我想在内核中引入 Rust 的原因:这些问题会直接消失,让开发者和维护者能够把更多时间投入到真正的错误上(比如逻辑问题、竞争条件等)。”
Greg K-H 进一步表示,他同样支持让 C 代码变得更健壮,这方面的工作并不会停止。“但是对于新的代码和驱动来说,用 Rust 编写可以杜绝(或大大减少)这些类型的错误,这对我们所有人来说都是好事,我们为什么不这么做呢?”
“C++ 在未来十年也无法为我们提供这方面的帮助,而且根据最近 C++ 语言委员会的讨论来看,如果你希望代码库能长期维持可维护性,那么最好尽快放弃 C++ 。”
当然,他也承认 Rust 并不是银弹,不会魔法般地解决所有问题。但他坚信这会有所帮助。
两周前辞去了内核维护者一职的 Hector Martin 认为,为了生存,Linux 需要主要利益相关方的支持,但 Linus 的“放任”态度让子系统维护者可以阻挠并滥用其他贡献者,打击社区士气却毫无后果。他举了一个例子:Rust for Linux 维护者、微软软件工程师 Wedson Almeida Filho 曾于今年 8 月辞职(离开 R4L),这在社区内广受关注。
确实,Linus 本人也曾在与贡献者互动时显得言辞尖锐。比如去年,他曾对谷歌的一名开发者说:“你的代码就是垃圾(your code IS GARBAGE)。” 和 Martin 的情况类似,这也引发了开源社区“维护者倦怠”的讨论。
开源社区的“维护者倦怠”(burnout)已是老生常谈。原因包括高强度的义务劳动、激烈的人身攻击、缺乏对志愿者工作的认可,以及超负荷的工作量等。Rust 语言工程师 Jynn Nelson 去年也曾指出,“因为倦怠而离开 Rust 项目的人数之多令人震惊,而仍处在倦怠边缘的人数也同样惊人。”
Sonatype 联合创始人兼 CTO Brian Fox近期接受技术媒体The Register采访时表示,“开源软件的开发者正以惊人的速度出现倦怠,这对软件供应链安全构成威胁。……那些被遗弃或维护不善的旧软件会留下巨大的安全漏洞。”
“我们最近发布的《软件供应链现状》报告发现,自 2020 年以来,开源项目更新频率陷入停滞或下降,这表明这些非营利性的维护者正面临倦怠或资源短缺,”他说,“到 2024 年,将有超过 30 万个项目的发布节奏放缓或停滞。”
Fox 认为,一个健康的软件生态系统需要一个运转良好的社区,而这需要资金来支持。“为项目维护者提供薪酬并雇佣更多开发者是一个好的开始;考虑到很多项目是由非营利基金会维护的,下游的主要用户也应该联合起来提供资金支持这些开源项目。”
当然,资金并非一切。Martin 称,他曾试图通过限制自己对内核上游维护的投入来避免倦怠。但去年,他经历了一系列个人挑战,其中包括“不得不应对各类骚扰者和跟踪者,他们对我和我的家人进行骚扰和攻击(并且仍在继续)。”
Martin 还表示,他之所以决定离开 Asahi Linux 和 Linux 内核社区,部分原因是感到自己被“背叛”:
“在(Linus 对我批评)之后的几天里,我得知一些内核和相关 Linux 圈子里的人一直在对我玩弄两面派手段,他们表面上对我和 Asahi Linux 表现出支持,私底下却对我心生抵触,并在背后煽动抵触情绪,”他说,“这一切都发生在完全没有任何人私下写邮件或以其它方式向我透露任何信息的情况下。我还听说,其中有一位在多个 Asahi Linux 生存所必需的项目中都身居高位的成员,竟然站在曾经直接伤害和骚扰我的人那边,并继续支持他们。”
参考链接:
https://www.theregister.com/2025/02/21/linux_c_rust_debate_continues/\\"
https://www.theregister.com/2025/02/11/rust_for_linux_project_support/?td=keepreading\\"
https://lore.kernel.org/rust-for-linux/2025021954-flaccid-pucker-f7d9@gregkh/\\"
https://lore.kernel.org/rust-for-linux/Z7SwcnUzjZYfuJ4-@infradead.org/\\"
","description":"自从 2022 年 Rust 代码首次被合并到 Linux 内核中,围绕它的争议就不断升温。Rust 因其在内存安全方面的优势而备受推崇,也被各国政府和安全专家认为能够有效减少由于内存安全漏洞导致的高危安全问题。 近段时间以来,围绕在 Linux 内核中引入 Rust 语言的讨论愈演愈烈。\\n\\n本周,一直以来对 Rust 持质疑态度的 Linux 内核关键维护者 Christoph Hellwig 在 Linux 内核邮件列表上的一条讨论线程中无奈披露,Linus Torvalds 私下说过,他绝对会不顾维护者的反对,合并 Rust 代码。\\n\\nHellwig 直言:…","guid":"https://www.infoq.cn/article/y3hRPLwDSQAdImaClNCe","author":"罗燕珊","authorUrl":null,"authorAvatar":null,"publishedAt":"2025-02-21T09:08:16.343Z","media":[{"url":"https://static001.geekbang.org/infoq/36/3613742cdf261231446d72557ef550b7.png","type":"photo","width":0,"height":0,"blurhash":""}],"categories":["编程语言","开源"],"attachments":null,"extra":null,"language":null},{"title":"分叉自 Terraform的OpenTofu 添加供应商迭代的功能","url":"https://www.infoq.cn/article/LbPIVKiBQ3JlrD43sj3Z","content":"OpenTofu OpenTofu 是一年前从 Hashicorp 的 Terraform 分叉(fork)出来的基础设施即代码工具,目前该工具发布了 1.9.0 版本。该版本带来了多项重要的特性,包括通过 for_each 进行供应商迭代的功能,从而能够简化多可用区(multi-zone)和多区域(multi-region)的部署。
根据 OpenTofu 的 “新功能”页面所述,for_each 是一个元参数,可用于模块和任意的资源类型。它会为字符串 map 或集合中的每个条目创建一个实例,允许创建、更新或销毁每个单独的实例。由于该功能对 OpenTofu 的运行方式有很大的改变,所以建议开发人员要谨慎使用,它只能用于静态变量和本地变量,无法用于从其他数据源或资源中获取的变量。
新的-exclude标记允许用户在plan或apply的操作过程中跳过特定的资源,实际上它与现有的-target选项功能恰好相反。该特性是本次版本发布中得到投票最多的特性请求之一。举个简单的例子,当使用tofu apply -exclude local_file.b运行如下配置时,a.txt和c.txt会被创建,而b.txt则不会被创建。
该版本的其他改进还包括更好的提前评估功能,以及加密、AzureRM 和 HTTP 后端的更新。此外,还有性能方面的提升。
在 LinkedIn 的一篇博客文章中,来自 MasterPoint 的 Matt Gowie 对新版本表示了欢迎,但是由于新的 for_each 功能非常强大,他建议大家谨慎使用:
“如果你知道自己正在做什么,并且知道它所带来的后果,那么 [for_each] 可能会成为你的 IaC 工具箱中一个很有意思的补充。”——Matt Gowie
来自 Datolabs 的 Tomas Daba 在回帖中补充到:
对于那些需要管理较小范围的供应商的人来说,for_each 将会解救他们,比如,OpenStack(管理多个项目)、GitHub(管理多个组织)和 PostgreSQL(管理多个数据库)。很高兴 OpenTofu 添加了这个功能!
Reddit 上的用户对 OpenTofu 独立于 Terraform 的发展轨迹褒贬不一。有人对 OpenTofu 增加了 Terraform 尚未提供的特性而感到高兴,而另一些人则对 OpenTofu 跟不上自分叉 Terraform 以来的变化而感到遗憾。用户“wywywywy”对新 for_each 功能大加赞赏:
“哇,这个特性在 Terraform 中都没有吧?它将大大简化我的代码”。wywywywy on Reddit
其他用户的评论则认为 for_each 的运行方式与 Terraform Stacks 类似,后者在商用版本的 HCP Terraform 中可用,但是在开源 Terraform 产品中并未提供。用户“aleques-itj”感叹 OpenTofu 中缺少暂存资源,去年 Terraform 就引入了该功能,OpenTofu 的维护者之一“fooallthebar”解释说,由于 AWS 功能仍处于实验阶段,所以尚未添加到 OpenTofu 中。
帖子还介绍了 OpenTofu 的搜索页面现在如何索引 4000 多个供应商和 20000 多个模块的文档,它们每 15 到 30 分钟会更新一次。JetBrains 宣布在其 2024.3 版本中会支持 OpenTofu,其功能包括 OpenTofu 特有的代码自动补全和状态加密检测。
宣布版本发布的新闻稿还强调了 OpenTofu 自去年作为 Terraform 的一个分叉版本创建以来所取得的成功。OpenTofu 项目的注册请求增加了两倍,达到每天 600 多万次,数据传输峰值达到每天 140GB。GitHub 下载量增加了约 30%,达到 150 万次,项目的 GitHub 评星现在已经超过 23000 个。
它的社区参与度很高,49 位贡献者为主仓库提交了 200 多个拉取请求,创建的新问题已超过 150 个,这表明用户群和社区参与很活跃。
OpenTofu 团队目前正专注于开发 OCI 提供商注册表,其工作原型正在开发中。
查看英文原文:
Terraform Fork OpenTofu Adds Provider Iteration and Exclusions(https://www.infoq.com/news/2025/01/opentofu-190/\\")
","description":"OpenTofu OpenTofu 是一年前从 Hashicorp 的 Terraform 分叉(fork)出来的基础设施即代码工具,目前该工具发布了 1.9.0 版本。该版本带来了多项重要的特性,包括通过 for_each 进行供应商迭代的功能,从而能够简化多可用区(multi-zone)和多区域(multi-region)的部署。 根据 OpenTofu 的 “新功能”页面所述,for_each 是一个元参数,可用于模块和任意的资源类型。它会为字符串 map 或集合中的每个条目创建一个实例,允许创建、更新或销毁每个单独的实例。由于该功能对…","guid":"https://www.infoq.cn/article/LbPIVKiBQ3JlrD43sj3Z","author":"作者:Matt Saunders","authorUrl":null,"authorAvatar":null,"publishedAt":"2025-02-21T07:00:00.948Z","media":[{"url":"https://static001.geekbang.org/wechat/images/1d/1d572210c8c020e7679b85aec3a7c1c8.png","type":"photo","width":0,"height":0,"blurhash":""}],"categories":["编程语言"],"attachments":null,"extra":null,"language":null},{"title":"2024 年数据库年度回顾: 增长、变化与争议","url":"https://www.infoq.cn/article/PuBDFmCys55k528MoP9P","content":"最近,Andrew Pavlo 的数据库领域年度回顾报告发布,报告涵盖了过去一年的趋势和创新。这份题为“ 2024 年数据库年度回顾”的报告观点鲜明:报告强调,虽然我们可能确实处于 “数据库的黄金时代”,但去年也见证了重大的许可证变化、DuckDB 的快速发展以及一些令人惊讶的新发布。
在讨论开源数据库 “动荡”的一年(包括 Redis 和 Elasticsearch 许可证的重大变化)时,Pavlo 写道:
请注意,与其他采取类似举措的系统相比,Redis 和 Elasticsearch 引起的反响更大。(…)这不可能是因为 Redis 和 Elasticsearch 的安装数量比其他系统大得多(…),因为 MongoDB 和 Kafka 在更换许可证时的安装数量也同样庞大。就 Redis 而言,我只能认为,人们认为 Redis 公司从他人的工作中获利并不公平,因为该公司的创始人并非该系统最初的创建者。
根据 2024 年的报告文章,与 Postgres 近年来成为操作型数据库的默认选项类似,DuckDB “成为运行数据分析查询的默认选项”。正如 Pavlo 所说的那样,这一趋势证明,最近发布的将 OLAP 数据库与 Postgres 相集成的四种不同的扩展是合理的:
大多数 OLAP 查询不会访问那么多数据。Fivetran 分析了来自 Snowflake 和 Redshift 的跟踪数据,结果显示,查询扫描的数据量中位数仅为 100 MB。这么小的数据量意味着,一个 DuckDB 实例就足以处理大多数的查询。
Pavlo 是卡内基梅隆大学的副教授,也是 OtterTune 的前联合创始人。他从 2021 年开始发布年度分析报告,重点关注 PostgreSQL 的主导地位。2022 年的主题是 “区块链数据库仍然是个愚蠢的想法”,而到了 2023 年,他又将重点转移到了向量数据库的崛起上。
这位数据库管理系统专家 2024 年的回顾引起了广泛的关注,在 Reddit 和 Hacker News 上引发了热烈的讨论。其中有一段观点鲜明的陈述(我不喜欢 Redis。它很慢,有假事务,查询语法也很怪异。)在 Hacker News 上引发了一场与 Redis 创建者 Salvatore Sanfilippo(绰号 ”antirez\\")的激烈争论,争论的焦点是这个曾经开源的键值存储的重要性和设计。
年度回顾关注了一些重要的发布,重点介绍了 Microsoft Garnet 和 Valkey ,它们都是值得注意的键值存储。不过,Pavlo 对 MySQL v9 的功能列表表示失望,并认为亚马逊 QLDB 的退出意义重大:
如果连亚马逊都不知道如何在区块链数据库上赚钱,那就没人能做到了。
在谈到最近发布的 Aurora DSQL 预览版时,他补充道:
这一公告表明,在数据库领域,“ Aurora ”这个名字有很高的品牌知名度。这个 DBMS 似乎并没有共享其旗舰产品 Aurora Postgres RDS 的代码,但亚马逊云科技还是使用了这个名字。
继 Pavlo 之后,ByteBase 团队最近也发布了 “ 2024 年数据库工具年度回顾“。感兴趣的读者可以在 YouTube 上观看 Pavlo 的许多大学课程以及最近的演讲 “What Goes Around Comes Around… And Around… ”。
原文链接:
https://www.infoq.com/news/2025/01/database-review-2024/\\"
","description":"最近,Andrew Pavlo 的数据库领域年度回顾报告发布,报告涵盖了过去一年的趋势和创新。这份题为“ 2024 年数据库年度回顾”的报告观点鲜明:报告强调,虽然我们可能确实处于 “数据库的黄金时代”,但去年也见证了重大的许可证变化、DuckDB 的快速发展以及一些令人惊讶的新发布。 在讨论开源数据库 “动荡”的一年(包括 Redis 和 Elasticsearch 许可证的重大变化)时,Pavlo 写道:\\n\\n请注意,与其他采取类似举措的系统相比,Redis 和 Elasticsearch 引起的反响更大。(…)这不可能是因为 Redis 和…","guid":"https://www.infoq.cn/article/PuBDFmCys55k528MoP9P","author":"作者:Renato Losio","authorUrl":null,"authorAvatar":null,"publishedAt":"2025-02-20T07:00:00.045Z","media":null,"categories":["数据库"],"attachments":null,"extra":null,"language":null},{"title":"Dagger:我们用Go和WebAssembly替换了React前端","url":"https://www.infoq.cn/article/zFH5IHDKiyZBOZ1vpSAC","content":"几周前,我们正式推出Dagger Cloud v3,全新的Dagger Cloud用户界面。v3与v2之间一个显著的区别在于,新的用户界面是用Go语言编写,并基于WebAssembly(WASM)实现的。乍看之下,这似乎是一个不同寻常的选择——在开发Web UI时,Go通常不是人们首先想到的语言——但我们有充分的理由。在这篇博文中,我将详细阐述我们选择WebAssembly的原因,我们在实现过程中遇到的挑战(以及我们是如何解决的这些问题)以及最终的结果。
Dagger的工作原理是构建操作的有向无环图(DAG),并对其进行评估(通常是并行评估)。本质上,这是一个很难直观展示的过程。为了帮助用户更好地理解,我们提供了两种实时可视化界面:Dagger Terminal UI(TUI),包含在Dagger CLI中,以及Dagger Cloud,一个在线Web仪表盘。Dagger TUI是用Go实现的,而Dagger Cloud(v3之前)是用React编写的。
我们希望这两个用户界面尽可能保持一致。然而,实时解析Dagger事件流并生成用户界面的过程相当复杂。在一些更复杂的场景中,事件流可能包含数十万个OpenTelemetry Span数据,管理这些数据结构的复杂性会迅速攀升。这导致Web UI常常因数据量过大而变得卡顿和缓慢。为了解决这一性能瓶颈,我们不得不为React应用程序采用一种不同的实现方式。
因此,我们最终有了两个实现相同目标的界面,一个使用TypeScript和React语言及生态系统,另一个则使用完全不同的语言和生态系统(Go)。我们无法在这两者之间轻松地共享业务逻辑。作为一个小团队,我们需要快速交付功能,不得不为每个功能分别实现两次,这对我们的开发速度造成了巨大的阻碍。
我们开始考虑一种新的方法,主要要达成两个目标:
统一代码库,消除重复,能够更快推出新功能。构建清晰、流畅的Web UI,与Terminal UI的速度和性能相当。
我们的初步目标是让Dagger Cloud和TUI共享同一个代码库。我们很早就决定采用Go代码库。从技术上讲,我们也可以反过来,使用TypeScript开发TUI,但考虑到我们主要是Go工程师团队,选择Go能让其他成员更容易参与其中,无论是添加新功能还是帮忙调试问题。除了统一为一种语言外,这一选择还为我们带来了灵活性,打破了团队内部的隔阂。
既然我们决定直接在浏览器中运行Go代码,WebAssembly就成了顺理成章的选择。但这仍然带来了一些挑战:
Go + WebAssembly组合不如React和其他JavaScript框架成熟。没有现成的组件库可用,开发工具也不够丰富,等等。我们清楚地意识到,我们将不得不从头开始构建大部分用户界面组件。大多数浏览器对WebAssembly应用程序设定了硬性2 GB内存限制。我们预计在查看大量追踪信息时这可能会是一个问题,我们知道我们需要进行大量的优化,减少内存使用并确保用户界面的稳定性。不过,这也有积极的一面——对WebAssembly UI所做的任何内存优化也会惠及TUI用户,因为它们现在共享同一个代码库。
接下来的问题便是:“我们该如何构建它?”我们选择使用go-app(https://go-app.dev/)框架开发新的基于WebAssembly的用户界面。go-app是一个专为WebAssembly渐进式Web应用程序(PWA)设计的高级框架。它保留了Go语言的核心优势,例如快速编译和原生静态类型支持,同时采用了基于组件的用户界面模型,与React类似,这使得迁移过程变得更加容易。
由于Go + WebAssembly组合并不是主流,Dagger团队内部对其可行性自然存在一些怀疑。例如,目前没有真正成熟的go-app UI组件生态系统,我们不得不自行开发,但我们不清楚这一过程会有多容易或多困难。我们还担心与其他服务(Tailwind、Auth0、Intercom、PostHog)的集成,以及同时渲染数百个需要实时更新的组件的性能问题。
为了回答这些问题并降低项目风险,我花了将近一个月的时间进行原型设计,目标是尽可能多地使用go-app重新实现现有的用户界面。事实证明,我们没有遇到太多障碍:WebAssembly已经是一个文档完备的开放标准,而大多数其他问题都可以在go-app的文档中找到答案。正如预期的那样,最大的挑战是内存使用限制,这需要进行精心的设计和优化。
在成功完成一个可行的概念验证后,团队的信心大幅提升,我们随即启动了“awesome wasm”项目,致力于打造一个生产级的实现。以下是这段旅程的一些关键要点:
内存使用无疑是项目成功面临的最大挑战。我化了大量时间研究如何渲染超过20万行的日志输出而不崩溃。我们因此对虚拟终端渲染库进行了深度优化,同时这也显著降低了TUI的内存使用(正如前面提到的,共享代码库意味着在一个界面的优化成果可以无缝惠及另一个界面)。在处理大量JSON数据时,Go WASM的解析速度较慢,这促使我们对架构进行了重大调整,我们构建了一个“智能后端”,通过WebSockets增量加载数据,并采用了Go语言中相对鲜为人知的encoding/gob格式。最初,WASM文件大小约为32MB。通过应用Brotli压缩技术,我们将其缩减至约4.6MB。我们曾尝试在CDN中实时进行Brotli压缩,但由于文件太大,最终决定将压缩步骤放在构建流程中。除了内存挑战之外,我们最初的大多数担忧都证明是多余的。编写用户界面组件并不难,与其他服务的集成也非常顺利,我还找到了高效处理组件实时更新的方法。我找到了一些有用的NPM包,想知道是否可以在Go中使用它们。WebAssembly提供了一个可以连接Go和JavaScript的接口,于是我构建了一个使用Browserify加载NPM包的Dagger模块。这个模块允许我们生成一个可以嵌入到Go应用程序中的JavaScript文件。这样一来,我们就可以主要使用Go开发,在必要时也能加载用原生JavaScript实现的辅助工具。我不是React专家,在我看来,React的组件实现方式有点僵化,而go-app则灵活得多。在go-app中,你可以随时更新任何组件,有更多优化的自由度。例如,我需要优化一个渲染超过15万行输出的组件,我能够尝试不同的方法,并从中选择效果最好的一种,让整个优化过程变得更加轻松!虽然go-app没有像React那样的内置浏览器开发工具,但我可以借助Go自身的工具(例如pprof)以及浏览器自带的分析器来进行分析和调试。这非常有助于检查函数调用、跟踪CPU和内存使用情况以及评估不同优化方法对内存使用的影响。使用go-app的另一个意外收获是:由于Dagger Cloud是一个PWA,它可以打包成桌面或移动应用。这意味着用户可以像启动原生应用一样启动Dagger Cloud,获得全屏浸入式体验,而无需先打开浏览器,它甚至可以在桌面任务栏或移动设备的程序坞拥有一个专有的图标。
几周前,我们向Dagger指挥官们推出了Dagger Cloud v3,用以收集反馈,并计划在不久后向所有人正式开放。
从React切换到WASM,不仅使所有Dagger界面的用户体验更加一致,还在渲染大型和复杂的追踪信息时实现了更高的整体性能和更低的内存使用。
从工程角度来看,这也为我们团队带来了显著的好处。优化工作往往与实际实现功能的工作量相当,甚至更多。我们因此能够避免分别优化Web UI和TUI,而是将精力集中在交付新功能上,实在是令人欣慰。
Dagger Cloud v3在Dagger社区引起了热议,最近我们被问到的一个较多的问题是:谁应该考虑这种技术,谁又不适合?
我们想强调的是,我们并不是推荐普遍都用Go开发前端。我们之所以选择这条路线,是基于一系列具体且充分的理由:我们拥有一支出色的Go工程师团队;面对一个复杂且难以用TypeScript/React扩展的UI;需要在两个代码库之间实现标准化和代码复用;以及在公司范围内整体提升开发速度的要求。这确实是一个相当特殊的情况。如果你也有类似的情况,那么这种方案当然值得考虑。但如果你的情况有所不同,那么或许应该优先考虑其他更通用的工具和标准。
原文链接:https://dagger.io/blog/replaced-react-with-go\\"
","description":"几周前,我们正式推出Dagger Cloud v3,全新的Dagger Cloud用户界面。v3与v2之间一个显著的区别在于,新的用户界面是用Go语言编写,并基于WebAssembly(WASM)实现的。乍看之下,这似乎是一个不同寻常的选择——在开发Web UI时,Go通常不是人们首先想到的语言——但我们有充分的理由。在这篇博文中,我将详细阐述我们选择WebAssembly的原因,我们在实现过程中遇到的挑战(以及我们是如何解决的这些问题)以及最终的结果。 两套代码库 = 更多的工作量,更少的功能\\n\\nDagger的工作原理是构建操作的有向无环图(DAG…","guid":"https://www.infoq.cn/article/zFH5IHDKiyZBOZ1vpSAC","author":"Alex Suraci","authorUrl":null,"authorAvatar":null,"publishedAt":"2025-02-19T09:48:03.679Z","media":null,"categories":["编程语言"],"attachments":null,"extra":null,"language":null},{"title":"马斯克“查账”曝150岁老人领福利,竟是COBOL惹的祸?","url":"https://www.infoq.cn/article/7OFw27GfLm370K4M1lR3","content":"最近,马斯克表示他领导的“政府效率部”(DOGE)查账时发现了一些很离谱的事:比如美国财政部每年给一群连身份都说不清的人发了1000多亿美元的福利金,他看到的记录里,有大约150岁的人。
对此,马斯克不无嘲讽地表示:“有些事情太荒谬了。比如,只是粗略检查了一下社会保障系统,就发现里面有些人的年龄大约 150 岁。你认识 150 岁的人吗?我不认识。他们要么早该被列入吉尼斯世界纪录,却错过了机会;要么,我猜他们已经去世了。总之,肯定有问题。”
马斯克在说这些话时,他的表情是一脸的不可思议,而原本认真倾听的特朗普,也是忍不住笑了出来。
美国媒体事实核查员表示,他们无法证实或否认马斯克的说法,但也指出他们目前“没有发现任何 150 岁老人申领福利的具体证据。”
有不少人对马斯克的说法表示怀疑,还有人给出了一种既简单又搞笑的解释:据说马斯克的DOGE 团队成员都很年轻,但这些年轻人可能不知道,美国社会保障系统用的是非常老旧的计算机,而这些计算机运行的是古老版本的编程语言 COBOL。1875 年 5 月 20 日,一些国家成立了国际度量衡局,制定了统一的质量和长度标准。后来,该机构也制定了日期标准,并以 1875 年 5 月 20 日作为起始日期,以纪念这一历史事件。老版本的 COBOL 就采用了这个日期作为基准。美国社会保障系统的计算机沿用了这种设计。
那么,如果社会保障系统中某人的出生日期未知,会发生什么情况呢?那一栏就会是空的,而系统会默认这个人出生于 1875 年 5 月 20 日——也就是大约 150 年前。这正是马斯克团队发现 “150 岁老人” 的原因。
于是,围绕着这是否是编程语言导致的bug,大家展开了激烈讨论,各方说法不一。有自称是COBOL程序员认为这就是由于COBOL缺少出生日期导致的。
我是一个老程序员,用今天的说法就是“Coder”。许多老程序员都知道 COBOL,而年轻的编程人员则不太了解。我觉得应该有人告诉马斯克,在 COBOL 中,如果缺少日期,程序会默认使用 1875 年。例如,2025 - 1875 = 150。
是真的,因为我的公司在 COBOL 系统上工作,当客户没有日期时,它就是 1875。
但还是有更多程序员不断提出质疑,主要是大家找不到任何能够支持这一结论的技术资料。毕竟大家见过的默认日期主要是 1970-01-01,甚至也有程序员指出COBOL 并不使用 ISO 8601 日期格式。
我见过的唯一默认日期是 1970-01-01,这是 Unix 时间中的 0 点,肯定早于 ISO 8601 的制定。上个月我在看 Brian Goetz (甲骨文公司的 Java 语言架构师)的演讲时还在思考默认日期的问题,但他并未提到 1875 年。我觉得 1875 年这个说法是胡编乱造的。
我曾在 COBOL 系统上工作过......COBOL 不使用 ISO 8601 日期格式。
大家莫衷一是,密歇根大学经济学教授Justin Wolfers从统计学角度指出,确认这个问题并不需要成为一名程序员,只需输入:tab age,你会发现有一些99岁的人,少数100岁的人,几位101岁的人,以及一堆150岁的人,但没有人在130岁或140岁之间。这至少清楚地表明,这是一个编码问题,而不是欺诈行为。
如果确实是一个编程问题,而且 COBOL 不使用 ISO 8601 日期格式,那还有什么其他原因可能导致这个现象的出现呢?
昨天,有一名“年轻程序员”在StackExchange上发出了灵魂提问:“是否有确凿证据表明,COBOL规范或者实现在以这种方式运行?如果没有,那是否存在某些与COBOL相关的软件(例如DBMS)能够解决这种默认设置?”这个问题的最佳答案给出了一个不一样的解释:1875年作为日期基准的起源并非技术规范要求,而是基于社会保障制度的实施时间(1935年)结合存储优化需求设计的经验性方案,它体现的是早期程序员在硬件限制下\\"空间换逻辑\\"的设计哲学。
简单的说,这取决于具体要记录什么样的数据。 曾有一段时间,数据结构是为了满足特定目标而制作,并非围绕编译器特性。通过下面的描述,可以清晰地看到有效日期的限制条件:社保制度于1935年推出。要想领取福利,必须满足以下条件:至少支付40个季度,即10年;年龄至少为65岁。这意味着,第一批定期领取社会保障金的人群是1945年时65岁的群体,也就是1880年出生的人。而1880年之前出生的人不符合条件,因为他们的年龄太大,大多数因未缴纳足够年限的社保而无法享受政策。而年龄较小的人(即仍在支付社保的人群)将在未来退休时享受待遇。因此,考虑到5年的容错空间,我们最终将1875年定为最早的年份起点。这个日期区间的判断过程看起来是相当合理的,对吧? 所以从严格意义上讲,这并不是COBOL的问题,而是为了适应任务数据。当然,这样的细节很难与公众沟通。所以既然COBOL(包括汇编语言)程序中确实经常出现这类问题,那么将其归咎于语言本身也没啥大问题。毕竟这种编程方式在COBOL中算是一种良好实践,当时就这要求。 那么,COBOL是否会将损坏或缺失的日期默认设置为1875-05-20?并不会,而且这事的核心其实在于如何优化数据存储。这是一种如今几乎失传的手艺,毕竟如今的程序员们会使用最强大的类型来处理所有事务(例如用float来存储bool)。那时人们不仅关心过程逻辑,还需要关心代码和数据的最佳实现。 当然,人们会用1875-05-20是《米制公约》的签署日期还有这是“老程序员们”的独到智慧来强行解释,但这只是对结果的解释、而非根本原因。事实上,这完全只是个随意取值的巧合,随机碰上了《米制公约》的签署日。 哪怕找不到任何技术资料来支持这个说法,相信有经验的程序员也很清楚,根据某些固定点来确定日期是种常见做法。毕竟所有日历系统都要设定这样一个锚点,比如公元1年;或者以Unix为例,其日历以1970年作为基准。这项技术标准中从来就没明确提到过1975年的意义,而且我也不是唯一持这种“随机取值”观点的人。毕竟1875年最大的意义,就是前面提到的跟社保制度的落地时间相匹配。 “那么作为一名‘年轻程序员’,我们不禁要问:是否有确凿证据表明,COBOL规范或者实现在以这种方式运行?”这跟COBOL或者任何其他数据无关,而是一种常识性的数据结构设计思路。 “如果答案仍然是否定的,那有没有一些虽有力的论据能够支持或者驳斥这种说法的合理性?”恰恰相反,任何对结构化数据拥有最底限了解的人,都能理解为什么要这样做。再次强调,这是一种常识。 请注意,我们这里讨论的是上世纪30年代到50年代期间设计出来的系统。当时的主流存储方案是打孔卡,每个字符都对应着很高的成本。将日期存储为8个字符代表着极大的浪费,因此当时大多数商业应用程序会将日期存储为5个字符。其中3个字符表示日期,2个字符表示年份,这明显是在用糟糕的编码实践来换取成本节约。 现在,社保制度需要覆盖超过100岁的群体,因此将合理的截止年份定义为基准有助于节约后续字符需求量。所以说,出生日期确实可以用6个字符、而非8个字符来编码,其中3个字符表示日期,加上3个字符表示年份(减去1875后的数字)。 反过来说,未填写的日期(例如出生日期未知,也就是数值缺失)代表内容为空。按照以上逻辑,该值会输出1875,确保不致报告异常。 整个问题的逻辑,就是这么简单。
网友们经过了两天的激烈讨论,发现马斯克又在今天晒出了一个更详细的年龄/人口表,夸张的是超过150岁的人还不是少数。
不管是不是编程的问题,都说明老古董社会保障系统的数据管理和监管问题很大,不仅仅是一个COBOL语言缺省日期的问题。
而且这些年轻工程师们已经在“大动干戈”,DOGE表示,他们的目标是实现政府系统“现代化”,这意味着需要对系统内的代码加以修改。也就是说,效率部的成员们很可能正在面对自己从未见过的东西:COBOL,即面向业务的通用语言。
COBOL语言由五角大楼及IBM等公私合作组织于上世纪50年代开发而成,其目标是为商业应用程序构建一种通用且与英语相似的编程语言。在之后的几十年间,私营企业已经不再使用这种语言。而该语言的代码维护起来难度大、成本高,且主要面向批处理需求所打造,因此无法与其他基于云环境的现代实时应用程序进行良好集成。但在华盛顿特区,情况则完全不同。尽管最近几十年来也在陆续推动各项现代化进程,但COBOL语言仍在政府部门内用于管理各类金融交易的大型机系统中广泛存在,具体涵盖纳税、退税、社会保障、福利政策乃至医疗保险报销等业务流程。
只要维护得当,这些系统其实相当可靠。正如一位专家所言,COBOL是在各大型机组件之间充当“粘合剂”,靠代码协调硬件同应用程序及数据库之间的协同运作。大型机本身就具备冗余和容错等能力,因此永远不会发生故障。所以时至今日,基于COBOL语言的大型机系统仍在金融服务、电信和医疗保健等受到严格监管的行业中发挥作用。
有些人担心这群年轻工程师可能会闯入COBOL代码库,并在尚不了解影响情况的同时草率动手。一般来讲,涉及到系统底层代码的任何变更,都必须遵循其他机构工作人员编写的详尽业务需求。而这些系统中的任何延迟或者停机,都会对现实生活中人们的生活产生直接影响。面对马斯克和他的效率部顾问们,软件工程师和机构内的其他人员当然会给予指导并强调尊重既定规范的重要性。但马斯克的这支队伍显然相当难以预测。如果效率部工作人员贸然重写COBOL代码中的某些部分,很可能会导致意想不到的后果,包括对关键服务的严重破坏。而且哪怕不是必然出事,引发意外后果的可能性也相当之高。
从某种意义上讲,COBOL语言象征着这批年轻理想主义者与真实世界之间的脱节。维护COBOL代码是一个将新法规逐步转化为具体业务需求、将需求整理为计算机代码、在安全环境中全面测试代码、将最终产品投入生产,并在系统中记录其用途的漫长过程。但由于自上世纪90年代以来COBOL不再作为计算机科学课中的学习内容,因此从事这项工作的人们往往年龄较大,且整体人员数量也在不断减少。
技术服务商Very Little Gravitas的负责人Don Hon表示,马斯克和他的效率部成员大多是来自硅谷文化圈的年轻软件工程师。他们习惯于以一种极具特色的“快速行动、打破常规”流程作为指导,来实现复杂服务与产品的现代化。
Hon强调“看看特斯拉早期开发全自动驾驶软件的方式就能明白,我们科技行业具有一种通行文化,即「让我们一起想办法,先得到一套能够运行起来的东西。它会崩溃,之后我们再想办法修复」。”可以肯定的是,这样的理念在过去已经为马斯克这样的企业家们带来了巨大成功。但这样的计算风险对于由数亿人依赖的政府系统来说,则意味着完全不同的情况。整个职业生涯都在开发面向消费者软件的工程师们,恐怕并没有能力为变更政府支付系统而绘制出正确的风险曲线。
Hon解释道,“有人可能会说,最多就是错过一笔医疗补助之类的,那有什么大不了,我们可以稍后解决嘛。”但实际上,COBOL软件其实很脆弱。比方说,一旦代码更新了与现有策略相冲突的新策略,则整个系统会彻底崩溃。有些系统还缺少自动测试程序,因此软件工程师必须手动编写测试,并在合并新代码之前一遍遍完成耗时的测试任务。而对于那些缺少正确记录的代码片段,很多之前没接触过项目的人很可能搞不清这些代码是做什么的,最终导致情况进一步复杂化。
所以鉴于现在的情况,美国人能做的只能是希望DOGE能三思而后行,保留那些掌握COBOL语言并了解项目历程进程的资深员工。毕竟,COBOL那些难以理解和不够健壮的要素只能算是特点,而非纯粹的缺陷。
参考链接:
https://www.threads.net/@ashmore_glenn/post/DGDfmj6TsZS\\"
https://x.com/i/trending/1890706819724824578\\"
https://x.com/JustinWolfers/status/1890836472174924143\\"
https://retrocomputing.stackexchange.com/questions/31288/does-or-did-\\"COBOL\\"-default-to-1875-05-20-for-corrupt-or-missing-dates\\"
https://www.fastcompany.com/91278597/elon-musk-doge-\\"COBOL\\"-language\\"
","description":"最近,马斯克表示他领导的“政府效率部”(DOGE)查账时发现了一些很离谱的事:比如美国财政部每年给一群连身份都说不清的人发了1000多亿美元的福利金,他看到的记录里,有大约150岁的人。 \\n\\n对此,马斯克不无嘲讽地表示:“有些事情太荒谬了。比如,只是粗略检查了一下社会保障系统,就发现里面有些人的年龄大约 150 岁。你认识 150 岁的人吗?我不认识。他们要么早该被列入吉尼斯世界纪录,却错过了机会;要么,我猜他们已经去世了。总之,肯定有问题。”\\n\\n \\n\\n马斯克在说这些话时,他的表情是一脸的不可思议,而原本认真倾听的特朗普,也是忍不住笑了出来。\\n\\n \\n\\n这是个编程问题吗?\\n\\n \\n\\n美…","guid":"https://www.infoq.cn/article/7OFw27GfLm370K4M1lR3","author":"Tina,核子可乐","authorUrl":null,"authorAvatar":null,"publishedAt":"2025-02-17T12:36:06.503Z","media":[{"url":"https://static001.geekbang.org/infoq/64/64a785ae1b638d2019b2fa1e9d8a2e28.jpeg","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/9f/9f11fb7410a1b00391441d6799adfa49.jpeg","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/51/513ba7a68371775fbc7e1169aa5b6d24.jpeg","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/82/82762a8b144519f6beb72a5c0965d6be.jpeg","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/9e/9e9d34f4082dd1997cdc1953212fbc01.jpeg","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/05/0587299bedd2f81912334393b3d7e63b.jpeg","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/6e/6e18720b139e72a5b9d6bc1cefb86105.jpeg","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/31/31f86db81fbd46bb47b67d26987729f7.jpeg","type":"photo","width":0,"height":0,"blurhash":""}],"categories":["编程语言"],"attachments":null,"extra":null,"language":null},{"title":"浙江霖梓基于 Doris + Paimon 打造实时/离线一体化湖仓架构技术实践","url":"https://www.infoq.cn/article/wSRPozYpL7GsvrYjEdl0","content":"
导读:浙江霖梓早期使用 CDH 产品套件搭建了大数据系统,面临业务逻辑冗余、查询效率低下等问题,基于 Apache Doris 进行整体架构与表结构的重构,并基于湖仓一体和查询加速展开深度探索与实践,打造了 Doris\\" + Paimon 的实时/离线一体化湖仓架构,实现查询提速 30 倍、资源成本节省 67% 等显著成效。
浙江霖梓是一家专注于深度学习和人工智能应用的金融创新企业,为企业提供精准经营决策,并基于大数据的风控能力的一系列高效便捷的金融服务产品。随着业务的持续扩展,大数据业务系统的局限逐渐暴露:报表系统计算缓慢、运维成本持续攀升、组件间的高度耦合导致架构稳定性较差等,严重影响了大数据系统产出效率,因此浙江霖梓引入 Doris+Paimon 重新构建了实时/离线一体化湖仓架构,为反欺诈策略、用户⾏为分析、BI 应用等若干系统提供了高效准确的服务,实现了查询提速 30 倍、资源成本节省 67% 等显著成效。
下图是早期的 CDH 架构示意图,MySQL 数据通过 Sqoop 全量导入至 Hive,埋点数据通过 Java 程序清洗后进入 Flume 的 source 端,并最终 sink 到 Hive 的分区表中,离线数仓任务的 ETL 由 Hive 执行,批处理作业则通过 Spark SQL 运行,所有任务都从 ODS 层出发直接进入到 APP 层。数据开发与分析工作则依赖 CDH 自带的 Hue 平台,任务调度依赖 easyScheduler,最终与自主研发的报表平台对接,实现数据的可视化。
随着业务扩展,早期架构的局限逐渐暴露:数据采集、变更及分析效率低下的同时,整体运维成本也在持续攀升,并且各组件间的高度耦合降低了架构的整体稳定性。此外,由于各部门未统一指标⼝径,不同取数逻辑的分析结果存在较大差异,使得业务痛点的精准定位变得异常困难,传统的 Hive+BI 系统已无法满足需求。
为了解决上述痛点,浙江霖梓考察了市⾯上较为常⻅的大数据分析组件,如 HBase、ClickHouse、Apache Doris 等,最终从查询性能、写入性能、投⼊成本等⽅⾯评估,最终选择了综合实⼒⾮常突出的 Apache Doris\\"。以下为前期技术选型调研结果:
相较于其他产品,Apache Doris 的核心优势如下:
查询快:⽀持物化视图和向量化执⾏引擎,并⽀持多种表模型以及 Rollup 、BloomFilter、倒排索引等,离线跑批速度非常快,并对查询性能有显著加速效果。存储省:通过表的优化和冷热数据分层特性,能够充分利用机械盘和固态盘,显著提升资源利用率。此外,采用高效的 ZSTD 压缩算法,压缩比高达 10 倍,大幅降低了存储费用。运维简单:不依赖外部系统, 原架构一旦某个服务发生异常,与其关联的服务都会受到影响,给运维增加了难度。⽽ Apache Doris 的原生运维工具 Doris Manager 可以满⾜⽇常绝⼤多数的运维需求,再加上 Doris 架构简单且不存在⼩⽂件问题,在线扩展节点十分方便,⼤⼤降低了运维难度。便捷迁移:兼容 MySQL 协议,报表系统只需要修改源配置就可以轻松对接。社区活跃:Apache Doris 的社区⾮常活跃,技术团队解决问题的能⼒较强;版本迭代速度快,能很好的解决业务痛点。
经过七个月的设计与实施,最终完成了基于 Apache Doris\\" 离线 / 实时一体化湖仓统一架构。如上图所示,离线数据通过 DataX 同步、实时数据通过 Flink CDC 采集加工,这些数据最终存储到 Doris 或 Paimon 表格式中。
目前基于 Paimon 的全量数据入湖还在持续完善,原先的部分离线数据通过 Flink CDC 实时入湖,而另一部分会直接进入 Doris 来缩短数据链路。这些数据经由 Doris 统一分析处理后,最终服务于自研数据服务。在这其中,Doris 集群被灵活拆分为多个资源组,分别满足离线数仓、数据集市、实时业务监控等不同上游服务的数据处理与分析需求。Apache Doris 的引入,也带来许多显著收益:
查询效率提升:Hive ⾯对复杂的⼤数据量跑批任务时,耗时往往超过 20min,亿级别的⼤表 Join 甚至需要花费 35-50min,⽽ Apache Doris 在未经优化的初次跑批中耗时 7min ,经过基础优化后缩减至 40s-90s,查询速度提升近 30 倍。开发效率提高:原架构使用 Spark 进行 ETL 之后导入数仓,业务开发需要结合 Spark、Hive、Kafka 等多组件;切换至 Doris 后,只需专注 Doris SQL 的开发与优化,开发工作大大简化。此外,Doris 与 Kafka、DataX、Flink 等组件兼容性较高且包含丰富的插件库,进一步提高了开发效率。负载隔离:利⽤ Workload Group 、Resource Group 等配置代替 Yarn,实现更加合理的资源隔离。更低使用成本:依赖 Doris 极致的压缩与计算性能,原架构的 27 台服务器精简至 10 台左右,总体资源开销降低至原来的 1/3(节省了 67%),为⽇后 PB 级别的数据量提供了更优的成本方案。运维更加便捷:通过 Doris Manager\\" 轻松部署和接管 Doris 集群,实时查看集群的运行状态和详情,快捷地对集群进行扩缩容、升级及重启操作,数据管理更流畅、更高效。
详细可参考 Doris Manager 介绍文档\\"与安装手册\\"
离线数据处理:将 Sqoop+Flume 替换成 DataX,并新增了 Data X Doris Json 一键生成功能,利用主键模型的 Replace 特性,将全量同步优化为增量同步。改造后,数据采集时间从原来的 5h 缩短至 1.5h,处理效率提升 70%。第三方埋点数据:之前需要通过大数据后端项目的接口 ETL 后传输到 Flume,改造后,ETL 逻辑依靠 Doris 实现,以 StreamLoad 的方式直接接入埋点数据。后端日志数据迁移:由于后端日志打印频繁,MySQL 存储压力较大,影响业务分析效率。改造后通过 Routine Load 对接 Kafka 消费日志数据,并设置了 TTL,此外还根据业务开发侧的需求进行了简单的数据清洗,实现高性能的日志检索功能。风控业务的实时命中策略与反欺诈实时指标处理:Flink 负责将 ETL 处理后的数据写入 Paimon,通过结合 Doris 的湖分析能力接入 Paimon,凭借 Doris 的统一查询入口为业务决策系统和数据分析提供数据服务。这一优化确保了业务问题能够迅速被发现并解决,有效避免了以往 T+1 数据模式下因数据滞后和业务感知延迟所带来的问题。
在构建新架构的同时,对数据表也进行了深度重构。基于 OneData 理论和 Apache Doris 的表模型设计,我们从底层建表逻辑出发,精心整理了以下内容,现与大家分享:
ODS 贴源层:使用主键模型备份 MySQL 的原始数据,可以接受 MySQL 历史数据的物理删除,从⽽减轻业务压⼒,降低云上存储成本。
DWD 明细层:主要使用主键模型,为了确保明细数据的准确性,也可以采用其他模型进行校验。在此层将屏蔽 ODS 层的数据,以提高数据表的复用性。
DWS 汇总层:采用聚合模型来汇集不同维度的表数据,形成若⼲张 Base 表,后续基于 Base 表进⾏维度上卷或 BI 分析,使 SQL 语句更加简洁、批处理性能得到提升。
APP 报表层:对接报表系统并定期通过邮件或办公软件发送至业务⽅,以供业务监控与业务决策。 由于该层涉及到基于不同时间字段维度以及维度上卷,因此选用明细模型。
重构后的数据表结构更加简洁,显著提升了 SQL 语句的可读性,也使得数据同步性能,有效减轻了大规模数据全量同步所带来的沉重负担,从而避免业务阻塞。
早期业务结算系统的核心数据难以复用,资源浪费的同时,数据批处理的效率也较为低下。引入 Doris 后,基于 Doris 的数仓建模复用了 DM 层的数据,有效支撑了结算代偿、回购对账、账户管理等核心业务需求的及时处理。此外还接入了风控决策引擎,为其提供了实时反欺诈数据指标,实现了高效实时计算和核心数据回流。
得益于 Doris 出色的即席查询和实时写入能力,数据回流的调度执行耗时平均不超过 2 秒,业务系统的灵活性和数据响应速度相比之前提高了 8-12 倍。
改造初期,由于资源管理配置不当,集群性能未达预期,可以通过调整 Workload Group 的并⾏查询数量、等待队列容量和超时时间,避免多条 SQL 语句抢占资源从⽽降低集群整体性能,此外,调整 Workload Group 的 max_concurrency、max_queue_size、queue_timeout 等参数,避免查询超时。
Workload Group 相关数据开发的逻辑概念如下:
早期架构由于缺乏系统性的架构设计理论依据,导致了组件开发与维护工作十分复杂,既未设置合理的数据分区,也未对存储效率、查询索引等数据管理机制进行合理规划,所以在升级成为新架构时,浙江霖梓全面梳理并提炼业务关键指标,并针对 Doris 的各项基础性能进一步优化,有效提高了离线 / 实时一体化数仓的数据处理效率。
分区分桶
在建表时设置合理的分区分桶字段,其⼤⼩根据业务查询时间区间与数据体量决定,原理与 Hive 分区分桶基本—致,需要注意的是,业务变更频率较⾼的场景,不建议使⽤⾃动分区。我们综合考虑表数据量、增⻓趋势、表使⽤⽅法等情况,设置了动态分区,建表示例 SQL 如下:
PARTITION BY RANGE(k1) () \\nDISTRIBUTED BY HASH(k1) \\nPROPERTIES \\n( \\n \\"dynamic_partition.enable\\" = \\"true\\", \\n \\"dynamic_partition.time_unit\\" = \\"DAY\\", \\n \\"dynamic_partition.start\\" = \\"-7\\", \\n \\"dynamic_partition.end\\" = \\"3\\", \\n \\"dynamic_partition.prefix\\" = \\"p\\", \\n \\"dynamic_partition.buckets\\" = \\"32\\" \\n); \\n
前缀索引
Apache Doris 的前缀索引属于稀疏索引,表中按照相应的⾏数的数据构成—个逻辑数据块( Data Block),每个逻辑数据块在前缀索引表中存储—个索引项,其⻓度不超过 36 字节,查找前缀索引表时,可以帮助确定该⾏数据所在逻辑数据块的起始⾏号。由于前缀索引内存占⽤较⼩,可以全量在内存缓存,并快速定位数据块。设计原则⼀般遵循:<时间字段> + <分桶键> + <主键 id> ,对于 ODS 表, 要确保这些字段不存在 NULL 值 ,否则会导致输出数据不⼀致。
倒排索引
主要⽤于规则明细表与⽇志表中,⽤于快速统计规则路由情况以及关键词出现频次,减少资源占⽤率。Table 中的⾏对应⽂档、列对应⽂档中的某个字段,可以根据关键词快速定位其所在⾏,达到 WHERE ⼦句加速的⽬的。
BitMap 去重
BITMAP 类型的列可以在 Aggregate 表、Unique 表或 Duplicate 表中使⽤ ,针对—些特定的场景如 UV 、规则命中次数进⾏查询加速。SQL 示例如下:
#建表 \\ncreate table metric_table ( \\n dt int, \\n hour int, \\n device_id bitmap BITMAP_UNION \\n) \\naggregate key (dt, hour) \\ndistributed by hash(dt, hour) buckets 1 \\nproperties( \\n \\"replication_num\\" = \\"1\\" \\n); \\n#查询 \\nselect hour, BITMAP_UNION_COUNT(pv) over(order by hour) uv from( \\n select hour, BITMAP_UNION(device_id) as pv \\n from metric_table -- 查询每⼩时的累计UV \\n where dt=xxx \\ngroup by hour order by 1 \\n) res; \\n
开启执行优化器
在 Doris 2.1.x 版本中,建议启用 Pipeline X 和 local shuffle,以进一步提升复杂查询的执行效率。经过压测,开启 Pipeline X 优化器之后,性能提升了 20-30%。以下是 Pipeline X 优化器开启状态确认步骤:
#查看新优化器是否开启\\n#确保值全为true \\nshow variables like \'%enable_nereids_dml%\'; \\nshow variables like \'%experimental_enable_nereids_dml_with_pipeline%\'; \\nshow variables like \'%experimental_enable_nereids_planner%\'; \\n#默认 30,根据实际情况调整 \\nshow variables like \'%nereids_timeout_second%\'; \\n
此时对 Doris 、Hive 、Spark 进行压测,具体是对 15 个大表执行 join 操作,每张大表的平均数量约 13 亿条,测试过程中还涉及了 2 个表之间的笛卡尔积计算。根据执行结果,Doris 平均耗时只需 6 分钟。相比之下,Hive 执行相同任务耗时长达 2 小时,而 Spark 则执行失败。
报表优化
ADS 报表层在建表时开启 Merge-On-Write,以提升报表数据响应性能,同时开启⾏列混存以及查询缓存,避免刷新导致静态数据重复查询,影响集群性能。
#开启⾏存\\n\\"store_row_column\\" = \\"true\\" \\n
截至目前,基于 Doris + Paimon 的实时/离线一体化湖仓架构已为反欺诈策略、用户⾏为分析、业务监控、 BI 应用等若干系统提供了服务,实现查询提速 30 倍、资源成本节省 67% 等显著成效。未来,浙江霖梓将持续扩大 Apache Doris 在内部系统的使用范围,并将对数据湖能力、智能实时应用进行探索及应用:
全面接入数据湖:逐渐扩大 Doris + Paimon 湖仓⼀体化架构的应用范围,打通存量数据湖与 Doris 数仓的对接,为日后 PB 级数据的分析做好充分准备。打造实时智能金融客服:推动 Doris App 报表丰富度的提升,将 Doris 数据导出到 Elasticsearch 做知识库并接入⼤模型,通过 Prompt 与 GraphRAG 增强智能检索落地智能⾦融问答系统。打造智能营销系统:将 Doris 作为知识库做实现精准营销,节约人力并且降低⼈为决策误差,深度挖掘数据潜在价值
","description":"导读:浙江霖梓早期使用 CDH 产品套件搭建了大数据系统,面临业务逻辑冗余、查询效率低下等问题,基于 Apache Doris 进行整体架构与表结构的重构,并基于湖仓一体和查询加速展开深度探索与实践,打造了 Doris\\" + Paimon 的实时/离线一体化湖仓架构,实现查询提速 30 倍、资源成本节省 67% 等显著成效。 浙江霖梓是一家专注于深度学习和人工智能应用的金融创新企业,为企业提供精准经营决策,并基于大数据的风控能力的一系列高效便捷的金融服务产品。随着业务的持续扩展,大数据业务系统的局限逐渐暴露:报表系统计算缓慢、运维成本持续攀升…","guid":"https://www.infoq.cn/article/wSRPozYpL7GsvrYjEdl0","author":"SelectDB","authorUrl":null,"authorAvatar":null,"publishedAt":"2025-02-14T08:53:20.309Z","media":[{"url":"https://static001.geekbang.org/infoq/1d/1d4ec8624c34494e23f59e25b22b99cd.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/13/13abf89aa5b757c2998c3979c62ca633.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/35/35c044588b97b15cb298fd0b4c00d516.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/49/4906e2131e58f18b5af96e5d3184d8a3.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/90/90020294a7da198efad801c51bb0e020.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/20/2027eeffc05af66ea4c54dad6d298041.png","type":"photo","width":0,"height":0,"blurhash":""}],"categories":["数据库"],"attachments":null,"extra":null,"language":null},{"title":"打造AI存储底座,贝壳找房将OceanBase作为JuiceFS元数据引擎的建设实践","url":"https://www.infoq.cn/article/E98HuXvsWheTyqLI6gWb","content":"作者|王天庆,贝壳计算存储方向容器引擎团队负责人,目前工作聚焦于云原生和AI基础设施的架构设计和建设实施,为公司提供高效可靠的基础设施并帮助大模型在企业内部快速落地。
从AI大模型爆火到成为技术领域新的应用方向,许多企业将AI列入战略规划。贝壳找房作为国内先进的居住产业数字化服务平台,也加大了对AI技术设施的投入。而其底层的数据库产品选用蚂蚁集团自主研发的单机分布式一体化数据库OceanBase,那么,数据库在AI基础设施建设过程中能起到什么样的核心作用?本文通过分享贝壳找房在AI存储底座的实践,展开这一话题的讨论。
贝壳找房是中国最大的居住服务平台之一,业务包括二手房交易、新房交易、租赁、家装、家居、家服等,作为居住产业数字化服务平台,贝壳是最早将VR、AI等新技术应用于居住服务的企业,其致力于推进居住服务的产业数字化、智能化进程。
自AI大模型爆火后,贝壳找房很快加大了对AI的投入。目前我们团队有三大模块致力于AI的发展:一是机器学习平台,帮助算法工程师做模型训练和模型推理;二是在机器学习平台下层有两套内部的基础设施提供高性能存储服务;三是内部的云原生基础设施。
在AI基础设施建设的过程中,由于数据的快速增长和对算力的不断调整,存储架构不断演化,在各阶段面临不同的挑战。
贝壳找房AI基础设施建设始于几年前,受AI技术发展态势迅速变化的影响,至今已历经四个阶段的演化。
在非大模型时代,算法工程师训练模型特别简单,只需要一台GPU和一块硬盘,即单机单卡。训练模型逐渐变大,超出了一台机器能够承载的范围。随即便出现了多机多卡的场景,其本质上不会脱离机房,但该场景下无法再使用一块磁盘解决问题,需要网络共享存储。彼时,常用的共享存储开源方案是基于NFS。
2023年大模型的火爆促使模型训练对GPU算力需求及资源使用方式发生巨大变化,我们也从多机多卡单机房结构变成平台化的交付方式,完全云原生化。底层也使用统一文件系统存储千亿规模的文件。
随着算力资源因供不应求导致的稀缺,我们的算力分布在多家公有云的多个地域,包括北京、上海、天津等地,算力的供给多样性给数据集合模型管理带来了更多的技术挑战。
同时,大模型的发展使存储系统存在着两大技术挑战,一类是模型训练过程中的存储瓶颈,随着AI模型的参数量越来越大,文件系统的数据传输能力和Checkpoint的写入效率很容易成为模型训练过程中的性能瓶颈,因此要求存储底座需要具备极高的并发、吞吐的能力。另一类是数据流转的效率。数据集对于大模型工程体系来说,贯穿了整个生命周期。在传统场景中,不同的场景都存在独立的存储介质来满足业务场景,但在大模型的迭代过程中,为了提高GPU资源的使用效率,我们需要尽量减少数据在流转过程中消耗的存储成本和时间成本。
数据流转周期牵涉整个贝壳找房AI工程,从用户端的数据采集到数据处理,再到转化成数据集,最后流转到GPU支撑模型训练。该流程最理想的形式是以文件系统卷的形式挂载。对于整个数据流转来说,无论是数据流入、数据处理、模型训练还是生成模型文件来做模型推理,整个数据的存在形式都是以同一个共享卷的方式存在的话,能极大的减少数据复制带来的时间消耗。
贝壳在此理念的基础上,开发并设计了符合贝壳当下物理环境的分层存储底座来满足数据流转的效率。
分层存储架构分为存储编排和文件系统存储两部分。我们选择了开源的Fluid作为数据编排部分,其具备云原生的数据编排以及缓存加速的能力。
底层的文件存储选用开源分布式文件系统JuiceFS,这是一款面向云原生设计的高性能分布式文件系统,提供POSIX、HDFS和S3协议的接入方式,其高性能特性比较依赖于高性能的元数据引擎和对象存储服务。
目前贝壳内部还存在着一些其他的文件系统,比如CubeFS,为了更好的提高数据流转的效率,我们通过整合多种底层存储并围绕着JuiceFS我们打造了混合云存储底座。
第一层就是接入层,满足各类场景的数据写入/读取的需求,包括云原生场景下、HDFS协议或者直接使用S3协议来对文件进行操作。
第二层是数据编排层,主要是解决跨地域数据流转和数据就近访问的能力。因为数据可能在北京区被生产,但是在上海区被消费,所以需要把数据传输到离算力最近的地方。
第三、四层组成了基于JuiceFS的完整的文件系统底座。JuiceFS依赖元数据和对象存储服务的能力。需要一个高效的元数据引擎和能够满足我们多地域需求的对象存储服务。
然而,元数据引擎的技术选型是非常困难的,如果基于高性能的Redis,存在数据丢失的风险,可能是文件系统的灾难,我们无法容忍。如果是全靠自研,人力投入和时间成本过高,短期内无法落地。综合考虑下,我们确定首要需求是稳定且不丢数据,其次是承载我们数据流转、跨地域的需求。
在调研了目前市面上的多种元数据引擎存储系统后,我们最终选择将OceanBase作为元数据引擎的技术方案和存储底座。主要原因如下:
1. 对于整个数据流转系统而言,OceanBase可以提供高可用和容灾能力,解决数据流转中跨地域数据同步的问题。
a) OceanBase的每个数据分片都有多个副本,分布在不同的物理节点上,当某个节点出现故障时,系统可以自动切换到其他副本,保证服务的连续性。
b) 通过配置数据副本的存储位置,可实现机架级、机房级、城市级容灾,帮助金融机构应对容灾挑战。
2. 我们有很多机房,算力分散在不同区域,我们需要把数据充分地利用起来,就需要元数据能够在各区域飘来飘去,在离算力最近的地方读到元数据可以保证文件系统的读取效率。OceanBase的多活能力可以解决这个问题。
3. 我们是云原生和AI基础设施建设的团队,不太擅长数据库运维,上文也提到数据流转涉及整个企业的多个业务模块,因此我们需要存储底座具备资源隔离能力和较高的可运维、可管理能力。OceanBase提供了强大的运维管理平台OCP对数据库进行7*24小时监控,安全可靠。
4. OceanBase的原生多租户架构和租户级资源隔离能力,可以满足我们的需求。同时,其性能均衡,能支持百亿到千亿量级数据。
举个例子,下图是京津区算力中心和上海区算力中心的元数据传输的架构解决方案。可以看到整体的算力资源分为IDC和公有云,且拥有多家公有云供应商。我们在IDC内尤其是同区的机房内,使用OceanBase多zone的能力,通过OBProxy分别转化到不同的副本中。针对跨云甚至跨区的场景,以腾讯云为例,我们巧妙借助了腾讯云MySQL的能力,当 IDC的数据飘在上海时,先把数据基于OMS同步到京津区腾讯云的数据库,再通过云上的DTS工具同步到上海区的数据库,由上海区的数据库提供元数据的处理能力。
为什么出现这么复杂的架构,而非利用OceanBase在上海区整体做同步?
这是出于物理限制,我们测试过一些场景,如果让OceanBase在上海区同步数据,受限于云联网和带宽会出现极高的同步延迟。而目前的方案可以保证最低的数据延迟,我们只需解决数据流转在2w TPS时从京津区写入上海区在秒级内完成,这个速度在整体数据生产过程中可以满足大部分业务场景需求。另外,IDC和其他算力中心基本都在OceanBase的多zone管理模式下,数据流转速度更快。
OceanBase作为JuiceFS的元数据引擎,在同机房访问文件系统场景下,表现也很出色。在单客户端场景下,文件规模在2000万左右时,Oceanbase的响应时间可以控制在1~2ms之间,只有在一些大量list删除时才会偶有抖动,耗时基本能控制在2~10ms之间。
贝壳找房内部自研了一套对象存储服务,作为JuiceFS的数据持久化层。由于我们存在跨区读取数据的场景,比如对象存储数据存储在北京区,但是需要从上海区读取,甚至我们还面临着跨公有云的情况。
因此,我们希望对象存储服务具备跨区甚至是跨云数据复制的能力,可以把一份数据同步到不同公有云的不同地区,离算力更近一些。为此我们自研了一套对象存储系统KOS来满足我们的需求。该系统本质上并不提供真实的存储能力,而是一层S3协议代理层,最终数据都在落在公有云的对象存储上,比如腾讯云COS上。我们的对象存储系统只解决一个问题——访问加速。对象存储系统的部署形式是在京津区和上海区部署我们KOS服务,通过跨区复制能力,保证上海区、京津区之间KOS文件复制的实时同步。
对象存储本身也是有元数据的,在海量数据的场景下,对象存储元数据访问的性能也会极大的影响对象存储的整体性能,尤其是在文件系统这类需要频繁查询文件元信息的情况下。因此,我们使用OceanBase作为KOS的元数据的底座,以推动整个对象存储服务加速。如下图所示,对象存储系统分三个组件:
KOS-Proxy 协议代理层:主要用于实现S3接口协议,该组件是完全无状态服务,元数据主要从KOS控制面中获取。KOS-Cache 数据缓存层:主要功能是从底层真实的对象存储中缓存数据到本地磁盘中,并且可以分布式部署形成缓存集群来提高对象存储的吞吐能力。KOS-Meta元数据层:主要对对象存储服务提供元数据能力,以OceanBase为底层元数据引擎,提供就近获取到对象存储元数据信息的能力。
在这个流程中,对于文件的读取,会优先判断文件是否启用了数据缓存,如果存在缓存的话会优先从缓存节点KOS-Cache读取数据,否则降级到远端的对象存储读取。为了保证数据一致性,所有归属于同一组的缓存节点都会以哈希环的形式分布好,每个cache服务通过etcd对外分享自己在环中持有的Token信息和位置信息。数据的读写都会通过一致性hash算法写入到指定节点,保证数据的一致性。最终元数据加速的原理是通过S3协议在对象存储文件生命周期过程中,生成文件对应的元信息并写入OceanBase中,同时OceanBase做好多AZ和多地域的同步支持,此时就可以通过OceanBase实现支持海量数据的对象存储服务。
拥有对象存储能力后,我们访问云上的对象存储都会转化为本地机房访问的对象存储,实现了加速。访问文件系统时非常高效。下图展示了本地访问与云上访问的性能对比数据。
从图中可见,对于大量小文件加速效果比较明显,强依赖OceanBase提供的强大性能。在跨机房场景下,性能提升比较明显,有效提升读场景下的吞吐上限。不过,该方案对于对象存储的写场景提升效果不明显。
对象存储服务优化后,我们考虑怎么把JuiceFS用起来。在用户侧,数据要先在京津区计算后再拷贝到上海区,然后从上海区拉取数据进行训练。这个流程中要么存在带宽小、专线贵的问题,要么会遇到部分小文件场景难以优化吞吐导致延迟较高的问题。
一种优化思路是做镜像文件系统。首先用户在京津区创建一个普通卷,该卷的自动接入会连接到京津区的元数据引擎和对象存储服务。然后用户在上海区创建一个京津区卷的镜像卷,用户使用该卷的时候,自动接入会自动识别并接入到上海区的元数据引擎和对象存储服务。该思路减少了数据流转的时间,从传统的数据生产到数据清洗、数据复制、训练,到优化为数据生产、进行数据清洗、再训练,可以降低数据复制的时间成本。数据量较小时可秒级完成。对于不需要所有的数据都多地区多写的情况,还可以通过镜像文件系统的能力,进行跨地区预热,将数据同步到其他地区,JuiceFS的文件块大小对于公有云对象存储的数据同步比较友好,同步效率会更高。进而还能帮助省钱,因为在AI领域有一个共识——GPU很贵,闲着就是烧钱,所以一定要保证数据同步效率跟得上算力的速度。
除了将OceanBase作为AI基础设施的存储底座外,我们在其他的场景中,也对OceanBase的应用进行了探索。
在维护数千台服务器和KOS集群时,我们面临的最大挑战是系统的可观测性。传统的可观测性系统,如日志系统Loki、Prometheus等无时无刻都在采集各个系统的日志、指标数据,这些数据庞大繁杂其缺乏实时分析的能力,对运维人员而言是一种困扰,当遇到故障需要快速定位分析的时候,往往无法快速的检索出重要的指标数据。所以我们基于云原生标准,结合OceanBase的能力补齐了可观测的领域实时分析的能力。
这套系统的核心是将可观测数据经过过滤、分组、提取、转化及路由,汇聚到不同的存储系统中,对于海量偏归档类数据,我们会写入到比较廉价的存储系统中,比如对象存储。对于使用频率高以及重要巡检的可观测数据时,经过数据清洗后日志和指标数据会流入OceanBase以借助实时分析的能力能够更快速的定位异常。以域名类场景为例,当出现报警时,我们会面临额外的风险,比如外部攻击、爬虫等,我们需要尽快排查风险的IP来源,以及每一个IP的增长趋势。OceanBase的实时分析能力能够帮助我们快速定位异常,增加报警解决的效率。
最后简单分享一下,也算是贝壳后续对OB的探索,这个比较简单,因为这个也是最近开始尝试,基于OBKV在文件系统层面的尝试,我们内部现在只是做了第一版的基于OBKV的元数据引擎的实践,整体从SQL引擎切到OBKV上,因为文件元数据结构相对简单,对应的表结构也比较简单,本质上并不需要SQL的形式,KV的方式就能满足我们全部功能需求,并且抛开掉SQL解析的时间消耗,也能够提升元数据引擎的整体性能,所以我们做了一些尝试和探索。
近期我们针对该探索进行压测发现整体效果非常理想,OBKV 场景下,百万级的文件读写的响应时间提升2~4倍,原来的2~10ms变为1ms甚至更低,偶尔在抖动情况下也会稳定在5ms左右。OBKV少一层SQL解析,理论性能更高。另外,由于OceanBase具备多模KV能力,支持HBase和Redis协议,且拥有丰富的工具体系,我们可以直接复用OceanBase的运维能力。
在贝壳我们也在尝试引入和使用ob-operator。因为我们团队是容器团队,有相对完善的本地盘的存储方案以及完善的容器基础设施,很多基础组件运维过程中存在着大量的数据库需求,所以通过operator的方式按需做集群交付可以最大程度复用我们的容器基础设施,一定程度上也能够实现OceanBase集群的快速交付,相对裸金属的形式更具有灵活性。
","description":"作者|王天庆,贝壳计算存储方向容器引擎团队负责人,目前工作聚焦于云原生和AI基础设施的架构设计和建设实施,为公司提供高效可靠的基础设施并帮助大模型在企业内部快速落地。 \\n\\n从AI大模型爆火到成为技术领域新的应用方向,许多企业将AI列入战略规划。贝壳找房作为国内先进的居住产业数字化服务平台,也加大了对AI技术设施的投入。而其底层的数据库产品选用蚂蚁集团自主研发的单机分布式一体化数据库OceanBase,那么,数据库在AI基础设施建设过程中能起到什么样的核心作用?本文通过分享贝壳找房在AI存储底座的实践,展开这一话题的讨论。\\n\\n贝壳找房AI基础设施建设背景\\n\\n贝壳找房是…","guid":"https://www.infoq.cn/article/E98HuXvsWheTyqLI6gWb","author":"李冬梅","authorUrl":null,"authorAvatar":null,"publishedAt":"2025-02-12T08:06:36.202Z","media":[{"url":"https://static001.geekbang.org/infoq/cb/cb2c6e29a6ee057fd7a0c750715689e1.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/ef/efb8ce86a22851766cf8434660e63437.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/3f/3fa549ba4a33843268686ae7c0cb5658.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/b1/b1b41a6da2ae317b6f775755969ac5f0.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/a8/a8131b5cc09911d8e7a793d0b11ad694.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/3f/3f4796ab0b42bc8ba53fef2a18a1e9ee.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/70/7084e7c090ecd590f570c45d5aad9b5b.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/12/127744a6dd2042c4d77b193bdd90283c.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/ba/bab57562d98fae2ded1030dc9eb9aab8.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/35/3546073bbcfbf71e31fe81a1ed6950cf.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/28/282cfe5058740644605863c6b7cb9d4f.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/da/da33b9030d84550d6d07d31f5bf36001.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/4a/4a9a06a7ebc6fac3270068e9e3c44152.png","type":"photo","width":0,"height":0,"blurhash":""}],"categories":["数据库"],"attachments":null,"extra":null,"language":null},{"title":"Cloudflare 开源文档并采用 Astro 提高其可扩展性","url":"https://www.infoq.cn/article/xqzPRqbWKPeXDrze7U7P","content":"最近,Cloudflare 发表了一篇文章,详细介绍了他们为了升级开发文档而从 Hugo 迁移到 Astro 生态系统的情况。Cloudflare 的所有文档都已在 GitHub 上开源,使社区有机会做出贡献。
Developers.cloudflare.com 网站之前是将一系列 Workers 站点合并成 单个 Cloudflare Pages 实例。他们使用了 Hugo 和 Gatsby 等工具,将数千个 Markdown 页面转换为 HTML、CSS 和 JavaScript。Cloudflare 产品内容主管 Kim Jeske、Cloudflare 文档平台工程师 Kian Newman-Hazel 和 Cloudflare 技术写作经理 Kody Jackson 解释了更换 Web 框架的原因:
尽管 Cloudflare 的内容团队在发布产品的同时提供了文档,但开源文档网站本身却没有得到很好的扩展。Developers.cloudflare.com 并不适合贡献者,而我们因此错过了社区开发人员创建的所有精彩内容。
2021 年,Cloudflare 采用了 “内容即产品” 战略,强调要预测用户的需求,通过提供世界一流的内容来支持无障碍产品的创建。Jeske、Newman-Hazel 和 Jackson 写道:
开源文档使开发社区的任何人在任何地方都可以贡献内容。通过公开文档网站的内容和框架,我们不仅为开发人员提供了对资料本身进行完善的机会,还让他们可以了解并参与到文档的构建、审批和维护过程中。
根据该团队的说法,Astro 的文档主题 Starlight 是决定迁移文档网站的关键因素:该主题提供了强大的组件重载和一个可利用内置组件和基本样式的插件系统。CloudZero 研究总监 Jeremy Daly 评论说:
Cloudflare 已将其所有开发文档开源,并从 Hugo 迁移到 Astro,JavaScript 生态系统又多了一位受害者。无论你的文档有多好,要保持文档的及时更新,并使所有人可以访问,用户的反馈至关重要。
根据 Cloudflare 团队的说法,将所有文档开源可以让公司与社区保持联系,并迅速落实反馈意见。在其他超大规模企业中,这并不是一个经常采用的策略。正如 InfoQ 此前报道的那样,亚马逊云科技在将大部分文档开源五年之后,转变了做法。2023 年,这家云提供商退役了所有公开的 GitHub 文档,理由是保持文档与内部版本一致存在挑战。而且,与 GitHub 存储库同步需要人工操作。当时,亚马逊云科技首席布道师 Jeff Barr 写道:
管理成本非常高,确实耗费了许多宝贵的时间,而这些时间本可以直接用来提高文档质量。
Mathi 软件工程师 Gianluca Arbezzano 认为这个话题很有意义:
如果你认为 “这只是文档而已\\",那么我认为你应该多用点心!我们配拥有最好的!来自 Cloudflare 的这篇关于从 Hugo 迁移到 Astro 的文章是一篇好文章。
在 Hacker News 上评论 Cloudflare 的文章时,Alex Hovhannisyan 提醒 道:
我很抱歉,但作为一个最近从 Netlify 迁移过来的人,我必须实话实说(并且正在考虑迁回去):文档做得好不好与技术栈无关。最终用户并不关心你的文档使用了什么技术栈。
所有 Cloudflare 文档都可以在网站 developers.cloudflare.com 上查阅。
原文链接:
https://www.infoq.com/news/2025/02/cloudflare-documentation-astro/\\"
","description":"最近,Cloudflare 发表了一篇文章,详细介绍了他们为了升级开发文档而从 Hugo 迁移到 Astro 生态系统的情况。Cloudflare 的所有文档都已在 GitHub 上开源,使社区有机会做出贡献。 Developers.cloudflare.com 网站之前是将一系列 Workers 站点合并成 单个 Cloudflare Pages 实例。他们使用了 Hugo 和 Gatsby 等工具,将数千个 Markdown 页面转换为 HTML、CSS 和 JavaScript。Cloudflare 产品内容主管 Kim Jeske…","guid":"https://www.infoq.cn/article/xqzPRqbWKPeXDrze7U7P","author":"作者:Renato Losio","authorUrl":null,"authorAvatar":null,"publishedAt":"2025-02-12T03:30:00.282Z","media":null,"categories":["编程语言"],"attachments":null,"extra":null,"language":null},{"title":"微软的 Hyperlight WebAssembly 虚拟机现已开源","url":"https://www.infoq.cn/article/Ei4Zx95O6AtIHGBoaHWL","content":"Hyperlight 是一个 Rust 库,意在帮助开发者利用基于内核的虚拟机(KVM)或微软原生的 Hyper-V 运行不受信任的代码,而无需加载完整的操作系统。
图源:B. Cameron Gain.
微软的 Azure Core Upstream 团队表示,Hyperlight 可将 无服务器 应用的冷启动延迟降低一倍以上的同时,也能享受 WebAssembly(Wasm)的沙箱安全机制。该项目现已开源,并计划捐赠给 CNCF。Hyperlight 依赖于小型的嵌入式函数,并通过基于虚拟化的保护机制,在大规模调用时为每个函数提供安全隔离。此外,每一个函数请求都有其独立的虚拟化层进行保护。
长期以来,虚拟机都是云原生基础设施的基石,被广泛用于安全隔离主机和客机环境。微软 Azure 首席工程师 Rita Zhang 在 11 月的 KubeCon+CloudNativeCon 大会上表示:“然而,在无服务器计算等事件驱动的场景中,传统虚拟机启动速度实在太慢。那么,我们如何在保证应用程序安全运行的同时减少这种延迟呢?”
Hyperlight 是一个 Rust 库,意在帮助开发者在不加载完整操作系统的同时,利用基于内核的虚拟机(KVM)或微软原生的 Hyper-V 运行不受信任的代码。Zhang 称,这些 microVM(微型虚拟器)可以在微秒级时间内创建。
在演示中,Zhang 展示了应用是如何从虚拟机中顺序调用主机功能,并将主机返回的值传回客机的。Hyperlight 为每次调用创建一个新的 microVM,平均每个请求仅耗时 900 微秒。Zhang 强调:“这是微秒级的,用时甚至不到一毫秒。”
利用 Wasm 模块所提供的轻量级沙箱安全机制,这种想法已经存在很久了。云服务商不同,microVM 的叫法也不同,但它们的作用都是用于在本地或云端环境中高效分发来自本地系统的大量数据流量。谷歌云预计会在 2025 年推出类似的标准化解决方案。
“我们现在可以利用这些轻量级沙箱,在网络流量进入系统时直接进行处理,”微软 Azure 首席技术官兼技术院士 Mark Russinovich 在微软 Ignite 用户大会上表示,“这为实时、高效的网络处理打开了全新的可能性。”
Adobe 和谷歌是推动 WebAssembly 标准发展的技术领军企业。此外,Netflix、Amazon Prime、Disney 等公司也在利用 WebAssembly 进行视频流媒体传输。
虽然微软鲜有公开讨论其在 WebAssembly 方面的早期工作(此前询问过微软但但未得到回应),但可以确认,该公司已在多个业务场景中使用 WebAssembly,并持续为 Wasm 社区的发展做出贡献。事实上,微软早在多年前就开始研究 WebAssembly。例如,《微软飞行模拟器》游戏一直在使用 WebAssembly 来保护游戏 Mod,这不仅提升了安全性,还增强了插件的可移植性。此外,Excel Online 也采用 WebAssembly 计算 Lambda 函数。
目前,微软的主要工作集中在推动即将到来的 WebAssembly 组件模型和 WASI(WebAssembly System Interface)。例如,微软正在扩展 Azure Kubernetes 服务的 WASI NodePool 预览版,并通过 Hyperlight 项目在 Wasm 沙箱基础上为每个请求提供额外的虚拟化保护。
除了 Edge 浏览器之外,微软的 WebAssembly 重点投资方向主要在服务器端 Wasm 及围绕 Bytecode Alliance 构建的 Wasm 组件生态,同时也在基础设施和语言工具方面进行投资,以促进 WASI 的高效应用。此外,微软还在开发 Containerd 相关项目 Runwasi,该项目是 SpinKube 计划的一部分。
“Hyperlight 是我们一直缺少的关键组件,它能真正隔离细粒度的轻量级代码片段。你可能会想,‘这不就是容器的作用吗?’但老实说,容器的开销并不小。”微软高级开发倡导者 Yosh Wuyts 和 Azure Core Upstream 负责人 Ralph Squillace 在博客中写道。
“在存储服务中的用户自定义函数或边缘网络流量处理等场景下,系统需要更轻量级的解决方案。同时,它还必须具备抗攻击能力,并还能支持多租户安全,以确保多个客户可以共享同一环境而不影响安全性。因此,我们开发了‘微型沙箱(micro sandbox)’或者说‘微型虚拟机(microVM)’。”
“那一刻的灵感来自于 Azure 的一位同事,他有一天走到我面前,说,‘嘿,我能使用 Hyper-V 的 API 创建一个虚拟机,除了要加载一小段代码外,其他的都不需要。它可以在微秒级时间内启动,并且同样快速关闭,’” Squillace 写道。“就这样,我们有了 Hyperlight——一个通过虚拟化隔离的微型虚拟机。”
微软推出了基于虚拟机的 Hyperlight 安全解决方案,并如前所述,已经将其开源。目前,Hyperlight 不仅与 Hyper-V 兼容,还支持 KVM。此外,微软还将 Hyperlight 贡献给 CNCF,正如 Wuyts 和 Squillace 所写:“我们的目标是提升整个社区,让每个人都能使用微型虚拟机技术。Hyperlight 是我们通过安全沙箱提供这一能力的方式。”
查看英文原文:
Microsoft’s Hyperlight WebAssembly for VMs Is Open Source(https://thenewstack.io/microsofts-hyperlight-webassembly-for-vms-is-open-source/)\\"
","description":"Hyperlight 是一个 Rust 库,意在帮助开发者利用基于内核的虚拟机(KVM)或微软原生的 Hyper-V 运行不受信任的代码,而无需加载完整的操作系统。 图源:B. Cameron Gain.\\n\\n微软的 Azure Core Upstream 团队表示,Hyperlight 可将 无服务器 应用的冷启动延迟降低一倍以上的同时,也能享受 WebAssembly(Wasm)的沙箱安全机制。该项目现已开源,并计划捐赠给 CNCF。Hyperlight 依赖于小型的嵌入式函数,并通过基于虚拟化的保护机制,在大规模调用时为每个函数提供安全隔离。此外…","guid":"https://www.infoq.cn/article/Ei4Zx95O6AtIHGBoaHWL","author":"作者:B. Cameron Gain","authorUrl":null,"authorAvatar":null,"publishedAt":"2025-02-11T06:00:00.239Z","media":[{"url":"https://static001.geekbang.org/wechat/images/56/5636c4f8ad4eabb7b5e86c32a10eff55.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/wechat/images/30/30b3f6bfc9ebdf920f22184b0804e6cb.png","type":"photo","width":0,"height":0,"blurhash":""}],"categories":["操作系统"],"attachments":null,"extra":null,"language":null},{"title":"”2025年将成Python主导AI领域的最后一年“","url":"https://www.infoq.cn/article/ZTvSRhdQT7FICWJNSk84","content":"Java,这头在企业应用领域深耕 30 年的“猛兽”,如今正虎视眈眈地瞄准 AI 这块 Python 的“固有领地”。尤其是在企业级 AI 应用方面,Python 的优势似乎正在逐渐减弱。一家大型 Java 平台公司的技术负责人甚至预测,2025 年将是 Python 在 AI 领域占据主导地位的最后一年。
今年,Java 迎来了 30 周年,它在企业应用领域的影响力依然稳固。这种多用途编程语言经历了二十多个版本的演进、2010 年 Sun Microsystems 被 Oracle 收购,以及最近的许可变更。
尽管已有悠久历史,Java 仍然广泛应用于从 Web 到云计算的各类商业应用中。
“Java 就像企业的砂浆和砖墙——它无处不在,”Azul 首席执行官 Scott Sellers 表示。“确实有一些企业不使用 Java,但总体而言,几乎找不到一家规模较大的企业完全不依赖 Java。”
如今,随着 GenAI 变得越来越重要,Python 被广泛认为是生成式 AI 的首选编程语言。这对 Java 开发人员意味着什么,是一个值得思考的重要问题。
目前来看,在 AI 应用的开发过程中,不同角色各司其职,包括 AI 工程师、数据工程师和应用开发者。其中,AI 工程师专注于模型的开发与部署,数据工程师负责数据的管理与处理。虽然 AI 工程师和数据工程师的工作至关重要,但应用程序开发人员同样扮演着关键角色。我们需要大量的应用程序开发人员来将 AI 融入到实际应用中,创造出实用的AI解决方案。
在这一过程中,应用平台、数据平台和 AI 服务三者共同作用,构建出完整的 AI 生态系统。现在是 Java 开发者学习 AI 并将其应用于企业级应用的绝佳时机,尤其是在大量企业应用都运行在 Java 生态上的背景下。
而且,近年来,Java 在 AI 领域的技术突破愈发明显,多个关键项目正在推进 Java 在 AI 开发中的竞争力。比如,Langchain4J框架旨在简化将大模型 (LLM) 集成到 Java 应用程序中的过程,在过去一年内已发布十余个版本,不断完善对 Java 生态的支持。自推出后,该库便迅速在 Java 社区中获得了关注和认可,尤其是在开发基于 LLM 的应用程序的开发人员中。
而Pivotal 开源的 Spring AI 近期则正式推出 1.0.0 版本,标志着 Java 在 AI 领域的进一步成熟。国内阿里云也发布了基于通义大模型的 Spring AI Alibaba 开源项目,将 Spring 生态系统的可移植性、模块化设计等企业级特性应用到 AI 领域。Jlama 则提供了一个原生的 Java LLM 推理引擎。Jlama 完全由 Java 构建,使用 Java 库和 API 处理所有 LLM 相关操作,并支持在 Java 虚拟机(JVM)内本地执行模型推理。
为了解企业如何在不断发展的技术环境中使用 Java,大型Java平台提供商Azul Systems发起了一项调查,调查报告显示,50% 的组织使用 Java 来构建 AI 功能,在以 Java 为中心的企业中,其 AI 开发使用量超过了 Python 和 JavaScript。
Azul公司副CTO Simon Ritter在采访中表示,Java语言很可能在未来一年半内顶替Python在AI开发领域的优势地位。
Ritter写道,“众所周知,开发者圈子都认为Java语言更适合开发企业级AI应用程序,因为它的可扩展性和性能更好,只是目前Python凭借丰富的依赖库和其他支持性的AI开发基础设施暂时取得优势。然而,企业已经意识到Java才是业务部署的更佳选择。我们很可能在未来一年半到三年之内,见证Java超越Python。”
Ritter解释道,Python目前在AI领域的主导地位实际更多是文化因素的结果,因为Python作为编程语言更简单。他指出,熟悉AI技术的群体往往长于数学能力、而非软件开发背景,因此Python的简单易用对他们更具吸引力。
然而,“随着企业越来越依赖AI部署,我们将遭遇障碍、撞上Python语言的能力边界,就是说必须对应用程序进行大量重写和重构。组织必须确保自己的应用程序能够与Python和Java协同运行,逐步建立起Java AI应用体系,最终突破这道壁垒。”
Ritter同时提到,Java最终能够占据主导的关键因素,在于它能够从GPU中获得更好的性能。例如,“JDK已经交付Project Panama,使得开发者能够在Java代码中轻松使用非Java库。
Project Babylon则对此做出增强,探索如何在无需更改代码的前提下,通过Java直接调用GPU以实现更好的性能表现。”
Azul报告指出,Java开发者正积极使用AI,“这凸显出Java在AI中「契合需求」的天然性质,即提供更好的可扩展性、广泛的依赖库以及与现有企业系统的无缝集成。”
事实上,Java在性能、可扩展性以及稳定性方面的长期优势,使其成为开发AI驱动应用程序的天然选择。报告强调,Java能够为AI解决方案提供必要的计算效率与企业级可靠性。
此外,在使用Java构建AI功能的组织当中,JavaML成为使用频率最高的Java AI库。由于AI已经开始影响组织制定策略、构建代码以及维护应用程序和基础设施的全新方式,所有这些活动都需要消耗算力资源。因此调查中有72%的受访者表示,他们需要储备更多算力才能支撑起具有AI功能的Java应用程序。
在被问及是否相信Java能够取代Python在AI开发领域的主导地位时,IDC公司分析师Arnal Dayaratna表示“是的,而且可能性很大,毕竟Java在大规模、企业级、关键任务类应用程序的开发方面无人能敌。”
然而,另一位经验丰富的应用开发市场观察者却有着不同的观点。Omdia公司分析师Brad Shimmin在采访中表示,他不相信Java能够取代Python的AI开发一哥地位。
“如今Python语言自身的性能正在提升,加上开发者能够使用的库(PyTorch、Panda等)已经孕育出蓬勃发展的生态系统,我并不觉得Java能够在支撑AI用例方面超越Python。当然,在安全和性能极其重要的领域,例如金融行业,我们也希望能把一部分Python代码重构成Java或者Scala的形式。可即便如此,AI从业者也更愿意从Python起步。随着生成式AI的兴起,预计其他语言也会发挥作用,特别是TypeScript等更适合全栈开发的语言。”
与此同时,一部分开发人员(要求匿名)提到,他们认为Java社区还需要在语言自身多做创新,确保其更适合AI开发。
作为Java语言和平台的管理者,甲骨文正在努力实现这一目标。
甲骨文Java平台高级副总裁兼OpenJDK管理委员会主席Georges Saab表示,随着新兴技术的成熟,甲骨文看到Java在新兴技术中的应用越来越多,AI场景自然也不例外。
Saab在采访中解释道,“Java在企业业务逻辑当中占据主体地位,强类型、内存安全、良好的核心库以及广泛的工具分布意味着Java天然会被这些不断发展的新生态所吸引。在计算密集型AI训练和模型创建领域,凭借原生库集成和JIT性能改进选项,我们看到人们对Java的关注度与日俱增。更进一步讲,Project Babylon的目标就是将Java的应用范围扩展到GPU编程模型,借此将Java深度嵌入至AI领域。而Project Valhalla则有望将复杂数据类型的处理效率拉升至数值类型基元的水平,从而让JVM更好地实现内存扁平化。”
此外,在推理方面,Project Amber允许开发人员使用密封类型、记录类和模式匹配,更加轻松且富有表现力地对数据进行建模。
Saab解释称,“比如说,langchain4j能够要求大模型返回直接填充至记录中的答案,从而有效将AI生成的非结构化答案编组到强类型系统当中。而且,考虑到很大一部分业务应用程序已经是由Java编写,因此这些应用程序的开发者将能够「在Java中」构建AI智能。”
Azul的这份报告囊括了来自全球各地2000多名Java专业人士的回复,研究了企业如何应对Oracle Java的定价与许可挑战、组织在解决云成本方面采取的策略、影响DevOps生产力的因素,以及Java在AI开发领域发挥的作用。
在全球参与这份《Azul 2025 Java现状调查报告》的所有企业中,只有1%的受访者因完全未在企业中使用Java而被取消了调查资格——就是说有99%的受访组织已经在主动使用Java。此外,近70%的受访者表示,他们有半数以上的应用程序是用Java构建、或者运行在Java虚拟机(JVM)之上,这也证实了Java在当今企业级应用领域的江湖地位。
这份《Azul 2025 Java现状调查报告》中的其他主要发现还有:
Azul发现,在甲骨文发布以员工为单元的Oracle Java SE定价政策已经两年之后,人们仍然对此忧心忡忡。82%的Oracle Java用户对这种成本模式感到不安,与《Azul 2023 Java现状调查报告》中的百分比相同。报告还提到,考虑使用Oracle Java替代方案的组织占比则大幅上升,从2023年的72%一路来到如今的88%。
报告显示,考虑逃离Oracle Java的五大核心原因(受访者可随意多选)包括使用成本(42%)、开源偏好性(40%)、甲骨文销售策略(37%)、定价与许可持续变化所造成的不确定性(36%)以及严苛的甲骨文政策(33%)。
Shimmin提到,“调查对象都是Java开发专家,这肯定会对结论造成影响”,同时也承认Azul是甲骨文的主要竞争对手。“但相信大家也都清楚,甲骨文在Java的问题上存在着很多顽疾。Azul及其他厂商发布了大量替代性JDK,跟甲骨文的Oracle Java SE Universal Subscription相比不仅许可模式更灵活,使用成本也往往更低。”
“所以最终结果,将取决于甲骨文能不能证明其提供的软件维护、修复和支持服务值这个价格——毕竟红帽、Databricks等开源厂商都证明这种商业模式做好了也站得住脚。但在我看来,考虑到市场上还有很多其他选择,甲骨文必须积极与现有客群合作,在消除财务或技术摩擦的同时帮助客户前进。如果我是甲骨文的负责人,可能会考虑提供免费版本和承诺用量许可证,再根据客户的实际需求进行扩展和缩减。”
IDC分析师Dayaratna对此深以为然。
“我对调查的结果有些担忧:毕竟任何组织都完全有理由放弃昂贵且成熟的技术……只是放弃的速度有快有慢。从调查结果来看,可能很多企业已经考虑过,甚至为此制定了过渡计划。”
关于这项调查,Constellation Research 分析师 Holger Mueller 表示“Azul的报告有点自我中心,目标明显是说服更多人放弃Oracle Java。但现实问题在于,平台迁移非常困难,而且多数商业案例都值得怀疑……但如果Azul能够提供由AI驱动的有效代码迁移,那就还好。毕竟自动迁移能够大大降低迁移的成本和风险……我们将拭目以待。”
与此同时,Azul还在调查中研究了DevOps和安全问题。有62%的受访者表示死代码或未使用代码影响了DevOps生产力;33%的DevOps团队把超一半工作时间都用在了处理关于Java漏洞的误报上;49%的受访者称他们在生产中仍会遇到Log4j安全漏洞。
Azul公司联合创始人兼CEO Scott Sellers在一份声明中表示,“随着Java继续在企业的业务关键型应用程序中扮演支柱性角色,我们观察到了这波重要的复合性趋势——即从对Oracle Java替代方案的日益关注到云优化策略,再到DevOps生产力提升以及AI领域创新。”
参考链接:
https://thenewstack.io/2025-is-the-last-year-of-python-dominance-in-ai-java-comin/\\"
https://inside.java/2025/01/29/evolution-of-java-ecosystem-for-integrating-ai/\\"
https://www.infoq.com/presentations/ai-java-integrate/\\"
","description":"Java,这头在企业应用领域深耕 30 年的“猛兽”,如今正虎视眈眈地瞄准 AI 这块 Python 的“固有领地”。尤其是在企业级 AI 应用方面,Python 的优势似乎正在逐渐减弱。一家大型 Java 平台公司的技术负责人甚至预测,2025 年将是 Python 在 AI 领域占据主导地位的最后一年。 \\n\\nJava 强势进军 AI 领域,Python 能否守住阵地?\\n\\n \\n\\n今年,Java 迎来了 30 周年,它在企业应用领域的影响力依然稳固。这种多用途编程语言经历了二十多个版本的演进、2010 年 Sun Microsystems 被 Oracle 收购…","guid":"https://www.infoq.cn/article/ZTvSRhdQT7FICWJNSk84","author":"核子可乐,Tina","authorUrl":null,"authorAvatar":null,"publishedAt":"2025-02-11T03:01:00.722Z","media":[{"url":"https://static001.geekbang.org/infoq/6f/6f1bbf065a2348ebf8dbf7d849def823.jpeg","type":"photo","width":0,"height":0,"blurhash":""}],"categories":["编程语言"],"attachments":null,"extra":null,"language":null},{"title":"使用 DuckDB 的进程中分析数据管理","url":"https://www.infoq.cn/article/QyqSOLZD8L7OkrhqsvNz","content":"DuckDB 是一款专为分析数据管理设计的开源 OLAP 数据库,与 SQLite 类似,这是一款可被嵌入到应用中的进程中数据库。进程中的数据库引擎处于应用之中,允许同一内存地址空间内的数据传输,不再需要通过套接字复制大量数据,从而提升了性能。DuckDB 利用矢量处理查询,允许在 CPU 缓存中的有效操作,最小化函数调用开销。DuckDB 所使用的小块数据驱动(Morsel-Driven)的并行,允许在多个核心上有效并行化的同时,保留对对核心处理的认知。
我为什么要踏上这条构建新数据库的旅程?这还要从著名统计学家和软件开发者 Hadley Wickham\\" 的一句话说起:
把能放到内存中的数据放到数据库中是没有任何好处的,只会更慢更让人头疼。
这句话对我们这些数据库研究者而言既是打击也是挑战。是什么让数据库变得慢且头疼呢?罪魁祸首首先要数客户端-服务器模式。
在进行数据分析、将大量数据从应用转移至数据库,或者是将数据从数据库中提取到 R 或 Python 这类分析环境中时,整个过程可能会慢到折磨。
我曾试图理解客户端-服务器这一架构模式的起源,并撰写了论文《不要挟持我的数据——客户端协议重设案例\\"》。
我对比了各类数据管理系统中的数据库客户端协议,计算了在客户端程序和不同数据库系统中,传输固定大小数据集所需要的时间。
我以 Netcat\\" 工具通过网络套接字传输相同数据集的情况作为基准:
图一:不同客户端的对比,虚线为 Netcat 传输 CSV 数据所需的实际时间
对比 Netcat,MySQL 传输同样大小的数据需要十倍长的时间,Hive 和 MongoDB 则需要超过一个小时的时间。这个客户端-服务器模式似乎充满了问题。
我又想起了 SQLite,坐拥数十亿\\"份拷贝的 SQLite 无疑是世界上使用最为广泛的 SQL 系统。它们几乎时无处不在,人们每天都在与几十、乃至上百的实例打交道,但却意识不到。
SQLite 在进程中运行,这种不同以往的架构方式将数据库的管理系统直接整合到客户端应用之中,避免了传统的客户端-服务器模式。数据可直接在同一内存地址中进行传输,不再需要通过套接字复制和序列化大量数据。
然而,SQLite 并不是为大规模数据分析而设计,它的主要目的是为处理事务性工作负载。
几年之前,Mark Raasveldt\\" 和我一同开始研究新数据库 DuckDB\\"。DuckDB 是完全由 C++ 编写数据库管理系统,采用矢量执行引擎,作为一款进程中数据库引擎,我们常常称其为“分析性 SQLite”。该项目在极其宽松的 MIT 许可下发布,由基金会\\"管理运作,而不是传统的风险投资模式。
DuckDB 的交互是什么样的?
import duckdbduckdb.sql(\'LOAD httpfs\')duckdb.sql(\\"SELECT * FROM \'https://github.com/duckdb/duckdb/blob/master/data/parquet-testing/userdata1.parquet\'\\").df()
在这短短几行中,DuckDB 以 Python 包的形式导入,加载了一个扩展以实现与 HTTPS 资源的通信,通过 URL 读取了一份 Parquet 文件并将其转换为 Panda 数据框架(DF)。
正如这个例子中所示,DuckDB 可直接支持 Parquet 文件,我们将其视作是新版 CSV 文件。LOAD httpfs 调用则展示了 DuckDB 是如何通过插件进行扩展。
DF 的转换过程中隐含了许多复杂的工作,涉及到一个可能包含几百万行结果集的传输。但由于是在同一地址空间内进行的操作,我们可以绕过序列化或套接字传输,让整个过程快到难以置信。
我们还开发了一个具备查询语句自动完成和 SQL 语法高亮等功能的命令行客户端。例如,我在电脑上启动一个 DuckDB shell,读取同一个 Parquet 文件:
如果想用这条查询语句:
SELECT * FROM userdata.parquet;
会发现传统的 SQL 系统在这里通常不太行。userdata.parquet 是个文件而不是表,没有 userdata.parquet 这张表,但却有这个 Parquet 文件。如果找不到叫这个名字的表,DuckDB 会搜索该名称的其他实体并执行查询语句,如 Parquet 文件。
从架构的角度来说,DuckDB 有一个新的数据管理系统类别:进程中 OLAP 数据库。
SQLite 是面向 OLTP(在线事务处理)的进程中系统,但对于传统 OLTP 客户端-服务器架构而言,PostgreSQL 反而是更常见的选择。
图二:OLTP 对比 OLAP
对于 OLAP 而言,客户端-服务器系统有不少的可选项,其中便有最为公认的开源选项 ClickHouse\\"。但在 DuckDB 出现之前,进程中 OLAP 还没有任何选项可言。
让我们来看看 DuckDB 的技术层面,从下面这条 SQL 语句的处理阶段开始:
图三:DuckDB 中的一条简单选择语句
在这段示例中,我们从共用 cid 列的 customer 和 sale 这两张表的 JOIN 中选择名字和总和,通过将客户(customer)的所有收入和交易的税金相加,从而计算每个客户的总收入。
在运行这条语句时,系统会将两张表相连(JOIN),根据 cid 列的值对客户进行汇总。随后系统会计算对应的 revenue + tax,再按照 cid 进行分组聚合,从而得出名字和最终总和。
DuckDB 对这条语句的处理有如下几个标准阶段:查询规划、查询优化、物理规划。其中查询规划阶段又被进一步划分为所谓的管道。
举例来说,这段查询有三个管道,由它们在流中运作的方式定义。流在中断操作符,也就是需要取回全部输入时结束。
图四:第一管道
首条管道负责扫描 customer 表并构建一个哈希表。哈希的连接(join)被分为两个阶段,构建哈希列表和探测。哈希表的构建通常需要能接触到 join 左侧的所有数据,也就是说 customer 表必须全部被执行并输入到 hash join build 阶段。这一管道完成后,我们将进入第二管道。
图五:第二管道
第二条管道更大且包含更多流运算符:可扫描 sales 表,查看上一步构建的哈希表,从 customer 表中找到相连的伙伴,随后对 revenue + tax 一行进行对应并执行聚合以及中断操作符,最后再执行 group by build 阶段从而完成第二管道。
图六:第三管道
我们可以让第三和最后一条管道,使其读取 GROUP BY 的结果并输出最终结果。这是段非常标准的过程,许多数据库都采取了类似的查询规划方法。
要想理解 DuckDB 对查询语句的处理,让我们先看看传统火山迭代模型是如何在一系列迭代器中,让所有操作符都以一个迭代器为输入的同时暴露另一个迭代器。
语句的执行从最上层的运算符读取开始,也就是例子中的 GROUP BY BUILD 阶段。但此时因为还没有任何数据进入,所以它还读取不到任何东西。这也就触发了对其子运算符(映射)的读取请求,后者再从它自己的子运算符 HASH JOIN PROBE 中读取,该过程会逐级向下,直到最终的 sale 表。
图七:火山迭代模型
sale 表会生成一个元组以代表 ID、收入(revenue)以及税款这三列,比如 42、1233、422。该元组会向上移动到 HASH JOIN PROBE 并查询其建立的哈希表。比如,在知道 ID 42 对应的是 ASML 公司后,它会生成新的一行作为连接结果,也就是 ASML、1233、42。
新生成的这一行随后会被下一个运算符处理,映射运算符会将最后两列相加,从而生成新的一行:ASML、1355。这一行最终会进入 GROUP BY BUILD 阶段。
这种一次一个元组、一次一行,以“行”为重点的方式在 PostgreSQL、MySQL、Oracle、SQL 服务器,以及 SQLite 等众多数据库系统中都很常见,在事务性用例中非常有效,但却在数据分析处理方面存在一个明显的弱点:在运算符和迭代器之间的不断切换,会产生巨大的开销。
理论上来说是可以通过及时(JIT)编译整条流水线,这条方案虽然可行,但却不是唯一的解决方案。
让我们考虑简单的流式运算符操作,比如映射。
图八:映射的实现
我们将传入一行和部分伪代码:input.readRow 会读取一行输入,将第一个数值不变,但输出的第二个值会变成输入的第二和第三个相加之和,随后这行输出会被写入。这种方式虽然实施起来简单,但由于每一次数值读取都需要函数调用,因此会产生巨大的性能成本。
这种“一次一行”模型可优化为“一次一矢量”模型,该模型概念首次于2005年的“MonetDB/X100:超管道查询执行\\"”中被首次提出。
对这类模型而言,每次处理的不再是单一的值,而是被统称为矢量的几列;每次处理的也不是一行中的一个值,而是列中的多个值。类型的切换是在多个值的矢量中进行,而不是单行数值上,因此这种方式可减少开销。
图九:“一次一矢量”模型
“一次一矢量”模型在列和行的执行之间找到了平衡点。按列执行的高效性是以内存为代价的,通过将列的数量控制在一定范围内,这种“一次一矢量”模型能避免 JIT 编译的同时,促进局限性缓存,后者对效率而言是至关重要的。
在著名的“人人都应知道的延迟数据\\"”中展示了缓存局限性的重要性。
图十:人人都应知道的延迟数据
这张图由谷歌的 Peter Norvig 和 Jeff Dean 提出,高亮了 L1 缓存引用(0.5纳秒)和猪内存引用(100 纳秒)之间差距为200倍。而考虑到1990年起 L1 的缓存引用就已经快了200倍,而内存引用只加快了两倍,将操作放在 CPU 缓存中是具有极大优势的。
这也就是矢量查询的魅力所在。
图十一:通过矢量查询处理实现映射
让我们再回到之前的 revenue + tax 映射例子。这次我们不再只取一行,而是用三个矢量值作为输入,两个矢量作为输出。我们读取的不再是之前的一行,而是一小块数据(多个矢量列的集合)。第一个矢量保持不变,并被重新分配至输出;随后再创建新的结果矢量,对0到2048范围内的每一个单独值进行加法运算。
这种方式允许编译器自动插入特殊指令,仅在矢量级进行的数据类型解释和转换也避免了函数调用的开销。这就是矢量处理的核心所在。
单 CPU 的高效率对矢量处理而言还不够好,它还需要能在多个 CPU 上有良好的表现。我们又是如何支持并行的呢?
谷歌首席科学家 Goetz Graefe\\" 在他的论文《火山——可扩展的并行查询评估系统\\"》中描述了交换器并行的概念。
图十二:交换运算符的并行
在这个例子中,三个分区同时读取。应用过滤器、数据预聚合,之后再哈希。数据根据哈希值被分割,进一步聚合、重聚合,最后输出被合并。这样一来,查询的大部分都能被有效地并行化。
举例来说,这种方式在 Spark 执行简单语句时就有用到。在完成文件扫描后,一个哈希聚合器会执行 partial_sum,随后一个独立的操作会对数据进行分割、重聚合从而计算出总和。然而,这在很多情况下有被证明是会出问题的。
在 SQL 引擎中实现并行化更为现代的模型是“小块数据驱动(Morsel-Driven)的并行”。与前文提到的方式类似,输出层面的扫描被分割,从而实现部分扫描。在我们的第二条管道中,我们有两次对 sale 表的部分扫描,第一次扫描前半部分,第二次扫描剩下半部分。
图十三:小块数据驱动的并行
其中,HASH JOIN PROBE 维持不变,因为它是从两条管道中对同一哈希表进行操作。映射操作独立进行,所有结果都会被同步到 GROUP BY 操作符中,也就是我们的阻塞操作符。注意看,这里我们没有用到任何一个交换操作符。
与基于交换操作符的传统模型不同,GROUP BY 知道并行的存在,且可有效地管理不同线程读取可能存在冲突的分组所导致的问题。
图十四:分割哈希表以实现并行合并
在小块数据驱动的并行中,每个线程都会在流程开始时(第一阶段)预先聚合其数值,输入数据的独立子集活小块数据会被构建在独立的哈希表中。
下一阶段(第二阶段)中涉及分区聚合:在本地哈希表中,数据根据组键的基数进行分区,以确保每个哈希表中不会包含其他哈希表中的键值。在读取完成所有数据后,就可以最终确定哈希表和聚合,我们从每个参与的线程中选择相同的分区,并规划更多的线程将其全部读取。
虽然整体过程比标准的哈希表聚合还要复杂,但这却能允许小块数据为驱动的模型实现极大的并行性。该模型可有效地在多个输入上构建聚合,避免了交换操作符所带来的相关问题。
我通过文中演示的查询示例,再加上 ORDER BY 和 LIMIT 子句进行了一个简单的基准测试。SQL 语句从 customer 和 sale 表中选择 name 和 revenue + tax 的综合,这两张表通过 customer 进行分组和连接。
实验涉及两张表,其中一张有一百万的客户数,另一张则有上亿条销售记录。相当于1.4 GB 的 CSV 数据,数据大小刚刚好。
图十五:简单的基准测试
DuckDB 只需要半秒就可以在我的笔记本上完成查询,但 PostgreSQL 却在我优化了配置后花费11秒才完成任务,默认配置下则需要21秒。
虽然 DuckDB 的查询处理速度比 PostgreSQL 快40倍左右,但别忘了这种对比并不公平,PostgreSQL 主要还是为 OLTP 工作负载而设计的。
本文是为解释 DuckDB 的设计、功能和原理而编写。作为一款封装紧实的数据引擎,Duck DB 可以库的形式直接与应用程序相连,它的足迹小且无依赖性,允许开发人员将其轻松继承为一个可用于分析的 SQL 引擎。
我着重强调了进程内数据库的强大之处在于,其能有效将结果集转移至客户端并将结果写入数据库。
DuckDB 设计的一个重要组成部分在于矢量查询处理,这种技术允许高效的缓存内操作,消除了函数调用所带来的开销负担。
最后,我对 DuckDB 的并行模型也有谈及。小块数据驱动的并行模型允许跨任意数量核心的高效并行化的同时,也能维持对多核处理的认知,有助于提高 DuckDB 整体的性能和效率。
","description":"摘要 DuckDB 是一款专为分析数据管理设计的开源 OLAP 数据库,与 SQLite 类似,这是一款可被嵌入到应用中的进程中数据库。进程中的数据库引擎处于应用之中,允许同一内存地址空间内的数据传输,不再需要通过套接字复制大量数据,从而提升了性能。DuckDB 利用矢量处理查询,允许在 CPU 缓存中的有效操作,最小化函数调用开销。DuckDB 所使用的小块数据驱动(Morsel-Driven)的并行,允许在多个核心上有效并行化的同时,保留对对核心处理的认知。\\n\\n我为什么要踏上这条构建新数据库的旅程?这还要从著名统计学家和软件开发者 Hadley…","guid":"https://www.infoq.cn/article/QyqSOLZD8L7OkrhqsvNz","author":"作者:Hannes Mühleisen","authorUrl":null,"authorAvatar":null,"publishedAt":"2025-02-08T08:00:00.736Z","media":[{"url":"https://imgopt.infoq.com/articles/analytical-data-management-duckdb/en/resources/30figure-1-1686238750825.jpg","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://imgopt.infoq.com/articles/analytical-data-management-duckdb/en/resources/1code-1-1686238750825.jpg","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://imgopt.infoq.com/articles/analytical-data-management-duckdb/en/resources/21figure-2-1686238750825.jpg","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://imgopt.infoq.com/articles/analytical-data-management-duckdb/en/resources/17figure-3-1686238750825.jpg","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://imgopt.infoq.com/articles/analytical-data-management-duckdb/en/resources/1figure-4-small-1686241029787.jpg","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://imgopt.infoq.com/articles/analytical-data-management-duckdb/en/resources/7figure-5-1686238750825.jpg","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://imgopt.infoq.com/articles/analytical-data-management-duckdb/en/resources/1figure-6-small-1686241029787.jpg","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://imgopt.infoq.com/articles/analytical-data-management-duckdb/en/resources/2figure-7-1686238750824.jpg","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://imgopt.infoq.com/articles/analytical-data-management-duckdb/en/resources/3figure-8-1686238750825.jpg","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://imgopt.infoq.com/articles/analytical-data-management-duckdb/en/resources/3figure-9-1686238750825.jpg","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://imgopt.infoq.com/articles/analytical-data-management-duckdb/en/resources/3figure-10-1686238750825.jpg","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://imgopt.infoq.com/articles/analytical-data-management-duckdb/en/resources/3figure-11-1686238750825.jpg","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://imgopt.infoq.com/articles/analytical-data-management-duckdb/en/resources/1figure-12-small-1686241029787.jpg","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://imgopt.infoq.com/articles/analytical-data-management-duckdb/en/resources/2figure-13-1686238750825.jpg","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://imgopt.infoq.com/articles/analytical-data-management-duckdb/en/resources/2figure-14-1686239395390.jpg","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://imgopt.infoq.com/articles/analytical-data-management-duckdb/en/resources/2figure-15-1686239395391.jpg","type":"photo","width":0,"height":0,"blurhash":""}],"categories":["数据库"],"attachments":null,"extra":null,"language":null},{"title":"Rust 补丁两年零通过,34年开发者煽动网友逼Linus表态,维护者激烈反击:Rust 就是 Linux 的“癌症”!","url":"https://www.infoq.cn/article/4EKoyBq6rHy9NNo870vb","content":"
近日,Linux 社区再次爆发关于是否在内核中使用 Rust 语言的激烈争论。一些开发者试图将 Rust 代码添加到 Linux 内核中,但遭到了一些内核维护人员的强烈反对。他们认为,在内核中引入多种语言会增加复杂性,带来安全风险,并且不受欢迎。
赞成将Rust代码添加到Linux 内核中的代表——Asahi Linux首席开发者Hector Martin因为提交的代码屡屡被拒近日刚刚愤然离职。
Asahi Linux 是一个旨在为苹果 Silicon 芯片(如 M1、M2 等)设备提供 Linux 支持的项目。苹果 Silicon 芯片(如 M1、M2)采用了与传统 x86 架构完全不同的 ARM 架构,这导致 Linux 社区需要重新适配内核和驱动程序。
这个项目的目标就是将 Linux 移植到基于 ARM 架构的苹果硬件上,使用户能够在这些设备上运行 Linux 操作系统。Asahi Linux 项目由开发者 Hector Martin(又名 Marcan)领导,专注于为这些设备提供完整的 Linux 支持,包括 GPU 加速、电源管理和其他硬件功能。
“Asahi”(朝日)在日语中意为“朝阳”或“早晨的太阳”,象征着新的开始和希望。这个名字反映了该项目为苹果 Silicon 设备带来 Linux 支持的创新性和开拓性。
这个项目一直由 Hector Martin领导,但近日 Hector Martin在社交媒体发文称自己已经离开了Asahi Linux内核团队。
那么,这背后到底发生了什么?事情要从Hector Martin与内核维护者 Christoph Hellwig 发生的冲突说起。
而这场冲突似乎已经预埋已久。早在去年 9 月,微软软件工程师 Wedson Almeida Filho 就因不满 Rust for Linux 项目中出现的“非技术性废话”而选择退出。他表示,与持有不同目标的人合作非常困难,这引发了人们对 Rust 在内核中应用前景的担忧。
上个月,冲突再次升级。Linux内核维护者 Christoph Hellwig 再次公开抵制一项允许 Rust 编写的设备驱动程序调用内核核心 DMA API 的提议。该补丁旨在允许 Rust 驱动程序使用 DMA API 的 dma_alloc_coherent() C 函数来分配和映射大内存区域以进行直接内存访问。然而,Hellwig 坚决拒绝了该补丁。
面对 Hellwig 的阻挠,Martin 敦促 Rust for Linux 团队“在审核并准备就绪后立即合并该系列,而不要理会 Christoph 公然破坏该项目的行为”。
Hellwig在发给Linux内核邮件列表的邮件中写道:“请不要在kernel/dma中使用Rust代码。”据我们了解,这个补丁将代码添加到了Linux源代码树的rust/kernel,而不是kernel/dma。
Rust for Linux 项目的 Miguel Ojeda 试图缓和矛盾,他要求 Hellwig 提出替代方案,而不是一味地拒绝。
Hellwig回复说:“把包装器留在你的代码里,而不是给其他人添麻烦。”他还进一步指出,“DMA API的接口应该保留在可读的C代码中,而不是奇怪的绑定中,这样才能保持它的可搜索性和可维护性。”Hellwig似乎希望非C语言驱动程序有自己的私有C代码绑定,并且这些抽象不应单独维护,甚至不应在rust/kernel树中维护。
红帽软件工程师Danilo Krummrich参与了Rust for Linux项目,他向Hellwig提出质疑,而Hellwig则明确表示他不想处理Rust代码。
他写道:“别硬要我迎合那些当下时髦的编程语言。维护多语言项目是件痛苦的事。如果你想用C语言之外的东西,无论是汇编语言还是Rust,你得自己解决与C语言接口的兼容性问题。”
对此,Krummrich解释说,Rust for Linux项目正在开发Rust代码,抽象出供所有Rust驱动程序使用的C语言API,并由Rust开发人员集中维护。换句话说,内核的C语言部分保持不变,而Rust驱动程序通过这些抽象来调用C代码,且这些抽象由rust/kernel团队集中维护,这或许比每个驱动程序都有自己的独立C语言绑定要好。
但Hellwig似乎不想单独维护DMA的Rust抽象层。他解释说,他不想再增加一个维护者:
“如果你打算因为跨语言代码库而让Linux变得难以维护,那就在你自己的驱动程序里做吧,而不是把这种“癌症”传播到核心子系统中。(这里的‘癌症’是指跨语言代码库,而不是Rust本身,只是为了避开那些喜欢煽风点火的人)。”
学技术历史的人或许应该记得,2001年,时任微软首席执行官的Steve Ballmer曾将Linux比作癌症。Ballmer当时说:“Linux是一种癌症,它会在知识产权层面附着于它所接触到的一切。”那时Linux还没有发展到可以融入Windows Subsystem for Linux。
Hellwig继续争辩道,将DMA一致性分配器的Rust抽象层单独交给其他人维护,并不能改善现状,反而会削弱内核的可维护性:
“每增加一点其他语言的内容,都会极大地降低内核的可维护性。Linux之所以能够存活这么久,是因为它没有内部界限,而引入另一种语言则会完全破坏这一点。你可能不喜欢我的回答,但我会尽我所能阻止这种情况。这并不是因为我讨厌Rust。尽管它不是我最喜欢的编程语言,但肯定是最好的新语言之一,我鼓励人们在适合的项目中使用它。我只是不希望它出现在我需要维护的庞大的C语言代码库里。”
面对Hellwig一再的强硬拒绝之词,Ashai Linux项目负责人Hector Martin坐不住了。Hector Martin向外界公开表示,他认为Hellwig的言论违反了行为准则,但他怀疑是否会真的采取纪律处分。
Martin认为,Rust for Linux的开发人员应该忽略Hellwig的担忧,并将补丁提交给内核负责人Linus Torvalds评审:
“如果Linus不在这个话题上发表权威意见,Miguel和其他Rust团队成员应该在补丁经过评审后直接合并,无视Christoph试图破坏项目的企图。如果Linus接受了这个拉取请求,Christoph说什么都不重要。如果Linus不接受,Rust for Linux项目基本上就死了,除非Linus或Christoph采取下一步的行动。其他的都是在兜圈子。”
针对这一纠纷,外媒The Register曾询问Hellwig是否愿意就本文发表评论,他拒绝了。我们还曾向Linux基金会研究员Greg Kroah-Hartman征求意见,但他尚未回复。
这次争议再次暴露了 Linux 社区在 Rust 应用问题上的分歧。一部分开发者积极拥抱 Rust,认为它可以提高内核的安全性、性能和开发效率;而另一部分开发者则坚持使用 C 语言,对 Rust 持谨慎态度。
在这种分歧下,作为Linux 社区的核心人员,Linus Torvalds对于Rust for Linux的态度一直备受关注。偏偏,这位敢怒敢言的大佬也参与了Hellwig和Martin的这场纷争中。
2月6日,Linus向Martin 发送了一封邮件,邮件中隐晦地指责了Martin“煽动”网友情绪——在社交媒体上争取支持。Linus在邮件中写道:
你能否接受这个事实:也许问题就出在你身上? 你以为自己知道得更多。但当前的流程是有效的。 (流程)确实存在问题,但问题就是生活的事实。没有完美的事物。 然而,我要说的是,社交媒体的攻击让我不想要和你的方法有任何瓜葛。 因为如果我们在内核开发模型中遇到问题,那么社交媒体肯定不是解决方案。同样,它肯定也不是政治分歧的解决方案。 技术补丁和讨论很重要。社交媒体宣传——婉拒了哈 谢谢。
看到Linus发来的邮件,Martin也倍感委屈。
Martin回复邮件称,之所以将这些争论在网上公布出来,是因为自己已经别无选择。
如果在社交媒体上羞辱别人没用,那告诉我什么有用? 因为我已经没招了。 我真心希望技术补丁和讨论能成为真正重要的东西,但我觉得我们在这方面遇到了困难,至少在内核开发过程的某些环节中是这样。 没有人会把这句话理解为支持在社交媒体上辱骂别人作为“解决方案”。
Martin提到自己从 1991 年开始参与 Linux 开发,见证了 Linux 的成长,但现在他对一些现状感到遗憾。他最近领导了一个旨在为 Linux 社区提供通用安全模型的倡议,但两年内提交了四个补丁系列,却没有一行代码被审查过。尽管他们非常谨慎地提交代码,并尝试参与技术讨论,但几乎没有得到任何有意义的反馈或交流。
我是从 1991 年 12 月开始参与 Linux 开发的,对这个问题的看法也基于此。1995 年,我在麻省理工学院由 Stallman 赞助的自由软件会议上第一次见到你(这里指Linus)和 Tove。当时我告诉你,北达科他州的癌症患者因为我们在 Linux 上的工作以及优化癌症中心的医疗流程,能够享受更多与家人在一起的时光。 90 年代,RedHat 请我在多个会议上演讲,谈论 Linux 将如何主导企业计算,因为这是技术人员做“正确”技术的事情。 我现在看到的一些事情让我后悔说了那些话。 可能我职业生涯的最后一项技术贡献是领导一个为 Linux 社区提供通用安全模型架构的倡议。这不是要取代或替换当前正在做的任何事情,而是为了在这个机器学习和建模的时代,为开发和定制工作负载模型提供一个灵活的替代方案。 两年内提交了四个补丁系列,截至昨天,没有一行代码被审查过。 这个贡献只涉及它自己的目录,除非人们选择在其控制下执行工作负载,否则它不会做任何事情。 我们在提交时非常小心,以免浪费维护者的时间。我们甚至等了两个月,没有任何消息,才发送了一封询问其中一份提案状态的邮件。我们被告知,相当简短地说,如果我们曾经询问过它们,我们发送的任何东西都可能被忽略。 我们尝试参与技术讨论,可能是过度参与,试图解释我们为什么以及如何选择实施我们的提案。包括来自运行生产 IT 系统的顾问的意见,他们认为需要更好的方法来满足他们的安全需求。 从来没有进行过任何相关的技术交流。讨论的内容是,我们已经决定以某种方式做事,没有讨论,如果你不喜欢,你真的应该考虑做一些其他事情,而不是提交给上游 Linux。
Martin认为,当前的内核开发模式存在一些问题,尤其是缺乏对新思想的开放和尊重。虽然 Linux 是操作系统领域创新的重要平台,但如果继续忽视贡献者的努力,可能会扼杀创新。他还提到,行为准则虽然存在,但在实际执行中似乎并没有起到应有的作用。
如果大型科技公司能雇佣到“无所不知”的专家来担任内核子系统的维护者,这种模型会很好用。但现实中,这样的人非常稀缺。如果没有足够多的高水平维护者,创新可能会被扼杀,而 Linux 是操作系统领域唯一能真正推动创新的地方。 (但项目管理仍然存在一些问题。)从项目管理角度看,目前还没有明确的解决方案。科技行业从未遇到过如此复杂的挑战。传统的开源“分叉”模式(即通过分叉项目来解决问题)在 Linux 这种规模的项目上行不通。 虽然已经有了行为准则(比如禁止辱骂和人身攻击),但如果想有效推进项目,维护者们还需要一套更明确的行为标准。而这些,Jim,你听见了吗? 尊重他人和开放接纳新思想是项目顺利运行的润滑剂。但遗憾的是,这种态度在科技行业中非常罕见,就像“无所不知”的专家一样稀缺。
最后,Hector 向 Linus 及其家人致以祝福,并感叹这段经历让他对行业现状有了更深的思考。他希望未来能够找到一种更有效的方式,让技术讨论和创新能够顺利进行。
2022年10月3日,Linux内核增加了对Rust代码的支持。此前不久,微软Azure首席技术官Mark Russinovich曾主张新的编程项目应该用Rust而不是C或C++来编写。
Russinovich说:“为了安全性和可靠性,行业应该宣布这些语言已经过时。”
他的理由是,Rust代码可以避免困扰C和C++代码的内存安全漏洞(例如缓冲区溢出),而这些漏洞是大型项目中大多数严重漏洞的根源。这种观点随后得到了世界各地政府安全机构的支持。
C和C++开发者注意到人们对Rust兴趣的增长,并承认需要解决内存安全问题。因此,目前有许多项目正在进行中,例如TrapC、FilC、Mini-C和Safe C++,旨在增强C和C++对内存漏洞的抵抗能力。此外还有DARPA的TRACTOR项目,目标是自动将C代码转换为Rust。
在Filho去年宣布退出Rust for Linux项目后不久,Linux负责人Linus在奥地利维也纳的Linux基金会开源峰会上谈到了C和Rust开发人员之间存在的摩擦。
Linus说:“显然,有些人就是不喜欢Rust这个概念,也不希望Rust进入他们的领域。甚至有人在谈论Rust集成是一个失败……我们已经做了两年,现在说这个还为时过早,但我认为,即使它最终会失败——但我不认为它会——这也是学习的一部分。”
到目前为止,Linux开发者社区已经清楚地意识到,Rust并不总是受欢迎的。
2月3日,Hector Martin要求移除其Linux维护者的身份。
他在发给Linux内核邮件列表的邮件中写道:“我对内核开发流程或社区管理方式已经失去了信心。”
“苹果/ARM平台的开发将继续在下游进行。如果我以后自己想为某个子代码树提交一些补丁到上游,或许我会,或许不会。任何愿意自己去争取上游合并的人都可以去做。”
这次争议不仅阻碍了 Rust 代码进入 Linux 内核的进程,也加剧了社区内部的对立情绪。Rust for Linux 项目的未来发展面临诸多不确定性。
Martain的离职在社交媒体上引发了激烈讨论。在Hacker News上,有位用户的对于该事件的评论获得了诸多网友的赞同。
“简单来说,Linus Torvalds 在处理 Rust 问题上表现得很犹豫,没有明确表态支持或反对,导致 Linux 社区内部产生了信任危机。他的模糊态度让问题变得更糟,尤其是他平时对 C++ 等技术的立场都很明确,但这次却一反常态。 Rust-for-Linux(R4L)项目早就该有个明确的结果了,但经过几年的开发,它的未来依然不明朗。Linus 没有积极推动共识,反而坐视团队内部争吵,最后把责任推给了 Martin。这种做法让人失望。 他对 Martin 的批评其实暗示了他对 Rust 的不看好,但他始终没有公开明确表态。可能是因为他担心会引起更大的争议。不过,现在可能是他该直接表态的时候了。 如果 Linus 从一开始就果断地说‘不’,很多时间和精力(尤其是 Martin 的)都可以省下来,这场闹剧也能避免。”
甚至有人认为,Linus对 Martin 的斥责已经表明了他对Rust的态度——可能永远不会真正支持 Rust。
“Linus 对 Martin 的批评其实暗示了他对 Rust 的态度——他可能永远不会真正支持 Rust。不过,这件事更多和 Hector 的行为有关,而不是 Rust 本身。Hector 威胁要通过社交媒体曝光别人,这种行为是非常不好的。 他只是一个长期贡献者,可能有点粗鲁,但并不是什么十恶不赦的人。 另外,关于 Rust 的讨论并不是简单的“支持”或“反对”问题。没人完全反对在内核的某些部分使用 Rust,但具体在哪些部分用、怎么用、用在哪里,这些才是大家争论的焦点。Linus 对这类分歧一向比较放任,没有强行推动共识。”
有人怀念Hector 所做的贡献,并认可他对于 Rust for Linux 未来悲惨状况的预判。
“从旁观者的角度来看,有时你需要有人站在你这边,成为改变现状的倡导者。我会怀念 Hector 的贡献,并且认为他对 Linux 内核开发过程的悲惨状况的判断基本上是正确的。 如果这个社区对变革更加开放,那么像Hector 这样的人就能够创新,而不会产生怨恨”
事实上,网友认为,作为Linux社区中最有话语权的关键人物,Linus应该公开声明不应该对Rust for Linux贡献者进行攻击。
“我认为他有义务公开声明这种对 Rust for Linux 贡献者的攻击是不可接受的,并授权未来在类似情况下的补丁尽管收到 NACK 但仍继续前进,特别是考虑到补丁作者已在邮件列表中明确寻求他和 GKH 的处理方式。”
尽管 Rust for Linux 团队在技术上取得了显著进展,但如何与内核维护者达成共识仍是该项目面临的最大挑战。随着争论的持续,Linux 社区将不得不权衡 Rust 带来的潜在好处与维护多语言内核的复杂性。这场争论的结果可能会对 Linux 内核的未来发展产生深远影响。
参考链接:
https://www.theregister.com/2025/02/05/mixing_rust_and_c_linux\\"
https://www.reddit.com/r/rust/comments/1iju93d/asahi_linux_lead_developer_hector_martin_resigns/\\"
https://news.ycombinator.com/item?id=42972062\\"
https://lore.kernel.org/rust-for-linux/20250207121638.GA7356@wind.enjellic.com/\\"
https://www.theregister.com/2025/02/05/mixing_rust_and_c_linux/\\"
","description":"Asahi Linux首席开发者Hector Martin离开内核团队 \\n\\n近日,Linux 社区再次爆发关于是否在内核中使用 Rust 语言的激烈争论。一些开发者试图将 Rust 代码添加到 Linux 内核中,但遭到了一些内核维护人员的强烈反对。他们认为,在内核中引入多种语言会增加复杂性,带来安全风险,并且不受欢迎。\\n\\n \\n\\n赞成将Rust代码添加到Linux 内核中的代表——Asahi Linux首席开发者Hector Martin因为提交的代码屡屡被拒近日刚刚愤然离职。\\n\\n \\n\\nAsahi Linux 是一个旨在为苹果 Silicon 芯片(如 M1、M2 等…","guid":"https://www.infoq.cn/article/4EKoyBq6rHy9NNo870vb","author":"李冬梅,明知山","authorUrl":null,"authorAvatar":null,"publishedAt":"2025-02-08T06:08:05.511Z","media":[{"url":"https://static001.geekbang.org/infoq/1e/1e314fff6d9bb57181bd8c1a3ed208ec.png","type":"photo","width":0,"height":0,"blurhash":""}],"categories":["操作系统"],"attachments":null,"extra":null,"language":null},{"title":"Apache Hudi 1.0 正式发布","url":"https://www.infoq.cn/article/JyfP0ITJMtFbBBdC1aU0","content":"最近,Apache 软件基金会宣布 Apache Hudi 1.0 正式发布。这是一个支持近实时分析的事务型数据湖平台,最初于 2017 年推出。它提供了一种做过专门优化的开放式表格式,可实现增量数据管道的高效写入,提供可靠的查询性能。
最近,Apache 软件基金会宣布 Apache Hudi 1.0 正式发布\\"。这是一个支持近实时分析的事务型数据湖平台,最初于 2017 年推出。Apache Hudi\\" 提供了一种做过专门优化的开放式表格式,可实现增量数据管道的高效写入,提供可靠的查询性能。
最初,Hudi 是作为 Apache Hadoop\\" 上的增量处理框架\\"在 Uber 开发的,并于 2019 年提交给 Apache 软件基金会\\",旨在弥合类似数据库的功能与开放的数据湖架构之间的差距。Hudi 的主要优势在于能够同时支持近实时查询和批量查询。
最新版本引入的新特性旨在将数据湖转化为项目社区所认为的完备的 “数据湖管理系统”(DLMS)。Uber Hudi 项目创建者、Onehouse 首席执行官 Vinoth Chandar\\" 写道:
Hudi 的亮点在于提供了高性能的开放式表格格式以及全面的开源软件栈,可对数据湖进行摄取、存储、优化和有效的自管理。在 Hudi 所处的大型供应商生态系统中,开放格式和开放软件之间的区别经常被忽略。尽管如此,对于 Hudi 的用户来说,避免与任何特定的数据供应商的计算锁定仍然是一个重要的考虑因素。
Hudi 1.0 (遵循 Apache 2.0 许可)引入了新的二级索引系统,旨在提高查询性能并降低数据扫描成本。现在,用户可以在二级列上创建基于 SQL 的索引,从而大大加快查询执行速度。该版本还包括基于表达式的索引,和 PostgreSQL 中的一项功能类似,它取代了传统的分区策略,使数据组织更加灵活高效。去年,当预览版发布\\"时,Snyk 首席软件工程师 Boris Litvak 曾经写道\\":
在对象存储的三大 ACID 存储格式中,Apache Hudi 1.0(测试版)是第一个引入数据 “函数索引 ”的格式。在 SQL DB 术语中,我们通常称之为 “二级索引”。Delta.io 和 Apache Iceberg 何时会跟进?
图片来源:Apache Hudi 博客
该版本引入了对部分更新的支持,允许对特定字段而不是整行进行更新,从而提高了存储和计算效率。此外,非阻塞并发控制使多个流作业可以写入同一个数据集,而且不会造成瓶颈或故障。在谈到数据库架构时,Chandar 补充道:
至于完备的 DLMS 功能,Hudi 1.0 可以通过 Apache Spark 提供最接近的体验。用户可以部署安装了 Hudi 1.0 的 Spark 服务器(或 Spark Connect),提交 SQL/任务,通过 SQL 命令协调表服务,尽情使用二级索引功能,从而像 DBMS 一样加快查询速度。
Hudi 1.0 增强了存储引擎,包括采用日志结构合并(LSM)树来实现高效的时间线管理。这样就可以支持长期数据保留,并确保高性能查询规划,即使是包含数十亿条记录的数据集也不例外。Onehouse 和 Apache Hudi PMC 软件工程师 Bhavani Sudha Saktheeswaran\\" 评论\\"说:
无论是要构建开放式数据平台,将数据流导入数据湖仓,并摒弃数据仓库,还是要优化高性能查询,Hudi 1.0.0 都能让你比以往更轻松地使用数据湖仓。
在旧金山 QCon 大会上,Saktheeswaran 和 Uber 软件工程师 Saketh Chintapalli\\" 发表了关于使用 Apache Hudi 进行增量数据处理的演讲。会议录音可从 InfoQ 上获取\\"。
声明:本文为InfoQ翻译,未经许可禁止转载。
原文链接:https://www.infoq.com/news/2025/01/apache-hudi/\\"
","description":"最近,Apache 软件基金会宣布 Apache Hudi 1.0 正式发布。这是一个支持近实时分析的事务型数据湖平台,最初于 2017 年推出。它提供了一种做过专门优化的开放式表格式,可实现增量数据管道的高效写入,提供可靠的查询性能。 最近,Apache 软件基金会宣布 Apache Hudi 1.0 正式发布\\"。这是一个支持近实时分析的事务型数据湖平台,最初于 2017 年推出。Apache Hudi\\" 提供了一种做过专门优化的开放式表格式,可实现增量数据管道的高效写入,提供可靠的查询性能。\\n\\n \\n\\n最初,Hudi 是作为 Apache Hadoop\\" 上的增…","guid":"https://www.infoq.cn/article/JyfP0ITJMtFbBBdC1aU0","author":"作者:Hannes Mühleisen","authorUrl":null,"authorAvatar":null,"publishedAt":"2025-02-08T03:00:00.931Z","media":[{"url":"https://static001.geekbang.org/infoq/ff/ff2fafa1654d11e72be4ee5cbe02b314.png","type":"photo","width":0,"height":0,"blurhash":""}],"categories":["数据库"],"attachments":null,"extra":null,"language":null},{"title":"Java 近期新闻:WildFly 35、Jakarta EE 11更新、Java Operator SDK 5.0-RC1","url":"https://www.infoq.cn/article/4YEBM0vJU5pCMGRkFoC4","content":"JDK 24 早期访问版本的第 31 个构建版本已发布,包含从第 30 个构建版本以来的更新,修复了各种问题。更多关于此版本的详细信息可在发行说明中查看。
JDK 25 早期访问版本的第 5 个构建版本 也已发布,包含从第 4 个构建版本以来的 更新,修复了各种问题。更多关于此版本的详细信息可在发行说明中查看。
对于 JDK 24 和 JDK 25,开发者可以通过 Java Bug 数据库报告漏洞。
Eclipse 基金会的 Jakarta EE 开发布道师 Ivar Grimstad 在其每周的 Hashtag Jakarta EE 博客中提供了关于 Jakarta EE 11 的更新,内容如下:
Jakarta EE Core Profile 11 于 12 月发布。你可以在更新的 Jakarta EE Core Profile 11 规范页面查看所有详细信息。下一个发布将是 Jakarta EE Web Profile 11,一旦有兼容的实现通过重构的 TCK 测试就会发布。Jakarta EE Platform 11 将在 Web Profile 之后发布。
Jakarta EE 11 的发布过程包含了四个里程碑版本,Core Profile 的发布以及在 2025 年第一季度 Platform 和 Web Profile 正式发布之前根据需要发布的候选版本。
Spring Cloud 2023.0.5(代号 Leyton)已 发布,包含错误修复和对子项目的更新:Spring Cloud Kubernetes 3.1.5;Spring Cloud Function 4.1.5;Spring Cloud Stream 4.1.5;以及 Spring Cloud Circuit Breaker 3.1.4。此版本基于 Spring Boot 3.4.0。更多关于此版本的详细信息可在发行说明中查看。
WildFly 3.5 发布,主要提供对 MicroProfile 7.0 和更新规范的支持,包括:MicroProfile Telemetry 2.0;MicroProfile Open API 4.0;MicroProfile Rest Client 4.0;以及 MicroProfile Fault Tolerance 4.1。除了错误修复和依赖项升级外,其他增强功能还包括:对 WildFlyOpenTelemetryConfig 类进行了重构,因为它变得过于庞大且难以维护;在源代码库中添加了配置文件,旨在“实现清晰地组织构建和测试套件的执行,让基础部分和扩展部分可以独立构建,更重要的是可以独立测试”。更多关于此版本的详细信息可在发行说明中查看。InfoQ 将跟进更详细的新闻报道。
Micronaut 基金会发布了 Micronaut Framework 的 4.7.4 版本,包含 Micronaut Core 4.7.11、对 Micronaut Serialization 和 Micronaut Discovery Client 模块的错误修复和补丁更新。更多关于此版本的详细信息可在发行说明中查看。
Quarkus 3.17.6 是第五个维护版本(由于出现了回归问题,跳过了 3.17.1),包含了错误修复、依赖项升级,并解决了一些重要问题,例如:由 BuildTimeConfigurationReader 类中定义的 mappingToNames() 方法引起的 NullPointerException,该方法使用 SmallRye Config 的 PropertyName 类进行映射名称映射;使用 Dev Console 启动应用程序时发生崩溃。更多关于此版本的详细信息可在变更日志中查看。
Java Operator SDK 5.0.0 的第一个候选版本发布,包含对新功能的持续改进,例如:Kubernetes Server-Side Apply 被提升为一等公民,并作为修补状态资源的默认方法;EventSource 接口的变更,用于监控资源并处理访问缓存资源、过滤和额外功能,这些功能之前由 ResourceEventSource 子接口维护。更多关于此版本的详细信息可在变更日志中查看。
在 1.9.2 版本发布一周后,Arquillian 1.9.3 随之发布,包含了依赖项升级和对 ExceptionProxy 类的改进,可以在客户端缺少异常类时生成有意义的堆栈跟踪信息。更多关于此版本的详细信息可在发行说明中查看。
原文链接:
https://www.infoq.com/news/2025/01/java-news-roundup-jan06-2025/\\"
","description":"JDK 24 JDK 24 早期访问版本的第 31 个构建版本已发布,包含从第 30 个构建版本以来的更新,修复了各种问题。更多关于此版本的详细信息可在发行说明中查看。\\n\\nJDK 25\\n\\nJDK 25 早期访问版本的第 5 个构建版本 也已发布,包含从第 4 个构建版本以来的 更新,修复了各种问题。更多关于此版本的详细信息可在发行说明中查看。\\n\\n对于 JDK 24 和 JDK 25,开发者可以通过 Java Bug 数据库报告漏洞。\\n\\nJakarta EE 11\\n\\nEclipse 基金会的 Jakarta EE 开发布道师 Ivar Grimstad 在其每周的…","guid":"https://www.infoq.cn/article/4YEBM0vJU5pCMGRkFoC4","author":"作者:Michael Redlich","authorUrl":null,"authorAvatar":null,"publishedAt":"2025-02-07T03:00:00.025Z","media":null,"categories":["编程语言"],"attachments":null,"extra":null,"language":null},{"title":"Express.js 时隔十年发布 5.0.0 版本,聚焦稳定性与安全性","url":"https://www.infoq.cn/article/JNIbSkl9QocBsmYbRm4D","content":"Express.js 团队发布了 5.0.0 版本,这距离该团队 2014 年发布第一个主版本已经过去了 10 年的时间。这个版本主要关注稳定性和安全性,其目标是帮助开发人员编写更健壮的 Node.js 应用程序。
Express 5 放弃了对旧版本 Node.js 的支持。发布说明这样写到:
该版本不再支持 v18 版本以前的 Node.js。这是一个重要的变化,因为对旧版本 Node.js 的支持阻碍了性能和可维护性方面的很多重要变更。这一变化还使持续集成(CI)更加稳定且可维护性更高,也易于采用新语言和新运行时的特性并放弃不再需要的依赖关系。
在进行安全审计后,团队决定对路径路由匹配的运行方式进行修改。为了避免 正则表达式拒绝服务(regular expression Denial of Service,ReDoS)攻击,Express 5 不再支持正则表达式中的子表达式,例如/:foo(\\\\\\\\d+)。
// Express 4 的样例\\napp.get(\'/:id(\\\\\\\\d+)\', (req, res) => res.send(`ID: ${req.params.id}`));
Express.JS 技术委员会的成员 Blake Embrey 提供了一个正则表达式的样例(例如,/^\\\\/flights\\\\/([^\\\\/]+?)-([^\\\\/]+?)\\\\/?$/i),当与’/flights/’ + ‘-’.repeat(16_000) + \'/x’匹配时,可能需要 300 毫秒,而不是低于 1 毫秒。Express 团队建议使用强大的输入校验库。
Express 5 还要求正则表达式中的通配符必须明确命名或用 (.*)** 替换,以提高清晰度和可预测性。因此,像 /foo
这样的路径必须更新为 /foo(.*)。
路由中可选参数的语法也发生了变化。Express 4 中的:name? 变成了{/:name}:
// Express 4 的样例\\napp.get(\'/user/:id?\', (req, res) => res.send(req.params.id || \'No ID\'));\\n\\n\\n// Express 5 的样例\\napp.get(\'/user{/:id}\', (req, res) => res.send(req.params.id || \'No ID\'));
正则捕获组中的未命名参数不再允许通过索引进行访问。现在的参数必须命名:
// Express 4 的样例\\napp.get(\'/user(s?)\', (req, res) => res.send(req.params[0])); // \'s\'\\n\\n\\n// Express 5 的样例\\napp.get(\'/user:plural?\', (req, res) => res.send(req.params.plural));
Express 5 还强制执行 HTTP 状态码的有效性检查,作为防止静默失败的防御措施,也避免艰难的调试过程。
// Express 4 的样例\\nres.status(978).send(\'Invalid status\'); // Silently fails\\n\\n\\n// Express 5 的样例\\nres.status(978).send(\'Invalid status\'); // Throws an error
Express.js 5 让异步中间件和路由中的错误处理变得更加简单。Express 5 改进了异步中间件和路由中的错误处理,它自动将拒绝的 promise 传递给错误处理中间件,无需再使用 try/catch 块。
// Express 4 的样例\\napp.get(\'/data\', async (req, res, next) => {\\n try {\\n const result = await fetchData();\\n res.send(result);\\n } catch (err) {\\n next(err);\\n }\\n});\\n\\n\\n// Express 5 的样例\\napp.get(\'/data\', async (req, res) => {\\n const result = await fetchData();\\n res.send(result);\\n});
虽然 Express 团队努力将破坏性改动保持在最低水平,但希望将 Express 代码升级到新版本的开发人员还是要小心留意。开发人员可查看在线的迁移指南。
Express.js 是 OpenJS 基金会(At-Large 类别)的一个项目。开发人员可以阅读完整的发布说明,了解更多技术细节和样例。
原文链接:
Express 5.0 Released, Focuses on Stability and Security(https://www.infoq.com/news/2025/01/express-5-released/\\")
","description":"Express.js 团队发布了 5.0.0 版本,这距离该团队 2014 年发布第一个主版本已经过去了 10 年的时间。这个版本主要关注稳定性和安全性,其目标是帮助开发人员编写更健壮的 Node.js 应用程序。 Express 5 放弃了对旧版本 Node.js 的支持。发布说明这样写到:\\n\\n该版本不再支持 v18 版本以前的 Node.js。这是一个重要的变化,因为对旧版本 Node.js 的支持阻碍了性能和可维护性方面的很多重要变更。这一变化还使持续集成(CI)更加稳定且可维护性更高,也易于采用新语言和新运行时的特性并放弃不再需要的依赖关系。\\n\\n在进行安全…","guid":"https://www.infoq.cn/article/JNIbSkl9QocBsmYbRm4D","author":"作者:Bruno Couriol","authorUrl":null,"authorAvatar":null,"publishedAt":"2025-02-06T03:00:00.860Z","media":null,"categories":["编程语言"],"attachments":null,"extra":null,"language":null},{"title":"Java近期新闻:Java Operator SDK 5.0、Open Liberty、Quarkus MCP、Vert.x、JBang、TornadoVM","url":"https://www.infoq.cn/article/i4BLrHLv9k9CZm5k7Bsh","content":"JDK 24 早期访问版本\\"的 Build 34\\" 已发布,包含自 Build 33 以来的 更新\\",解决了多个问题\\"。更多关于此版本的详细信息可以在发布说明\\"中找到。
JDK 25 早期访问版本\\" 的 Build 8\\" 已发布,包含自 Build 7 以来的更新\\",解决了多个问题\\"。更多关于此版本的详细信息可以在发布说明\\"中找到。
对于 JDK 24\\" 和 JDK 25\\",开发人员可以通过 Java Bug Database\\" 提交问题。
TornadoVM 1.0.10\\" 包含了错误修复、兼容性增强和改进:新增命令行选项 -Dtornado.spirv.runtimes,用于选择调度和管理 SPIR-V\\" 的运行时(Level Zero 和/或 OpenCL);支持使用 HalfFloat\\" 类型进行矩阵乘法。更多关于此版本的详细信息可以在发布说明\\"中找到。
Spring Cloud\\" 2025.0.0 第一个里程碑版本\\"(代号 Northfields)包含了错误修复和对子项目的更新:Spring Cloud Kubernetes\\" 3.3.0-M1、Spring Cloud Function\\" 4.3.0-M1、Spring Cloud Stream\\" 4.3.0-M1以及 Spring Cloud Circuit Breaker\\" 3.3.0-M1。此版本基于 Spring Boot 3.5.0-M1。更多关于此版本的详细信息可以在发布说明\\"中找到。
IBM 发布 Open Liberty 25.0.0.1\\",更新了以下功能:Batch API\\" (batch-1.0)、Jakarta Batch 2.0\\" (batch-2.0)、Jakarta Batch 2.1\\" (batch-2.1)、Java Connector Architecture Security Inflow 1.0\\" (jcaInboundSecurity-1.0) 和 Jakarta Connectors Inbound Security 2.0\\" (connectorsInboundSecurity-2.0),以支持 InstantOn\\";并引入了 webModuleClassPathLoader 配置属性,用于控制由 Web 模块 Class-Path 属性引用的 JAR 文件所使用的类加载器,从而简化 Web 模块迁移。
Quarkus\\" 3.18.0\\" 发布,包含了错误修复、依赖项升级和一些显著的变更,例如:将 Micrometer\\" 集成到 WebSockets Next\\" 扩展中;在 OpenID Connect\\" 和 OpenID Connect Client\\" 扩展中支持使用文件系统加载的客户端断言进行 JWT Bearer 客户端身份验证;新增 OpenID Connect Redis Token State Manager\\" 扩展,用于将 OIDC 连接令牌状态存储在 Redis 缓存数据源中。更多关于此版本的详细信息可以在更新日志\\"中找到。
Quarkus 团队还推出了\\"他们自己的 Model Context Protocol\\"(MCP)协议实现\\",目前包含三个服务器:JDBC、文件系统和 JavaFX。这些服务器已通过 Claude for Desktop\\"、Model Context Protocol CLI\\" 和 Goose\\" 客户端进行了测试。为简单起见,团队推荐使用 JBang\\" 来使用这些服务器,但不是必需的。
为与 Quarkus 保持一致,Camel Quarkus\\" 3.18.0\\" 发布(包含 Camel 4.9.0 和 Quarkus 3.18.0),解决了一些问题,例如:Kamelet\\" 扩展无法将 ClasspathResolver 实例(在 DefaultResourceResolvers\\" 中定义的内部类)序列化为字节码;Debezium\\" BOM 自 Debezium 1.19.2.Final 发布以来对 Cassandra CQL\\" 扩展驱动程序的单元测试产生的影响。更多关于此版本的详细信息可以在发布说明\\"中找到。
Infinispan 15.1.5\\" 发布,包含了依赖项升级和问题修复,例如:使用 DELETE 语句并发删除导致 cache::removeAsync 返回 null,从而引发 NullPointerException;HotRodUpgradeContainerSSLTest\\" 类的实例因 PersistenceManagerImpl\\" 类无法启动而导致测试套件崩溃。更多关于此版本的详细信息可以在发布说明\\"中找到。
Java Operator SDK\\" 5.0.0\\" 发布,持续改进新功能,例如:Kubernetes Server-Side Apply\\" 被提升为一等公民,默认用于修补状态资源;EventSource\\" 接口的责任发生了变化,现在负责监控资源和处理访问缓存资源、过滤以及之前由 ResourceEventSource\\" 子接口维护的其他功能。更多关于此版本的详细信息可以在发布说明\\"中找到。
JBang 0.123.0\\" 发布,包含了错误修复、文档改进和新功能:现在支持在捆绑的 MANIFEST.MF 文件中使用 add-open 和 exports 等选项;在受支持的 IDE 列表中新增了 Cursor\\"(AI 代码编辑器)。更多关于此版本的详细信息可以在发布说明\\"中找到。
Eclipse Vert.x\\" 5.0 的第四个候选版本\\" 发布,主要变更包括:移除了已弃用的类——ServiceAuthInterceptor 和 ProxyHelper,以及在 ServiceBinder 类中定义的两个重载的 addInterceptor() 方法;支持 Java 平台模块系统(JPMS)。更多关于此版本的详细信息可以在发布说明\\"和弃用及重大变更\\"中找到。
JHipster Lite\\" 1.26.0\\" 和 1.25.0\\" 发布,包含了错误修复、依赖项升级和新功能/增强,例如:新增了 PostgreSQL、MariaDB、MySQL 和 MSSQL 的数据源模块;重构模块的状态排名系统。1.26.0 版本是 JHipster Lite 的第 100 次发布版本。更多关于这些版本的详细信息可以在 1.26.0 的发布说明\\"和 1.25.0 的发布说明\\"中找到。
原文链接:
https://www.infoq.com/news/2025/02/java-news-roundup-jan27-2025/\\"
","description":"JDK 24 JDK 24 早期访问版本\\"的 Build 34\\" 已发布,包含自 Build 33 以来的 更新\\",解决了多个问题\\"。更多关于此版本的详细信息可以在发布说明\\"中找到。\\n\\nJDK 25\\n\\nJDK 25 早期访问版本\\" 的 Build 8\\" 已发布,包含自 Build 7 以来的更新\\",解决了多个问题\\"。更多关于此版本的详细信息可以在发布说明\\"中找到。\\n\\n对于 JDK 24\\" 和 JDK 25\\",开发人员可以通过 Java Bug Database\\" 提交问题。\\n\\nTornadoVM\\n\\nTornadoVM 1.0.10\\" 包含了错误修复、兼容性增强和改进…","guid":"https://www.infoq.cn/article/i4BLrHLv9k9CZm5k7Bsh","author":"Michael Redlich","authorUrl":null,"authorAvatar":null,"publishedAt":"2025-02-06T02:21:32.439Z","media":null,"categories":["编程语言"],"attachments":null,"extra":null,"language":null},{"title":"使用 DuckDB 的进程中分析数据管理","url":"https://www.infoq.cn/article/u3Sl6xOopvzFWo5h1WJG","content":"本文要点
DuckDB 是一款专为分析数据管理设计的开源 OLAP 数据库,与 SQLite 类似,这是一款可被嵌入到应用中的进程中数据库。进程中的数据库引擎处于应用之中,允许同一内存地址空间内的数据传输,不再需要通过套接字复制大量数据,从而提升了性能。DuckDB 利用矢量处理查询,允许在 CPU 缓存中的有效操作,最小化函数调用开销。DuckDB 所使用的小块数据驱动(Morsel-Driven)的并行,允许在多个核心上有效并行化的同时,保留对对核心处理的认知。
我为什么要踏上这条构建新数据库的旅程?这还要从著名统计学家和软件开发者 Hadley Wickham 的一句话说起:
把能放到内存中的数据放到数据库中是没有任何好处的,只会更慢更让人头疼。
这句话对我们这些数据库研究者而言既是打击也是挑战。是什么让数据库变得慢且头疼呢?罪魁祸首首先要数客户端 - 服务器模式。
在进行数据分析、将大量数据从应用转移至数据库,或者是将数据从数据库中提取到 R 或 Python 这类分析环境中时,整个过程可能会慢到折磨。
我曾试图理解客户端 - 服务器这一架构模式的起源,并撰写了论文《不要挟持我的数据——客户端协议重设案例》。
我对比了各类数据管理系统中的数据库客户端协议,计算了在客户端程序和不同数据库系统中,传输固定大小数据集所需要的时间。
我以 Netcat 工具通过网络套接字传输相同数据集的情况作为基准:
图一:不同客户端的对比,虚线为 Netcat 传输 CSV 数据所需的实际时间
对比 Netcat,MySQL 传输同样大小的数据需要十倍长的时间,Hive 和 MongoDB 则需要超过一个小时的时间。这个客户端 - 服务器模式似乎充满了问题。
我又想起了 SQLite,坐拥数十亿份拷贝的 SQLite 无疑是世界上使用最为广泛的 SQL 系统。它们几乎时无处不在,人们每天都在与几十、乃至上百的实例打交道,但却意识不到。
SQLite 在进程中运行,这种不同以往的架构方式将数据库的管理系统直接整合到客户端应用之中,避免了传统的客户端 - 服务器模式。数据可直接在同一内存地址中进行传输,不再需要通过套接字复制和序列化大量数据。
然而,SQLite 并不是为大规模数据分析而设计,它的主要目的是为处理事务性工作负载。
几年之前,Mark Raasveldt 和我一同开始研究新数据库 DuckDB。DuckDB 是完全由 C++ 编写数据库管理系统,采用矢量执行引擎,作为一款进程中数据库引擎,我们常常称其为“分析性 SQLite”。该项目在极其宽松的 MIT 许可下发布,由基金会管理运作,而不是传统的风险投资模式。
DuckDB 的交互是什么样的?
import duckdb\\nduckdb.sql(\'LOAD httpfs\')\\nduckdb.sql(\\"SELECT * FROM \'https://github.com/duckdb/duckdb/blob/master/data/parquet-testing/userdata1.parquet\'\\").df()\\n
在这短短几行中,DuckDB 以 Python 包的形式导入,加载了一个扩展以实现与 HTTPS 资源的通信,通过 URL 读取了一份 Parquet 文件并将其转换为 Panda 数据框架(DF)。正如这个例子中所示,DuckDB 可直接支持 Parquet 文件,我们将其视作是新版 CSV 文件。LOAD httpfs 调用则展示了 DuckDB 是如何通过插件进行扩展。
DF 的转换过程中隐含了许多复杂的工作,涉及到一个可能包含几百万行结果集的传输。但由于是在同一地址空间内进行的操作,我们可以绕过序列化或套接字传输,让整个过程快到难以置信。
我们还开发了一个具备查询语句自动完成和 SQL 语法高亮等功能的命令行客户端。例如,我在电脑上启动一个 DuckDB shell,读取同一个 Parquet 文件:
如果想用这条查询语句:
SELECT * FROM userdata.parquet;\\n
会发现传统的 SQL 系统在这里通常不太行。userdata.parquet 是个文件而不是表,没有 userdata.parquet 这张表,但却有这个 Parquet 文件。如果找不到叫这个名字的表,DuckDB 会搜索该名称的其他实体并执行查询语句,如 Parquet 文件。
从架构的角度来说,DuckDB 有一个新的数据管理系统类别:进程中 OLAP 数据库。
SQLite 是面向 OLTP(在线事务处理)的进程中系统,但对于传统 OLTP 客户端 - 服务器架构而言,PostgreSQL 反而是更常见的选择。
图二:OLTP 对比 OLAP
对于 OLAP 而言,客户端 - 服务器系统有不少的可选项,其中便有最为公认的开源选项 ClickHouse。但在 DuckDB 出现之前,进程中 OLAP 还没有任何选项可言。
让我们来看看 DuckDB 的技术层面,从下面这条 SQL 语句的处理阶段开始:
图三:DuckDB 中的一条简单选择语句
在这段示例中,我们从共用 cid 列的 customer 和 sale 这两张表的 JOIN 中选择名字和总和,通过将客户(customer)的所有收入和交易的税金相加,从而计算每个客户的总收入。
在运行这条语句时,系统会将两张表相连(JOIN),根据 cid 列的值对客户进行汇总。随后系统会计算对应的 revenue + tax,再按照 cid 进行分组聚合,从而得出名字和最终总和。
DuckDB 对这条语句的处理有如下几个标准阶段:查询规划、查询优化、物理规划。其中查询规划阶段又被进一步划分为所谓的管道。
举例来说,这段查询有三个管道,由它们在流中运作的方式定义。流在中断操作符,也就是需要取回全部输入时结束。
图四:第一管道
首条管道负责扫描 customer 表并构建一个哈希表。哈希的连接(join)被分为两个阶段,构建哈希列表和探测。哈希表的构建通常需要能接触到 join 左侧的所有数据,也就是说 customer 表必须全部被执行并输入到 hash join build 阶段。这一管道完成后,我们将进入第二管道。
图五:第二管道
第二条管道更大且包含更多流运算符:可扫描 sales 表,查看上一步构建的哈希表,从 customer 表中找到相连的伙伴,随后对 revenue + tax 一行进行对应并执行聚合以及中断操作符,最后再执行 group by build 阶段从而完成第二管道。
图六:第三管道
我们可以让第三和最后一条管道,使其读取 GROUP BY 的结果并输出最终结果。这是段非常标准的过程,许多数据库都采取了类似的查询规划方法。
要想理解 DuckDB 对查询语句的处理,让我们先看看传统火山迭代模型是如何在一系列迭代器中,让所有操作符都以一个迭代器为输入的同时暴露另一个迭代器。
语句的执行从最上层的运算符读取开始,也就是例子中的 GROUP BY BUILD 阶段。但此时因为还没有任何数据进入,所以它还读取不到任何东西。这也就触发了对其子运算符(映射)的读取请求,后者再从它自己的子运算符 HASH JOIN PROBE 中读取,该过程会逐级向下,直到最终的 sale 表。
图七:火山迭代模型
sale 表会生成一个元组以代表 ID、收入(revenue)以及税款这三列,比如 42、1233、422。该元组会向上移动到 HASH JOIN PROBE 并查询其建立的哈希表。比如,在知道 ID 42 对应的是 ASML 公司后,它会生成新的一行作为连接结果,也就是 ASML、1233、42。
新生成的这一行随后会被下一个运算符处理,映射运算符会将最后两列相加,从而生成新的一行:ASML、1355。这一行最终会进入 GROUP BY BUILD 阶段。
这种一次一个元组、一次一行,以“行”为重点的方式在 PostgreSQL、MySQL、Oracle、SQL 服务器,以及 SQLite 等众多数据库系统中都很常见,在事务性用例中非常有效,但却在数据分析处理方面存在一个明显的弱点:在运算符和迭代器之间的不断切换,会产生巨大的开销。
理论上来说是可以通过及时(JIT)编译整条流水线,这条方案虽然可行,但却不是唯一的解决方案。
让我们考虑简单的流式运算符操作,比如映射。
图八:映射的实现
我们将传入一行和部分伪代码:input.readRow 会读取一行输入,将第一个数值不变,但输出的第二个值会变成输入的第二和第三个相加之和,随后这行输出会被写入。这种方式虽然实施起来简单,但由于每一次数值读取都需要函数调用,因此会产生巨大的性能成本。
这种“一次一行”模型可优化为“一次一矢量”模型,该模型概念首次于 2005 年的“MonetDB/X100:超管道查询执行”中被首次提出。
对这类模型而言,每次处理的不再是单一的值,而是被统称为矢量的几列;每次处理的也不是一行中的一个值,而是列中的多个值。类型的切换是在多个值的矢量中进行,而不是单行数值上,因此这种方式可减少开销。
图九:“一次一矢量”模型
“一次一矢量”模型在列和行的执行之间找到了平衡点。按列执行的高效性是以内存为代价的,通过将列的数量控制在一定范围内,这种“一次一矢量”模型能避免 JIT 编译的同时,促进局限性缓存,后者对效率而言是至关重要的。
在著名的“人人都应知道的延迟数据”中展示了缓存局限性的重要性。
图十:人人都应知道的延迟数据
这张图由谷歌的 Peter Norvig 和 Jeff Dean 提出,高亮了 L1 缓存引用(0.5 纳秒)和猪内存引用(100 纳秒)之间差距为 200 倍。而考虑到 1990 年起 L1 的缓存引用就已经快了 200 倍,而内存引用只加快了两倍,将操作放在 CPU 缓存中是具有极大优势的。
这也就是矢量查询的魅力所在。
图十一:通过矢量查询处理实现映射
让我们再回到之前的 revenue + tax 映射例子。这次我们不再只取一行,而是用三个矢量值作为输入,两个矢量作为输出。我们读取的不再是之前的一行,而是一小块数据(多个矢量列的集合)。第一个矢量保持不变,并被重新分配至输出;随后再创建新的结果矢量,对 0 到 2048 范围内的每一个单独值进行加法运算。
这种方式允许编译器自动插入特殊指令,仅在矢量级进行的数据类型解释和转换也避免了函数调用的开销。这就是矢量处理的核心所在。
单 CPU 的高效率对矢量处理而言还不够好,它还需要能在多个 CPU 上有良好的表现。我们又是如何支持并行的呢?
谷歌首席科学家 Goetz Graefe 在他的论文《火山——可扩展的并行查询评估系统》中描述了交换器并行的概念。
图十二:交换运算符的并行
在这个例子中,三个分区同时读取。应用过滤器、数据预聚合,之后再哈希。数据根据哈希值被分割,进一步聚合、重聚合,最后输出被合并。这样一来,查询的大部分都能被有效地并行化。
举例来说,这种方式在 Spark 执行简单语句时就有用到。在完成文件扫描后,一个哈希聚合器会执行 partial_sum,随后一个独立的操作会对数据进行分割、重聚合从而计算出总和。然而,这在很多情况下有被证明是会出问题的。
在 SQL 引擎中实现并行化更为现代的模型是“小块数据驱动(Morsel-Driven)的并行”。与前文提到的方式类似,输出层面的扫描被分割,从而实现部分扫描。在我们的第二条管道中,我们有两次对 sale 表的部分扫描,第一次扫描前半部分,第二次扫描剩下半部分。
图十三:小块数据驱动的并行
其中,HASH JOIN PROBE 维持不变,因为它是从两条管道中对同一哈希表进行操作。映射操作独立进行,所有结果都会被同步到 GROUP BY 操作符中,也就是我们的阻塞操作符。注意看,这里我们没有用到任何一个交换操作符。
与基于交换操作符的传统模型不同,GROUP BY 知道并行的存在,且可有效地管理不同线程读取可能存在冲突的分组所导致的问题。
图十四:分割哈希表以实现并行合并
在小块数据驱动的并行中,每个线程都会在流程开始时(第一阶段)预先聚合其数值,输入数据的独立子集活小块数据会被构建在独立的哈希表中。
下一阶段(第二阶段)中涉及分区聚合:在本地哈希表中,数据根据组键的基数进行分区,以确保每个哈希表中不会包含其他哈希表中的键值。在读取完成所有数据后,就可以最终确定哈希表和聚合,我们从每个参与的线程中选择相同的分区,并规划更多的线程将其全部读取。
虽然整体过程比标准的哈希表聚合还要复杂,但这却能允许小块数据为驱动的模型实现极大的并行性。该模型可有效地在多个输入上构建聚合,避免了交换操作符所带来的相关问题。
我通过文中演示的查询示例,再加上 ORDER BY 和 LIMIT 子句进行了一个简单的基准测试。SQL 语句从 customer 和 sale 表中选择 name 和 revenue + tax 的综合,这两张表通过 customer 进行分组和连接。
实验涉及两张表,其中一张有一百万的客户数,另一张则有上亿条销售记录。相当于 1.4 GB 的 CSV 数据,数据大小刚刚好。
图十五:简单的基准测试
DuckDB 只需要半秒就可以在我的笔记本上完成查询,但 PostgreSQL 却在我优化了配置后花费 11 秒才完成任务,默认配置下则需要 21 秒。
虽然 DuckDB 的查询处理速度比 PostgreSQL 快 40 倍左右,但别忘了这种对比并不公平,PostgreSQL 主要还是为 OLTP 工作负载而设计的。
本文是为解释 DuckDB 的设计、功能和原理而编写。作为一款封装紧实的数据引擎,Duck DB 可以库的形式直接与应用程序相连,它的足迹小且无依赖性,允许开发人员将其轻松继承为一个可用于分析的 SQL 引擎。
我着重强调了进程内数据库的强大之处在于,其能有效将结果集转移至客户端并将结果写入数据库。
DuckDB 设计的一个重要组成部分在于矢量查询处理,这种技术允许高效的缓存内操作,消除了函数调用所带来的开销负担。
最后,我对 DuckDB 的并行模型也有谈及。小块数据驱动的并行模型允许跨任意数量核心的高效并行化的同时,也能维持对多核处理的认知,有助于提高 DuckDB 整体的性能和效率。
原文链接:
https://www.infoq.com/articles/analytical-data-management-duckdb/\\"
","description":"本文要点 DuckDB 是一款专为分析数据管理设计的开源 OLAP 数据库,与 SQLite 类似,这是一款可被嵌入到应用中的进程中数据库。进程中的数据库引擎处于应用之中,允许同一内存地址空间内的数据传输,不再需要通过套接字复制大量数据,从而提升了性能。DuckDB 利用矢量处理查询,允许在 CPU 缓存中的有效操作,最小化函数调用开销。DuckDB 所使用的小块数据驱动(Morsel-Driven)的并行,允许在多个核心上有效并行化的同时,保留对对核心处理的认知。\\n\\n我为什么要踏上这条构建新数据库的旅程?这还要从著名统计学家和软件开发者 Hadley…","guid":"https://www.infoq.cn/article/u3Sl6xOopvzFWo5h1WJG","author":"作者:Hannes Mühleisen","authorUrl":null,"authorAvatar":null,"publishedAt":"2025-01-29T15:59:59.211Z","media":[{"url":"https://static001.geekbang.org/wechat/images/7c/7cffa61a5835165b4faa66b845a7a1c8.jpg","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/wechat/images/cf/cfa7164dd2ec22e9b18b77f1f7b3f24a.jpg","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/wechat/images/bb/bb2c470a8a794b70936fc285caee4d47.jpg","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/wechat/images/08/08e109e54d5bbc3bb95fb478f0b9a955.jpg","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/wechat/images/10/101f46319262a1efbacccc1d54ab0523.jpg","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/wechat/images/45/45627de6d0b743dded5d6b007a74e4ab.jpg","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/wechat/images/c0/c0e978684aca16f3937336e2a25d9214.jpg","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/wechat/images/78/7833b6368354af8bf4d9b0f17a78e55f.jpg","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/wechat/images/f7/f76e16e8c1a72696fcb0b2058dc17ac4.jpg","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/wechat/images/d3/d3045b96e78e3e281ed7201666c071d4.jpg","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/wechat/images/0e/0e14e0201ddad51bc40780d972c14c23.jpg","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/wechat/images/db/db06804368fa088dce64282afa2ad495.jpg","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/wechat/images/07/073e189fbed8a9097a7810f275275b1a.jpg","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/wechat/images/55/55d76b34a62edc6e9eaa1590239e4cb6.jpg","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/wechat/images/ae/ae342188befdae377faa3097791a5059.jpg","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/wechat/images/fa/facf3bab90745b9f87dcc77908db9b4f.jpg","type":"photo","width":0,"height":0,"blurhash":""}],"categories":["数据库"],"attachments":null,"extra":null,"language":null},{"title":"2025年,我的第一个建议是别当程序员了!但如果非要当,这些办法可以教会你如何提升自己","url":"https://www.infoq.cn/article/00ZflUA3lzstmwIMRYDs","content":"编者按:
比学软件更重要的,是理解软件行业发展趋势。放眼世界,软件和科技公司的影响力愈发显著,IT行业已成为全球经济增长的重要引擎。去年年中,有报道称,美国七大科技公司创下了新的里程碑,总市值历史上首次突破 15 万亿美元,占美国GDP一半。与此同时,中国软件产业尽管还存在差距但也发展迅速,因此我们也要清醒地认识到,要想在激烈的全球竞争中脱颖而出,就必须不断学习,成为具有国际竞争力的软件人才。
此外,云原生是过去十年最重要的计算范式,而大模型则推动着云计算等基础架构以及工具层面的变革。云原生和大模型的快速发展,对软件工程师提出了更高的要求。作为软件工程师,我们不仅需要掌握传统的编程技能,还需要不断学习新的技术和工具,以适应快速变化的技术环境。
在这样的背景下,InfoQ策划了这场圆桌对话,分享嘉宾视角下对AI时代下软件行业发展趋势及开发者职业成长路径的见解和心得,帮助开发者群体掌握未来技术发展趋势,树立个人技术竞争力,从而助力每一位软件工程师在未来的职业道路上走得更远、更稳。
嘉宾|黄东旭,PingCAP联合创始人兼CTO;李令辉,云原生数据库 ClapDB 创始人,前滴滴出行首席架构师;马驰,北欧 FinTech 平台工程师,瑞典马工(主持人)
马驰:数据库被誉为计算机领域的明珠,然而一个值得深思的问题是,为何中国厂商在技术软件领域尚未具备足够的国际竞争力。美国的Oracle、PostgreSQL,瑞典的MySQL等数据库产品都具有强大的国际竞争力。反观国内,一些程序员被质疑能力不足,认为他们只会按照产品经理的要求编写业务代码,然而正是这些程序员打造出了具有国际影响力的小红书、TikTok、支付宝、微信等应用。作为技术精英,你们却在国际舞台上缺乏竞争力,这该如何解释呢?
黄东旭:我们确实是在做国际市场相关的工作。先说结论,再探讨原因。从PingCAP过去30年做国际化的观察来看,中国技术软件厂商是有竞争力的。在与海外竞争对手正面交锋时,我发现中国出海的这一波厂商,尤其是我认识的很多朋友,技术实力并不逊色。比如在数据库或开源数据库领域,像Redis刚出来时,只有一万多行代码,规模很小,难道中国人就写不出来吗?显然不是。再看MySQL,其代码其实有些混乱,毕竟它是一个发展了二三十年的项目。从软件工程师水平来看,中国走在最前列的软件开发者他们自身技术实力是过硬的,他们开发的产品在实际应用场景中也具有很强的竞争力。然而,体感上会觉得美国有Oracle、PostgreSQL、MySQL等,而中国产品的声量和影响力似乎没那么大。这其实主要在于如何让别人知道中国产品产生的影响力。一方面,中国的产品已经在全球市场产生重要影响,比如PingCAP的TiDB,它支持了LBMB Pinterest等海外应用,还支撑了日本的PayPay,这是日本国民线上支付的重要应用,背后的数据存储全靠TiDB,几百台服务器的规模相当庞大。
从宏观或客观角度看,过去中国技术软件开发者与世界交流脱节,中国有自己的生态系统,包括开源生态。像PingCAP和TiDB在国内已发展10年,很多人知晓并使用,但刚出海时发现,中国的开源社区与海外是割裂的。海外社区对中国的一些平台和内容并不了解。PingCAP开始认真在海外做社区建设、品牌和知名度提升,也只是近两年的事。而像MySQL有20年历史,Oracle有40年历史,这是一个客观的实践差距。另一方面,中国基础软件开发者参与国际社区的方式方法还在摸索。PingCAP算是做得不错的,10年前就开始在GitHub上开源,语言也用英文,但即便如此,这两年在与海外打交道过程中也踩了无数坑。
总结一下,第一,从产品硬核能力上,我们不用妄自菲薄,中国技术软件顶级人才与美国差不多;第二,我们现在刚出去,处于建立品牌认知阶段,还需要时间;第三,我们做事的方法有些不太对,也在不断摸索。
李令辉:马工刚才的问题里有你一贯的风格,就是偷换概念。比如把基础软件公司和小红书、TikTok、抖音去对比,这就好比不能拿美国的ARM和苹果对比。ARM虽然是更基础的软件公司,但它的市值跟苹果没法比,苹果每天跌掉的市值可能都比ARM高。这说明越靠近消费市场、越靠近最终用户的产品,声浪越大、市值越高、收入越高。但这并不意味着底层的技术提供商和供应商不重要。苹果公司几乎全世界人都知道,但除了从业者,知道ARM的人并不多。
再来说说中美基础软件开发者对比这个话题。其实创业做数据库之前,我不算基础软件开发者,更像是使用者,也曾是PingCAP的客户。严格来说,这并非我们的问题,而是行业发展规律使然。我认为之前整个行业没有真正意义上的技术性公司。我曾在社交媒体上吐槽,中国之前没有所谓的科技公司,只是利用科技做传统行业的公司,如利用科技做电商、媒体、聊天等。在没有科技时,用传统方式不也能进行吗?所以科技是造福其他行业的,但我们没有真正意义上的自己的科技行业。严格来说,2010年以后,随着GDP增长,中国大公司有钱投入,才有了真正的计算科技公司,像华为,早期也是通信领域的设备公司。
关于影响力的问题,我们不太擅长掌握规范、话语权,我觉得责任主要在教育。中国教育让学生都在做题,做题的人怎么去研发新试卷呢?Oracle数据库诞生后,创造了数据库行业,这张卷子是谁出的?亚马逊做云之前连云都没有,这张卷子又是谁给的?如果把所有优秀的人才在20岁前都困在屋里做卷子,以此筛选人才,筛选出来的人将来却要开创,这不是开玩笑吗?这就相当于培养赛跑运动员去游泳,通过跑步选拔了你,但家里却没有水。现在你长大了要去游泳,这本来就是缘木求鱼。我觉得从业者要思考这个问题,更关键的是整个行业的上下游,上游是生产人才的学校,下游是招聘方和消费者,我们是中间环节,学校培养人才,我们生产商品再卖出去,形成闭环。美国大学靠校友捐款培养人才。
总结一下,如果在别人出好的试题和赛道上,中国基础软件的竞争力和美国差不多。但如果要开辟新赛道,或重塑客户认知、塑造新标准,中国整体差距还较大。
黄东旭:我完全认同这个结论,虽然可能不是全部原因,但至少这是一个从宏观上看很重要的能力缺陷。就拿Databricks来说,大家都知道它最近融了一大笔钱。回顾其历史,在大概三年前甚至更早一点的时候,Databricks推出了一款新的云端计算引擎叫Photon,这个引擎并未开源。当时它原有的产品线还是基于Spark的批量处理云平台。但有了Photon这个新东西后,Databricks做的第一件事并不是急着去卖,而是先定义了一个市场,叫做Delta Lake,宣称自己的产品就是Delta Lake,说以前的数据仓库已经过时了,它的Delta Lake最厉害。这么一宣传,赛道里就成了它一家独大,用户一试,确实不错。从技术层面剖析,它用的还是那些老技术,如存算分离、存储引擎优化等。我觉得中国在性能、数据量等方面很擅长“内卷”,但在像Databricks这样定义赛道方面,确实与美国差距较大。
马驰:如果我现在是一名程序员,我能出色地完成任务,做出很好的优化,领导交代的工作也都完成得很好。但你们说这还不够,因为不能定义标准。那对于一个已经年年拿A的程序员来说,下一步该做什么呢?从你们的个人经历来看,在这方面有没有突破呢?还是说你们也受限于教育、文化或惯性,难以突破呢?
李令辉:首先,我觉得这个问题还是得让教育来背锅,但咱们就不深入展开了,大家只要记住是教育的问题就好。我们太喜欢做题了,我有个朋友曾跟我说他孩子数学考试分数不错,但数学本质上不是算数比赛,而是抽象概念的比赛。真正的数学家一辈子没算过几个数,他们主要是推导公式。
其次,从我个人的创业感受以及在大公司工作的经历来看,我发现创业过程中我的抽象思维不断提高,这是一个被动的过程。核心原因是我手里的研发资源变少了,抽象能力就提高了。当我手下有200个程序员时,我就不想费劲去抽象,直接把子功能、子模块拆分给大家做就行。但当我发现手里只有两个人时,我就会想着要么写个代码生成器,要么写个编译器。所以我觉得很多时候创新是被逼出来的,我真的是这么觉得的。我自己创业时,公司研发人员很少,对外却宣称有百万大军,其实也就不到10个人。我觉得我们的代码其实就是个代码生成器,先生成一堆代码,再生成一堆代码,原因并非后来发现这样做有很多好处,起初完全是因为人手不够。如果我像华为那样有上万开发人员,我干嘛费劲写代码生成器呢,直接给每人分配一个SQL去优化就行。
我觉得美国人这么做也有一个原因是他们人力成本太高。这件事很可能在我们的人均GDP越来越高时发生变化,当大家发现与其雇10个人,不如让一个人闲下来,冷静下来,抽象一下更划算时,情况就会改变。有个很好的比喻,他说只要看中国什么时候洗碗机普及了,就说明人均GDP上去了,因为总有人算账,觉得让老婆洗碗比用洗碗机便宜。只有当洗碗机比人工洗碗更划算时,我们才会更愿意使用机器。想想大公司里那些年薪五六十万、七八十万的程序员,他们在做一些非常细节、具体的小优化,比如一个页面分给三个人,这三个人写了10年,这是真的。有什么必要把这三个才华横溢的年轻人限制在一个页面上呢?还是因为页面优化和人力成本差不多,差不多1000个页面,就分配500个程序员,每人两个;或者两个人一个团队,分四个页面。我觉得核心还是行业从业者应该提高要求,让工作更有挑战性,有更多的事情可做,这是一种被动提高的方法,主动提高我觉得挺难的。
黄东旭:我每年都会回头看团队的效率,特别关注这个指标,即多少人能干出多少事。对我们这样的公司来说,大部分成本是人力成本,而人力成本里绝大多数是程序员。所以一个优秀的程序员,他产生的影响一定比很多人要大。我在做事时,倾向于不轻易说“给你10个人去做”。因为一旦给团队说10个人去做,团队就不思考了。加人是最简单的动作。有时为了防止大家陷入思考惰性,我会故意提出一些看似疯狂的要求,比如让系统性能提升100倍,成本下降1000倍。如果目标只是让性能提升10%,大家就不会去思考和创新,因为10%的小修小补很容易实现。但如果目标是优化1000倍,虽然你自己心里得先有可行性验证,但不能直接告诉团队答案,因为思考过程也是达成共识的过程。总之,优秀的程序员通过自己的思考,产生的影响是非线性的,一定要用好这种能力。
从刚才聊的宏观层面,如思考方式、抽象能力,单从程序员个人发展角度看,如何锻炼这些能力呢?我的经验是,程序员不要自己乱思考。世界上很多好东西已经发明出来了,比如Unix等,人家已经做出来了,背后的思考成果和过程都以博客、文章、访谈等形式存在。我的建议是,动手前先多看经典的东西,多思考,写代码并非关键动作。我会花很多时间看一些老东西,如Unix、Plan9等漂亮的设计,这个过程也是学习过程,思考人家为什么要这么做。
马驰:很多创新都是在资源受限的情况下被迫发生的。以前我在国内华为做程序员,大家都了解华为的工作文化。后来跳槽到北欧公司,对比非常明显。在北欧,不可能像华为那样投入大量人力,比如给你100个人或50个专家,这种情况是没有的。北欧公司在做同样的事情时,更多地借助外部工具,大量使用工具来提高单个程序员的效率,程序员做的无用功也更少,所以总体效率并不比国内差,甚至从长期来看速度可能会更快一些,因为浪费率非常低。举个直观的例子,在国内我们也会用代码检查工具,工具检查后会给出一个Excel表,程序员就得拿着这个表一行一行对照。这项工作可能占工作量的80%,真正编程的时间很少,大部分时间都花在了一些莫名其妙的事情上。但当我进入北欧公司后,发现那里的工具非常尊重用户时间,不会让用户在Excel里给1000行打勾,而是尽量提高信噪比。这导致了一个现象,同样是互联网程序员或基础软件的使用者、开发者,北欧同行的生活质量比中国同行要高很多。但从技能上来说,我不觉得北欧程序员就比中国程序员强,甚至我觉得中国天才程序员的比例可能会更高一些。
现在来探讨一个具体问题。对于刚毕业的年轻人,如果他们也想成为像你们一样的顶尖程序员,能从你们身上学到什么呢?他们肯定无法直接复制你们的经验,那么他们应该从哪里学习技术?看经典固然重要,但能在微信公众号上看到经典内容吗?另外,如果他们想去做市场营销,去改变用户的认知,又该如何培养这种能力呢?
黄东旭:微信公众号上肯定无法让你看到真正的经典,那上面的内容大多很表面。因为这世界上所有不花努力、茶余饭后花10分钟就能获得的东西,一定不是好东西,也不会让你有实质性的收获。比如看微信公众号,你能因此变成好的乐器演奏者或钢琴家吗?显然不能。所以,我觉得有两点很重要。第一,要去找到经典,从历史入手,追溯到最根源、最接近经典源头的地方,看第一手资料。不一定非要看具体代码,我以前就犯过这个错误,初中、高中时对Linux很感兴趣,一上来就看源码,但感觉没什么用,当时虽然看起来很努力,最后却没什么收获,看过就忘了。反而是去看一些访谈,了解设计思想、作者背后设计系统的哲学,先理解这些,再深入细节,这才是看经典的好方式。
第二,即使你理解了系统为何精妙、设计为何出色、经典为何是经典,也还不够,关键在于实践。实践部分其实更重要,就像成为钢琴家必须练琴一样。前面听音乐、了解好东西是在培养品位,不能只听低俗音乐,要听经典,培养审美。然后通过练习,让手形成肌肉记忆。我觉得知行合一,把这两者结合起来是比较好的。以前我和很多年轻人交流,他们说平时天天996,没时间干别的。但我认为,现在大环境变差了,996拿的钱也有限,不如趁这时候多提升自己,把心态放平,这也不耽误挣钱。
李令辉:这个问题确实挺难回答的。东旭的观点我完全认同,他对经典的欣赏很有见地,比如Plan 9我也看过一些。不过,我们俩是殊途同归。我觉得他像个具有古典浪漫主义的艺术家气质的程序员,会从经典出发去实践。而我恰恰相反,我是个实用主义者,我所学的所有技术都是因为别人付钱让我去做项目。我从不免费学习知识或做项目。所以,我的判断完全不是从美感或品位出发的,在我看来,品位就是用最低的成本赚最多的钱。如果一个设计不能让我后续用最低成本维护、用最少时间达到效果并赚到钱,那它就不是好设计。
我当CTO多年,带过很多程序员,他们写的有些代码虽然在形式上看起来很完美,变量名、函数名起得很漂亮,注释位置也很讲究,但从实用角度来看,这些代码可能存在很大问题。因为它们没有从实际运行、维护以及最终效果等角度去考虑,所以在我看来,这样的代码并不好,甚至可以说是糟糕的。毕竟我们的代码最终是要运行的,要编译出来、解释执行,还要方便别人维护。如果只注重表面的美观而忽视了实用性,那么这种所谓的“美”只是主观的,并不符合业界的实际需求和标准。
在我看来,什么是品味?我从Linus Torvalds的观点说起。虽然我不太喜欢他的品味,但他讲的有道理。在庞大的Linux kernel项目中,保持简洁的代码,不搞魔法,用基础的C语言而非高级语言,是完全正确的。这样能有效维持项目的简单直白和可维护性,也不易被黑客埋后门。但这换到其他项目未必适用。很多程序员讲品味时,会引用Linus Torvalds的观点,但Linus Torvalds也只是在Linux kernel中如此。所以,我认为所谓品味,你应该问自己:解决这个问题该用什么方法最优雅?这包括几方面考虑:一是你面临的脑力负担,需不需要了解全貌才能解决;二是你要承担多大风险,作为工程师,首先要考虑的是项目会不会因你的选择而失败;三是收益。
不同项目的品味是不一样的,但核心是,如果你不能量化为什么做这个选择,那这个选择很可能是人云亦云。中国人其实很谦卑,我面试时喜欢问程序员都看什么技术文章和博客。如果他列举超过3个,我就不太想要;超过10个,我觉得这人肯定有问题。因为中文媒体没什么可读的,有那么多时间看中文媒体,不如去干别的。这也说明他品位差,看不出哪些是垃圾。更可怕的是,他很可能被这些垃圾影响。我最害怕的是,一些程序员在项目讨论中搬出大名词,却不知道这些人的真实水平。你放着权威的教材不看,去看中文博客,如果你要相信权威,就找最权威的。东旭读经典的做法是对的,因为经典被那么多人筛选过,你获得营养的概率远高于垃圾,时间不会白费,比订阅一些不靠谱的博客强多了。
黄东旭:我觉得品位这种事,最终体现在你做选择时。作为一名CTO或资深程序员,设计众多系统,每时每刻都在做决定,比如这个接口设计成什么样,或者这个地方要不要抽象成一个模块。品位就是在这些决定中的一种行为准则。你会觉得某个地方需要这么设计接口,虽然当下看不到收益,但相信未来你会感谢自己当初的决定。
有意思的是,现在我回头去看PingCAP系统,至少是我参与决策的那些部分,发现大多数正确的决定在当时看起来都非常反直觉。如果当时按照那个环境下所谓的大V或主流设计方案去做,最后回头看你会庆幸自己没听那些微信公众号或主流人士的说法。尤其是当你的组织变大后,作为技术掌舵人或决策者,你做出反直觉的决定,就意味着底下的人会问为什么要这么做,眼前的利益明明应该这么做,为什么不做呢?所以我自己在做重大决定时,第一个倾向是能不做就不做,能晚点做就晚点做,保持系统的简洁,也就是所谓的品味。作为古典程序员流派,我更倾向于以简单为美。
马驰:作为仍在一线写代码或看代码的CTO,我想问一个比较尖锐的问题。国内很多高级技术人才,如高P、大V或技术专家,他们早已不再从事一线工作,主要转向管理岗位,但仍以技术专家的身份去指导年轻人。我想知道,你们觉得自己和他们最大的区别在哪里?在对外输出方面,你们有什么不同?如果年轻人想要超越你们,他们应该怎么做呢?
黄东旭:程序员并没有绝对的优秀与否之分,评价标准并非线性。写代码比我快一秒钟,或者接口设计比我好一点点,都不能简单判定谁更出色。不存在这样一个明确的标准,每个人都可以从他人身上学到东西。如果真有值得学习之处,交流其实更为重要,而不是纠结于谁更优秀。这涉及到自我认知的问题,我建议就是放弃所有这种自我优越感,每个人都能从对方身上学到东西。不用总想着超越,没有什么超越不超越的。若要谈超越,我觉得现在的年轻人学习环境比我们当年学计算机时好太多了,但这也可能带来选择焦虑。当信息过多时,反而容易让人失焦,这或许是一个挑战。
李令辉:我给他的第一个建议是别当程序员了,因为程序员很可能是末代职业,现在加入这个行业并不是一个很好的选择。第二个建议是我自己也可能要转行了,因为随着行业发展,“打不过就加入”似乎成了常态。我认为“超越”这个词用得不好。这是因为我在中国参加技术大会听了几年之后,后来不太愿意参加了。我发现大家讲的内容都类似,比如在前端领域,四场演讲中有三场都是关于React的四种场景应用,其中80%的内容都是重复的。我觉得大家没必要都讲一样的东西,一场就够了,或者大家事先沟通一下。后来我当了演讲人,发现大家还会对稿,这就更夸张了,难道没发现和别人讲的内容一样吗?既然一样,为什么还要重复说呢?
我觉得程序员这个职业和传统职业最大的不同在于,我们不需要做前人做过的工作。传统工作比如做面,你做不到别人做的面,所以你要不断练习,做到接近那碗面的水平,才能成为好厨师。但程序员不是这样,别人把一个库放到GitHub上,你拉下来就能用。TiDB开源了,你直接用就好了,何必换种语言再写一遍呢?大厂最喜欢做这种事,他们喜欢把别人的东西换种语言再写一遍,然后证明自己更厉害,评完级就把项目扔掉。我觉得这是考核机制的问题,一个人把别人做过的事再做一遍,这没什么了不起,甚至在这个行业是可耻的。如果所有人都重复做一件事,我们就不会有现在的计算机科学和互联网。我们是在前人的肩膀上再走一步,才形成了现在的巨塔。Google那么厉害,它重写Nginx了吗?它做的GFS、BigTable等都是以前世界上没有的东西,它需要这些东西。至少一开始,Google的初心不是为了考试。我觉得不存在超越,你可以做最好的自己。看看世界上需要什么,有什么问题需要解决,把问题解决好,你就厉害了。你不需要和任何人比较,你就是最厉害的。
我们应该庆幸现在的年轻人比我们那时候卷多了。比如东旭他们刚创业时,用Rust写的Raft应该是市场上的第一家。现在你知道市场上有多少家吗?大厂几乎人均一套Raft。有什么必要每个年轻人都写一遍?写完了又怎么样?也没有发明Raft。为什么要把别人的工作再做一遍呢?如果你觉得这就是一种超越,那我觉得你永远超越不了,这就是最大的问题。
在我之前两三年,经济还没这么差的时候,我面试了很多大厂的年轻人,人人都擅长Raft,每个人都精通。我不知道我们为什么需要这么多精通的人,硅谷可能都没有这么多精通的人。Google也就一个组在做这个事,Meta也是一个组在做,而且那些组也不是专门做这个事的,我觉得没必要这样。
马驰:回到年轻人的视角,如果他们想做一些有趣的东西,肯定需要利用一些新技术和最近的技术进展。在2025年,会有哪些新技术能够帮助年轻人更好地解决一些旧问题,提出新的方案呢?我们知道AI肯定是其中之一。除了AI,还有其他一些技术也值得关注,比如Rust语言和云原生技术。这些技术能否给年轻人一些探索的方向呢?
黄东旭:我觉得我做很多事情的出发点,不仅仅是公司业务上的探索,更多的是因为有趣,或者是因为我自己需要。比如我现在的助理不够智能,我想用人工智能来整理我的日历、邮件和个人数据。这可能看起来是一个有趣的挑战,或者是我自己需要的东西。在做的过程中,我至少会倾向使用以前没用过的那些技术。
因为公司大了,我现在不需要亲自写代码赚钱了。现在我写的代码大多是框架型的,让团队成员把它重构为可用于生产的东西。虽然角色有所变化,但我写代码的核心依然是尝试使用以前没用过的技术和架构。我学习和做事的方式,不是看技术是否过时或新颖,而是看这个技术本身是否有趣,我能从中学到什么,或者最简单的就是觉得这东西很酷,能让这个周末过得开心。大概就是这样,不要太功利心重。当然,这可能也是作为创始人的一个特权。比如我特别不喜欢管理团队,作为创始人,我可以把这些日常管理事务交给我们的副总裁,我则专注于技术方面。所以还是要相信团队和分工。
马驰:因为东旭现在不需要面试了,但是作为要面试的年轻人,令辉老师有哪些建议给他们呢?
李令辉:在面试这个问题上,我始终秉持着初心,我是一个实用主义程序员。我的第一个建议其实和东旭有点相似,那就是跟着兴趣走。人活几十年,社会上现在也没到饿肚子的地步,尤其在咱们国家,吃饭是不用担心的。所以,在这个前提下,没必要逼着自己做不喜欢的事。我觉得这是最重要的,因为你不喜欢的事,很可能你不擅长,或者这件事本身就有问题。不喜欢一定是有原因的,要么违反你的人性,要么违反你的道德。不做自己不感兴趣的事本身就是一个加分项,你会更有意愿去钻研,不会觉得累。比如我过去三四年,每天工作十四五个小时很常见,虽然赚钱也不多,但核心是开心,因为做了自己感兴趣的事,就不会觉得累。
第二个建议是,我也面试过很多人,曾帮大厂主持过校招。记得有个年轻人过来跟我说:“面试官,我有想法了,可以吗?”我反问他:“你觉得我们公司缺想法吗?我们公司领导们想法多得很,缺的是干活的人。”我觉得年轻人不要太好高骛远,第一件事是把手头的问题解决好。你对技术感兴趣没问题,对什么感兴趣都可以。倒退30年,那些获得图灵奖的人做的事也是非主流的。科学这东西谁知道呢?你感兴趣什么就去做什么,任何感兴趣的事都值得投入时间。人生就是用来浪费的,花在自己感兴趣的事上就结束了,没关系。至于哪个东西能中彩票,这个不知道,知道了也没用。将来我们知道搬砖特别挣钱,但身体又搬不了。
马驰改变了我的一个观点。我以前觉得抬杠很没意义,虽然我自己以前也爱抬杠,后来反思觉得挺浪费时间,就不怎么抬了。但后来我发现抬杠有两个好处:一是去魅。你不抬杠,容易在我们这个文化体系里把位高权重人的话奉为圭臬,觉得他说什么都是对的。其实你抬抬杠,会发现没人总是对的。在这个过程中,你能了解对方是怎么想的,想想这个想法对不对。如果这个人连思考过程都没有,就是拍脑袋,你不用听了。抬杠的过程有助于去魅,并且强迫自己找证据、了解真相。拍人马屁时你不需要时间,只要付出点尊严就行,但抬杠不一样,你不学习就不能抬杠。敢于抬杠是一个挑战权威的过程,并且强迫自己学习。对很多想从事真正有价值事情的人来说,这是有意义的。无论是创业还是做科研,其实都是挑战别人的共识。没有跟一万个人抬杠的勇气和决心,很难做成事。无论做什么创新的事,都是这样。
我记得当时有很多自媒体说中国有多少数据库公司、软件公司。他们没去看国外的情况,只是看到国外成功的几个,就觉得国内的不行。我做过竞品调研后才知道世界上有多少奇奇怪怪的数据库。数据库真的很多,只有足够多才能产生好的。如果大家都做一样的,那确实没意义。但如果大家都做不一样的,剩下的那个可能就是好的。所以,年轻人要想办法做和别人不一样的那个人,无论是做人还是做事。别人都做得那么好了,你还有什么希望?你要做点自己感兴趣,觉得还没人好好做的事。
黄东旭:我觉得“去魅”这件事在程序员或软件开发行业里特别重要。老实说,编程本质上是个手艺活。编程语言其实没那么了不起,无非就是那几个关键字。程序这东西,你写多了,自然就熟练了,大家水平也差不多。所以,没必要因为谁说过什么就觉得他特别厉害。这种盲目崇拜权威的做法其实不太好。
我也不是完全反对抬杠这件事。抬杠更多是一种心态。现在我年纪大了,有时候会说“你说得都对”,但心里其实会想一遍抬杠的过程。这种内心的质疑很重要。我回想一下自己,编程能力最强、精力最充沛、头脑最开放的时候大概是在初中和高中。那时候我学编程比较早,正好处于叛逆期,又赶上了开源运动的浪潮。90年代中后期的开源社区,大家的共同“敌人”是微软,一提到微软大家都嗤之以鼻。大家都觉得自己是民主战士,这种氛围让我在各种论坛里很活跃,也让我对权威有了更多的质疑。但后来我发现,真正重要的不是怼天怼地,而是完成“去魅”之后,能够发自内心地欣赏曾经的“敌人”做得好的地方。比如以前我觉得微软的东西都不好,但后来才发现,微软的IOCP(输入/输出完成端口)在并发和异步处理方面做得非常好。这就是我想说的最后一个建议:当你完成内心的质疑和“去魅”之后,能够真正欣赏对手的优点,这就是一种成功。放弃自己的自我优越感,你会发现无论是朋友还是曾经的“敌人”,都有值得学习的地方。
马驰:我觉得在很多领域,我抬杠都能抬胜,但这并不是因为我经验丰富或能力超强。我觉得有一点特别重要,尤其是在中文圈子——就是要和国际上最先进的技术和社区保持接触。开源社区就是一个很好的例子,它不分国籍,是世界上最前沿的圈子。如果你能融入这个圈子,就能站在巨人的肩膀上。当你再去看一些封闭行业里的所谓权威、老师傅或大V时,就会发现他们其实已经和时代脱节了十几年甚至几十年。
李令辉:对于年轻人的焦虑问题,我可能不知道具体该做什么,但我清楚不该做什么。首先,不用再花太多时间去研究传统的CRUD架构。一方面,云计算的发展导致存算分离,这一趋势将带来巨大变化。我坚信未来业务代码会全部运行在这种分离架构上。大约在2020年,我在飞书群里和人争论过这件事,甚至愿意赌上10万美金。虽然目前还没完全实现,但我相信这只是时间问题,因为网络发展实在太快了。旧时代的经验可能反而会成为束缚,所以不要再去研究那些所谓的“企业Java架构”,那些东西已经过时了。
其次,传统软件工程在未来也会因AI的加持而发生重大变化。过去,软件工程是在全人工条件下保证可靠性,但我一直是这套流程的反对者,尤其是反对其中20%~30%的教条主义,比如严格的测试覆盖。我觉得有些地方没必要那么严格。虽然我反对这些,但我仍然接受并使用了70%以上的内容。我发现,代码工具虽然看起来很方便,比如自动生成代码的功能,但可能会带来很多问题,让我陷入无尽的bug排查中。所以,我建议大家谨慎对待这些工具。总之,如果你擅长的都是那些特别边缘的技术或经验,那么在未来一两年内,这些可能就会被完全替代,变得毫无价值。
黄东旭:现在很多工具可以自动生成代码,比如Cursor,它在局部生成代码可能还算可以,但如果一次性生成几百行代码,我觉得这种做法完全不可靠。现在很多人还在鼓吹Coding Agent之类的东西,但在我看来,除非你只是开发一些简单的系统,比如食堂管理系统,或者做一些前端的简单功能,这些工具或许还能用。但如果指望它们能替代一个优秀的工程师,那我觉得还差得很远。
说到学习建议,我还是觉得要回归一些万变不离其宗的基础知识。比如现在大家都在讨论Serverless、Lambda,包括我们自己也在用,TiDB的云服务也很快会完全运行在Lambda架构上。但你会发现,很多基础的东西其实并没有变。比如,一个系统的性能瓶颈在哪里?吞吐量和延迟受什么影响?在这个快速变化的时代,我对年轻程序员的期望是不要丢掉基本功。举个简单的例子,最近大家都在说云原生对象存储,S3是新的磁盘。很多年轻人看到这个结论,就觉得S3很厉害,是新的存储方式。但如果你真正去设计系统,会发现当S3遇到瓶颈时该怎么办?S3本身也是一个大型的分布式系统,可能需要扩容。你不一定非要自己做一个S3,但你得了解这个系统是怎么工作的。所以在这个日新月异的时代,我还是要建议大家去看经典的东西,这些才是根本。
马驰:我想再提一个问题,眼界是不是也很重要?我觉得程序员其实不应该仅仅追求成为中国最优秀的人,从一开始就应该立志成为全世界最优秀的人。我们的年轻人应该一开始就应该朝着“我要做到全世界第一”努力,而不是“中国第一”,因为“中国第一”可能只是全世界第100个。我也注意到,很多年轻人其实受限于语言、文化和网络接触的限制,在接触世界一流技术时有很多障碍。在这方面,你们有什么具体的建议吗?
黄东旭:我觉得这个问题其实很明确:如果不会英语,那就去学。现在全球化是大趋势,英语不仅是语言,更是一种思维方式,尤其是技术领域,它已经成为了全球交流的通用语言。如果你想进步,就必须克服语言障碍,融入全球化的交流中。中国年轻开发者确实需要提升眼界。有一个简单的方法就是多看像Hacker News这样的国际知名技术社区,并积极参与其中的讨论。
马驰:东旭,你们公司是一个国际化公司,在美国、新加坡和中国都有开发者。那你们有没有注意到,这些不同文化背景的程序员会有一些比较明显的区别呢?
黄东旭:我觉得不同文化背景的程序员确实存在一些明显区别。比如在美国,我发现程序员们会花更多时间去思考问题,他们在产品设计、宏观规划方面表现得更好,通常会在想清楚之后才动手。这是美国程序员的一个好习惯,美国程序员在产品设计和端到端体验驱动做事方面,比中国程序员做得更好。
而中国的那些优秀的程序员,编码速度非常快,但很多时候会出现返工的情况。比如做到一半发现方向不对,需要推倒重来。这是一个很有意思的现象。最近我跟很多国内外的同事做一对一交流,发现中国同事往往会直接跳到产品缺什么功能、某个地方要怎么改这种很具体的事情上,跳过了思考过程。相比之下,海外的高级工程师在面对同样的事情时,思考顺序是不一样的,他们会从为什么要做这件事、路径是什么、资源如何分配,最后才得出结论。简单来说,思维方式的不同是我体感上最大的区别。
我发现国内很难找到好的技术软件产品经理。之前国内有一些说法“人人都是产品经理”,“人人又都不是产品经理”。这两年我在做基础软件和产品化的工作,发现这是一个非常专业的工作,有很多方法论值得认真对待。但在基础软件或云产品领域,中国确实缺乏优秀的产品经理。
李令辉:我曾经做过一个无代码(No Code)项目,当时我们在招聘产品经理时,找了一些曾在无代码平台上实施过项目的人来面试。当时我有个比喻:这就好比把一个手动挡汽车司机找来开无人驾驶汽车,结果他天天问离合器在哪里,没有离合器怎么开车?这就是问题所在——最终用户并不一定能成为好的产品经理。要成为一名优秀的产品经理,需要非常有悟性的用户,最好是那些对整个产业链上下游都有深入了解的人,或者说是“天才”。毕竟,第一个产品往往是天才创造的,他们才有可能胜任产品经理的角色。
我也特别反感“人人都是产品经理”这种说法。我面试过的产品经理至少有几百人。因为在上次创业时,我主要负责产品和技术,发现很多时候是产品拖了技术的后腿。所以我们在招聘产品经理时,发现了一个现象:在互联网最火的时候,全北京能学会编程的人都去当程序员了,而那些学不会编程的人则都去当产品经理了。
马驰:我观察到在云计算和技术软件领域,很多产品经理有一种“低幼化”的倾向。他们会把一些很严肃的生产力工具,比如数据库、操作系统或对象存储,设计得过于可爱、甚至做一些布偶。这其实是一种非常独特的中国现象。在欧美,这种情况很少见到。我认为这种做法其实显得很不专业。
黄东旭:在美国,一些基础软件创业公司,尤其是近几年的小公司,也出现了类似的“低幼化”倾向,这其实随着“开发者关系”岗位的兴起而逐渐显现。你会发现,这些公司大多处于早期阶段,可能只有三五个人。他们这么做,一方面是为了招聘,因为这个群体大多是年轻人,公司需要打造一个酷炫的形象。但你会发现,这些公司一旦发展到一定规模,有了企业客户,他们的形象就一定会向更严肃的方向转变。举个例子,大家都知道的小强数据库(CockroachDB),其实有不少企业客户因为名字的问题而不喜欢它。当然,他们的CEO个性也比较强,但我个人认为,如果面向企业客户或做严肃的基础软件,还是应该更严肃一些。
国内的情况又有所不同。国内所谓的运营人员,我觉得很多时候是因为自己没有想清楚,就去参考海外比较火的开发者关系是怎么做的,然后无脑地照搬过来。因为大公司预算多,老板也愿意花钱,而花钱做事总是最容易的。比如搞个布偶之类的,又是花钱方式中最简单的一种。所以,归根结底还是缺乏思考。如果各个行业都处于互相内卷、不思考的状态,就会卷到一些稀奇古怪的方向上去。
李令辉:发公仔至少有两个好处。首先,它好歹是有用的,毕竟有些事情更没用。其次,中国作为生产大国,是公仔的原产地,公仔的成本比美国便宜多了。在北欧发公仔,成本至少要乘以20,而在中国发公仔几乎是白送,几乎没有成本。比如阿里和腾讯每年都要做很多公仔,可能根本不用加预算,直接拿其他部门发剩的公仔来发,就能完成一个KPI,这不挺好的吗?
我觉得运营和产品营销手段不存在唯一正确的方式。很多公司做完之后,别人怎么做我们就怎么做。比如开源,前几个靠开源起家的公司对微软来说也是“大逆不道”,微软当时觉得这些人靠免费倾销,简直不要脸。但实际上,只要有效就行。我倒觉得,只要有效就OK,关键是无效。所以,无效才是原罪。
我参加过很多大会,也被发过很多公仔,甚至曾经拥有全中国所有互联网公司的公仔。但公仔和公仔也不一样。如果公仔做得好看,放在家里确实会让人天天看到,对公司的印象也会加深。从这个角度看,公仔的成本可能比在分众传媒打广告更划算。我觉得更好的推广是做包。你看程序员们都背什么包?发包就是活广告。我觉得中国公司在运营上确实有一些独到之处,我们重新发明了一些外国人觉得无效,但我们觉得有效的方法。比如“砍一刀”,把美国人都搞晕了。
我觉得核心还是产品本身的问题。如果产品不好,怎么卖都不行。你不能怪营销不行,而是产品本身没做好。但如果产品真的很好,你也不知道是产品好还是营销厉害。比如当年ChatGPT刚出来的时候,一用就知道这是好东西,谁用谁知道,甚至有人愿意花钱去淘宝买账号,每个月多交钱去用。如果产品不好,怎么营销都没用。但如果产品很好,怎么卖都能找到办法。现在的问题是,老板给你一个烂产品,你用尽所有办法都卖不动,那该怎么办?最后发现送公仔可能还算便宜的。
我也看到很多中国软件公司的困境,比如花5美金买一个GitHub Star,这种事到底图什么呢?核心还是产品不够好,需求不够刚性,产品不够核心。对我们所有创业者来说,创业者首先是个产品经理,产品到底给谁用,为什么用户要用,这才是关键。
","description":"编者按: \\n\\n比学软件更重要的,是理解软件行业发展趋势。放眼世界,软件和科技公司的影响力愈发显著,IT行业已成为全球经济增长的重要引擎。去年年中,有报道称,美国七大科技公司创下了新的里程碑,总市值历史上首次突破 15 万亿美元,占美国GDP一半。与此同时,中国软件产业尽管还存在差距但也发展迅速,因此我们也要清醒地认识到,要想在激烈的全球竞争中脱颖而出,就必须不断学习,成为具有国际竞争力的软件人才。\\n\\n \\n\\n此外,云原生是过去十年最重要的计算范式,而大模型则推动着云计算等基础架构以及工具层面的变革。云原生和大模型的快速发展,对软件工程师提出了更高的要求。作为软件工程师…","guid":"https://www.infoq.cn/article/00ZflUA3lzstmwIMRYDs","author":"李冬梅","authorUrl":null,"authorAvatar":null,"publishedAt":"2025-01-28T03:55:57.137Z","media":null,"categories":["生成式 AI","数据库"],"attachments":null,"extra":null,"language":null},{"title":"Java近期新闻:JDK 24进入Rampdown Phase Two、Spring、JobRunr、Commonhaus基金会","url":"https://www.infoq.cn/article/yW9M13S1A0OqLSROqBgV","content":"JDK 24 早期访问构建版本\\"的第32个构建版本\\"已发布,包含了自第31个构建版本以来的更新\\" ,修复了多个 问题\\"。更多关于此版本的详细信息可以在发布说明\\"中找到。
根据 JDK 24 发布计划\\",Oracle Java 平台团队的首席架构师 Mark Reinhold\\" 正式宣布\\" JDK 24 已进入 Rampdown Phase Two。这意味着:不会再为 JDK 24\\" 添加新的 JEP,并将专注于通过修复请求流程\\"修复优先级为 P1 和 P2 的问题。尽管仍有可能通过后期增强请求流程\\"进行少量优化,但 Reinhold 表示,这一门槛“已变得异常高”。预计于 2025 年 3 月正式发布的 JDK 24 最终功能集将包括:
JEP 404: 分代 Shenandoah(实验性)\\"JEP 450: 紧凑的对象头(实验性)\\"JEP 472: 为限制 JNI 的使用做准备\\"JEP 475: G1 的后期屏障扩展\\"JEP 478: 密钥派生函数 API(预览)\\"JEP 479: 移除 Windows 32 位 x86 移植版本\\"JEP 483: 预先加载和链接类\\"JEP 484: 类文件 API\\"JEP 485: 流收集器\\"JEP 486: 永久禁用安全管理器\\"JEP 487: 作用域值(第四次预览)\\"JEP 488: 模式中的原始类型、instanceof 和 switch(第二次预览)\\"JEP 489: 向量 API(第九次孵化)\\"JEP 490: ZGC:移除非分代模式\\"JEP 491: 无需固定即可同步虚拟线程\\"JEP 492: 灵活的构造函数体(第三次预览)\\"JEP 493: 无需 JMOD 链接运行时镜像\\"JEP 494: 模块导入声明(第二次预览)\\"JEP 495: 简单源文件和实例主方法(第四次预览)\\"JEP 496: 量子抗性模块格基密钥封装机制\\"JEP 497: 量子抗性模块格基数字签名算法\\"JEP 498: 在 sun.misc.Unsafe 中使用内存访问方法时发出警告\\"JEP 499: 结构化并发(第四次预览)\\"JEP 501: 弃用 32 位 x86 移植版本\\"
JDK 25\\" 早期访问构建版本\\"的第 6 个构建版本\\"也已发布,包含从第 5 个构建版本以来的更新,修复了多个问题\\"。更多关于此版本的详细信息可以在发布说明\\"中找到。
对于 JDK 24\\" 和 JDK 25\\",开发人员可以通过 Java Bug 数据库\\"报告问题。
在每周的 Hashtag Jakarta EE\\" 博客中,Eclipse 基金会的 Jakarta EE 开发布道师 Ivar Grimstad\\" 提供了关于 Jakarta EE 11 的 更新\\"信息,内容如下:
Jakarta EE 11\\" TCK(兼容性测试套件)重构的最新消息,团队已经很接近发布 Jakarta EE Web Profile 11\\"。目前只剩下少量测试需要重构,TCK 用户指南的重写工作也已开始。关于 Jakarta EE 12\\" 的讨论正在加速。请查看 Jakarta EE Platform GitHub 问题跟踪器\\"中标记为 EE12 的问题。欢迎添加新问题或参与已有问题的讨论。你还可以加入 Jakarta EE Future Directions\\" 兴趣小组,参与有关平台发展的讨论。如果你无法参加每两周一次的电话会议(日历\\"),可以加入邮件列表\\"并在那里参与讨论。
Jakarta EE 11 的发布历程包含了四个里程碑版本,2024 年 12 月发布的 Core Profile,以及在 2025 年第一季度正式发布 Platform 和 Web Profile 之前的候选版本。
Spring Framework 6.2.2\\"发布,包含了错误修复、文档改进、依赖项升级和新功能,例如:修改 BeanOverrideHandler\\" 类,使其仅跟踪限定符注解,与 Spring Boot 的 QualifierDefinition\\" 类保持一致;将 @MockitoBean\\" 注解提升为支持字段和类型,与已废弃的 Spring Boot @MockBean\\" 注解保持一致。此版本将包含在即将发布的 Spring Boot 3.4.2 和 3.5.0-M1 中。更多关于此版本的详细信息可以在发布说明\\"中找到。
Spring Data\\" 2024.1.2 和 2024.0.8 发布,均为服务版本\\",包含了错误修复、依赖项升级以及对子项目的依赖项升级,例如:Spring Data Commons 3.4.2 和 3.3.8;Spring Data MongoDB 4.4.2 和 4.3.8;Spring Data Elasticsearch 5.4.2 和 5.3.8;以及 Spring Data Neo4j 7.4.2 和 7.3.8。这些版本将包含在即将发布的 Spring Boot 3.4.2 和 3.3.8 中。
Spring AI MCP\\" 团队发布了 0.5.0 版本\\",包含了一些新功能,例如:对传输层的增强,新增 HttpServletSseServerTransport\\" 类以及基于阻塞队列的 Spring Framework SseEmitter.SseEventBuilder\\" 接口的实现;新增物料清单。更多关于此版本的详细信息可以在发布说明\\"中找到。
Quarkus\\" 3.17.7 是第六个维护版本\\"(由于回归问题跳过了 3.17.1),包含了显著的变更,例如:解决当方法被 @PermissionsAllowed\\" 注解且有多个值时,@PermissionChecker\\" 注解的参数无法正确匹配的问题;将 MongoDB 连接健康检查\\"的执行从应用程序尝试将第一条记录存储到数据库时改为在启动时。更多关于此版本的详细信息可以在变更日志\\"中找到。
Micrometer Metrics\\" 1.15.0 的第一个里程碑版本包含了错误修复、文档改进、依赖项升级和新功能,例如:在可能的情况下使用 AssertJ AbstractAssert\\" 类中定义的 failWithActualExpectedAndMessage();一致使用 Java String 类的 toLowerCase() 和 toUpperCase()方法,并结合 Java Locale.ROOT\\" 增强安全性。更多关于这些版本的详细信息可以在发布说明\\"中找到。
类似的,Micrometer Metrics 的 1.14.3 和 1.13.10 版本包含了依赖项升级,并解决了一些问题,例如:在返回 CompletableFuture 的方法上应用切面时抛出的 NullPointerException;MeterRegistry\\" 类 remove() 方法的性能退化问题,当注册大量计量器时表现尤为明显。更多关于这些版本的详细信息可以在 1.14.3 版本\\"和 1.13.10 版本\\"的发布说明中找到。
Micrometer Tracing\\" 1.5.0 的第一个里程碑版本包含了错误修复、依赖项升级和新功能:避免创建多余的 OtelSpan\\" 类实例;为 FinishedSpan\\" 添加本地服务名称的设置和检索功能。更多关于此版本的详细信息可以在发布说明\\"中找到。
类似的,Micrometer Tracing 的 1.4.2 和 1.3.8 版本:依赖项分别升级到 Micrometer Metrics 1.14.3 和 1.13.10,解决了当 OtelTraceContextBuilder\\" 类实例设置 parentId 和 sampled 字段为 @Nullable 时,与 TraceContext\\" 接口中的相同字段保持一致的问题。更多关于这些版本的详细信息可以在 1.4.2 版本\\"和 1.3.8 版本\\"的发布说明中找到。
Piranha\\" 25.1.0 发布,包含了许多依赖项升级和显著的变化,例如:新增 SecurityConstraint\\" 类,增强自身的 SecurityManager\\" API;解决 GrizzlyHttpServer\\" 类实例在异步请求上不会无限期挂起的问题。更多关于此版本的详细信息可以在发布说明\\"、文档\\"和问题跟踪器\\"中找到。
Project Reactor\\" 2024.0.2 是第二个维护版本\\",包含了对 reactor-core 3.7.2、reactor-netty 1.2.2 和 reactor-pool 1.1.1 的依赖项升级。此外,2024.0.2 版本还与 reactor-addons 3.5.2、reactor-kotlin-extensions 1.2.3 和 reactor-kafka 1.3.23 这些保持不变的构件进行了版本对齐。更多关于此版本的详细信息可以在变更日志\\"中找到。
Project Reactor 2023.0.14 是第十四个维护版本\\",包含了对 reactor-pool 1.0.9 和 reactor-netty 1.1.26 的依赖项升级。此外,2023.0.12 版本还与 reactor-core 3.6.13、reactor-addons 3.5.2、reactor-kotlin-extensions 1.2.3 和 reactor-kafka 1.3.23 这些保持不变的构件进行了版本对齐。更多关于此版本的详细信息可以在变更日志\\"中找到。
JobRunr\\" 7.4.0 发布,支持 JDK 24、Spring Boot 3.4 和 Kotlin 2.1。增强功能包括:等待所有 RecurringJobPostProcessor\\" 类实例完成后再启动 Spring Boot 和 BackgroundJobServer\\" 类;确保所有 SQL 脚本中使用正确的大小写。此外,还解决了当 MongoDBStorageProvider\\" 类实例配置为 NO_VALIDATE 选项时跳过集合验证的问题。更多关于此版本的详细信息可以在发布说明\\"中找到。
OpenXava\\" 7.4.5 发布,包含了错误修复、文档改进、依赖项升级和增强功能,例如:在 Tab\\" 类中新增 filterByContentInAnyProperty() 方法,用于在任意列中过滤字符串值;在 Strings\\" 工具类中新增 isJavaIdentifier() 方法,用于确定 Java 标识符的存在。更多关于此版本的详细信息可以在发布说明\\"中找到。
Commonhaus 基金会\\"(一个致力于开源库和框架可持续性发展的非营利组织)宣布\\" Infinispan\\"加入该基金会。在 2025 年 1 月中旬发布的一篇博文中,Red Hat 高级首席软件工程师兼 Infinispan 项目负责人 Tristan Tarrant\\" 描述了他们加入基金会的动机,他写道\\":
Commonhaus 完全符合我们的需求:其轻量级治理模式非常理想。我们既能享受加入优秀的基金会所能获得的好处,又能按照自己的方式运作项目。Commonhaus 也是许多“友好项目”的所在地:Hibernate、Quarkus、Debezium、Jackson 等项目在我们的软件中扮演着关键角色,很高兴我们能共享一个“共同的家”。
其他加入该基金会的知名项目还包括:JReleaser\\"、JBang\\"、OpenRewrite\\"、SDKMAN\\"、EasyMock\\"、Objenesis\\" 和 Feign\\"。
原文链接:
https://www.infoq.com/news/2025/01/java-news-roundup-jan13-2025/\\"
","description":"JDK 24 JDK 24 早期访问构建版本\\"的第32个构建版本\\"已发布,包含了自第31个构建版本以来的更新\\" ,修复了多个 问题\\"。更多关于此版本的详细信息可以在发布说明\\"中找到。\\n\\n根据 JDK 24 发布计划\\",Oracle Java 平台团队的首席架构师 Mark Reinhold\\" 正式宣布\\" JDK 24 已进入 Rampdown Phase Two。这意味着:不会再为 JDK 24\\" 添加新的 JEP,并将专注于通过修复请求流程\\"修复优先级为 P1 和 P2 的问题。尽管仍有可能通过后期增强请求流程\\"进行少量优化,但 Reinhold 表示…","guid":"https://www.infoq.cn/article/yW9M13S1A0OqLSROqBgV","author":"Michael Redlich","authorUrl":null,"authorAvatar":null,"publishedAt":"2025-01-27T09:18:25.886Z","media":null,"categories":["编程语言"],"attachments":null,"extra":null,"language":null},{"title":"使用 Rust 重新实现 SQLite 以实现异步 I/O","url":"https://www.infoq.cn/article/GglyXWw1Yb3uKl2j8uOI","content":"本文最初发表于 DevClass 网站,由 InfoQ 中文站翻译分享。
Turso 是一家专注于数据库解决方案的初创公司,目前正在使用 Rust 重新实现 SQLite 数据库引擎,以实现主要的新特性,比如异步 I/O。
Turso 由 Glauber Costa 和 Pekka Enberg 在 2021 年创立。2022 年,这家当时名为 ChiselStrike 的初创公司 fork 了 SQLite,并创建了 libSQL。其基本思路是 SQLite 需要现代化,而且虽然该项目是开源的,但它不向希望对那些改进该项目的贡献者开放。
创始人现在 宣布,仅仅 fork SQLite 不足以实现他们想要的一些变更,包括异步 I/O。Enberg 开启了一个使用 Rust 重新实现 SQLite 的私人项目,这个项目已经被采纳为 Turso 的官方项目。
Limbo,一个使用 Rust 重新实现 SQLite 的项目
他的目标是 Limbo(这显然是一个代号,可能会更改)将与 SQLite 完全兼容,但具有“完全的内存安全性和新的现代化架构”。该项目目前正在进行中,并在 MIT 许可下在 GitHub 上开源。
SQLite 的可靠性部分归功于其广泛的测试套件。Costa 和 Enberg 表示,他们可以通过一种名为确定性模拟测试(Deterministic Simulation Testing,DST)的技术实现相同或更好的可靠性,它借助了 antithesis 的帮助,这是一款专门用于在模拟硬件和软件故障环境中进行测试的软件。Limbo 也有自己内置的 DST 框架。
在 Linux 上,Limbo 使用了内核系统调用 io_uring,它由 Meta 的一位工程师开发,用于高性能异步 I/O。新引擎扩展了 sqlite3_step,以便在数据尚未准备好使用时立即返回。Costa 和 Enberg 发现,虽然 SQLite 查询通常很快,但对于大型数据集来说,它们则可能比较慢。
Limbo 的另一个特性是编译为 Web assembly(WASM), Turso 的联合创始人说这是“SQLite 的补充”。
Limbo 的性能已经非常好了,在某些情况下比 SQLite 更快,不过,在有些情况下可能比 SQLite 慢。Costa 在 Hacker News 的评论中写道:“我们的目标不是声称它更快……而是强调我们在项目的早期就已经达到了良好的性能水平。”
我们能够在 Mac 上编译并运行 Limbo,不过需要将 Rust 编译器更新到最新版本以解决相关的错误。
在 Rust 中重新实现 SQLite 是一个有价值的项目吗?有的开发人员评论说,“考虑到代码质量和严格的测试,SQLite 可能是最不应该重写的项目”。也就是说,重写的目的不是为了避免 C 或 C 代码中常见的漏洞,而是为了添加特性(考虑到 SQLite 项目本身是相对封闭的),并利用 Rust 语言实现在 C 语言中难以实现的功能。
原文链接:
声明:本文为 InfoQ 翻译,未经许可禁止转载。
今日好文推荐
2024 年度技术热词来袭,AI 如何在可控生成和降本增效中寻找平衡\\"
OpenAI 史上最长宕机:自研 K8s 成“拦路虎”,导致数小时无法修复\\"
700 多亿打水漂后,这家巨头突然舍弃了无人驾驶出租车业务!新老员工炸锅:刚还在加班、“一群傻瓜”\\"
","description":"本文最初发表于 DevClass 网站,由 InfoQ 中文站翻译分享。 Turso 是一家专注于数据库解决方案的初创公司,目前正在使用 Rust 重新实现 SQLite 数据库引擎,以实现主要的新特性,比如异步 I/O。\\n\\nTurso 由 Glauber Costa 和 Pekka Enberg 在 2021 年创立。2022 年,这家当时名为 ChiselStrike 的初创公司 fork 了 SQLite,并创建了 libSQL。其基本思路是 SQLite 需要现代化,而且虽然该项目是开源的,但它不向希望对那些改进该项目的贡献者开放。\\n\\n创始人现在 宣布…","guid":"https://www.infoq.cn/article/GglyXWw1Yb3uKl2j8uOI","author":"Tim Anderson","authorUrl":null,"authorAvatar":null,"publishedAt":"2025-01-26T03:44:44.119Z","media":[{"url":"https://static001.geekbang.org/wechat/images/13/132d630c3953c7a0ec7854afa199c775.jpg","type":"photo","width":0,"height":0,"blurhash":""}],"categories":["编程语言"],"attachments":null,"extra":null,"language":null},{"title":"谷歌将空间内存安全功能“改造”到C++上","url":"https://www.infoq.cn/article/NIqJurRTxVlg1g2x4v3V","content":"本文最初发布于THENEWSTACK。
在分析了从2014年7月15日到2023年12月14日近10年的CVE后,谷歌研究人员计算得出,在C++中,至少40%的安全漏洞\\"与空间内存漏洞\\"(如越界写入内存)有关。
(查看大图)\\"
不过,谷歌正在努力解决这一问题,同时为这个充满不安全遗留代码的世界树立榜样。
谷歌研究人员\\"表示,他们能够将空间安全 “加装 ”到 C++ 代码库中,而且对性能的影响非常非常小。网上有一篇关于他们研究成果的博文\\",引发了更为广泛的讨论,其中不乏一些有趣的跟帖,有人甚至大声质疑,这种低影响是否意味着C++代码可以默认包含空间内存安全特性。
该文还提出了一种可能性,即一些已经存在很长时间的假设可能会随着时间的推移而受到挑战——当面临的问题比较严重时,或许可以尝试引入新技术。
这一切都源于一篇博文,该文描述了谷歌如何通过在C++代码中添加边界检查来保护其服务器端生产系统,从而提高Gmail、YouTube、谷歌地图甚至谷歌搜索引擎的安全性。谷歌是内存安全语言\\"和其他安全编码实践的早期采用者,但全面过渡往往需要数年时间。也就是说,他们还需要额外做一些工作: “尽可能地在现有C++代码库中改用安全设计原则\\"。
该博文由资深软件工程师Alex Rebert\\"和Kinuko Yasuda\\"(与谷歌的Max Shavrick\\"合作,后者也是安全基础团队的成员)撰写。该文首先指出,C++标准库的LLVM实现中包括几种用于发现未定义行为的加固模式\\",从而可以对C++代码进行边界检查\\"。
该文解释说:”[我们]现在已将其作为服务器端生产系统的默认设置,同时密切监控上线情况。“
结果如何?
该团队发现了1000多个Bug。(据谷歌估计,平均每年发现的Bug可增加到1000至2000个)。谷歌 “整个生产环境的基线分段故障率降低了30%”。在博文中,他们将此归功于更好的代码可靠性和质量: “除了崩溃之外,检查还发现了一些错误。这些错误可能会表现为不可预测的行为或损坏数据\\"。最终,它还帮助谷歌 “发现并修复了多个在代码中潜伏了十多年的Bug”。经过加固的C++检查 “将许多难以诊断的内存损坏转化为即时且易于调试的错误”。它甚至还瓦解了内部的一次红队演习,“证明了它在挫败漏洞利用方面的有效性”。
(查看大图)\\"
其中有一项结果\\"最引人关注。谷歌的博文称,加固libc++“对我们的服务平均造成了0.30%的性能影响”。
C++中的边界检查:有人问,0.3%的开销是否属实?这不仅仅是一个基准测试结果,我们是通过Google-Wide profiling得到的这个结果,我们通过它获得了来自DC的实时洞察。这也让我们大吃一惊,因为那比我们预想的要少得多。https://t.co/zBUvoYzGi1\\" https://t.co/7NAWBuxdtP\\"— Kinuko Yasuda (@kinu) 2024年11月16日\\"
谷歌杰出工程师Chandler Carruth\\"回应了他们的博文。他也是新兴编程语言Carbon\\"的创始人和联合牵头人。Carruth撰写了一篇博文,其中第一节的标题就是 \\"边界检查的开销:我错了\\"\\"。
“其他人关于成本的一些历史报告,再加上我自己的一些简单实验,让我坚定地认为,边界检查的成本不可能低到可以默认启用的程度。然而,到目前为止,它们看起来确实非常低。“
遗憾的是,这种普遍的看法使得高质量的动态安全检查没有出现在libc++及其他C++库中,最初也没有出现在LLVM中。
但Carruth看到,Microsoft Visual C++引入了基于编译器的检查,而 “在这里,苹果公司所有推动在C++中实现安全缓冲区\\"的人都做了一项了不起的工作,让LLVM生态系统(包括Clang和libc++)最终在这一领域拥有了一个可靠的工具”。Carruth认为,另一个因素是内存安全语言开发人员为LLVM做出了更多的贡献(因为更多的非C/C++语言开始使用LLVM),从而带来了 “一系列稳定而系统化的改进”。
回首过去,Carruth认为,虽然LLVM经过了多年的改进,但\\"我们并没有真正注意到什么时候已经达到了一个临界点。在那一刻,所有改进一起从根本上降低了此类检查的实际成本,使其在默认情况下就普遍适用。“
“这种水平的可用性改变了安全游戏的规则,因为我们不用再在性能或安全性之间做出痛苦的权衡取舍,我们可以两者兼得。“
Carruth用粗体字写道:\\"我认为,通过努力,借助编译器对内存安全检查的持续支持,我们确实有机会默认实现空间内存安全,即使是在C和C++中,即使是在性能最受限制的环境中。”
这就提出了一个问题:现在是否应该考虑下参考计数等其他安全检查——即使我们认为这些检查会带来令人望而却步的性能影响。
“我认为,有足够的证明表明,对于比较小的系统(手机、笔记本电脑、其他用电池的东西),缓存流量和潜在同步开销的成本即使再大也微不足道。我认为,Swift已经提供了强有力的证据,只要在优化基础设施上投入一些资金并认真实施,参考计数就能够在这些处理器上实现极高的效率。”
当然,谷歌的博文也在LinkedIn上引发了不少讨论:
(查看大图)\\"
(查看大图)\\"
Carruth还回顾了为了“让LLVM在优化加固方面做得更好”所作出的努力。他认为,性能敏感型工作负载得益于配置文件引导优化(或PGO),以及“人们系统性地构建优化基础设施......将代码的热门路径与安全检查的开销隔离开来,并释放了LLVM围绕它们所开发的所有其他优化技术,最大限度地降低了它们的成本”。
至于谷歌,他们的博文确实承认了这一点以及其他提高性能的技巧,但也补充说:\\"即使没有这些先进技术,边界检查的开销仍然微乎其微。(谷歌的博文将这种低影响归因于加固后的libc++的高效设计,以及编译器在优化过程中消除冗余检查的方式)。
不过,当发现LLVM在执行一项不必要的检查(并且对性能有很大影响)时,他们编写了一个修复程序,并将其贡献给了LLVM项目,“以便与广大的C++社区分享这项改进带来的好处”。
谷歌的博文在网络上引发了一些积极的反响。在Hacker News上,WebAssembly联合创始人Ben Titzer\\"对此作出了回应\\",他还记得20年前关于C++中边界检查必要性的争论。”程序中存在边界检查能捕捉到的Bug。将其作为一种内置特性,编译器就会对其进行专门针对边界检查的优化,这样可以消除许多Bug,并大大降低动态成本。“
“仅仅在库中打开安全检查并不一定能实现所有的编译器优化,但这只是一个开始。安全检查应该真正地内置于语言中\\"。
另一个回应来自Walter Bright\\",他创建了另一种编译器Zortech C++。Bright也是系统编程语言 D的创建者。他描述\\"了20年前D引入数组边界检查后发生的事情: “这是一个巨大的胜利“。在另一条评论中,Bright回忆\\"了如何使边界检查成为D语言的默认选项。
“事实证明,这是正确的选择。”
Rust基金会杰出顾问Shane Miller\\"发表\\"在LinkedIn上的回应可能是最积极的,“很高兴你们没有止步于通过这一举措获得安全方面的胜利。“
“你们在识别Bug和提高可靠性方面所掌握的数据是一个很好的参考\\"。
声明:本文为InfoQ翻译,未经许可禁止转载。
原文链接:https://thenewstack.io/google-retrofits-spatial-memory-safety-onto-c/\\"
","description":"本文最初发布于THENEWSTACK。 在分析了从2014年7月15日到2023年12月14日近10年的CVE后,谷歌研究人员计算得出,在C++中,至少40%的安全漏洞\\"与空间内存漏洞\\"(如越界写入内存)有关。\\n\\n (查看大图)\\"\\n\\n \\n\\n不过,谷歌正在努力解决这一问题,同时为这个充满不安全遗留代码的世界树立榜样。\\n\\n \\n\\n谷歌研究人员\\"表示,他们能够将空间安全 “加装 ”到 C++ 代码库中,而且对性能的影响非常非常小。网上有一篇关于他们研究成果的博文\\",引发了更为广泛的讨论,其中不乏一些有趣的跟帖,有人甚至大声质疑,这种低影响是否意味着C…","guid":"https://www.infoq.cn/article/NIqJurRTxVlg1g2x4v3V","author":"David Cassel","authorUrl":null,"authorAvatar":null,"publishedAt":"2025-01-26T03:32:00.402Z","media":[{"url":"https://static001.geekbang.org/infoq/3f/3fde6567e1f5828675640a344856f9c6.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/c6/c64450fb4735bca31afda4f6b08dc14a.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/24/24fbca1f98ef3ede6762ef97f567a028.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/dc/dc90e12e41be1d52cf5abf5935374744.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/35/354c963ed329ebd292ed3fa7793e055c.png","type":"photo","width":0,"height":0,"blurhash":""}],"categories":["编程语言"],"attachments":null,"extra":null,"language":null},{"title":"资源投入降低50%,中信银行信用卡中心从 Elasticsearch 到 Apache Doris 的技术实践","url":"https://www.infoq.cn/article/5kGidR9kGz9QT5viJTfq","content":"导读:中信银行信用卡中心每日新增日志数据 140 亿条(80TB),全量归档日志量超 40PB,早期基于 Elasticsearch 构建的日志云平台,面临存储成本高、实时写入性能差、文本检索慢以及日志分析能力不足等问题。因此使用 Apache Doris\\" 替换 Elasticsearch,实现资源投入降低 50%、查询速度提升 2~4 倍,同时显著提高了运维效率。
本文转录自陈地长(中信信用卡中心信息技术部 高级工程师)在 Doris Summit Asia 2024 上的演讲,经编辑整理。
中信银行信用卡中心(以下简称“卡中心”)隶属于中信银行,致力于为广大消费者提供涵盖支付结算、消费信贷、中收增值和特色权益的“金融+生活”全方位服务。卡中心构建了高端、商旅、年轻、商超、车主及零售六大主流产品体系,形成了产品、渠道、经营、合规风控和服务五大经营体系,综合实力在股份制银行中名列前茅。
为确保业务系统的稳定运行、提升运维效率和用户体验,卡中心建立了大规模的日志云分析平台。该平台不仅需支持实时监控和故障排查,还需满足金融监管对日志审计的严格要求。目前,平台每日新增日志数据突破 140 亿条、80TB,全量归档日志量超 40PB。
早期基于 Elasticsearch 构建的日志云平台面临存储成本高、实时写入性能差、文本检索慢以及日志分析能力不足等问题。因此,卡中心决定引入 Apache Doris\\" 替换 Elasticsearch,实现资源投入降低 50%、查询速度提升 2~4 倍,同时显著提高了运维效率。
在当前日益复杂的业务需求下,催生出了各种复杂的应用系统,这些应用系统分布在 Linux、Windows 等多种操作系统之上,同时依赖于各种网络设备、安全设备、中间件和数据库等服务,这些软硬件运行时每天可产生的日志量能达到 TB 级别。一旦系统运行出现异常,就需要通过分析日志进行问题排查。
日志的存在原本是通过其所记录多样化的数据、关键信息来帮助我们更好了解系统的运行状态。然而,面对卡中心每日新增 TB 级别日志数据,当系统异常时,日志格式的多样性同样也给数据分析带来极大的困难,主要挑战如下:
格式难以统一:日志数据以自由文本形式呈现,尽管相较于结构化数据信息更丰富,但其半结构化特性在数据分析和监控方面带来较大挑战。日志分析需求难以满足:日志种类繁多、分析需求各异。对不同业务、数据库和中间件全面分析与监控时,面临诸多挑战。运维效率低:出现问题时,运维工程师需要逐台登录服务器查看日志,效率低下,人为排障可能引发额外风险。缺乏可视化展示:常规日志分析方法无法以可视化展示,难以满足统计分析和业务指标趋势监控等更高水平的管理需求。难以评估影响范围:难以通过事件及其相关的软硬件日志了解对业务的影响,也无法对大量运行历史数据关联分析。
为确保业务系统的稳定运行,提升运维效率和用户体验,卡中心早期基于 Elasticsearch 构建日志云平台。整体采用 ELK 技术栈,支持应用日志、基础组件、中间件、数据库日志的存储与分析。架构图如下:
日志数据通过 Filebeat 采集到 Kafka ,经过 Logstash 处理后存储到 Elasticsearch 中。通过 Kibana UI 和自研 UI ,为开发和运维人员提供日志搜索以及全链路日志查询等服务。
存在的问题:
存储成本高:在降本增效大背景下,业务对降低存储成本的需求日益迫切。然而,由于 Elasticsearch 会对正排、倒排、列存等多份数据存储,给降本提效带来一定的挑战。高吞吐实时写入性能差:面对每天大量的新增数据,要求日志云平台具备 GB/s、百万条/s 的高吞吐写入能力,并保证数据秒级写入延迟,确保数据的实时性和可用性,但随着数据量的增长 Elasticsearch 很难满足。日志数据分析能力不足:Elasticsearch 分析能力较弱,只支持简单的单表分析,而不支持多表 Join、子查询、视图等复杂分析,难以满足愈发复杂的日志分析需求。
通过调研业界日志存储领域的新进展,发现 Apache Doris 有明显的优势:
高吞吐、低延迟日志写入:支持每天百 TB 级、GB/s 级日志数据持续稳定写入,同时保持延迟 1s 以内,确保数据的实时性和高效性。海量日志数据低成本存储:支持 PB 级海量数据的存储,相较于 Elasticsearch 的存储成本可节省 60% 到 80%,并支持将冷数据存储到 S3/HDFS 等低成本存储介质,存储成本可再降 50%。高性能日志全文检索:支持倒排索引和全文检索,对于日志场景中常见的查询(如关键词检索明细,趋势分析等)能够实现秒级响应,为用户提供极致的查询体验。强大的日志分析能力:支持检索、聚合、多表 JOIN、子查询、UDF、逻辑视图、物化视图等多种数据分析能力,满足复杂的数据处理分析需求。开放、易用的上下游生态:上游通过 HTTP API 对接常见的日志数据源,下游通过标准 MySQL 协议和语法对接可视化分析页面,为用户打造全方位的日志存储和分析生态。易维护、高可用集群管理:支持完善的分布式集群管理,支持在线扩缩容等操作,无需停止服务即可进行集群升级。
为更进一步验证其性能,卡中心基于 httplogs 数据集和实际日志数据对 Doris 和 Elasticsearch 进行了性能测试,测试结果显示:
在相同日志量下,Doris 相较于 Elasticsearch 表现优异:磁盘占用空间下降了58%,日志写入峰值提升 32%,查询耗时缩短了 38%。此外,Elasticsearch 使用了 9 台 16 核 32G 的服务器,Doris 只用了 4 台 8 核 32G 服务器,CPU 资源仅是 Elasticsearch 的 1/4。
综合上述对比及测试结果,卡中心决定引入 Apache Doris 进行升级,替换早期架构中的 Elasticsearch。基于 Doris 提供日志的统一采集、清洗、计算、存储、检索、监控和分析等多项服务,实现一站式日志管理与分析。同时,Kibana UI 被替换为 SelectDB UI,基于 Doris 自研 UI 更贴合卡中心业务的需求。
当前日志云集群规模约为 19 套,如果每套集群都有不同的查询入口,查询过程将显得尤为繁琐。因此,卡中心基于 Doris 建立了统一的日志云查询入口,用户可以在同一 UI 下查询不同机房和系统的日志。
卡中心整合了全链路监控体系的三大要素:指标、链路和日志,并基于 Doris 实现了日志链路分析及透传功能。可将全链路监控中的链路追踪 ID(Trace ID)传递到日志云查询 UI,使双向串联成为可能。
具体来说,每笔请求链路可自动与日志明细关联绑定,用户可查看每笔流量日志的整体上下游信息,并在每个阶段的对象上获取相关日志,实现从链路到日志、日志到链路的穿透式查询。此外,当发现错误链路或耗时链路时,可对关联日志明细进行分析,打通排障最后一公里。
为更好处理日志模式异常的问题,卡中心进一步开发了日志识别模版系统,可自动找出非预期的日志模式问题。
在日常运维排查中,注意到系统上线后,可能因潜在变更引发突发性问题,这些问题通常通过错误日志来体现。值得说明的是,这些错误日志的模式可能因变更而不同,例如,某些错误在变更前的系统中未曾出现,而在变更后却频繁出现,且其增长趋势与以往截然不同。
因此,利用该模板系统能够精准识别异常日志,并通过实时的告警推送机制,及时通知相关人员。这一功能不仅能够帮助我们提前发现系统中潜在的问题,还能够显著提升问题响应速度,确保系统的稳定运行。
在日志云场景中,使用 Apache Doris 构建新一代日志云存储分析平台,经过长时间的测试和验证,总结出以下一些优化经验。
表结构优化:
基于时间字段的分区设计,开启动态分区,提升数据管理和查询能力。设置基于冷热分离数据保留策略。设置基于磁盘属性的热数据写策略,SSD 盘用于热数据写,提高写入能力。使用 ZSTD 数据压缩算法,有效降低数据存储空间。合理设计字段索引,对于高基数字段使用 BloomFilter 索引,需要全文检索的字段使用倒排索引。
配置项优化:
Compaction 优化,加大 Compaction 线程数:max_cumu_compaction_threads增大写入端刷新前缓冲区大小: write_buffer_size。开启 tablet 均衡策略: enable_round_robin_create_tablet增大单个 tablet 版本数,提高写入能力: max_tablet_version_num
数据写入优化:
开启单副本导入,先写入一个副本,其他副本数据从第一个副本拉取,导入性能提升 200%开启单 tablet 导入,减少多个 tablet 写入时带来的文件读写开销。提高单次导入的数据量,一次写入 100MB 左右。
以一个机房集群投产为例,基于 Doris 的日志存储与分析平台上线后,相较于原有的 Elasticsearch 架构,成功减少了日志冗余存储,提高了日志数据存储效率,同时提供了强大且高效的日志检索与分析服务。以下是以东坝机房为例的具体收益:
资源投入节省 50%: CPU 使用率使用率约为 50%,整体资源使用率仅为之前的 1/2。原先同样数据规模,写入 Elasticsearch 需要 10TB 空间,采用 ZSTD 压缩技术,写入 Doris 规模仅需要 4TB 。查询提速 2~4 倍: 新架构以更低的 CPU 资源消耗带来了 2~4 倍的查询效率提升。增强日志可观测能力: 通过穿透链路、指标、告警等平台,提升了日志模式识别、分类聚合、日志收敛与异常分析等可观测能力。提高运维效率: 新平台提供极易安装和部署的程序,以及易于操作的管理工具,简化了服务、配置、监控和告警等操作,显著提高了集群的扩缩容灵活性。
未来卡中心将持续迭代日志系统, 并重点从以下几方面发力:
广泛推广 Doris:持续推进剩余机房 Elasticsearch 替换成 Doris,推进剩余的日志云 Elasticsearch 集群替换成 Doris。丰富日志导入预处理能力:增加日志采样和结构化等预处理功能,进一步提升数据的易用性和存储性价比。增强 Tracing 能力:打通监控、告警、Tracing 和日志等数据的可观测性系统,以提供全方位的运维洞察。基于大模型的 AIOps:持续探索智能运维的最佳实践,包括日志异常监测、故障预测和故障诊断等。扩大 Doris 使用范围:除了日志场景,Doris 将逐步引入数据分析和大数据处理场景,增强湖仓一体的能力建设。
","description":"导读:中信银行信用卡中心每日新增日志数据 140 亿条(80TB),全量归档日志量超 40PB,早期基于 Elasticsearch 构建的日志云平台,面临存储成本高、实时写入性能差、文本检索慢以及日志分析能力不足等问题。因此使用 Apache Doris\\" 替换 Elasticsearch,实现资源投入降低 50%、查询速度提升 2~4 倍,同时显著提高了运维效率。 本文转录自陈地长(中信信用卡中心信息技术部 高级工程师)在 Doris Summit Asia 2024 上的演讲,经编辑整理。\\n\\n中信银行信用卡中心(以下简称“卡中心”)隶属于中信银行…","guid":"https://www.infoq.cn/article/5kGidR9kGz9QT5viJTfq","author":"SelectDB","authorUrl":null,"authorAvatar":null,"publishedAt":"2025-01-23T09:24:22.641Z","media":[{"url":"https://static001.geekbang.org/infoq/6e/6e01f646add6d8468f42af0a1c5c59a9.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/52/52c12b220e85b00e0b550ea41ea97665.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/36/36300408c446b1166411f08670515d03.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/89/893bd6f0ad37ba048a38f780a81991bd.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/fe/fea639e3dc5a406ddaa79709ca02ee00.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/5e/5eb3172d9f24145be365a5aaf648a6d9.png","type":"photo","width":0,"height":0,"blurhash":""}],"categories":["数据库"],"attachments":null,"extra":null,"language":null},{"title":"故障恢复时间仅需8秒,OceanBase 在网易云信的落地实践","url":"https://www.infoq.cn/article/uJtjEet8F8iwrpdu1BZ6","content":"作者|曹佳俊,网易云信服务器研发专家
网易云信是网易集合IM与音视频技术打造的PaaS服务产品,为全球科技企业提供融合通信与视频的核心能力与组件。基于其丰富的服务场景与多样的业务需求,网易云信底层依赖多种数据库系统,以IM通讯系统为例,包括网易自研的关系型数据库DDB,以及包括Redis、HBase和Elasticsearch等组件都扮演着重要的角色。在业务需求不断增长的过程中,数据库在性能、成本、高可用等方面遇到了问题和挑战。在本文中,网易云信分享了其IM通讯系统数据库的架构设计与优化实践,以及在关系型和KV业务场景中使用OceanBase和OBKV对现有架构进行升级与简化,从而在性能、成本、运维、高可用等方面实现有效提升的思考和实测经验。
网易云信是来自网易核心架构的通信与视频云服务,稳定易用且功能全面,致力于提供全球领先的技术能力和场景化解决方案。云信提供融合通信与视频的核心能力与组件,包括IM即时通讯和短信信令等通信服务,以及RTC直播、点播及互动直播等音视频服务。此外,网易云信结合网易易盾推出一站式安全通信方案——安全通。
目前,网易云信融合通信已接入220 万企业开发者,全球注册应用数超 75 万,累计覆盖智能终端 SDK 数超 300 亿,月均消息量 3100+ 亿条,居行业首位,日活消息量表现突出。作为专为企业打造的融合通信的品牌,网易云信专注于文娱、社交、教育、医疗等行业,支持公有云、专属云、私有云与混合云四种部署方式。
对于如此体量的服务,数据库作为基石与支柱,扮演着极为重要的角色。随着业务规模的持续增长,我们也正在寻找一套适配网易云信业务场景的升级方案,在简化数据库系统架构、降低运维管理成本的同时,实现稳定提效。本文将分享网易云信数据库实践和运维经验,以及网易云信选型OceanBase背后的实践与思考。
在网易云信中,通讯和视频服务都高度依赖数据库,尤其是IM通讯系统。在IM通讯系统中,数据库种类较多。其中,最为重要的是关系数据库,也就是网易自研产品DDB,它采用分库分表设计,专门用于存储 账号、关系和离线消息 等关键数据。其次,Redis数据库、HBase和Elasticsearch也扮演着重要角色。
DDB是网易自研的分库分表中间件,目前在网易内部被广泛应用。不仅网易云信,网易云音乐、有道等众多产品也都深度依赖这套系统。
DDB的架构是一个很经典的架构。首先,接入层我们称为QS服务器,这是一个SQL-proxy。他的后端则是实际的存储节点,通常是MySQL。接入层支持两种接入方式。一种是通过挂载四层负载均衡器,如nlb或阿里云上的slb,来实现对QS的负载均衡和高可用。此外,对于Java程序,DDB还额外提供了lbd-driver驱动。它的优势在于能直接连接QS服务器,并自动发现服务器、优雅地进行上下线管理以及故障转移。因为省去了nlb组件,也提高了效率和可靠性。
Redis在网易云信IM系统中也占有重要角色,支撑着多种业务场景,我这边简单选取几个代表性的场景。
第一个场景是数据库缓存,基于自研数据库缓存框架,使用了简单的KV结构实现。它主要依赖简单的字符串操作,如set/get/delete。特点是读多写少,且读操作的TPS很高。
第二个场景是在线状态管理,用于记录账号和设备的在线状态,使用hash结构记录多端登录和实现复杂的多端互踢策略,也是消息分发时的关键组件。简单讲,用户登录时系统会进行在线状态的写入与更新,而发送消息时则需查询在线状态。如下图所示,这是一个典型的读多写多场景,尤其在处理大群消息或批量消息发送任务时,读操作的TPS会显著上升。
第三个典型场景是漫游消息,从用户角度来看,它主要用于实现最近消息的多端同步功能。为实现这一功能,我们采用了zset结构实现先进先出的最近逻辑。该功能的一个显著特点是,由于需要存储最近发送的消息以便进行同步,因此其存储开销相对较大。这是漫游消息功能的现状。
此外,我们还引入了HBase和Elasticsearch数据库,主要用于存储和查询历史消息。HBase的row-key全局有序的特点,非常适合适合根据时间进行历史消息分页查询的场景。而Elasticsearch被用于关键词检索等更复杂的搜索需求。为了降低存储开销,在Elasticsearch中我们并没有直接存储消息的完整内容,最终的搜索结果指向的是HBase中存储的消息。除了消息之外,用户和关系的检索等也会用到Elasticsearch相关的能力。
前面介绍了云信的数据库使用背景及现状,当前我们在使用数据库的过程中也面临一些问题和挑战。
首先,在关系数据库方面面临三个问题。
第一,性能瓶颈问题。尽管我们使用的分库分表架构已经相当稳定,并且依赖于内部强大的owl平台,能够自动化完成许多运维工作,如自动扩缩容、在线表变更等,但在某些特定场景下,我们仍然遇到一些瓶颈。为了进一步提升业务的灵活性和应对未来可能的扩展需求,我们希望能够引入原生的分布式数据库。这样不仅可以解决当前的性能瓶颈,还能为业务带来更多的弹性和可扩展性,这是我们最初的诉求。
第二,资源利用率问题。DDB基于MySQL存储作为数据节点,其B+tree结构既有优势也有局限,这是众所周知的。在云环境下,我们期望在某些场景中能提高磁盘利用率,以实现降本增效。
第三,资源隔离功能。DDB已提供一定程度的资源隔离能力,通过配置policy或者schema来实现。这些隔离策略能满足大多数业务场景的需求。然而,在某些特定的业务场景中,我们期望有更精细化的资源控制机制。现有的隔离机制可能是库表级别的,但我们希望它能进一步细化。对于云信这样一个多租户的PaaS系统来说,更细粒度的资源控制是很有必要的。
其次,是Redis
最初我们采用了开源的redis-cluster集群部署方案。Redis-cluster本身是多节点且支持水平扩缩容的,在初期单集群即可很好的满足云信的单一业务需求。然而,随着业务的持续增长,由于redis-cluster单集群节点数的上限(我们单集群一般不超过100主100从),我们遇到了单集群下的内存容量瓶颈和QPS容量瓶颈。
为了突破这些瓶颈,我们开发了一个Redis代理,以实现更灵活的水平扩展。这个代理服务可以将多个Redis-cluster集群使用分片的方式透明的对外提供服务,从而突破单节点的规模上限。此外,为了更平滑在多个集群之间迁移数据,我们还在redis代理上实现了双写功能。
然而伴随业务规模不断扩大,云信的集群数量也随之增加,这让我们开始思考如何降低成本。特别是针对漫游消息这一业务场景。
漫游消息用于在相同账号的不同设备之间同步最近n天的消息,因此它有一个显著特点,用户通常会频繁读取最近的消息,而几天前的消息则读取较少。针对其特点,我们实施了一个冷热数据分离的存储策略。具体来说,我们将热数据存储在Redis中,以便快速访问;而冷数据则被持久化到HBase中。之所以选择HBase作为冷数据的存储介质,主要是因为当时我们有一套现成的hbase集群,dba也有hbase的运维经验,此外hbase的扩展性也满足了我们业务增长带来的扩容需求。
我们发现冷热数据分离策略的效果相当不错。随即便开始思考如何将其打造得更加通用,不仅仅局限于漫游消息这一场景。为此,我们先将Redis中的冷热数据分离功能设置为可选,以适应那些TPS要求不那么高、希望所有数据都直接持久化在磁盘上的场景。
不久我们意识到持久化的KV存储不应局限于HBase这一种方案。因此,我们抽象出了一套通用的接口,使得替换存储方案变得更加简单灵活。这一改动上线后,云信的系统成功接入了更多业务,如在线状态发布订阅、云端会话列表等功能,都逐渐整合到了这套方案中。
值得一提的是,我们还开源了与这些功能相关的代码(开源地址:https://github.com/netease-im/camellia),有兴趣的朋友可以进一步了解。
目前线上我们主要使用hbase作为后端kv存储,然后由于其架构特性,宕机后的恢复时间可能会相对较长,基本要分钟级别。
另外,当我们通过proxy将Redis协议转换为KV协议时,会涉及将单个key的数据映射到多条kv的情况。这种转换过程中,数据不一致的风险是不可避免的,尽管并非所有场景都对数据一致性有严格要求,但这种风险确实存在。
此外,proxy与KV存储之间的映射也会带来proxy和kv-server之间的多次网络I/O,对性能造成一定的损耗。尽管我们做了很多优化工作来减少网络I/O,但显然无法完全覆盖所有场景,性能损耗问题依然存在。
在历史消息存储这一核心场景中,HBase发挥了重要作用,挑战也随之而来。
起初,我们选择使用单个HBase集群来存储所有的历史消息数据,考虑到数据规模比较大,为了节约成本,便采用了hdd磁盘作为存储介质。然而,随着数据量的不断增长,HBase也面临了一些挑战。特别是当某个节点出现故障后恢复周期相对较长,可能需要数分钟甚至数十分钟,这对业务运行造成了不小的影响。
为了应对这些挑战,我们后来决定采用双集群方案。在这个方案中,我们部署了两个HBase集群:一个是基于hdd的全量数据集群,另一个是基于ssd的小规模集群。ssd集群用于存储最近一年内的消息,以提供更快的读写速度;而超过一年的消息则存储在hdd集群中,以节约成本。
对于写操作,我们采用双写策略,确保数据同时写入两个集群。对于读操作,如果查询的是最近一年的消息,则直接从ssd集群中读取;如果需要查询超过一年的消息,我们会从hdd集群中检索,并在业务层进行合并后返回结果。为了确保双写操作的一致性,我们引入了Kafka作为中间件。当向两个HBase集群写入数据时,如果某个集群写入失败,我们会通过Kafka记录这条失败的写入命令,并触发重试机制,以确保两个集群最终达到一致状态。
这个方案确实带来了不少优势,但同时也伴随着一些潜在问题,尤其是HBase架构本身存在的固有缺陷。
尽管我们已经将部分数据迁移到了速度更快的ssd上,但HBase的故障恢复时间依然是一个需要重视的问题。虽然相比使用hdd时,恢复时间已经大大缩短,但分钟级别的恢复时间对于实时性要求极高的业务来说,仍然可能带来不小的风险。
在这个架构下,随着业务的不断扩张,ssd上的HBase集群所承受的读流量也在持续攀升。最初的设想中,在一个集群出现问题时,可以迅速切换到另一个节点以维持服务。然而,随着业务量的不断增长,特别是在高峰时段,这种切换策略变得愈发不可行。
具体来说,如果ssd节点发生故障时,切换到hdd集群是一个比较艰难抉择,因为我们不确认hdd集群是否能承担起流量,因此更多时候可能只能等待故障节点自行恢复。而这段等待时间,对于业务而言,可能就意味着服务质量的下降,甚至是有损状态。
鉴于上述数据库的这些痛点,我们开始寻找更符合业务需求的数据库。
在进行数据库选型的过程中,我们主要从兼容性和稳定性、平台统一性、成本、性能、高可用性、社区方面着重进行考量。
第一,稳定性和兼容性。这是我们着重考虑的因素。首先,稳定性至关重要,特别是对于云信的To B业务来说。鉴于云信拥有庞大的客户群体,任何微小的服务波动都可能迅速引发客户反馈,进而给前向团队和研发团队带来巨大压力。因此,稳定性无疑是数据库选型中的首要考量。其次,兼容性同样不容忽视。我们期望新数据库能够兼容现有mysql协议,以便业务能够顺利迁移,无需进行大规模修改。这样不仅能降低迁移成本,还能确保业务的连续性和稳定性。
第二,平台的统一性。如上文所述,当前许多数据库都具备多模和多功能的特点。我们期望新的数据库平台能够适应云信的多种业务场景,这样,在运维过程中,我们就能因为使用同一套系统而简化工作,进而降低运维成本。
第三,降本增效,特别是在数据存储方面。我们目前线上的数据库现状是,相较于存储需求,CPU资源往往相对闲置。经常出现的情况是,CPU还未充分利用,磁盘空间却已耗尽,且无法再增加磁盘。这时,云信不得不进行扩容。因此,如果能够通过利用CPU资源来换取存储成本的降低,对我们来说将是非常划算的。
第四,性能方面。虽然目前的DDB或HBase在性能上并未出现明显的瓶颈,但如果新数据库能进一步提升性能,那对我们来说无疑是更好的选择。
第五,高可用性的能力。这是我们曾经遇到问题,也是最希望得到改善的方面,特别是HBase。我们期望新数据库具备可控的故障恢复时间,这能显著提升云信服务的整体稳定性。稳定性不仅体现在日常运行的无故障上,更体现在故障发生后的快速恢复上。恢复速度越快,云信的服务中断时间就越短,对于To B业务来说,这直接关联到成本节约。
第六,社区。我们期望使用的数据库,是一个社区活跃、功能持续迭代的现代数据库。这样,未来一旦我们有新的需求,能得到迅速响应和及时满足,这是我们非常看重的一点。
基于上述关于数据库技术选型的考量,OceanBase在网易云业务场景中展现出显著优势。
首先对于关系数据库来说:
兼容MySQL协议。以关系数据库为例,我们特别欣赏OceanBase社区版对MySQL协议的兼容性,便于业务几乎无需修改即可平滑迁移。同时,我们的使用方式也无需做出特殊调整,大大简化了部署和运维过程。成本优势,关于这一点,我们有坚实的数据支持,在后文中会详细展示。在采用OceanBase之前,我们曾对MySQL 8.0版本与MySQL 5.7版本进行测试、对比,虽然前者在压缩能力上有所进步,但与OceanBase相比,压缩效率仍显不足。高可用能力。与DDB相比,OceanBase同样具备出色的高可用性能。然而,DDB的故障恢复时间依赖于DDB-switcher这一高可用切换工具,在最慢的情况下可能需要超过1分钟。相比之下,OceanBase的故障恢复时间可以缩短至8秒,这一优势在我们多次实际测试中得到了验证。原生分布式能力。与DDB这类分库分表中间件相比,OceanBase在扩缩容时数据迁移更加高效。虽然DDB也能实现一定程度的自动化,但在资源依赖和操作流程上,OceanBase显然更为便捷。多租户能力。对于云信这样的PaaS平台,用户众多且使用习惯各异,有时难免出现个别用户行为异常,可能影响到整个系统。此时,OceanBase的多租户资源隔离能力就显得尤为重要。通过OceanBase,我们可以将云信业务中的不同租户数据隔离到各自的数据库实例中,实现资源的独立调度和管理。这样,即使某个租户出现异常行为,也不会波及其他租户或整个系统,从而显著提升服务的稳定性。这一底层逻辑的设计,充分体现了OceanBase在多租户资源隔离方面的独特价值。性能优势。虽然DDB的性能对我们来说已经相当不错,但在某些特定场景下,由于其底层基于MySQL,因此在单行更新等方面可能会遇到一些性能瓶颈。相比之下,OceanBase在这方面进行了专项优化,表现更为出色。单机分布式一体化特性,这一特性是OceanBase 4.0版本提出的,它为云信带来了显著价值。因为并非所有业务都需部署如DDB般庞大的数据库,尤其对于发号器、配置中心等轻量级服务,单机版数据库便足以应对。OceanBase 正是满足了这一需求,其一体化架构统一了底层数据库,极大简化了运维流程,对云信而言意义非凡。
对于OceanBase多模KV产品OBKV,在网易云信的业务场景同样存在以下优势:
成本优势。相比HBase1.x,压缩率显著提升,大大降低了成本。官方数据也证实了这一点。高可用能力增强,这是我们尤为看重的一点。接入较简单。官方提供了一个与HBase兼容的客户端SDK,接入简便,因其与HBase客户端高度相似。运维部署简单。OBKV相比HBase极大的简化了部署,特别适合云信的私有化场景。
在私有化环境中,很多客户的需求并不需要大规模的部署。此时,如果采用HBase来处理历史消息,可能会显得过于庞大和复杂。
如果此时我们改用OBKV,部署将变得非常简单,能够更好地实现公有云与私有化环境的功能一致性。在私有化环境中,由于无法部署HBase,我们往往不得不割舍某些功能或采用其他方式实现,这不仅增加了开发成本,也损害了用户的体验。
采用OceanBase后,我们在私有化落地方面的挑战得到有效克服,实现了与公有云功能的一致性。OceanBase 相比HBase 组件少、部署简单、运维方便,解决了私有化过程中的难点。
在实践中,我们曾将线上数据库同步至OceanBase与MySQL 8.0进行对比测试。测试中,云信特别关注了核心大表,尤其是至关重要且规模庞大的离线消息表。OceanBase 的出色表现再次证明了其在处理这类核心数据上的卓越能力。
以下表为例,OceanBase的压缩比高达4:1左右。相比之下,无论是页压缩还是大字段压缩,SQL 8.0的压缩比都只能达到约1.5或更低,不超过2:1。显然,OceanBase在这方面具有显著优势。高压缩比直接转化为实实在在的成本节约,对云信而言意义重大。
此次单行更新测试,使用了OceanBase官方文档中的脚本。
结果显示,无论是低并发还是高并发场景,OceanBase 4.2.1版本相比MySQL 5.7和8.0都表现出明显优势。尤其在并发增加时,OceanBase的优势更为显著。这对于IM系统中需要单行更新的场景来说,将极大提升系统的稳定性。
单行更新测试
前文提及新的proxy+kv架构,它经过简单改造后,目前已能支持多种KV存储,包括新的OBKV产品。OBKV提供了table-api功能,并且已经开源。特别是,OBKV最近发布了4.2.5版本,其中包含了POC版本的obkv-redis功能。我们已经基于这一POC版本展开了初步测试,并将持续关注官方对这一功能的后续优化与升级。
相较之下,OBKV组件少,运维简单,降低了管理复杂度;高可用能力增加,故障恢复只需8秒,且性能提升明显。
下图是对一个简单字符串场景的性能测试,主要对比了HBase、TIKV、OBKV以及原生Redis(通过POC版本)在get/set方法上的表现。我们使用了一个性能压测程序来进行测试。结果显示,OBKV相较于云信之前使用的HBase,在性能上确实有所提升。特别是在P999上的表现尤为突出。
对于复杂数据结构而言,OBKV同样展现出了优势。这得益于它针对Redis数据结构进行的优化,使得其写入能力相较于Redis-proxy+kv架构更为出色。在读取方面,目前来看各种方案各有优劣,毕竟OBKV的这项功能刚推出不久,但是obkv-redis在部署上少了2台独立的redis-proxy,我们也将持续关注其后续发展。
尤为值得一提的是,若我们采用OBKV,并将关系数据库与KV数据库的底层全部替换为OceanBase,将实现底层技术的统一。这一变革极大地简化了我们的运维工作,为系统维护带来了巨大便利。
我们将OBKV与先前使用的HBase 2.4.1进行了对比测试。而线上之前实际使用的是HBase-1.2.6版本,性能可能更差。结果显示,在我们的业务场景下,OBKV与带来了显著的性能提升,对业务产生了积极的影响。
展望未来,我们将持续优化并推出新功能。
第一,逐步上线OceanBase。目前,我们的测试工作正在紧锣密鼓地进行中,测试环境已搭建完毕并投入运行。会按照先部署OBKV,再使用OceanBase替换MySQL的顺序逐步灰度和上线。当前部分业务已经正式上线使用OceanBase。
第二,异地容灾。由于之前数据库底座的限制,云信的容灾方案相对复杂。在OceanBase的支持下,有望简化整个容灾方案。目前,我们正对此进行深入研究。
第三,迁移obkv-redis。初期,我们可能会优先上线基于现有redis-proxy+KV的方案,只是将KV从HBase更换为OBKV。我们会先运行这种方案,待其逐渐稳定后,再考虑迁移到obkv-redis。
第四,使用OceanBase的HTAP功能。云信不仅拥有IM系统的核心在线功能,还集成了数据统计能力。当前,我们可能因系统分割,需借助数据平台和CDC来实现数据同步与数仓分析。若OceanBase的HTAP功能符合业务需求,将极大简化整体数据架构,促进系统间的高效集成。
另外,在测试过程中,我们对OceanBase提出了许多需求,都得到了OceanBase的积极反馈。未来也对OceanBase的新特性和新功能充满期待,最后祝OceanBase越来越好,谢谢大家。
","description":"作者|曹佳俊,网易云信服务器研发专家 网易云信是网易集合IM与音视频技术打造的PaaS服务产品,为全球科技企业提供融合通信与视频的核心能力与组件。基于其丰富的服务场景与多样的业务需求,网易云信底层依赖多种数据库系统,以IM通讯系统为例,包括网易自研的关系型数据库DDB,以及包括Redis、HBase和Elasticsearch等组件都扮演着重要的角色。在业务需求不断增长的过程中,数据库在性能、成本、高可用等方面遇到了问题和挑战。在本文中,网易云信分享了其IM通讯系统数据库的架构设计与优化实践,以及…","guid":"https://www.infoq.cn/article/uJtjEet8F8iwrpdu1BZ6","author":"曹佳俊","authorUrl":null,"authorAvatar":null,"publishedAt":"2025-01-23T09:20:18.868Z","media":[{"url":"https://static001.geekbang.org/infoq/8e/8e59e8cb1d57873b374332cb32d173dc.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/98/98b84d847335aaee2c4103ea1925911e.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/53/53abf4ccf310dfb52713345ffa14b928.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/c9/c9e0b986f9c8b902891d25cee6b1fbdc.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/2d/2ddaeed66b1bb6be3407193d62e4f8ae.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/12/125b57fbb7cbca342d3d79ced8aba7d5.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/ef/ef3f36a92552b497c1317365d1e44463.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/6a/6a9be25bc14b0d25fa4dd53bf6f881bf.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/cf/cf8314f8f8e2bfe4a7aeb77ec8536f16.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/35/3526588fa4fb50ae8a119c82abf6891c.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/d5/d5f2a38d6e2ab3892c3b2460da22c40a.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/1a/1abec1b1b72f06c1ee4cc44a54d8f534.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/89/8930355bdd1406e67bf5159daedf0780.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/8f/8ff0c3f0a95132f9b14793fbaf1b66a4.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/9c/9c3907cb924a456b4804d3a3d18b3f00.png","type":"photo","width":0,"height":0,"blurhash":""}],"categories":["数据库"],"attachments":null,"extra":null,"language":null},{"title":"Vercel 利用新型 MicroVM 基础设施缩短构建时间","url":"https://www.infoq.cn/article/butjXWfswt88Nqz9PJu7","content":"云平台即服务公司 Vercel 发布了一份针对 Hive 的深入研究报告。Hive 是其新的底层计算平台,为客户构建提供基础架构支持。自 2023 年 11 月以来,Vercel 已将 Hive 用于不受信任的临时计算任务。
Vercel 构建和计算产品经理 Mariano Cocirio 和首席工程师 Guðmundur Bjarni Ólafsson 在博文中解释说,他们开发 Hive 是为了满足客户日益增长的需求,同时保证多租户环境中的安全性。
我们之所以构建 Hive,是因为我们需要更精细的控制和更细粒度的管理,以便不断地改进 Vercel 的基础设施。
该平台由一个称为“ hives ”的区域集群系统组成,每个集群独立运行,有自己的故障边界。每个集群包含几个关键组件,包括 “ boxes ”(裸机服务器)、“ cells ”(虚拟机)、用于编排的控制面板以及每个 Hive 实例的专用 API 。
在技术层面,Hive 使用了 KVM(Kernel-based Virtual Machine)技术和 Firecracker,后者是亚马逊云科技最初为改进 Lambda 和 Fargate 而开发的一个开源 MicroVM。这些技术结合在一起,为运行构建进程创建了安全、隔离的环境。该系统有一个 “box 守护进程”,用于管理虚拟机准备以及与 “cell 守护进程 ”通信,而后者负责控制执行客户工作负载的构建容器。
Vercel 通过预热 cell 进一步简化了构建流程,使大多数构建工作无需等待 cell 创建即可立即开始。启动构建时,系统会根据客户和构建配置选择合适的 Hive 集群,然后在 cell 内的容器中执行构建。完成后,cell 将被销毁,以保持平台的临时性特点。
Vercel 专注于 Hive 架构的安全性和隔离性。每个虚拟机都分配有专用的 CPU 和内存,而磁盘和网络吞吐量则根据总体容量和 box 划分进行速率限制。这种方法可以确保潜在的恶意代码能够在多租户环境中安全地执行,而不会影响系统的完整性或性能。
在一段讨论 Vercel 博文的 YouTube 视频中,来自 Codedamn 的 Mehul Mohan 解释了实际的工作流程:当开发人员将代码推送到 GitHub 时,一个 webhook 会触发 Vercel 的构建流程,并说明了为什么 Hive 既是不受信任的又是临时的。Mohan 将其与 Codedamn 的游乐场做了比较,后者在运行不受信任的代码时也面临着类似的挑战,这可以帮助说明 Vercel 的架构为何使用多层隔离。
在 Sum Of Bytes 上发表的一篇文章中,Arpit Kumar 讨论了无服务器计算中的各种虚拟化方法,并特别介绍了 MicroVM,认为它是一种兼顾安全性、隔离性和性能的解决方案。传统的容器虽然速度快、效率高,但因为共享主机内核,如果恶意代码导致内核恐慌,就会带来安全风险。这推动了 MicroVM 的发展,Firecracker 就是一个成功的例子,它可以在短短 300 毫秒内完成启动。
Kumar 比较了各大公司不同的 MicroVM 实现。亚马逊云科技使用 Firecracker 实现 Lambda 和 Fargate,Cloudflare 使用 V8 Isolates 运行 Worker,谷歌的 gVisor 是另一种用于运行容器的以安全为本的虚拟机。他还提到, WebAssembly 是另一种速度接近原生的沙箱方法,以及其他新兴的基于 Rust 的 MicroVM 替代方案。
Hive 还集成了 Vercel 的安全计算产品,使企业能够在敏感的构建流程中使用私有网络连接。与以前的解决方案相比,这种集成有了很大的改进,特别是在安全构建的准备时间方面。
在另一篇文章中,Cocirio 和 Ólafsson 解释了这是如何实现的:
每个 Hive cell 都会通过连接器的 WireGuard 接口启动一个安全隧道。密钥在实例启动时生成,并通过密钥交换服务分发,不会持久存在或重复使用。
该平台的安全模型使用 Linux 网络命名空间,每个 WireGuard 接口都在 box 自己的命名空间中运行。这种架构可确保所有 cell 流量都经过了加密,并通过安全隧道正确路由回客户基础设施。
与以前基于 Fargate 的解决方案相比,该系统在性能上有明显改善。以前在私有网络内,安全构建需要长达 90 秒的准备时间。新的基于 Hive 的架构将这一时间缩短到了 5 秒,而且网络安全水平保持不变。与以前的解决方案相比,整体构建性能提高了 30%。Vercel 将这些成果部分归功于 Docker 镜像缓存等优化措施。这些措施本身就将启动时间缩短了约 45 秒。
该平台的成功促使 Vercel 考虑将 Hive 扩展到其他业务领域。虽然目前的重点是为客户构建基础设施,但该公司将 Hive 描述为一个通用计算平台,未来有可能实现更广泛的应用。伴随着 Vercel 继续探索改进和新用例,进一步加强缓存策略和优化 repo 克隆的工作也正在进行当中。
原文链接:
https://www.infoq.com/news/2025/01/vercel-hive/\\"
","description":"云平台即服务公司 Vercel 发布了一份针对 Hive 的深入研究报告。Hive 是其新的底层计算平台,为客户构建提供基础架构支持。自 2023 年 11 月以来,Vercel 已将 Hive 用于不受信任的临时计算任务。 Vercel 构建和计算产品经理 Mariano Cocirio 和首席工程师 Guðmundur Bjarni Ólafsson 在博文中解释说,他们开发 Hive 是为了满足客户日益增长的需求,同时保证多租户环境中的安全性。\\n\\n我们之所以构建 Hive,是因为我们需要更精细的控制和更细粒度的管理,以便不断地改进 Vercel…","guid":"https://www.infoq.cn/article/butjXWfswt88Nqz9PJu7","author":"作者:Matt Saunders","authorUrl":null,"authorAvatar":null,"publishedAt":"2025-01-23T08:00:00.301Z","media":[{"url":"https://static001.geekbang.org/wechat/images/f8/f8f087b0d8aa389568324aac62517825.png","type":"photo","width":0,"height":0,"blurhash":""}],"categories":["数据库"],"attachments":null,"extra":null,"language":null},{"title":"InfoQ 2024年Java趋势报告","url":"https://www.infoq.cn/article/EKLCiLj2wlk1mg6KOTI6","content":"虽然 Java 17 是最常用的 JDK ,但它并没有占大多数。相反,根据 New Relic 2024 年 Java 生态系统现状的数据,Java 17-11-8 的比例分别为 35-33-29% 。我们需要明确的是,根据 New Relic 的“快速采用”数据,Java 21 的采用率仅为 1.4%,但这仍然快于 Java 8 以来的任何 LTS,不过仍然只占很小的比例。Java 平台现在已经摆脱了速度缓慢、受传统限制的名声,有了明显的创新动力。2024 年的头几个月,人工智能的 “狂野西部 ”已经平静了下来,但仍然是一个热门话题。人们似乎有了一种更加清醒的态度,即人工智能并不一定是解决所有问题的 “锤子”。Commonhaus 基金会是一个新成立的非营利组织,致力于开源库和框架的可持续发展,为自治开源项目提供继任规划和财政支持。在 Java 领域,WebAssembly 终于获得了越来越多的关注,赶上了 Go 和 Rust 等生态系统。
本报告汇总了 InfoQ Java 编辑团队目前对 Java 领域的技术应用和新兴趋势的看法。我们重点关注 Java 语言、Java 相关语言(如 Kotlin 和 Scala )、Java 虚拟机(JVM)以及基于 Java 的框架和实用工具。我们讨论核心 Java 的趋势,如 Java 新版本的采用,以及 Spring Framework、Jakarta EE、Quarkus、Micronaut 、Helidon 、MicroProfile 和 EclipseStore( MicroStream 的前开源版本)等框架的演变。
欢迎收听由 Karakun 高级软件开发人员 Ixchel Ruiz 和 Decodable 软件工程师 Gunnar Morling 主持的 播客讨论。该讨论是对 2024 年 Java 趋势报告的一个补充。
本报告主要有两个目标:
帮助技术领导者做中长期技术投资决策。帮助个体开发人员选择将宝贵的时间和资源投入到何种知识的学习和技能的开发。
这是我们发布的第 6 份 Java 趋势报告。不过,由于我们自 2006 年以来一直在内部跟踪 Java 和 JVM 的发展趋势,所以这一话题已经得到了广泛的新闻报道。
为了帮助 InfoQ 和 QCon 把握当前和未来的趋势,我们采用了 Geoffrey Moore 在其 同名著作 中首创的 “跨越鸿沟 ”技术成功心理模型。我们试图找出 Moore 所说的早期市场:“客户群由技术爱好者和有远见的人组成,他们希望抓住机遇或解决迫在眉睫的问题。“
与 2023 年、2022 年、2021 年、2020 年和 2019 年的 Java 趋势报告一样,我们将首先呈现 2024 年的内部主题图:
方便起见,下面是 2023 年的内部主题图:
Jakarta EE 11 计划于 2024 年 11 月发布 GA 版本,由于 16 个规范的积极开发,它进入了创新者(Innovators)类别。这些规范均已提交更新并于 2024 年早些时候通过了各自的审查。Jakarta EE 11-M4 于 2024 年 6 月发布,使得开发人员可以使用 Jakarta Security 4.0 、Jakarta Validation 3.1 和 Jakarta Data 1.0 等规范中新增的功能。因此,2022 年 9 月发布的 Jakarta EE 10、2020 年 12 月发布的 Jakarta EE 9 和 2019 年 9 月发布的 Jakarta EE 8 分别进入了早期采用者(Eerly Adapters)、早期多数(Early Majority)和后期多数(Late Majority)类别。
GraalPy 和 GraalWasm 也进入了创新者类别,因为随着 GraalVM for JDK 23 的发布,这两个由 GraalVM 赞助的项目现在都被认为是稳定的,适合用于生产工作负载。
随着 Spring 、Jakarta EE 和 Helidon 等越来越多的框架要求将 Java 21 作为基线,或支持 Java 21 并以 Java 17 为最低基线要求,Java 21 已转入早期采用者类别。因此,Java 17 被归入早期多数类别。
虚拟线程框架(Helidon Nima 和 Vert.x)也进入了早期采用者类别,因为 Helidon 和 Vert.x 等框架已在其最新版本中实现了虚拟线程服务器。
由于 Helidon 4.0 于 2023 年 10 月发布,支持虚拟线程,并采用了新的重新改造过的虚拟线程 Web 服务器,所以我们将 Helidon 移至早期多数类别。Helidon 3.0 和 2.0 版本序列仍支持其反应式服务器。
Scala 3 于 2021 年 5 月发布,由于 Scala 3 发布序列的开发缓慢,已被移至后期多数类别。
由于 Azul 和 BellSoft 已在各自的 OpenJDK 下游发行版中实现了检查点协调恢复(CRaC),所以 Fast JVM Startup (CRaC) 已被移至早期采用者类别。因此,Fast JVM Startup (GraalVM) 已转入早期多数类别。
以下是数位参与各种主题讨论的 InfoQ Java Queue 编辑和 Java Champions 的简单介绍:
Michael Redlich:Java Champion | Garden State Java 用户组总监 | Payara 合约开发人员大使和技术撰稿人 | InfoQ Java Queue 主编 | ExxonMobil 科技工程公司已退休高级研究技术员Ben Evans:Java Champion | Red Hat Runtimes 可观测性负责人和高级首席软件工程师 | InfoQ Java Queue 编辑A N M Bazlur Rahman:Java Champion | DNAstack 软件开发人员 | InfoQ Java Queue 编辑Holly Cummins:Java Champion | 红帽公司高级首席软件工程师Grace Jansen:Java Champion | IBM 开发人员大使Emily Jiang:Java Champion | IBM 开发人员大使、云原生架构师、 MicroProfile 和 CDI 自由架构师Ivar Grimstad:Java Champion | Eclipse 基金会 Jakarta EE 开发人员大使Andrea Peruffo:红帽公司 Keycloak 云原生分发首席软件工程师
我们还要感谢 Java Queue 的编辑们,他们为我们更新 2024 年的 “跨越鸿沟 ”模型提供了宝贵的建议:
Erik Coslow:Azul 产品管理高级总监 | InfoQ Java Queue 编辑Johan Janssen:ASML 软件架构师 | InfoQ Java Queue 编辑Karsten Silz:Java 高级全栈开发人员 | InfoQ Java Queue 编辑
对于我们在内部主题图中对某些技术所做的归类,这份摘要提供了更多的背景信息。
Grace Jansen/ Emily Jiang:毋庸置疑,AI 在去年发生了很大的变化,而且目前仍然是一个热门话题。现在,在应用程序开发过程中,Java 开发人员可以从各种工具和集成中获得的编码辅助越来越多。
Ivar Grimstad:AI 来了,并迅速成了大家的口头禅。2024 年头几个月的 “狂野西部 ”似乎已经稍稍平静了下来。高调的宣传依然存在,但我认为,我们已经看到了一种更加清醒的态度,即 AI 并不一定是可以解决一切问题的锤子。我们现在看到的是,Java 领域的工具、库和框架正在走向成熟。情况已经从 “哦,我必须换成 Python ”变成 “我仍然可以使用 Java 进行 AI 开发”。像 LangChain4j 这样的库无疑有助于改善开发体验。
Commonhaus 基金会是一个新成立的非营利组织(在 Devnexus 2024 大会上被介绍给 Java 社区),致力于开源库和框架的可持续发展,为自治开源项目提供继任规划和财政支持。
他们的使命是:
赋能由开发人员、贡献者和用户组成的多元化社区,使他们能够创建、维护和开发开源库和框架,通过共享管理和社区协作来确保社区的长期发展与稳定。
Commonhaus 基金会的创始人包括红帽公司杰出工程师 Erin Schnabel、Lumigo OpenTelemetry 架构师 Ken Finnigan 和 GitLab 高级技术营销经理 Cesar Saavedra,他们分别担任基金会的主席、秘书和财务主管。
Holly Cummins: 开源出现了一些有趣的动向。Java 生态系统中的一些著名项目已经从开源转向商业开源许可。但是,我们也看到了一种相反的趋势,即更多的领域变得更加开放。Commonhaus 基金会是一个全新的多项目开源基金会,我们去年还没有这个基金会。
Bazlur Rahman: 作为 Hibernate、Jackson、OpenRewrite 和 JBang 的忠实用户,我很高兴看到这些项目在 Commonhaus 基金会找到了新家。我相信,基金会将确保这些项目的长期维护和可持续发展。对于这些重要工具的持续发展和对我们开发工作的支持,我们更有信心了。我希望基金会对透明度和社区协作的承诺会营造出一个环境,让像我这样的开发者和贡献者都能够茁壮地成长。
Ben Evans:CommonHaus 基金会为如何建立开源基金会提供了一种新的模式,同时也为企业提供了一种方法,使其可以通过一个不依赖于任何供应商的基金会直接资助对其至关重要的项目。而且,该基金会拥有项目的知识产权,并且不能对项目使用的开源代码进行再许可。CH 基金会是面向云时代的开源组织——它认识到一些基础项目的重要性以及许多项目在资金方面面临的挑战。
Bazlur Rahman: 我注意到,Spring 6 和 Spring Boot 3+ 的采用率很高。在我们公司,几乎所有的应用程序都迁移到了 Spring Boot 3+。我感觉 Spring Boot 和 Quarkus 正在成为云原生应用程序开发的首选框架。
Ben Evans:Quarkus 的崛起显然是不可阻挡的,它在继续夺取 Spring Boot 的市场份额,并巩固了自己在微服务框架领域的第二把交椅。
Grace Jansen/ Emily Jiang: 在过去的一年中,人们更加关注如何改进 Java 以更好地满足现代应用程序的需求,包括提高云计算的性能和安全性。人们对检查点恢复技术(如 Liberty InstantOn、CRIU [Checkpoint Restore In Userspace] 和 CRaC)的兴趣与日俱增。这些技术有助于缩短 Java 的启动时间,使 Java 应用程序更适合云计算和无服务器计算。
此外,虚拟线程的引入为 Java 并发编程带来了令人兴奋的进步,但值得注意的是,这项工作仍在不断改进,在某些情况下仍面临着性能挑战。在安全性方面,我们很高兴地看到,有更多的 Java 加密模块通过了最新的 FIPS 140-3 标准认证,从而使 Java 能够更广泛地应用于受监管的行业。
此外,由于 Oracle JDK 17 的免费商业用途将于今年 9 月到期,客户必须转而订购 Oracle Java SE Universal 才能继续使用,而这无疑会影响成本。我们看到,人们对基于开源协作项目 OpenJDK 的 Java 替代品的兴趣和采用率都在不断提高。这方面的例子包括 IBM Semeru Runtimes for Java,它刚刚实现了最新的 FIPS 140-3 标准。事实上,Azul 已经表示,“ 70% 以上的受访者(在他们的 Java 现状调查中)正在考虑非 Oracle Java 替代方案”。对于这些许可变化将如何影响 Java 开源软件的持续发展和创新,我们将拭目以待。
Andrea Peruffo:Java 已经摆脱了缓慢和受遗留平台束缚的名声。在保持强大的向后兼容性和 Bug 修复能力的同时,Java 现在也有了明显的创新动力。人们不再怀有对破坏性更改的恐惧,因为现在已经有了一种均衡的方法,使得 Java 可以在不牺牲稳定性的情况下向前发展。此外,Java 正在增强与其他生态系统的兼容性,使其更容易与不同的语言和技术进行交互,从而提高了其灵活性和对开发人员的吸引力。
Bazlur Rahman: 尽管大多数公司仍在使用 Java 17,但 Java 21 的快速采用也是显而易见。不过,与前几年相比,现在似乎有更多的公司正在从较旧的 JDK 版本转向较新的版本。
Ben Evans:Java 17 不断取得突破,正在成为最受欢迎的 JDK ——越来越多的人将 Java 17 视为新基线。以前,项目开始时可能会将 Java 8 作为 “必须支持 ”的版本;现在,Java 17 越来越多地取代了这一角色。虚拟线程、新模式和后续功能正陆续到来(尽管这些目前还只是预览版)。
Bazlur Rahman: 在 Jakarta EE 领域,人们为采用 JDK 21 所做的努力不胜枚举。因此,人们对 Jakarta EE 11 也充满了期待。
Michael Redlich: 为了更新即将发布的 Jakarta EE 11 中的 16 个 Jakarta EE 规范,我们做了大量的工作,涉及众多升级和改进,其中包括:删除了对已过时类 SecurityManager 的引用,并增加了对 Java 记录的支持。
我期待着在 2024 年 7 月成立的 Jakarta EE 未来方向兴趣小组中代表花园州 Java 用户组,集思广益并开展相关研究,提出 “需要优先考虑的具体建议,及时提交给 Jakarta EE 和 MicroProfile 工作组,以把握市场的发展方向”。
Holly Cummins: 与其他地方一样,AI 成了许多讨论的主角。在 Java 世界中,我们应该如何利用它?我们编写的 Java 代码有多少可以由 AI 编写?我也听到了很多关于 Leyden 项目的讨论,因为它的架构很有趣,有可能对性能产生很大的影响。
Ivar Grimstad: 显然,关于 AI 的讨论仍然很多,既有技术层面上的,也有对开发人员的具体影响。目前,讨论更多的是如何利用这些新工具和技术,而不是像年初那样担心失去工作。
Andrea Peruffo: 与其他科技行业一样,Java 社区也对 AI 充满了期待。Java 不断适应并在 AI 领域寻找新的机遇。为了弥补差距,各种令人兴奋的工具不断涌现,使得在 Java 应用程序中使用 AI 更容易。凭借数十年的经验,Java 已做好应对未来挑战的充分准备,并在各种情况下保持其价值。
Bazlur Rahman: 由于许多公司已开始采用 JDK 21,所以虚拟线程在社区中仍然是热门话题。有大量的用户分享他们的用例。虽然绝大多数反馈是积极的,但也发现了一些需要注意的事项。例如,Netflix 在使用虚拟线程时遇到了类似死锁的情况。
Ben Evans: 对于 OpenTelemetry 如何不断发展壮大,并继续巩固其作为 Java 可观测性技术领导者的地位,我听到了很多相关的信息。
Michael Redlich: 在过去的一年中,Java 社区出现了一些值得关注的趋势,但我尤其喜欢 Decodable 软件工程师 Gunnar Morling 发起的 “十亿行挑战”(One Billion Row Challenge)。这项挑战的目的是编写一个 Java 程序,从世界各地的气象站检索温度测量值,并计算每个气象站的最低、最高和平均温度。数据存储在一个 10 亿行的文本文件中。在 164 个参赛作品 中,由甲骨文公司软件开发副总裁、GraalVM 创始人 Thomas Wuerthinger 领导的团队用时最快,仅 1.5 秒多一点。
Holly Cummins:LangChain4j 绝对令人兴奋。它意味着你不需要懂 Python 就能利用 AI,并且可以帮助每个 AI 提供商减少使用专有 API 所需的工作。
Grace Jansen/ Emily Jiang: 平台工程的兴起,以及 Java 开发人员开始使用内部开发平台(IDP)(如 Backstage 和 Red Hat Developer Hub),有助于简化应用程序的交付,并能通过减少认知负荷减轻开发人员的负担。我看到,有些项目还更进一步,为特定的运行时和框架提供 SaaS 项目,使交付过程变得更加简单,这真是令人兴奋。这有望减轻开发团队的压力,因为之前,软件开发生命周期中有越来越多的责任和任务压在了开发人员的肩上。
Ivar Grimstad:我认为,我们并没有预料到整个行业对 AI 的热情会如此高涨。突然之间,其他一切都不重要了。不过我相信,这种情况在今年下半年已经有所缓和。
Andrea Peruffo:Java 6 个月的发布周期比预期的要快很多,它打破了以往对变化的恐惧,引发了一股创新的浪潮。库和框架维护者摆脱了支持过时版本的义务,开始接受这种新模式并利用 Java 的新特性和改进。这在整个生态系统中建立起了更快的创新、反馈和前进的良性循环,同时也在必要时保持了稳定性。
Bazlur Rahman:虽然没有太多意料之外的发展,但我觉得,JDK 21 和虚拟线程的采用正在推动 Jakarta EE 社区更快地采用 JDK 21。
Ben Evans:JSpecify 1.0.0 将空值标记引入 Java 语言层,这是 Java 开发人员自古以来就一直要求的。我们终于可以完成始于 JSR 305(软件缺陷检测注解)的工作,并开始构建一条更好的、空值更安全的 Java 程序匝道。
OpenTelemetry Profiling 已进入实验阶段(尽管在细节上仍有许多问题)。
Redlich:这并不令人兴奋,但绝对出乎意料。许多开发人员似乎对 JEP 465(字符串模板,第三次预览)的突然撤消感到惊讶。在 JDK 21 和 JDK 22 中发布了两个预览版之后,JDK 23 对该特性的推进引发了很多讨论。但这也带来了意想不到的后果。感兴趣的话,可以在甲骨文公司 Java 开发人员大使 Nicolai Parlog 的 Java 内部新闻播报第 71 期中了解更多有关撤销该特性的原因。
Holly Cummins:使 Java 更为云友好的驱动力与提高 IT 可持续性的需求之间存在很多重叠。多做前期工作,少做运行时工作,既能提高速度,又能降低成本(双赢!)。像 Quarkus 这样的工具已经这样做了一段时间了,但我认为,生态系统的各个部分现在都已经开始采用这类设计。Leyden 项目就是这种架构转变的一个很好的例子。
我也喜欢一段时间以来,随着发布速度的加快,不断有小的可用性改进推出。这意味着我必须不断学习,但这是件好事。
Grace Jansen/ Emily Jiang:不管是作为一种开发工具(用于新的应用程序以及现有应用程序的现代化),还是在 Java 应用程序中集成,AI 的应用幅增都非常令人振奋。
大型语言模型(LLM)的开源以及 Java API 的规范化加快了这一进程,开发人员可以利用 Java API(包括 LangChain4j 这样的框架)将 AI 技术注入自己的应用程序。这里提供了一些很好的示例,展示如何在企业级 Java 应用程序中轻松地使用 LangChain4J 。我们还看到,可供 Java 开发人员使用的代码辅助工具越来越多,而且它们都集成了 AI 和 LLM。
此外,令人兴奋的是,我们还看到,这些技术被引入了像 Quarkus 这样的云原生 Java 框架和运行时,我们也开始在像 MicroProfile 这样的社区规范中看到了这一点,并且已经有一份建议规范 MicroProfile AI 。我们看到,社区正在协力演进这种编程模型,以便云原生应用可以轻松、高效地与 LLM 协同工作。
我们很高兴地看到,AI 正在变成帮助软件开发人员(而不是取代他们)开发并提高开发人员工作效率的有效工具。事实上,已有研究表明,使用生成式 AI ,软件开发人员完成编码任务的速度可提高一倍!我非常期待看到这一领域的进步和发展,并通过使用 AI 获得更多的优势。
Ivar Grimstad:我对 Java 的发展速度感到非常兴奋。我认为,六个月的发布周期所带来的益处不言而喻。Jakarta EE 已经有了起色,并且以一个相当可预测的节奏发布新版本,这也让我感到非常兴奋和自豪。Jakarta EE 10 的更新似乎相当不错,在业界,大多数人已经解决了 Jakarta EE 9 将命名空间从 javax.*改为jakarta.*所造成的混乱。
Andrea Peruffo:WebAssembly 终于在 Java 领域占据了一席之地,赶上了 Go 和 Rust 等生态系统。GraalWasm 现在已经可以投入生产,Chicory 正在准备发布其首个稳定版本。WebAssembly 快速、安全,并且实现了多语言嵌入,大大减少了对现有库和工具进行完全重写的需求。我相信,它很快就会成为一种 “无聊的技术”,每个人都会在不知不觉中使用它,就像 WebAssembly 如今在浏览器中的应用一样。利用快速发展的 WebAssembly 生态系统可以改变游戏规则,即使在通常由其他语言主导的领域,Java 也成了一个强有力的选择。我鼓励大家探索 WebAssembly 及其所带来的令人兴奋的新可能性!
Bazlur Rahman:关于特性,我对虚拟线程和模式匹配特别感兴趣,因此,我们正在积极使用 JDK 21。我们所有的生产应用程序都运行在 JDK 21 上。关于结构化并发的 JEP 正在进行第三次预览;我对它充满期待。
Michael Redlich:AI 出现在 Java 生态系统中令我兴奋不已。有一个人 AI 应用我特别喜欢。在这个应用中,我输入自己的名字,就会出现一个满头秀发的年轻人的漫画!我渴望了解更多有关大型语言模型的知识,并构建自己的 Java/Jakarta EE 人工智能应用程序。MicroProfile 和 / 或 Jakarta EE 工作组已经围绕 AI 相关的新规范进行了一些讨论。
Grace Jansen/ Emily Jiang:很高兴听到越来越多的 Java 社区内部加强合作的例子,在各种活动和会议中相互学习的机会也越来越常见。从 Java 社区的朋友那里,我听到了更多关于项目的消息。在这些项目中,我们能够将专业知识和学习结合起来,创建更好、更高效的共享标准和开源规范。
例如,在 MicroProfile Telemetry 2.0 中集成 OpenTelemetry 可观测性标准的工作是从跟踪开始的。现在,作为 MicroProfile 7.0 的一部分,已经扩展到度量,为 Java 开发人员提供了一种更简单的获取日志、跟踪和度量的方法。另一个很好的例子是 MicroProfile JWT Bridge 项目,它是 MicroProfile 和 Jakarta EE 工作组之间的合作项目。我期待未来可以听到更多这样的事情,帮助 Java 社区保持蓬勃发展的势头,并始终是众多应用程序的首选语言。
另一个经常被提起的话题是,AI 是否会取代软件开发人员。随着这项技术及其周边工具的进步和发展,越来越多的人担心它很快就会完全取代软件开发人员。虽然我认为这是一个超级令人兴奋的领域,而且已经做了很多工作来改进 AI 在软件开发中的应用,但我认为这种情况不会很快发生。相反,我认为 AI 是一种工具,可以帮助开发人员完成他们的工作。
请注意,撰稿人的观点只反映了故事的一部分。Java 生态系统中的不同群体、领域和地区可能会有不同的体验。这份 2024 年报告应被视为辩论的起点,而非定论。同时,它也是对行业发展方向进行公开讨论的邀请。
原文链接:
https://www.infoq.com/articles/java-trends-report-2024\\"
","description":"虽然 Java 17 是最常用的 JDK ,但它并没有占大多数。相反,根据 New Relic 2024 年 Java 生态系统现状的数据,Java 17-11-8 的比例分别为 35-33-29% 。我们需要明确的是,根据 New Relic 的“快速采用”数据,Java 21 的采用率仅为 1.4%,但这仍然快于 Java 8 以来的任何 LTS,不过仍然只占很小的比例。Java 平台现在已经摆脱了速度缓慢、受传统限制的名声,有了明显的创新动力。2024 年的头几个月,人工智能的 “狂野西部 ”已经平静了下来,但仍然是一个热门话题…","guid":"https://www.infoq.cn/article/EKLCiLj2wlk1mg6KOTI6","author":"作者:InfoQ 英文站","authorUrl":null,"authorAvatar":null,"publishedAt":"2025-01-20T08:00:00.993Z","media":[{"url":"https://static001.geekbang.org/wechat/images/a6/a6441284305a1b5f409b1546b04b7905.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/wechat/images/e5/e5a91f93ccb36840334109771e521322.jpg","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/wechat/images/2b/2b9220d9427d858aa0f6ad1263589058.png","type":"photo","width":0,"height":0,"blurhash":""}],"categories":["编程语言"],"attachments":null,"extra":null,"language":null},{"title":"成为 Functionless:如何培养无服务器思维以减少代码编写!","url":"https://www.infoq.cn/article/4T3b6sZhKKmaS7ekHDaC","content":"使用无服务器(Serverless)技术构建应用程序并不完全是为了各种目的以实现函数。过度使用与其他服务相结合的相互依赖的函数会导致架构变成一团乱麻。必须培养一种将函数视为代码负担的思维方式。尽可能地消除它们可以降低成本和复杂性。在某些用例中,函数并不是最适合的。在这种情况下评估和避免函数有助于构建架构良好的应用程序,从而优化成本和效率,并促进可持续性。在现代分布式和事件驱动系统中,业务逻辑并不总是被整合为函数。例如,服务编排非常适合处理分布式业务逻辑。
由云提供商运营和管理服务(称为全托管服务)并不是什么新鲜事了。例如,Amazon Simple Queue Service (SQS)和 Amazon Simple Storage Service (S3)是 AWS 提供的全托管服务,已有近二十年的历史了。
随着平台和基础设施以亚马逊网络服务(AWS)、微软 Azure、谷歌云平台(GCP)以及其他云提供商提供的服务的形式出现,促进了独立软件供应商(ISV)的增长,这些供应商以软件即服务(Software as a Service,SaaS)的形式提供多种产品。
尽管“无服务器”(serverless)这一术语出现在 2012 年——其灵感来自于不断发展的云环境以及 SaaS 应用程序如何消除拥有和管理物理硬件的需要,但它与现有的全托管云服务的关联并不明显。
虽然 SaaS 市场的增长推动了创新,但该行业在托管服务库中缺少一个关键部分——云上的全托管计算服务。2014 年,亚马逊发布了 AWS Lambda——云上的全托管计算服务,俗称函数即服务(Function as a Service,FaaS)——它彻底地改变了云计算行业,立即将无服务器提升到了一个新的高度!不久之后,微软和谷歌分别推出了他们自己的 FaaS 产品 Azure Functions 和 Google Cloud Functions。
作为业界的首个 FaaS 产品,AWS Lambda 迅速流行起来。因此,关于无服务器开发的多个案例研究、经验教训、模式和反模式都是围绕着 Lambda 函数展开的。因此,它的名字与本文中提到的一些早期行业思想联系在一起。然而,这些想法同样适用于每个 FaaS 产品。
随着 API 网关和来自头部云提供商托管服务的发布,世界开始接受了消费函数的计算逻辑。因此,无服务器革命变得势不可挡,FaaS 的过度使用也随之而来!
编程纯粹主义者通常不太关注非计算性托管云服务,认为这些服务是面向配置的,适用于基础设施工程师。然而,这些纯粹主义者现在配置了云计算服务,以探索函数背后的编程模型。
随着 FaaS 采用率的不断提高,云提供商增加了各种语言的运行时来满足不同的计算需求、技能等,为大多数程序员提供了一些东西。语言运行时,如 Java、.NET、Node.js、Python、Ruby、Go 等是最受欢迎且最被广泛采用的。然而,这也给采用无服务器技术的组织带来了一些挑战。这些挑战不仅仅是技术的挑战,更是工程师思维方式的挑战。
下面将重点介绍在无服务器应用程序中过度使用 FaaS 的一些副作用。
“如果你唯一的工具是锤子,那么所有的东西看起来都像是钉子。”——Abraham Maslow
编写 FaaS 函数对工程团队来说非常容易,可以快速实现业务逻辑和功能特性的发布,从而提高团队速度。这种新获得的名声和开发速度不可避免地创造了一种将一切都当作函数来处理的思维——这是解决所有业务问题的唯一解决方案。在 AWS 上,Lambda 函数被认为是解决所有问题的唯一方法。因此,我们称之为 Lambda 锤子(Lambda Hammer)!
工程师形成 Lambda 锤子思维的主要原因之一可以归因于他们的行业经验和编程能力。许多在非云环境中开发传统应用程序的工程师主要关注软件工程的编程方面。在这样的环境中,孤立的团队共同承担将应用程序投入生产或向客户发布功能的责任。开发人员(仅限于编程)根据架构师的愿景实现解决方案,由 QA 工程师进行测试,然后将其移交给平台或基础设施团队进行部署和运维。
当以编程为中心的工程师转向使用无服务器技术时,Lambda 编程模型和 FaaS 的概念自然就成了吸引他们的点——它们被认为是解决所有问题的工具!
在弹球游戏中,球被推进一个柜子里,在那里它会在各种各样的灯、保险杠、斜坡和其他障碍物上反弹起来。——维基百科。
Thoughtworks 最初提出了“Lambda 弹球架构”(Lambda Pinball Architecture)这一术语,是为了警告这样一种情况:相互依赖且纠缠在一起的 Lambda 函数以及 S3 存储桶和 SQS 队列等服务组成的网络,会导致请求在系统中四处传递反弹,从而导致形成一个复杂且分布式的单体应用程序,该应用程序难以测试和维护。
尽管 Thoughtworks 强调的是 Lambda 和其他 AWS 服务,但这种弹球情况也可能发生在 Azure、谷歌云和其他提供商身上。所有主要的云提供商都提供了具有类似功能的服务。因此,无服务器开发最佳实践是相关的,适用于所有人。
出现上述情况的原因是,在实现计算逻辑、数据摄取、数据转换、数据传输、服务中介和其他活动时采用了设计不佳的架构方法,没有明确的服务边界。长期处于弹球状态的可怕结果是会导致一种纠结的架构,即“无服务器泥球”,如图 1 所示。
图 1:纠缠在一起的无服务器架构
使用 FaaS 函数,你只需为执行付费(如果你不使用一些高级特性的话)。然而,实施超过必要的函数会增加你的云成本和总体拥有成本(TCO)。
对于大多数云提供商来说,一个函数的成本主要有两部分组成:
为调用该函数而向云服务发出的每个请求的价格完成每次调用的时间和分配的内存(RAM)
假设你的函数
分配了 1024 MB 内存每月调用 300 万次(每天 100,000 次调用)每次调用平均执行 10 毫秒(ms)
对于部署在欧洲中部地区的 AWS Lambda 函数,上述费用为每月 0.40 美元(含免费套餐限额)。对于在德国中西部地区运行具有上述配置的 Azure 函数,费用是相同的。
但是,如果该函数的平均执行时间为 10 秒(而不是 10 毫秒),那么 AWS Lambda 函数的每月成本将跃升至 493 美元,而 Azure 函数的成本将增至 474 美元。
现在,想想如果有几个这样的函数可以执行通过其他方式(即以无函数的方式)实现的非计算任务,可以节省多少成本!
注意 :上述 Lambda 成本是针对使用 x86 处理器的。如果换成 Arm 处理器,价格将降至 395 美元。
可持续性是现代云操作的一个关键方面。使用可再生能源、减少碳足迹和实现绿色能源目标是云提供商的首要任务。云提供商投资于高效的电力和冷却技术,并运营高效的服务器群,以实现更高的利用率。因此,AWS 建议使用托管服务进行高效的云操作,作为其架构良好的框架(Well-Architected Framework)的可持续性最佳实践的一部分。
作为服务消费者,你也需要对可持续性负责。因此,主要的云提供商已经制定了架构良好的可持续性最佳实践,以促进提供商和消费者之间共担责任。
虽然云提供商管理 FaaS 的资源以实现云的可持续性,但你也有同等的责任在云上可持续地运行这些函数。这包括:
以最优的方式利用多个函数优化每个函数的内存分配将性能优化到所需的水平,而不是使用最大化
当你为不合适的目的实现 FaaS 函数或以次优的方式运行时,你会间接影响云的三个核心元素:计算、存储和网络。每个元素的运行都会消耗能量。
“你写的所有代码都是业务逻辑”。——Werner Vogels 博士,亚马逊首席技术官。
作为一名软件工程师,你会在行业中听到类似的关于程序代码的陈述和争论。
“对于一个组织来说,代码是一种负担,而不是资产”。
“你今天写的代码明天就会成为遗产”。
“一家公司拥有的代码越多,它花在维护上的钱就越多,从而增加了 TCO”。
不管这些争论如何,我们都无法避免编写代码——无论是函数代码、数据代码、集成代码还是基础设施代码。然而,这里的重点是不必要的和不需要的函数代码。
如前所述,Lambda 锤子思维通常会驱使工程师实现一个函数,而不是一个可替代的云服务或特性。该函数现在成为了团队维护的不必要负担。
当你考虑一个函数时,不要只想着编写它的乐趣,还要考虑测试、CI/CD 流程、发布、观测和云帐户的并发限制等。
对于刚接触无服务器的工程师来说,让他们的思维适应无服务器的需求可能是一个挑战。因此,你会听到无服务器思维是采用无服务器的先决条件。这是因为使用无服务器需要一种新的思维方式,在云上开发和操作应用程序。你必须将无服务器应用程序视为与基础设施代码编织在一起的托管云服务的编排。
通常,工程师用编程的眼光看待无服务器环境,忽略了托管服务的功能以及相关人员的角色和职责。
在我与 Luke Hedger 合著的《AWS 上的无服务器开发》(“Serverless Development on AWS” O’Reilly, 2024)一书中,我们建议将无服务器技术视为一个包含云提供商、FaaS 和其他托管服务、工具、框架、工程师、利益相关者等的生态系统。这为技术带来了 社会技术思维,这对于使用现代技术和工程实践来说至关重要。
图 2:无服务器生态系统的视图
另一种看待它的方式是通过系统思维。Diana Montalion 的新书《学习系统思考》(“Learning Systems Thinking”O’Reilly, 2024)指出,系统是一组相互关联的硬件、软件、人员、组织和其他元素,它们相互作用和 / 或相互依存,以服务于共同的目的。
当你构建微服务时,根据你的领域和团队的有界上下文,正如我在 QCon 2024 上的演讲“The Set Piece Strategy”中所解释的那样,并非所有的服务都会执行需要函数的计算。正如你将会在下面学习到的,服务的业务逻辑可以通过原生集成和事件驱动的通信方式来进行编排并与其他服务协作。
快速流程团队寻求对事件的快速周转处理。对于这样的团队来说,少即是多。
现代产品团队是遵循流对齐的(正如团队拓扑所倡导的),并在快速迭代中自主开发和发布新功能和更新。无服务器是一项能够实现快速流的伟大技术。
当团队在云上操作他们的工作负载时,观测和修复生产中的问题是至关重要的。平衡正方形(The square of balance)是《AWS 上的无服务器开发》(“Serverless Development on AWS” O’Reilly, 2024)中使用的一个术语,用来解释测试、交付、观测和恢复这四个活动是如何成为实现平衡的关键的。
图 3:快速流动的无服务器平衡正方形
当无服务器团队在快节奏的开发环境中运行时,拥有最小的代码负担是有利的。它减少了潜在的错误和故障点,并将更多的责任转移给了云提供商。
在无服务器上下文中,“无函数”(Functionless)、“无 Lambda”(Lambda-less)、“无代码”(Codeless)、“低代码”(Low-Code)等术语表达了对通过原生服务集成来减少应用程序中 FaaS 函数数量的想法。
我第一次听说 Functionless 是在 2019 年赫尔辛基的无服务器日(Serverless Days)会议上。我意识到有必要让工程师了解一下过多函数的副作用,因此一直在社区中倡导,重申在可行的情况下消除函数的好处。
除了了解云计算的细微差别之外,构建和开发无服务器应用程序的一个关键部分是超越 FaaS 的思维,并记住函数是无服务器生态系统的一部分,而不是全部。
当企业决定使用云提供商的服务或供应商的产品时,就会引入某种形式的锁定。企业意识到了这一点,并有意识地选择与提供商建立稳定而友好的合作关系来发展业务,而不是频繁地更换产品、服务和提供商。
使用原生服务集成和特定于云平台的功能的确会增加依赖性。即使使函数的计算逻辑脱离特定的云平台,也很难做到完全独立。如上所述,一个函数必须与一个或多个云服务协作才能提供业务功能。当你专注于使函数不依赖于特定的云平台时,实际上你并未充分利用云计算的优势。如果企业选择了某个云提供商,然后又决定违背其核心利益,这是违反直觉的,会损害业务。
“简单胜过繁复的修饰。有时,简单的东西比高级或复杂的东西更好”。—— 来自网络。
虽然提倡简单很容易,但做到简单并不总是那么容易。它需要有处理复杂架构的经验和知识,以及对可以实践简单性领域的认识。
你在构建无服务器应用程序方面的经验使你能够从简单的角度看待架构。本节将研究可以使用模式来避免使用函数并使架构 Functionless 的领域。
无服务器社区的一条建议是:你应该使用函数来转换数据,而不是传输数据。如果你使用函数在服务之间移动数据,就说明你将它用在了错误的目的上,或者云提供商缺乏原生功能。
数据处理是云计算的核心部分,现代数据集的数量和增长率呈指数级增长。从成本和规模的角度来看,在这种情况下,不建议对每个数据操作都使用函数。因此,你应该设法将繁重的工作留给核心云服务。
在传统上,数据库主要是指关系型数据库系统(RDBMS),在较小程度上指代其他存储变体,如向量和图形数据存储等。然而,现在云上提供了多种数据存储选项,如关系型或 SQL、NoSQL、对象、图、向量、文档等。
除此之外,包含消息和事件摄取、缓冲和路由的服务还提供了临时存储。你可以对许多此类服务操作应用 Functionless 和原生操作,这也是你必须要在你的架构思维中加以考虑的。
许多工程师都有一种先入为主的思维模式,即认为需要使用函数来执行数据操作。有了这样的想法,函数就会悄悄地出现在它们没什么用的地方。函数通常用于传输数据的两个地方是 API 网关后端和工作流编排。
下面将介绍几种无需函数帮助即可处理数据操作的方法。
将 API 请求的有效负载存储在数据表中:图 4 显示了一个简单的无服务器模式,其中函数接收 API 请求的有效负载,例如一本新书的标题,并将其保存在表中。大多数 API 网关都提供了对传入数据的模式验证。验证通过后,你可以使用原生服务集成将 API 中的数据直接存储到表中。因此,中间的函数就没有必要了。
图 4:消除数据操作中不必要的函数
和上面一样,你可以从数据表中获取数据,然后将其作为 API 的响应负载发送,中间无需使用函数。
没有函数的原子数据计数器操作:例如,Amazon DynamoDB 没有像传统关系型数据库那样内置生成唯一序列号的功能。但是,这可以通过 DynamoDB 中的原子计数器概念实现,如图 5 所示。如果你有一个服务,需要为订单、客户注册、网站访问者等生成唯一值,就可以在 API 和 DynamoDB 表之间实现。
图 5:API 网关和 DynamoDB 表之间的原生服务集成,以生成序列号
{\\n \\"TableName\\": \\"sequence-numbers\\",\\n \\"Key\\": {\\n \\"id\\": {\\n \\"S\\": \\"visitor\\"\\n }\\n },\\n \\"ExpressionAttributeValues\\": {\\n \\":val\\": {\\n \\"N\\": \\"1\\"\\n }\\n },\\n \\"UpdateExpression\\": \\"ADD sequence :val\\",\\n \\"ReturnValues\\": \\"UPDATED_NEW\\"\\n}
执行原子计数器增量的 VTL 脚本示例。
缓冲大容量的 API 请求:另一个被广泛使用的案例是处理尖峰 API 请求并异步处理它们,如图 6 所示。在这种情况下,控制负载以保护下游系统至关重要。在 API 后面添加队列可以作为控制数据流的缓冲区。在这种情况下,数据在处理之前先被存储,这称为存储优先模式(Storage First pattern)。这种模式在其他数据存储中很常见。
图 6:在队列中缓冲的 API 请求用于异步处理
从数据库中清除过期数据的一种传统方法是在调度器上运行一个任务,以查询具有特定参数的数据并执行删除操作。根据数据量的不同,此类清理任务可能需要几分钟或几小时才能完成。
当工程师将上述经验引入到无服务器开发时,查询和删除数据的明显选择是使用一套专门构建的函数。然而,现代数据存储提供了免费且不影响性能的自动数据清除。选择这种原生特性可以避免实现函数。
例如,Amazon DynamoDB 可以选择为表中的每个数据项(记录)设置生存时间(TTL)。尽管某些删除可能长达 48 小时,但这也比你自己以编程的方式处理要高效得多。Azure Cosmos DB 还提供了一个类似的 TTL 功能来删除不需要的数据。
云上最受欢迎的对象存储 Amazon S3 支持数据存储桶的数据保留策略。借助数据保留策略,你可以让 S3 管理数据对象的生命周期,以删除过期对象或将其移动到归档或低成本存储中,以满足你的业务需求。
使用服务的原生特性对你使用的每个数据存储执行数据清理。除了处理的函数较少这一好处之外,这还为你的云操作带来了可持续性的好处。虽然数据是我们所做的一切的核心,但并非所有数据都是有价值的,或者某个点之后仍然是有价值的。因此,考虑数据生命周期对于删除不需要的数据、减少计算存储和网络使用至关重要。
API 实现包括执行典型操作的端点,例如在数据库系统中创建、读取、更新和删除(CRUD)数据,并与适当的 HTTP 方法保持一致。尽管每个 API 契约和调用类型(同步或异步)都可以归类为这四种不同的数据操作之一,但在现代分布式系统中,后端操作并不总是严格的 CRUD。
如前所述,当同步 API 获取新订单号时,它将会执行原子数据操作。但是,在异步调用中,行为不必相同。例如,当客户下订单时,来自多个业务领域的多个团队拥有和运营的一个或多个服务将协同来完成请求。在这种情况下,并非各个服务内部或跨各种服务的每个活动都需要是原子性的。
从模块化和可扩展性的角度来看,由与多个服务交互以协调任务组成的复杂逻辑单体函数并不是一个理想的解决方案。在这种情况下,服务编排是一种值得考虑的恰当设计模式。服务工作流不再是一个函数,而是成为后端编排器,如图 7 所示。AWS Step Functions 和 Azure Logic Apps 等云服务是目前可用的流行工作流编排器。
图 7:启动异步操作并处理 API 请求的工作流
流行的全托管云服务可以采集和交付事件,提供了与许多其他服务的原生集成。事件过滤、转换、归档和向多个目的地传递交付是这些服务的一些核心特性,它们消除了对自定义函数的需求。
Amazon EventBridge、 Azure EventGrid、 Google Cloud Pub/Sub 等云服务,都提供了事件传输功能,并充当事件代理,以松耦合的事件驱动的通信方式轻松地与多个应用程序协调。
使用云服务的一个主要动机是将尽可能多的工作委托给云提供商。在这方面,减少不必要的函数代码的原生服务集成必须是构建无服务器和云应用程序时的一个因素。
然而,在培养 Functionless 思维的同时,同样重要的是要意识到它的一些局限性和权衡,如下所示。
大多数原生服务集成都是黑盒的,在运行时无法看到集成的代码。这可能会使调试缺陷变得更具挑战性。例如,在 AWS 中,集成代码是使用 Velocity 模板语言(VTL) 编写的。由于 VTL 的语法不同于我们熟悉的编程语言,学习和熟悉它需要时间。尽管 API 网关和托管服务支持与多个云服务的原生集成,但每个目标服务的集成格式并不统一。了解源和目标服务之间允许的数据有效负载大小的差异对于防止处理失败至关重要。与有效负载的大小一样,集成服务之间的服务超时和节流限制也可能不同。有时,你可能需要一个函数来执行非功能性操作,例如对部分请求上下文数据进行安全检查。
“改变的第一步是意识。第二步是接受”。——Nathaniel Branden。
作为云计算的演变,无服务器技术使组织能够通过消除不必要的服务器和硬件管理负担来快速增加价值。然而,在使用无服务器技术构建应用程序时,你必须继续探索简化架构和运维开销的方法。
想通过本文来捕获每一个减少 FaaS 占用的用例是不可能的。它旨在提高人们的意识。根据行业反馈,新采用的无服务器团队可能会犯下代价高昂的架构和实施错误。虽然这在某种程度上是可以理解的,但动机应该是从一开始就采用恰当的模式和原则来避免这种错误。
一刀切的方法并不适合所有人。业务领域和用例因团队而异。在实施模式(无函数或其他模式)时,你必须首先分析其适用性。当了解了各种可能性之后,你就可以采取必要的措施来简化你的架构了。
Sheen Brisals 是独立顾问、AWS 无服务器英雄、团队拓扑倡导者,也是《AWS 上的无服务器开发:构建企业级无服务器解决方案》(O’Reilly,2024)的合著者。作为一名技术专家,Sheen 曾在领先的软件组织担任过多个职位。他的想法帮助了多个团队和组织走上云和无服务器采用之路。他是一位主题演讲者,住在英国伦敦的郊外。
原文链接:
https://www.infoq.com/articles/functionless-serverless-mindset/\\"
","description":"本文要点 使用无服务器(Serverless)技术构建应用程序并不完全是为了各种目的以实现函数。过度使用与其他服务相结合的相互依赖的函数会导致架构变成一团乱麻。必须培养一种将函数视为代码负担的思维方式。尽可能地消除它们可以降低成本和复杂性。在某些用例中,函数并不是最适合的。在这种情况下评估和避免函数有助于构建架构良好的应用程序,从而优化成本和效率,并促进可持续性。在现代分布式和事件驱动系统中,业务逻辑并不总是被整合为函数。例如,服务编排非常适合处理分布式业务逻辑。\\n\\n由云提供商运营和管理服务(称为全托管服务)并不是什么新鲜事了。例如,Amazon Simple…","guid":"https://www.infoq.cn/article/4T3b6sZhKKmaS7ekHDaC","author":"作者:Sheen Brisals In","authorUrl":null,"authorAvatar":null,"publishedAt":"2025-01-17T03:30:00.251Z","media":[{"url":"https://static001.geekbang.org/wechat/images/48/4883eae0ede6eaaa4081c45b447368ec.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/wechat/images/46/46796a49821e6c818b0133fd3f087d88.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/wechat/images/6a/6ae6a25f1985663f06341149008386d2.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/wechat/images/b4/b4026f52efe971189371857d1900a10d.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/wechat/images/44/445978c86707f182ae981625f2aab755.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/wechat/images/e1/e1af62b27fee9c7d5b763713f0f83af3.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/wechat/images/fb/fb1d9577a9417c3ad514d03ad656a12b.png","type":"photo","width":0,"height":0,"blurhash":""}],"categories":["编程语言"],"attachments":null,"extra":null,"language":null},{"title":"从 Linux 内核隔离到 Java 透明协程,快手系统软件技术架构演进之路","url":"https://www.infoq.cn/article/F7gMOzFQLKc16RWjkV3x","content":"作者 | 快手系统软件负责人 熊刚
系统软件作为软件架构的基石,发挥着承上启下的关键作用。快手系统软件团队经过四年的探索与实践,成功积累了一系列创新技术与性能优化方法论,这些成果广泛涵盖 Java 协程、编译器优化、操作系统改进等多个关键领域。本篇作为系列文章的开篇,将为您勾勒出快手系统软件团队的整体风貌与成果概览,而后续的篇章则会针对各个重点方向逐一展开,进行深入而详尽的解析。
系统软件作为软件架构的基石,扮演着连接软件与硬件的桥梁角色,位于整个软件生态的最底层,处于关键核心的位置。系统软件最为显著的特征在于其规模效应,随着服务器体量的增加,系统软件研发的价值愈发凸显。
首先,系统软件技术能够显著提升服务器资源的利用率,实现翻倍效果,同时性能也能提升 30%~50%,从而大幅降低公司的服务器资源成本。其次,专业的系统软件团队能够迅速定位并解决底层技术问题,避免小故障累积成大故障,确保业务稳定运行,降低潜在风险。此外,系统软件还扮演着桥梁的角色,推动着服务器和上层软件的架构持续演进与创新,为公司的技术发展注入源源不断的动力。
然而,随着规模的扩大,系统软件研发也面临着更为严格的挑战和约束条件。特别是在快手这样的背景下,挑战尤为突出。一方面,系统软件团队需要具备深厚的技术底蕴,不仅要深入到底层软件和硬件领域,还要理解上层平台以及业务逻辑,才能与业务团队保持同频共振。另一方面,与行业内的大型企业相比,快手在系统软件研发上的人力和物力投入相对有限。因此,快手需要更加精准地识别并解决公司面临的关键技术问题,在解决关键问题上做到极致,不追求大而全。同时,快手需要站在巨人肩膀上,基于巨人创新突破,避免重复造轮子。
最后,在技术推广方面,快手也面临着不小的挑战。如何将底层技术成果有效地推广至全公司,是一个亟待解决的问题。这需要快手以公司和行业的成本效益战略为指导,紧密结合业务的实际需求,实现与业务的共赢。同时,快手需要降低技术推广的成本,甚至实现对业务的透明化,确保新技术的引入不会给业务带来稳定性和安全方面的隐患。在此基础上,快手还需要保持技术的先进性,不断推动系统软件的创新与发展,为公司的长远发展提供坚实的技术支撑。
自 2020 年初起,快手系统软件技术团队开始进行自研技术的探索,凭借对业务场景需求的深刻洞察及技术趋势的精准预判,成功构建了一套独特的“四横四竖”架构的系统软件技术体系。若将软件体系比作一棵参天大树,系统软件无疑是深植于土壤中的“树根”,它位于软件架构的最底层,既连接着硬件资源,又支撑着上层软件,发挥着承上启下的关键作用。向下做好资源管理和抽象,向上高效、稳定、安全支撑好平台和业务。因此,掌握系统软件技术对于技术人员而言,不仅是深入技术根基的必经之路,也是实现个人持续成长的重要阶梯。
快手的系统软件技术涵盖了操作系统、编译构建、运行时(JVM)、系统诊断、系统观测等多个方向,每一环节都至关重要。其中,操作系统作为最基础和核心的软件,更是我国亟待突破的关键核心技术之一。
最上层是 Java 运行底座——JVM,它为 Java 应用提供稳定高效的运行环境,是 Java 生态中不可或缺的一环。紧接着是编译系统层,主要聚焦于 C++ 构建系统与编译技术,确保代码的高效编译与优化。再往下则是操作系统层,作为系统软件的核心组成部分,它负责资源管理、任务调度等关键功能,是保障系统稳定运行的基础。而位于最底层的微架构层,涵盖了 CPU 微架构与 GPU 微架构,这一层直接决定了硬件的性能发挥,是技术大树深植土壤的根基所在。
Java 作为快手第一大语言,占有资源在千万核级别。面对 JDK 社区日新月异的发展,尽管新版本在稳定性、性能和功能方面不断优化,但直接使用开源版本在快手的实际应用场景中仍可能遭遇稳定性和性能瓶颈,阻碍了其在生产环境中的广泛应用。同时,快手正积极研发契合自身业务需求的 JVM 特性,这些特性亟需与上游 JDK 社区实现深度整合。鉴于此,快手组建专业的 JVM 团队显得尤为迫切。
在自研 JVM 的道路上,快手并非从零开始,而是站在巨人的肩膀上,吸取社区、行业新能力的基础上,进行自主创新。
在实践中,快手发现成本优化能全局统筹稳定性、性能和易用性这三个维度,符合公司降本增效的战略。为了极致提升单实例性能,我们从 IPC(每周期指令数)、利用率和复杂度降低三个维度入手。同时,为扩大其应用规模,需深入研究各类场景发生的小概率事件,确保 JVM 的稳定性和易用性。
近年来,快手在 JVM 领域取得了不少先进的技术成果。作为行业内首个将 Java 17 超大规模上线的公司,快手还最早大规模应用了 ISA-L 和弹性内存技术,并研发了首个 Java 17 透明协程和 JVM Checkpoint 技术等。
对于编程开发者,传统线程模型逻辑直观但性能受限,而异步模型虽性能高却复杂性大。协程以“同步编程,异步执行”平衡两者,成为现代语言标配。在阿里的 Wisp 协程基础上,我们进行了两大核心优化:一是重构协程调度,通过引入了就近调度、延迟睡眠、LIFO 策略、延迟满足以及线程复用等多种优化手段确保低负载工况下协程的高效执行,解决了低负载场景下利用率高的问题,使协程的覆盖率大幅提升。经此优化,快手协程在低负载工况下的 CPU 指标不仅解决了利用率比线程高 10% 的问题,甚至还优于传统线程模型 14%。二是通过协程队列与载体线程的分离技术,解决了 JNI(Java Native Interface)执行时间长导致的业务延时过长问题,进一步扩大了协程的适用场景。
从这两个问题的解决来看,为了做到上层无感知,JVM 需要处理很多复杂的场景,实际上将复杂度下沉到 JVM 层面,真正做到复杂留给自己,简单留给用户。此外,虽说系统软件有比较好的规模效应,但绝不是简单的复制,比如这里提到大规模落地需要解决很多小规模场景不用解决的问题,另外在扩量的过程中,一些小概率问题变成必然问题,例如在我们所面对的场景中,哪怕是十万分之一概率出现的问题,也需要修复打磨好,这对技术能力提出了极致的要求。
近期,我们在研发另一项有趣且极具挑战性的技术——JVM Checkpoint。这项技术能将 JVM 内部的 CodeCache、Metaspace 等数据快照保存到远程,下次 JVM 启动可以直接拉起快照,快速运行。从实际应用效果来看,在启用 Checkpoint 之前,启动时间需要 150s,而启用后,启动时间大幅度缩减至 80 秒,启动速度提升了近一半。此外,启动阶段利用率能从 23% 降低到 5%。这项技术将能大幅度提升应用启动速度,增加弹性能力,大幅减少回滚时间,也能节省启动阶段资源预留成本。值得一提的是,快手系统软件团队始终坚持做难而正确的事,我们提前 1-2 年进行技术规划和储备,以确保我们的技术始终走在行业的前沿。
编译器领域的核心使命是为公司提供高性能、稳定、安全且易用的编译技术,其中快手的主要承载产品是 KBuild。KBuild 助力快手大部分业务编译构建,其价值体现在四方面:研发效率上,通过分布式和缓存技术,KBuild 将 C++ 工程编译时间从超 1 小时缩短至 5 分钟内,大幅提升团队效率;稳定性上,通过灰度发布控制基础组件,减少代码变更引发的稳定性问题;代码质量上,配备静态扫描机制,发现开发 Review 阶段难以察觉的问题。性能优化方面,通过编译优化技术降低服务器用量,优化延时提升用户体验。
快手的 C++ 编译优化技术涵盖整个流程,包括编译期参数调优、AutoFDO、链接期 LTO 优化、链接后 BOLT 优化及基础库的 SIMD、高性能 Protobuf、JSON 优化等。这些技术不仅应用开源工具,更根据实际需求深度改造。例如,为解决 LTO 技术增加编译时间的问题,快手引入分布式集群编译和编译缓存技术,使编译时间仅秒级增长。BOLT 作为一项先进的链接后优化技术,其核心优势在于通过分析线上运行程序的 perf 数据来优化二进制文件。而 AutoFDO 则基于采集的 profile 数据在编译期进行优化,两者在多个场景下可以协同工作以提升性能。然而,在快手实际落地过程中,我们遇到了一个挑战:当尝试将 BOLT 与 AutoFDO 合并使用时,由于 AutoFDO 会导致二进制文件发生变化,使得为 BOLT 准备的 profile 数据失效,从而无法充分发挥两者的优化效果。为了解决这一问题,快手团队深入研究了最新的 Match+Infer 方案,并成功在公司的一个业务服务上进行了验证。结果显示,采用该方案后,优化效果从单独使用 BOLT 时的 8% 提升至了 12%(即 AutoFDO+BOLT 的组合优化效果)。
快手已大规模应用这些编译优化技术,整体性能提升了 10%~13%,同时延时降低了 4%~8%,不仅降低了成本,还在业务效果和用户体验上产生了显著收益。
快手工程师开发的 C++、Java、Python、Go 程序均运行在其自研内核上,该内核针对云原生场景进行了深度定制,包括内核隔离、GPU 虚拟化等特性。为确保 OS 的稳定性,快手建设了一系列工具,如自动化测试框架,以提高问题定位和修复效率。同时,针对新硬件如不同品牌的 CPU 和 GPU 的引入,内核也进行了大量适配,以支撑新硬件的演进。此外,由于 CentOS 停服,快手也自研 KwaiOS 来作为替代。
在当前环境下,为最大化资源利用和控制成本,我们期望在同一台机器上同时部署在线和离线业务。然而,这种高密度部署虽提高了资源利用率,却加剧了业务间的干扰,特别是在线业务易受抖动影响,威胁其可用性。为解决此问题,我们在操作系统内核层面加强了隔离。基于行业方案进行重构,我们将调度树拆分为在线和离线两棵,核内调度时优先在线业务,确保在线可绝对抢占离线资源,减少了离线对在线的干扰。但在推广搜等内存瓶颈突出、延时敏感的业务中,我们面临新的挑战。为此,我们推出快手 2.0 阶段的 CPU 调度策略优化方案,引入双队列,将在线和离线的负载均衡彻底分开,在整个物理机层面先调度在线,进一步降低离线对在线的干扰。上线调度 QoS 后,在线业务调度延时大幅下降。
上述 QoS 调度是内核隔离技术体系的关键一环,我们共研发了 15 种隔离能力,其中 7 项源自社区和阿里,8 项针对快手场景进行了重构和优化。我们还在研发 LLC 隔离和 CoreFirst 调度能力,实现极端敏感场景下的在线无感混部,做到几乎任意业务都具备在离混部的能力。采用这 10 多项内核隔离技术后,整机利用率在符合业务 SLO 标准下翻倍提升。然而,提升容器云整体利用率还需在集群层面努力,如统一调度、资源合池、运营治理等,这是一个庞大体系化工程,而内核隔离是基础和前置条件。目前,快手通用在线混部集群在规模和日均利用率上均达行业领先水平。
随着智算时代的到来,快手研发了 GPU 虚拟化技术,可将单张物理 GPU 卡虚拟为多张虚拟卡,支持多在线业务或在线与离线业务的混合部署,提升 GPU 利用率且对业务无影响。同时,鉴于内存成本上升及内存容量成为多业务场景的瓶颈,系统软件层面亦研发了 JVM 弹性内存和内核冷热内存技术,通过冷热分级和压缩下沉冷数据至低成本设备(如 ZRAM、SSD、云盘),实现整机内存节省超 20%。
系统诊断与微架构是快手系统软件比较有特色的地方。系统诊断团队专注于保障公司数十万台服务器的稳定运行,解决宕机、夯机及干扰等稳定性难题,无论是单机故障还是系统级复杂问题,均承担最终兜底责任。微架构团队深挖 CPU/GPU 微架构潜力,优化硬件性能。例如,针对 AMD CPU 在某些场景下性能优于 Intel 但早期表现不佳的情况,团队通过 NUMA/SubNUMA 技术优化,使 AMD 性能提升 20%~30%,成功推动数万台 AMD 服务器大规模部署。此外,采用大页技术(THP)减少 TLB miss,加速内存访问,性能提升 6%~10%,有效优化内存延时,解决内存墙问题。
快手系统软件常用的 CPU 性能优化方法论如下,其核心目标是在确保符合 SLO 的前提上,最大化提升单机吞吐能力(对于在线服务而言,通常体现为 QPS 的提升)。这一优化过程在三个维度发力:利用率提升让程序跑得更满,比如前面提到的协程和在离线混部就是这个维度;在 IPC 提升维度,比如前面提到的通过微架构优化能提升 IPC;另外复杂度降低维度,比如业务做的简化架构、请求合并、无用逻辑删除等等都是这个维度。
今年我们协助业务优化了一个看似简单的 size 函数,该函数仅占两行代码,却消耗了整体 8.4% 的 CPU。从算法复杂度看难以理解,但从微架构视角分析,其 cache 命中率极低,大部分时间用于从内存加载数据,即遇到内存墙问题。使用 prefetch 因数据地址无规律而无效。随后,我们从功能模块整体出发,增强乱序执行能力,降低数据依赖粒度,提升 CPU 乱序执行概率,最终使功能模块性能提升 30%,size 函数 CPU 占比降至 2.5% 左右。结合 BOLT、LTO 编译技术及 THP(透明大页)等,整体性能翻倍,节省数千台服务器资源。
在过去四年里,系统软件团队实现了从 0 到 1 的突破性演进,为快手带来了众多高价值的技术成果。尽管篇幅所限,许多精彩的技术细节未能详尽展现,但我们依然热忱地邀请您莅临快手,与我们深入交流探讨。系统软件技术团队汇聚了一群对技术充满热爱、敢于挑战自我的新老伙伴。他们与快手共同成长,不仅为公司创造了卓越的技术价值,也在个人成长的道路上不断前行。
如今,系统软件团队仍在持续进化,我们渴望吸纳更多有志于技术创新的人才加入,共同为公司的繁荣发展贡献智慧与力量。
如果您对我们的技术充满好奇,或者渴望与我们进行深度的技术交流,请随时联系我们(xionggang@kuaishou.com)。我们期待着与您携手共进,共同开创技术新篇章!
今日好文推荐
2025 年铁了心不再招软件工程师?!这位 15 岁就开公司、25 年创上万亿市值的巨头 CEO 再放“狂言”\\"
苹果监听实锤!一群人打了5年官司赢近7亿赔偿,但用户连200块都拿不到?\\"
刚刚过去的一年 GitHub 刷星大爆发?!450 万假 Star,项目风光仅撑 2 个月!\\"
","description":"作者 | 快手系统软件负责人 熊刚 系统软件作为软件架构的基石,发挥着承上启下的关键作用。快手系统软件团队经过四年的探索与实践,成功积累了一系列创新技术与性能优化方法论,这些成果广泛涵盖 Java 协程、编译器优化、操作系统改进等多个关键领域。本篇作为系列文章的开篇,将为您勾勒出快手系统软件团队的整体风貌与成果概览,而后续的篇章则会针对各个重点方向逐一展开,进行深入而详尽的解析。\\n\\n1 系统软件技术的核心价值与面临挑战\\n\\n系统软件作为软件架构的基石,扮演着连接软件与硬件的桥梁角色,位于整个软件生态的最底层,处于关键核心的位置。系统软件最为显著的特征在于其规模效应…","guid":"https://www.infoq.cn/article/F7gMOzFQLKc16RWjkV3x","author":"熊刚","authorUrl":null,"authorAvatar":null,"publishedAt":"2025-01-16T10:58:14.212Z","media":[{"url":"https://static001.geekbang.org/wechat/images/2a/2a564f5824737f02dbe97e695ccc1c76","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/wechat/images/5f/5ff07f7e6dfc276f9f3927f9964b0827","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/wechat/images/d7/d779a6223989511677999de75eb51508","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/wechat/images/ba/baaea23b2c441bd088933ebbbc105c71","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/wechat/images/69/69a7129376e54270600333f6e0ca1dbb","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/wechat/images/ab/ab26277d5762a4ee3d88ddd1b8b97d0a","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/wechat/images/94/945cb36bf92c9c7b9ca2a3aef4070866","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/wechat/images/80/80db0c2c7c26018c9c27eaad9cca43c8","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/wechat/images/de/de2a7abe974abfe0eb5de2075fca06a6","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/wechat/images/2d/2d0b1f6d6bee3a0d2a0a187ee7554af6","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/wechat/images/75/75f2fd3a2438666edf9eec50f306887f","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/wechat/images/36/368c0a098fd088beab82b1446463f055","type":"photo","width":0,"height":0,"blurhash":""}],"categories":["编程语言"],"attachments":null,"extra":null,"language":null},{"title":"薪资天花板语言Zig出神作!HashiCorp大神新作刷屏编程圈,Redis之父直呼真香!","url":"https://www.infoq.cn/article/FaGd0phA2La7N8zJs5Js","content":"最近,一款用 Zig 编写的终端模拟器正式发布了 1.0 版本。
Ghostty 自上线以来便迅速引发广泛关注,不仅因为其创始人 Mitchell Hashimoto 的背景,更因其卓越的品质让长期沉寂的终端模拟器领域焕发新机。作为 HashiCorp 的联合创始人,Hashimoto 在打造公司标志性产品(如 Terraform、Vagrant、Packer 和 Nomad)中发挥了至关重要的作用。这些工具已成为全球 DevOps 专业人士的核心利器。
这款应用是免费开源软件,基于 MIT 许可证发布,旨在为大多数用户提供开箱即用的体验,无需额外配置。Ghostty 采用 Zig 编写,支持 GPU 加速,支持跨平台运行,发布时即可在 Mac 和 Linux 系统上使用。
在支持跨平台时,Ghostty在 Linux 和 macOS 上都使用了各自平台的 GUI 构建,macOS 是基于 SwiftUI,而 Linux 是基于Zig和GTK。
Redis 之父antirez也对Ghostty 1.0 赞不绝口:“这将是一款改变游戏规则的工具。我刚在处理 Redis 的一些工作,输出了大量的调试信息和结果。通常情况下,终端会成为瓶颈,但这个工具却能在瞬间打印出50万条结果。而且,我还能在历史记录中快速回溯,性能丝毫没有下降。我太喜欢这个了!对于系统开发来说,这真的是一个巨大的提升。”
试用了 Ghostty 10 分钟,感觉 Emacs 可以退休了。
至于为什么选择Zig语言来编写,Mitchell Hashimoto非常简单直接地说:“选择Zig就是因为我喜欢它!它的语言特性非常适合这个终端项目。”
Mitchell Hashimoto 早在 2021 年底或 2022 年初就对 Zig 表现出了浓厚的兴趣。当时,他在推特上分享了自己对这门语言的好奇,但由于繁忙的工作,一直未能深入研究。然而,Zig 一直在他的脑海中挥之不去。
“背景上来说,我曾是一名专业的 C 程序员,大概干了一到两年的时间。我喜欢底层系统开发,其实我也喜欢 C。实际上,HashiCorp 的所有软件差点就用 C 写了,当时是在 C 和 Go 之间抉择,最终 Go 赢了,但我们非常接近选用 C。我想重回系统编程领域,但我也清楚 C 的各种缺陷,所以一直在寻找一种‘更好的 C’。对我来说,Zig 从一开始就像是这样的语言。在使用 Zig 几年后,我的感受依然如初,甚至更好了。写 Zig 代码每天都让我感到愉悦…… 这就是关键。”
关于为何未选择 Rust,Mitchell Hashimoto 明确表示:“我对 Rust 的使用已有足够经验,也因此知道自己不想每天都写 Rust。从哲学和技术成就的角度而言,我对 Rust 非常敬佩,认为它极其出色。然而,从个人体验来看,这种感受却显得较为表面化。当我在编写或阅读 Rust 代码时,并未感受到乐趣。而对我来说,开发的过程应该是有趣的,写代码本身就是一种快乐……这完全是一种风格上的选择。”
与大多数其他编程语言不同,Zig 实现了与现有 C 代码的真正无缝互操作性。这样的兼容性极为重要。正如 Zig 软件基金会社区副总裁 Loris Cro 所解释的那样:“Zig 基本上对传统编程基础设施进行了彻底革新,打破了过去 40 年间无人敢触碰的诸多惯例。C 和 C++ 是久负盛名的编程语言,也是开发工作的核心语言,它们能够完全控制硬件。然而,这些语言的工具链却问题重重。”Zig 则允许用户继承这些核心语言的功能,同时提供与之兼容、更强大的工具链和完善的功能集。
同时,他还指出,Zig 也解决了传统 C/C++ 开发中面临的一个核心问题:跨平台编译的难题。举个例子,如果我们正在开发一款小型独立游戏,并希望将成果交付给 Mac 平台的用户,问题就来了。将游戏代码从 Windows 编译到 Mac 一直是个非常棘手的过程。但有了 Zig,无论是 Zig、C 还是 C++ 编写的代码,甚至是混合编写的代码,Zig 都能确保顺利进行跨平台编译,支持 macOS 或 Linux 平台,并且效果十分优秀。
Zig是一门新兴编程语言,而Ghostty的爆火,也让它成为了Zig编程语言的代言人之一。
除Ghostty外,还有两家采用Zig的初创公司——Bun与Tiger Beetle,它们都对Zig寄予厚望。Bun正在开发Node.js的同类竞争方案;而Tiger Beetle则希望构建一套分布式金融数据库,其高度依赖于对资源的精确控制。另外,Uber也使用Zig(并非作为主要语言)为C和C++代码构建工具链,希望借此发挥Zig卓越的编译功能优势。
还值得一提的事情是,根据2024年的 Stack Overflow 调查,Zig 是该年度薪资最高的编程语言。这项调查涵盖了来自 185 个国家的 89,184 名软件开发人员,结果显示 Zig 开发人员的平均年薪达到 103,000 美元。Zig因此也一炮而红、迅速吸引到更多开发者关注。
接受调查的开发人员中,只有 0.83%表示他们精通 Zig,这凸显了它在人才库中相对不为人知和稀缺性。
也许也正是因为这种稀缺性,再加上对高性能系统编程的不断增长的需求,可能导致了 Zig 开发人员的薪酬数字相当可观。
创始人Andrew Kelley对Zig的未来有着清晰的愿景:他希望Zig能成为C语言的接班人。
Andrew深入研究了C语言的底层设计,发现许多我们习以为常的语言特性背后,其设计初衷并不总是最合理的。这种洞察促使他从根源上重新审视编程语言的设计。他认为,Zig不应该仅仅是C语言的升级版,而应该是一门从底层逻辑上就与众不同的语言。
Andrew提出了“全局最大化”的概念,即在设计语言时,要着眼于整体的最佳状态,而不是仅仅追求局部的优化。他认为,C语言的一些设计选择虽然在当时看来是合理的,但从长远来看却限制了语言的发展。Zig的目标是打破这些限制,构建一个更具可扩展性和适应性的编程语言。
为了实现这一目标,Zig团队对C语言的许多传统概念进行了重新审视。例如,他们彻底摒弃了预处理器和宏,这些在C语言中被广泛使用的特性。这种看似激进的决定,实际上是为了让语言的设计更加简洁、一致。事实证明,它的内存分配机制不仅比C更加直观,甚至在性能上也有所超越。
Zig的设计理念,无疑是对C语言的一场根本性变革。
Andrew 总是对编程语言背后的原理刨根问底。他不断挑战着 C 语言的一些根深蒂固的惯例,比如“为什么用 #define 而不用常量?”。许多程序员可能习惯了这么做,但很少有人去思考其中的缘由。Andrew 指出,这种设计其实是有问题的,因为在某些情况下,使用常量会触发编译错误,而这本不该发生。
在 Zig 中,他纠正了这些问题,“我们只是修复了问题,让该用常量的地方可以使用常量。就这么简单,这也是Zig的特色所在。”通过这样的设计理念,Andrew发现通过修复C中不合逻辑的种种细节,预处理器完全可以被直接跳过。相反,Zig选择使用条件编译。这也是Zig和C之间的关键差别:对于Zig来说,if语句的条件在编译过程中是否已知才是重点。如果if语句的死分支中存在编译错误,则不会对其进行评估。
正因为如此,Zig才能够放弃一部分C语言特性,但同时继续保持(甚至优化)可用性、安全性和运行速度。正是由于依托不同于以往的设计理念,Zig的调整也带来了新的开发思路。
Zig最初的诞生是为了“填补C语言的空白”,但随着项目的深入,它逐渐成长为一个功能更加强大、灵活的编程工具。尤其在内存管理方面,Zig展现出了独特的优势。
这门语言采用不同于以往的内存分配方法:Zig中没有全局分配器;相反,如果需要内存,则会传递自定义分配器,因此其能够在无法使用标准库的环境下正常起效,例如内核或者arduino。
Zig中的这种内存分配方法,旨在消除隐藏的内存分配机制。隐藏分配会以破坏直观性的方式干扰控制流与函数调用,导致开发人员很难在不加干预的前提下顺利复用现有代码。
Zig内存分配器属于可选的标准库功能,而不再内置于语言本体当中。这些分配器可以定制,因此在桌面运行时使用可以malloc(),而在内核上运行时则可使用标准库中的内核分配器,避免开发者重写HashMap数据结构。按照惯例,Zig也拥有一个全局分配器。Andrew呼吁开发者在所有单元测试中使用该分配器,这样如果存在内存漏洞,单元测试就能在代码发生实际内存泄漏之前及时报警。
Zig的性能比C还要强。这在一定程度上源自其面向数据设计方法,使得Zig编程性能得以增强,最终达成了在其他语言中无法实现的出色运行速度。
Zig的创始人关于CPU缓存系统工作方式的模型非常直观:占用的内存越少,则CPU的处理压力就越小。根据这一观察,他专注于减少在Zig自托管编译器中创建对象时使用的内存量。如此一来编译器占用的内存更少,CPU缓存的压力也随之下降,从而加快了代码运行速度——测试发现,Zig的速度优势最高可达35%。
Andrew解释称,这样的优化程度在Rust等语言中根本不可能实现。Zig性能提升的核心组件之一是其untagged union。通过将标签存放在单独的数组之内,这样可以减少缓存压力。然而在Rust当中,如果不使用untagged union,则会影响到代码安全性。
所以Rust的权衡在于:要编写速度更快的安全代码,就要牺牲掉充分利用计算机硬件的能力;而要想发挥硬件的全部性能,则须放弃一部分代码安全。Zig与Rust的不同之处,就在于它全都要:用户既可以编写出运行速度更快的代码,也能通过对untagged union进行安全检查以保障安全。
Zig在安全性方面采取了更加渐进的方法,由此回避必须符合“整体通用模式”所带来的安全设计陷阱。所以Zig创始人在创建Zig时做出的设计决策,使得该语言具备更高的性能与功能完备表现。
参考链接:
https://survey.stackoverflow.co/2023/#section-top-paying-technologies-top-paying-technologies\\"
https://mitchellh.com/writing/ghostty-and-useful-zig-patterns\\"
https://news.ycombinator.com/item?id=42517447\\"
https://changelog.com/podcast/622\\"
https://sourcegraph.com/podcast/andrew-kelley\\"
","description":"最近,一款用 Zig 编写的终端模拟器正式发布了 1.0 版本。 \\n\\nGhostty 自上线以来便迅速引发广泛关注,不仅因为其创始人 Mitchell Hashimoto 的背景,更因其卓越的品质让长期沉寂的终端模拟器领域焕发新机。作为 HashiCorp 的联合创始人,Hashimoto 在打造公司标志性产品(如 Terraform、Vagrant、Packer 和 Nomad)中发挥了至关重要的作用。这些工具已成为全球 DevOps 专业人士的核心利器。\\n\\n \\n\\n \\n\\n这款应用是免费开源软件,基于 MIT 许可证发布,旨在为大多数用户提供开箱即用的体验,无需额外配置…","guid":"https://www.infoq.cn/article/FaGd0phA2La7N8zJs5Js","author":"Tina,核子可乐","authorUrl":null,"authorAvatar":null,"publishedAt":"2025-01-16T09:34:05.986Z","media":[{"url":"https://static001.geekbang.org/infoq/96/963d97f0f417fe703e77cd6758d1e926.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/93/936f7775cbee40abdab273916fbf8458.jpeg","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/f3/f357bc1d4a7cbc24393bf00c08d49ece.jpeg","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/aa/aa31961a0e226eb31c880a26a7707540.jpeg","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/1a/1ab4ec89e127cefb96467e3f37b05277.jpeg","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/47/4791dbe2b6098ba5c80984df727695e3.jpeg","type":"photo","width":0,"height":0,"blurhash":""}],"categories":["编程语言"],"attachments":null,"extra":null,"language":null},{"title":"Java 近期新闻:GlassFish、Spring AI MCP、Grails、Helidon、JReleaser、Resilience4j、Arquillian","url":"https://www.infoq.cn/article/Qz7GDD16AuGZ1MiFR1oE","content":"
JDK 24 早期访问版本的 Build 30\\" 已于上周发布,其中包含 Build 29 以来的更新\\",有对各种问题\\"的修复。有关此版本的更多细节,请参阅发行说明\\"。
JDK 25 早期访问版本的 Build 4\\" 也于上周发布,其中包含 Build 3 以来的更新\\",有对各种问题\\"的修复。有关此版本的更多细节,请参阅发行说明\\"。
对于 JDK 24 和 JDK 25,鼓励开发人员通过 Java Bug Database\\" 报告错误。
GlassFish 7.0.21 是第 21 个维护版本\\",它提供了错误修复、依赖项升级和改进,例如:默认情况下禁用已弃用\\"的 TLS 1.0 和 TLS 1.1 规范;以及在管理控制台中部署超过上传大小限制的应用程序时改进了错误消息。有关此版本的更多细节,请参阅发行说明\\"。
Spring AI MCP 团队发布了 0.4.0 和 0.3.0 版本(分别在此处\\"和此处\\"发布),以提供错误修复、文档改进和新特性,例如:一个新的 McpServer\\" 接口用作一个工厂,具有构建器模式,用于构建 MCP 服务器;以及新的标记接口 ClientMcpTransport\\" 和 ServerMcpTransport\\",用于客户端和服务端的 MCP 传输。有关这些版本的更多细节,请参阅 0.4.0\\" 版和 0.3.0\\" 版的发行说明。
Grails 基金会发布\\"了 Grails 框架的 6.2.3 版,其中包含许多依赖项升级,以及当应用程序有两个使用继承命令的端点时对 ClassCastException 的解决方案。有关此版本的更多细节,请参阅发行说明\\"。
Helidon 4.1.6 版本\\"修复了因使用 h2spec\\"(一种用于 HTTP/2 实现的一致性测试工具)测试失败而导致的一个重要错误:RFC 7540\\" 中定义的 §5.1.2(流并发)和 §8.1.2(HTTP 标头字段)。有关此版本的更多细节,请参阅变更日志\\"。
JReleaser 是一款简化项目发布创建的 Java 实用程序,1.16.0 版现已发布\\",提供了错误修复、文档改进、依赖项升级和新特性,例如:一个新的 Matrix\\" 部分,具有相应的新 Matrix\\" 接口和 matrix 属性,可用于构建文件,定义可用于参数化 Hooks\\" 和 Archive\\" 的变量;并确保了会搜索完整指纹以查看是否已发布 GPG 密钥。有关此版本的更多细节,请参阅发行说明\\"。
自上次发布以来仅一年多,Resilience4j 2.3.0\\" 就发布了错误修复和增强特性,例如:用 Java ReentrantLock\\" 类的实例替换 Java synchronized 关键字的使用,以避免虚拟线程的固定问题;并添加了在 CircuitBreakerConfig\\" 类中定义的 clock() 方法,用于 CircuitBreakerStateMachine\\" 和 CircuitBreakerMetrics\\" 类,以便在测试中使用时钟更好地控制时间流逝。有关此版本的更多细节,请参阅发行说明\\"。
Arquillian\\" 1.9.2.Final 提供依赖项升级和显著更改,例如:新的 @ArquillianTest\\" 注释,用于扩展 ArquillianExtension\\" 类在测试中的使用并替换 JUnit 5 集成测试注释;以及 Arqiuillian 能够注入通过 TestEnricher\\" 接口实例解析的方法参数。有关此版本的更多细节,请参阅发行说明\\"。
原文链接:
Java News Roundup: GlassFish, Spring AI MCP, Grails, Helidon, JReleaser, Resilience4j, Arquillian\\"
","description":"JDK 24 JDK 24 早期访问版本的 Build 30\\" 已于上周发布,其中包含 Build 29 以来的更新\\",有对各种问题\\"的修复。有关此版本的更多细节,请参阅发行说明\\"。\\n\\nJDK 25\\n\\nJDK 25 早期访问版本的 Build 4\\" 也于上周发布,其中包含 Build 3 以来的更新\\",有对各种问题\\"的修复。有关此版本的更多细节,请参阅发行说明\\"。\\n\\n \\n\\n对于 JDK 24 和 JDK 25,鼓励开发人员通过 Java Bug Database\\" 报告错误。\\n\\nGlassFish\\n\\nGlassFish 7.0.21 是第 21 个维护版本\\",它提供了错误修复…","guid":"https://www.infoq.cn/article/Qz7GDD16AuGZ1MiFR1oE","author":"Michael Redlich","authorUrl":null,"authorAvatar":null,"publishedAt":"2025-01-16T00:00:00.116Z","media":null,"categories":["编程语言"],"attachments":null,"extra":null,"language":null},{"title":"RTE 与 AI 共舞:Voice Agent 点燃生态新引擎","url":"https://www.infoq.cn/article/dlOm4f26UuN5UQTjaLzy","content":"2024年,是RTE(实时互动)与AI深度融合的一年。5月,支持文本、音频、视觉多模态推理的GPT-4o发布。10月,OpenAI 发布支持语音实时交互的 Realtime API,并官宣3家合作伙伴 Agora、LiveKit和Twilio。11月,WebRTC 作者之一,Justin Uberti 宣布加入 OpenAI。在一系列的相关演示视频中,我们看见了实时互动智能在用户体验方面带来的巨大提升,也为我们提供了包括实时对话和翻译在内的诸多潜力应用场景。
与此同时,技术市场对开发和商业化路径的探索也在提速。InfoQ研究中心观察到,越来越多基于 Voice Agent 的场景探索与产品发布正在涌现,涵盖了从情感陪伴、实时翻译到智能外呼等应用领域。
基于这一背景,InfoQ研究中心认为,这正是联合RTE开发者社区推出实时互动智能领域报告的绝佳时机,在这个节点通过报告的形式,回顾实时互动与 AI 如何实现生态融合,剖析当前 Voice Agent 生态的构成,也围绕现阶段的发展特点为生态的下一步发展提出建议。
本篇文章基于刚刚发布的《 RTE 和 AI 融合生态洞察报告 2024》\\",简要回顾 RTE 与 AI 的生态融合价值,描绘 Voice Agent 生态图谱,并对生态的下一步发展提出一些问题以供读者思考。各位读者也可以点击文中链接\\",进行完整报告的下载。
从 OpenAI 发布的 Realtime API 到 Minimax 即将推出的端到端实时语音对话产品,RTE 与 AI 之间的共生关系愈发紧密。而这股从独立到共生的趋势下,交互体验突破了用户对实时性(毫秒级延迟)、互动性(语音、视频、表情的多模态融合)、沉浸感(AR/VR 真实程度)的感知,带来了全新的使用体验,也为实时互动智能生态奠定了坚实基础。
超真实的拟人人声和情感表达:通过语音合成技术和大模型带来的理解能力,实时互动智能不仅能模拟接近人类的声音,还能根据情境表达丰富的情感,呈现高度拟人化的语音体验。极低延迟,极速响应:通过采集、传输等环节的优化,实现毫秒级的响应时间,确保语音交互流畅自然。智能打断,沉浸对话:通过VAD技术,支持实时智能打断功能,模拟真实对话互动,创造更自然的沉浸式对话体验。嘈杂环境,正常对话:噪声抑制、噪音过滤,语音增强,实现在嘈杂环境下的持续对话。
在众多的实时互动智能场景中,Voice Agent 以其自然直观的交互形式和成熟可靠的技术实现,展现出在特定场景中高效且稳定的优势,正在率先突破。
Voice Agent 是利用语音 AI 和实时互动技术,通过语音及多模态交互解决特定场景问题的智能体。相比传统语音助手,Voice Agent 具有高性能、高准确、好体验的特点:
高性能:云、边、端算力结合助力 Voice Agent 实现更稳定的性能表现。高准确:端到端模型提高了实时性和语义理解的质量,实时 API 简化了语音交互的工作流程。好体验:Voice Agent 的交互方式更接近人类自然沟通,具备情感表达和语义理解优势。
在报告的研究过程中,我们发现,Voice Agent 正在智能外呼、医疗、游戏、情感陪伴、实时翻译、招聘等多种应用场景中,逐步成为创新产品的核心技术支撑。这些场景不仅为 Voice Agent 提供了广阔的应用舞台,还使其展现出与行业需求高度契合的能力。与此同时,以 AI 玩具、AI 手机等为代表的AI硬件产品的孵化和推出,也为 Voice Agent 的普及和商业化打开了新的增长空间。
基于对 Voice Agent 生态的深入研究,InfoQ研究中心围绕其产品研发、商业化和增长的完整生命周期,总结并绘制了当前的 Voice Agent 图谱。InfoQ研究中心也期待,更多开发者、企业和技术社区加入 Voice Agent 的生态共建,共同推动这一领域的技术创新、应用场景拓展和商业模式探索。
在快速发展的过程中,Voice Agent 生态并非一帆风顺,同时也面临着多方面的协作挑战,其中有五大关键问题亟待解决:
算力分布:Voice Agent 产品如何平衡云端与端侧算力分布?
算力是Voice Agent应用落地的核心。云端算力支持高精度模型,但高成本和响应延迟限制了普及;端侧算力延迟低,但能力有限,需依赖云端补充。如何平衡云端与端侧算力分布,实现高性能与经济性的兼顾,成为整个生态的共同难题。
终端适配:Voice Agent 场景应用如何适配多终端体验?
多样化的设备和场景对终端体验提出了更高要求,例如降噪处理、弱网对抗和低延迟交互等技术挑战。单凭应用层难以全面适配,亟需硬件厂商、基础设施提供方与开发者协同优化技术方案,提升多终端环境下的适配效率。
专用工具:如何围绕Voice Agent的场景特性,提供更专用、更灵活的API/SDK?
当前API和SDK在Voice Agent原生场景中的设计适配性不足。交互中的打断处理、语句分割、多轮对话逻辑等需求未能得到有效支持,加剧了开发复杂性。如何围绕Voice Agent的场景特性,优化接口设计,提供更专用、更灵活的工具,成为提升开发效率的重要方向。
流量渠道:Voice Agent 产品如何快速高效触达目标用户?
在用户分散的市场中,Voice Agent应用难以通过传统方式高效触达目标群体。如何通过数据共享、算法优化和场景协同,实现精准覆盖、减少无效流量,成为生态共建的重要课题。
人才交流:Voice Agent 产品构建需要怎样的人才?以及如何为这些新人才提供更多的交流场合?
Voice Agent 的生态构建需要跨领域的人才协作,包括 AI Builder、RTE Builder 等。然而,不同背景的人才在技术语言、思维方式和目标优先级上往往存在差异。如何搭建跨领域的交流平台,促进技术、业务与用户需求的深度融合,成为推动Voice Agent生态发展的关键。
在 Voice Agent 生态中,已有开发者和组织率先围绕技术共建、产业支持和人才交流展开了一系列思考和实践,为行业提供了有益参考。
然而,Voice Agent 的未来需要更多力量的参与——无论你是开发者、企业家还是行业观察者,都能为这场变革添砖加瓦。从技术突破到生态繁荣,共同推动实时互动智能走向新高度。
点击链接\\",下载完整报告,加入我们的讨论,探索更多实时互动智能和 Voice Agent 的可能性,共创实时互动智能的崭新时代!
","description":"2024年,是RTE(实时互动)与AI深度融合的一年。5月,支持文本、音频、视觉多模态推理的GPT-4o发布。10月,OpenAI 发布支持语音实时交互的 Realtime API,并官宣3家合作伙伴 Agora、LiveKit和Twilio。11月,WebRTC 作者之一,Justin Uberti 宣布加入 OpenAI。在一系列的相关演示视频中,我们看见了实时互动智能在用户体验方面带来的巨大提升,也为我们提供了包括实时对话和翻译在内的诸多潜力应用场景。 与此同时,技术市场对开发和商业化路径的探索也在提速。InfoQ研究中心观察到,越来越多基于…","guid":"https://www.infoq.cn/article/dlOm4f26UuN5UQTjaLzy","author":"InfoQ研究中心","authorUrl":null,"authorAvatar":null,"publishedAt":"2025-01-15T07:10:03.096Z","media":[{"url":"https://static001.geekbang.org/infoq/91/917ab940f7e2283745ed4cd2f6917a4a.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/a5/a58fc8ae88dba7c1f1e4334444fab8b8.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/9a/9aa325c8e41265ac181a6521849d409d.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/05/05d80b78bea51ee3c236180067dfac2c.png","type":"photo","width":0,"height":0,"blurhash":""}],"categories":["AI&大模型","音视频(后端)"],"attachments":null,"extra":null,"language":null},{"title":"Amazon Aurora DSQL:具有多活高可用性的分布式 SQL 数据库","url":"https://www.infoq.cn/article/JcotZlWdIIGli5HkAy1E","content":"在最近于拉斯维加斯举行的亚马逊云科技 re:Invent 大会上,亚马逊发布了 Aurora DSQL 的公开预览版,这是一款具有多活高可用性的无服务器分布式 SQL 数据库。这个新的与 PostgreSQL 兼容的数据库选项在 AWS 社区中引起了极大的热情,并被与会者广泛视为本次大会的一大亮点。
Aurora DSQL 是一个分布式 SQL 数据库,号称有无限的可扩展性、99.99% 的单区域可用性和 99.999% 的多区域多活可用性。该数据库可处理水平扩展、多区域多活运维、连接管理,还支持 缩放至零,后者是最近添加到 Aurora 的一项期待已久的特性。PostNL 首席工程师 Luc van Donkersgoed 写道:
它来了!Amazon Aurora 分布式 SQL(DSQL)。它是 DynamoDB 和 Postgres 合并而成的一个真正的无服务器关系型数据库。这是 Re:Invent 2024 的最大亮点。其他一切都不重要。
Aurora 已经通过 Global Database 提供了跨多个区域的 与 PostgreSQL 兼容的数据库,但 DSQL 背后的技术有很大不同。在 DSQL 中,两个区域都以多活模式运行,都接受写入和交叉复制数据。相比之下,Global Database 只能将数据从一个区域复制到另一个区域,并且只允许一个区域写入数据库。次级区域充当只读副本,如果需要可以提升为主区域。
在单区域配置中,Aurora DSQL 将所有写入事务提交到分布式事务日志,并同步将提交的日志数据复制到三个可用区中的用户存储副本。在多区域配置中,集群通过两个区域端点(每个链接集群区域一个)提高可用性。在介绍这项新服务时,亚马逊云科技高级数据库工程师 Raluca Constantin 和公司专业解决方案架构师 Arun Sankaranarayanan 写道:
链接集群的两个端点都呈现同一个逻辑数据库,并支持具有强大数据一致性的并发读写操作。这让你可以为地理位置、性能或弹性目的平衡应用程序和连接,确保读取器始终看到相同的数据。第三个区域充当见证区域,接收写入链接集群的数据并存储一个有限的加密事务日志窗口,以确保多区域持久性和可用性。
来源:亚马逊云科技博客
正如另一篇文章中解释的那样,Aurora DSQL 采用乐观并发控制 (OCC) 而不是传统的锁定方法。亚马逊云科技高级数据库专家 Rajesh Kantamani 和公司数据库专家 Prasad Matkar 写道:
由于其分布式架构,将 OCC 与 Aurora DSQL 结合使用非常合适,因为它可以避免在事务执行期间锁定资源,从而实现更高的吞吐量和系统效率。
这家云提供商强调,OCC 不仅可以防止单个慢速事务影响或减慢其他事务的速度,还可以为查询处理提供更好的可扩展性,并为实际故障提供更强大的集群。这是通过避免依赖锁定机制来实现的,锁定机制可能会导致死锁或性能瓶颈。
亚马逊云科技副总裁兼杰出工程师 Marc Brooker 发布了一系列技术文章,分享了对 Aurora DSQL 实现的见解。他描述了事务延迟是怎样相对于事务语句计数保持不变的,即使跨区域也是如此。Brooker 还解释了如何管理写入、冲突检测和持久性,以及事务隔离和查询性能的实现。这些文章很受欢迎,他在会议上的深度分享现已在 YouTube 上发布。
来源:Brooker 的博客
社区中的许多人认为,亚马逊云科技的这些新产品是对兼容 PostgreSQL 的 Neon、Cloudflare D1 和 Google Cloud Spanner 的挑战。亚马逊的首席执行官在台上声称,通过将事务逻辑与存储层分离并以强一致性处理事务,新数据库的读写速度达到了 Spanner 的四倍。
Hacker News 上的反应褒贬不一,许多开发人员强调了一系列重大局限性。虽然该实现依赖于亚马逊云科技的精确时间基础设施——该基础设施提供了具有强错误界限的精确时钟,但一些专家认为 DSQL 是一个给开源数据库带来启发的项目。用户 Edwinr95 写道:
没有临时表、没有外键、没有视图,事务中不超过 10k 行。除了与 Postgres 协议的一些基本线路兼容性外,我很难将其称为“数据库”,而更像是一个键值存储。
新服务旨在在全球范围内提供低延迟和同步复制能力。但它的公共预览版目前仅在美国三个地区提供:北弗吉尼亚州、俄亥俄州和俄勒冈州。
原文链接:
Amazon Aurora DSQL: Distributed SQL Database with Active-Active High Availability(https://www.infoq.com/news/2024/12/amazon-aurora-dsql/\\")
","description":"在最近于拉斯维加斯举行的亚马逊云科技 re:Invent 大会上,亚马逊发布了 Aurora DSQL 的公开预览版,这是一款具有多活高可用性的无服务器分布式 SQL 数据库。这个新的与 PostgreSQL 兼容的数据库选项在 AWS 社区中引起了极大的热情,并被与会者广泛视为本次大会的一大亮点。 Aurora DSQL 是一个分布式 SQL 数据库,号称有无限的可扩展性、99.99% 的单区域可用性和 99.999% 的多区域多活可用性。该数据库可处理水平扩展、多区域多活运维、连接管理,还支持 缩放至零,后者是最近添加到 Aurora…","guid":"https://www.infoq.cn/article/JcotZlWdIIGli5HkAy1E","author":"作者:Renato Losio","authorUrl":null,"authorAvatar":null,"publishedAt":"2025-01-13T09:30:00.356Z","media":[{"url":"https://static001.geekbang.org/wechat/images/21/216f103ce0b2c65d8a1c7b256813b653.jpeg","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/wechat/images/4a/4a0361e53789ba59d3b4a2a869f9bab8.png","type":"photo","width":0,"height":0,"blurhash":""}],"categories":["数据库"],"attachments":null,"extra":null,"language":null},{"title":"纯血鸿蒙微信App正式上线!依然使用了Flutter,依然没说清哪里用了Flutter","url":"https://www.infoq.cn/article/dZk6S3uFAyTRpvRDkOBI","content":"
1月9日晚,搭载纯血鸿蒙操作系统微信App正式登陆华为应用商城,版本号为1.0.3.42。相比此前的测试版本,正式版微信功能更加齐全,基础通讯、社交、微信支付、公众号、小程序、视频号及直播等功能齐备,使用上已经与其他平台无异。但目前版本的部分功能仍在进一步迭代中,可能会受到限制或暂时不可用。
当正式版本上线之际,,腾讯官方账号“鹅厂黑板报”发文,讲述了内部技术团队历时295 天开发鸿蒙微信App的完整过程。此外,腾讯微信事业群(WXG)员工@客村小蒋也在微博发布了一篇长文,从“局内人”的角度讲述了App开发背后的“笑与泪”。
他表示:“原生鸿蒙(HarmonyOS NEXT)完全是一套新的技术框架,编程语言是独特的ArkTS语言,这意味着所有的App都要完全重写。”
由于鸿蒙官宣不再兼容安卓应用,业内将其称之为“纯血鸿蒙”。“纯血”,也意味着一切都要重做。
2024年3月21日,开发团队收到了“简单又正式”的通知,由曾经负责开发塞班系统微信的技术负责人带头开搞鸿蒙微信。
由于鸿蒙是一个全新的系统,所以技术团队要手搓App的同时,还要和鸿蒙团队不断沟通过程中遇到的问题。就这样这个庞大的工程项目迈出了第一步。
2024年4月,鸿蒙微信开搭基建。团队凭借Alita跨平台内核优势,全力投身鸿蒙系统的适配与基础库移植工作,与华为频繁沟通技术细节,反复测试验证。
2024年5月,技术团队启动了客户端架构设计,着手为鸿蒙系统适配微信。在这一阶段,团队面临的挑战不仅是满足业务需求,还需要确保微信客户端架构具备高度的解耦性和长期的高可扩展性。目标是使各个相互依赖的模块尽量减少技术上的耦合,避免单一模块故障对整个系统的影响,同时构建一个能够轻松扩展的框架。
到了2024年6月,微信开始进入实际的开发阶段。团队借助 Flutter、liteapp等工具,全力整合支付、VoIP等功能。
腾讯称:“Flutter(跨平台应用程序开发框架)、liteapp(专为移动端设计的跨平台开发框架)等,都是这个阶段的关键工作。”
1月9日,鸿蒙微信正式版本上线。用户除了能稳定下载和使用微信外,还可以用到QQ、腾讯视频、腾讯新闻、QQ音乐等App。
鹅厂黑板报中提到他们前端架构使用了Flutter,然而,经过深入了解后我们发现,这一表述实际上存在细微的差别。据我们从业内专家处了解到,鹅厂所提及的Flutter应用并非在其主体产品中全面铺开,而是在其小程序渲染引擎的部分,这一发现与鹅厂黑板报上的某些文章所述内容存在出入但我们寻求官方确认未果。
另一方面,由于谷歌官方版Flutter不支持鸿蒙系统,所以一些跨平台框架,比如React Native和Flutter都是以分支的形式来支持鸿蒙开发的。比如 React Native (RN) 是从 0.72.5 版本开始,实现对鸿蒙系统的初步支持。然而,这一支持并非由 RN 官方实现,而是由华为开发者基于官方某一版本拉取的分支来实现的。类似地,Flutter 对鸿蒙的支持也是由国内开发者通过拉取分支来完成的,而非 Flutter 官方提供的支持。这种分支模式的问题在于,开源社区会持续迭代主干版本,而分支版本往往难以跟上主干的更新进度。
微信和Flutter的渊源可以追溯到20241年企业微信的开发。
企业微信作为一款涵盖Android、iOS、macOS、Windows PC以及Web五大平台的超大型工程项目(其代码量超过千万行),在每一个功能迭代周期中,实现五端同步开发与发布是一项极为艰巨的任务。这对开发团队、产品经理、设计师以及测试人员而言,都构成了极大的挑战。
在企业微信的早期架构设计阶段,就已经将底层的网络通信、数据库管理以及大部分业务逻辑抽象出来,采用C++语言实现,以便能够在多个平台上复用。然而,在用户界面(UI)层面,各个平台仍然需要各自处理。这就意味着,对于移动端(Android和iOS)与电脑端(macOS和Windows PC)来说,即便是相同的界面布局,也需要编写两套逻辑代码。因此,UI跨平台的需求成为了企业微信面临的一大难题。
为了解决这个问题,企业微信团队曾经尝试过H5和小程序等方案,但由于性能和用户体验方面的局限,这些方案并不能满足大部分业务场景的需求。因此,团队一直在寻找一个高性能的跨平台框架。
幸运的是,当谷歌推出了Flutter这一框架时,企业微信团队看到了希望。他们进行了一些Demo验证,发现Flutter不仅体验效果接近原生应用,而且底层采用了Skia自绘引擎进行渲染,能够满足高复杂度的需求场景。此外,Flutter还拥有丰富的Pub社区支持,这加速了框架的成熟和完善。
于是就这样,企业微信团队决定引入Flutter框架,以进一步提升项目的跨平台开发效率和用户体验。
当时,对于微信选择flutter在圈内引发了不小的震动。在X平台上,有网友对微信的选择表示惊讶。
“最大的应用程序之一微信居然选择了Flutter,真让人匪夷所思。”
更让人想不通的是,腾讯到底在哪些内部板块用到了Flutter?
腾讯只说使用Flutter开发了几款应用程序,但这里使用的措辞含糊不清,几乎是有意传递错误信息(尽管没有直接谎称微信现在是一个Flutter应用程序)。如果真的是一款flutter应用程序,那他们应该会说得更清楚。
当时,Flutter还是很受欢迎的,不只是腾讯,包括字节跳动、阿里等多个科技巨头都在应用中使用了Flutter。
“目前,仅在Play Store中就有超过20万个应用程序使用Flutter,其中包括拥有超过10亿用户的微信,以及仅来自字节跳动的70多个Flutter应用程序。”
如今,重新写的鸿蒙依然选择了Flutter作为跨平台应用程序开发框架。但其实,由于谷歌团队缩水严重,bug堆积如山等原因,业内对于Flutter的期待逐年降低。
早在 2024 年 5 月,谷歌 Flutter 团队就受到了全公司裁员浪潮的影响。对于那些投入无数时间和精力开发 Flutter 的开发人员们来说,这样的消息令人不安,种种焦虑和猜忌的情绪也随之而来。一位网名叫 xeladu 的 Flutter 与 Firebase 开发人员写道,“说实话,我宁愿劝大家干脆别学 Flutter。”
他告诫新手们不要把自己的长期职业生涯押注在 Flutter 身上,先观察谷歌的动作再行决定。“现在玩玩可以,但成为一名专业 Flutter 开发人员可能是在浪费时间。
10月30日,曾在 Flutter 团队工作的前谷歌员工 Carroll 发表了一篇长文,详细解释了他为何要推动对 Flock 的分叉。他认为 Flutter 团队一直存在“人手不足”的问题——目前全球保守估计有 100 万 Flutter 开发者,而 Flutter 团队的规模估计是 50 人,也就是说每 2 万名 Flutter 用户只对应一名开发人员。
另外,还有网友分析谷歌 Flutter 团队甚至不到 50 人:这可以通过 GitHub 的月活跃情况大致估算,还需考虑 CI 机器人带来的大量提交记录。
“劳动力短缺通常可以通过增加招聘来解决。然而,由于谷歌内部的整体问题,Flutter 团队的人员编制在 2023 年前后被冻结,而在 2024 年初还出现了少量裁员。似乎团队目前可能通过外包扩充人手,但 Flutter 团队的规模在短期内大幅扩大的可能性不大。”
在他看来,这一令人震惊的投入比例,直接导致越来越多的 bug 积压和愈发严重的功能发布延迟。
“由于开发人员不足,许多问题会长期停留在待办清单中,甚至可能多年无人问津,最终被搁置而得不到解决。”
对于这些积压的 bug,根据 Carroll 的介绍,部分关于 bug 修复和功能发布的请求多年来一直没有得到答复。他还报告了自己的亲身经历,称直到退出项目很久之后才收到关于申请的反馈意见。可这时候,他早已忘记关于 bug 修复的更多细节信息。
时间延误不仅影响故障修复,还会成为产品风险,“设想一下,如果你是某公司的工程总监或 CTO,而你们的下一个版本发布因 Flutter 的某个问题受阻。假如团队需要两年时间才处理这个问题,你会怎么做?如果这个问题对公司至关重要,你只能放弃 Flutter。你没有选择,因为你需要继续向前推进,而你的团队并不具备维护 Flutter 框架的能力,而 Flutter 团队要么没有响应,要么完全没有解决问题的承诺。于是,只能放弃 Flutter。如果这种情况普遍化,Flutter 的发展将会受到严重影响。”
上周, Carroll 又发文控诉Flutter内部的混乱情况。Carroll 表示他已经看到了开源丑陋的一面——在不理解的情况下做出反应、强制误报而忽略真正问题。
Carroll 和Jesse Ezell\\"分叉了 Flutter 并创建了Flock\\",他和 Ezell 表示,Flutter 将尽可能地接近 Flutter,同时充当“释放阀”,直到 Flutter 能够赶上社区要求但尚未解决的各种修复程序。
他希望社区能听取他的意见,给 Flock 一个机会。他在最近的一系列播客中表示,社区中有太多人完全误解了他的意图。
值得注意的是,这并不是 Flutter 第一次被分叉。当被问及 Flock 的创建时,谷歌发言人指出 Flutter 多年来已被分叉数千次,并补充说“出于多种原因(例如研究实验性想法或针对特定用例调整项目),这是开源的正常程序。”
还有这一点:Carroll 多次表示,Flock 实际上并不是一个旨在创建完全独立产品的分叉。
“我们来这里不是为了脱离 Flutter,”Carroll在播客中告诉基于\\"Dart\\"的服务器解决方案Serverpod\\"的创始人Viktor Lidholt\\"。“当我们说有人需要某些东西但尚未得到满足时,我们确实是认真的。因此,如果您能得到服务,如果如您所说的那样,您提交的每个错误都会被合并,那就太好了。我希望您继续使用 Flutter 提交错误,我希望他们继续修复您的错误。”
参考链接:
https://m.weibo.cn/status/5121016231625856\\"
https://www.woshipm.com/share/6169728.html\\"
","description":"历时295天,纯血鸿蒙微信App登陆应用商店 \\n\\n1月9日晚,搭载纯血鸿蒙操作系统微信App正式登陆华为应用商城,版本号为1.0.3.42。相比此前的测试版本,正式版微信功能更加齐全,基础通讯、社交、微信支付、公众号、小程序、视频号及直播等功能齐备,使用上已经与其他平台无异。但目前版本的部分功能仍在进一步迭代中,可能会受到限制或暂时不可用。\\n\\n \\n\\n当正式版本上线之际,,腾讯官方账号“鹅厂黑板报”发文,讲述了内部技术团队历时295 天开发鸿蒙微信App的完整过程。此外,腾讯微信事业群(WXG)员工@客村小蒋也在微博发布了一篇长文,从“局内人…","guid":"https://www.infoq.cn/article/dZk6S3uFAyTRpvRDkOBI","author":"李冬梅","authorUrl":null,"authorAvatar":null,"publishedAt":"2025-01-13T07:06:45.714Z","media":[{"url":"https://static001.geekbang.org/infoq/f9/f9fca98d5e7ab6dc9a7d82be3f1d554e.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/27/27851b70d4de6e18dffc3699b9ed2e15.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/3a/3a2c188c82b534f50d60d97cc74f0065.png","type":"photo","width":0,"height":0,"blurhash":""}],"categories":["腾讯","操作系统"],"attachments":null,"extra":null,"language":null},{"title":"Rome 失败后,VoidZero 成为统一 JavaScript 工具链的最近尝试","url":"https://www.infoq.cn/article/PG59GGohIWgSB5zrOaUA","content":"Vue.JS Web 框架 和 Vite 构建工具的创建者,Evan You 近期宣布成立 VoidZero Inc.,这是一家致力于为 JavaScript 生态系统构建统一开发工具链的公司。You 认为 VoidZero 不会和 先前目标类似的项目 Rome 一样失败,因为它会继承流行工具链 Vite 中的大量用户群。虽然 VoidZero 会发布开源软件,但该公司本身是由风险投资资助的。
VoidZero 的目标是为 JavaScript 生态系统创建一个开源、高性能的统一开发工具链,涵盖解析、格式化、linting、捆绑、最小化、测试,以及网络开发生命周期中的其他常见任务。虽然说是统一工具链,但却会涵盖开发周期中的特定任务组件,也能被单独使用。
使用 Rust 语言做系统开发可以提升性能。Rust 的原生编译避免了层层的抽象,使其运行速度接近原生速度了。Rust 内存安全的特性 也有利于运行并发任务并更好地利用多核架构。优秀的设计还带来了更高的性能提升,如开发周期中所有任务都只解析一次,且使用相同的 AST。
发布说明中还提到了要为所有 JavaScript 运行时提供相同的开发者体验。目前的 JavaScript 可在许多不同的环境中运行,其中也包括边缘环境,近年来出现的新运行时也反映了这些新的执行环境,如 Deno、Bun、Cloudflare Workers,已经亚马逊的 LLRT。
You 在 推特上解释其愿景如下:
统一工具链所面临的最大挑战是“从零到一”的问题,只有指数级应用的临界质量才能证明继续开发的合理性,但这道鸿沟在真正实现愿景之前很难跨越。VoidZero 不存在这个问题,因为 Vite 已经是 JavaScript 生态系统中发展最快的工具链。即使是从纯粹的实施进度来看,我们已经超越了 Rome 在过渡到 Biome 之前的进度。我认为,JS 将会受益于统一工具链的前提是毫无疑问的,重点在于执行。
Reddit 上的一些开发者对 VoidZero 的风险投资支持表示担忧。发布说明中提到,企业市场对规模和安全性有特殊要求,针对企业市场的端到端解决方案会让已经发布的开源组件带来潜在收入。由于企业的采用率和企业外部(开发人员的来源)的采用率绑定,VoidZero 得以在一般的开源开发的好处外,保持对其核心产品的免费访问。Trevor I. Lasn 在一片文章中阐述了风险投资的利弊:
(高级功能或企业级解决方案)不一定全是坏事。可持续开源对所有人都有好处,但它确实会引发长期可访问性和潜在锁定的问题。
发布说明的全文可在网上查看,其中包括了更多的技术细节和常见问题的解答。
查看原文:
After Rome Failure, VoidZero is the Newest Attempt to Create Unified JavaScript Toolchain (https://www.infoq.com/news/2024/12/voidzero-unified-js-toolchain/\\")
","description":"Vue.JS Web 框架 和 Vite 构建工具的创建者,Evan You 近期宣布成立 VoidZero Inc.,这是一家致力于为 JavaScript 生态系统构建统一开发工具链的公司。You 认为 VoidZero 不会和 先前目标类似的项目 Rome 一样失败,因为它会继承流行工具链 Vite 中的大量用户群。虽然 VoidZero 会发布开源软件,但该公司本身是由风险投资资助的。 VoidZero 的目标是为 JavaScript 生态系统创建一个开源、高性能的统一开发工具链,涵盖解析、格式化、linting、捆绑、最小化、测试…","guid":"https://www.infoq.cn/article/PG59GGohIWgSB5zrOaUA","author":"作者:Bruno Couriol In","authorUrl":null,"authorAvatar":null,"publishedAt":"2025-01-10T08:00:00.573Z","media":null,"categories":["编程语言"],"attachments":null,"extra":null,"language":null},{"title":"Java近期新闻:Spring AI 1.0-M5、LangChain4j 1.0-Alpha1、Grails 7.0-M1、JHipster 8.8","url":"https://www.infoq.cn/article/tIfwXE25vHtpqRailZcH","content":"JDK 24 早期访问构建版本\\"的当前构建版本仍然是 Build 29\\"。有关此版本的更多详细信息可以在发布说明\\"中找到。
同样,JDK 25 早期访问构建版本\\"的当前构建版本仍然是 Build 3\\"。有关此版本的更多详细信息可以在发布说明\\"中找到。
对于 JDK 24\\" 和 JDK 25\\",开发者可以通过 Java Bug Database\\" 报告错误。
在向 Java 社区引入实验性 Spring AI MCP\\"(Model Context Protocol\\"的 Java SDK 实现)十天后,Spring AI 团队发布了 0.2.0 里程碑版本\\"。该版本简化了 McpClient\\" 接口,使得列表操作不再需要游标参数;新增 SseServerTransport\\" 类,这是 MCP HTTP 的服务器端实现,遵循 SSE 传输规范\\"。重大变更包括一些为了提高一致性而进行的模块重命名。有关此版本的更多详细信息可以在发布说明\\"中找到。
Spring AI\\" 1.0 的第五个里程碑版本\\"提供了:对 Model Context Protocol 的孵化支持;对 Zhipuai Embedding-3\\" 和 Pixtral\\" 等模型的支持;以及对 MariaDB\\" 和 Azure Cosmos DB\\" 等向量存储的支持。一些重大变更包括:将 MilvusVectorStore\\" 类从 org.springframework.ai.vectorstore 包移动到 org.springframework.ai.vectorstore.milvus 包。Spring AI 团队计划在 2025 年 1 月发布第六个里程碑版本,然后发布一个候选版本,最后发布最终的 GA 版本。
TornadoVM\\" 1.0.9发布\\",带来了一些错误修复和改进,例如:支持 RISC-V 64 CPU 端口,可以使用 RVV 1.0 板载的 OpenCL 向量指令;通过创建新的矩阵类支持 int、double、long 和 short 三维数组;在没有传递参数时为 tornado 启动器脚本添加一个帮助菜单。有关此版本的更多详细信息可以在发布说明\\"中找到。
Micronaut 基金会发布 Micronaut Framework\\" 4.7.3\\" 版本,包含了 Micronaut Core 4.7.10\\"、错误修复和模块补丁更新:Micronaut Logging\\"、Micronaut Flyway\\"、Micronaut Liquibase\\"、Micronaut Oracle Cloud\\" 和 Micronaut Pulsar\\"。有关此版本的更多详细信息可以在发布说明\\"中找到。
Grails\\" 7.0.0 的第一个里程碑版本发布,包含了错误修复、依赖项升级和一些重要变更,例如:最小版本要求为 JDK 17、Spring Framework 6.0、Spring Boot 3.0 和 Groovy 4.0;更新了 PublishGuide\\" 类,使用 Gradle AntBuilder\\" 类而不是已弃用的 Groovy AntBuilder\\" 类。有关此版本的更多详细信息可以在发布说明\\"中找到。
经过 18 个月的开发,LangChain4j\\" 1.0.0 的第一个 alpha 版本发布:更新了 ChatLanguageModel\\" 和 StreamingChatLanguageModel\\" 接口,可以支持更多用例和新功能;Model Context Protocol\\" 的初步实现。团队计划在 2025 年第一季度发布 GA 版本。有关此版本的更多详细信息可以在发布说明\\"中找到。
Apache Camel\\" 团队宣布\\" 3.0 系列版本已达到生命周期结束。最近发布的\\" Apache Camel 3.22.3 将是最后一个版本。开发者可以通过此迁移指南\\"升级到 4.0 系列版本。
JHipster\\" 8.8.0 发布\\":升级到 Spring Boot 3.4、Angular 19 和 Gradle 8.12;在 Angular 中对 esbuild\\" 的实验性支持;改进单页面应用的 CSRF 令牌处理。有关此版本的更多详细信息可以在发布说明\\"中找到。
同样,JHipster Lite\\" 1.24.0 发布\\",升级到 Spring Boot 3.4.1 并带来一些新功能/增强,例如:一个新的模块,用于配置 Liquibase\\" linter;在预处理器中添加元数据以解决 ESLint 缓存错误。有关此版本的更多详细信息可以在发布说明\\"中找到。
原文链接:
https://www.infoq.com/news/2024/12/java-news-roundup-dec23-2024/\\"
","description":"JDK 24 JDK 24 早期访问构建版本\\"的当前构建版本仍然是 Build 29\\"。有关此版本的更多详细信息可以在发布说明\\"中找到。\\n\\nJDK 25\\n\\n同样,JDK 25 早期访问构建版本\\"的当前构建版本仍然是 Build 3\\"。有关此版本的更多详细信息可以在发布说明\\"中找到。\\n\\n对于 JDK 24\\" 和 JDK 25\\",开发者可以通过 Java Bug Database\\" 报告错误。\\n\\nSpring Framework\\n\\n在向 Java 社区引入实验性 Spring AI MCP\\"(Model Context Protocol\\"的 Java SDK 实现)十天后…","guid":"https://www.infoq.cn/article/tIfwXE25vHtpqRailZcH","author":"Michael Redlich","authorUrl":null,"authorAvatar":null,"publishedAt":"2025-01-10T03:13:32.888Z","media":null,"categories":["编程语言"],"attachments":null,"extra":null,"language":null},{"title":"Deno 2发布,重点关注与传统JavaScript基础设施的互操作性和大规模使用","url":"https://www.infoq.cn/article/2itapaFwyWIGgsCSgrhf","content":"最近,Deno 团队发布了 Deno 2。据该团队介绍,Deno 2 可以无缝地与传统的 JavaScript 基础设施进行互操作,并提供了稳定的标准库,用于跨运行时共享 JavaScript 库的现代注册表等。
据称,Deno 2 向后兼容 Node 和 npm。发布说明中写道:
Deno 2 可以解析package.json、node_modules文件夹,甚至是 npm 工作区,这让你可以在任何使用 ESM 的 Node 项目中运行 Deno。如果有你需要的语法微调,可以使用deno lint --fix进行修复。
上述兼容性使团队能够逐步采用 Deno 及其一体化工具链。Deno 开发人员可以通过npm:指定符导入 npm 包:
import chalk from \\"npm:chalk@5.3.0\\";\\n\\n\\nconsole.log(chalk.blue(\\"Hello, world!\\"));\\n// Hello, world! (in blue)
开发人员还可以利用 import 映射为其 npm 包设置裸指定符:
// deno.json\\n{\\n \\"imports\\": {\\n \\"chalk\\": \\"npm:chalk@5.3.0\\"\\n }\\n}
然后就可以通过裸指定符使用这个模块了:
import chalk from \\"chalk\\";\\n\\n\\nconsole.log(chalk.blue(\\"Hello, world!\\"));\\n// Hello, world! (in blue)
Deno 2 还声称支持各种常用的 Web 框架,如 Next.js、Astro、Remix、Angular、SvelteKit 和 QwikCity 等。
Deno 2 还通过deno install、deno add和deno remove支持依赖管理。后两个命令分别用于向package.json文件中添加以及从其中删除包。
Deno 标准库现已稳定,并且已经包含在了 Deno 2 中。它包括数十个已经经过审核的实用模块,涵盖数据操作、Web 相关逻辑、JavaScript 特有的功能等。开发人员可以在 Deno 的 JavaScript 注册表(JSR)中查看标准库的完整模块列表。该注册表是一个开源的 JavaScript 注册表,支持 ESM(JavaScript 本机模块),并且接受 TypeScript 包。
发布说明介绍了 JSR 的好处:
它原生支持 TypeScript(你可以将模块发布为 TypeScript 源代码),能够处理多个运行时和环境中模块加载的复杂问题,只允许使用 ESM,通过 JSDoc 样式的注释自动生成文档,并且可以与 npm 和 npx 类似的系统一起使用(是的,JSR 也可以将 TypeScript 转换为.js和.d.ts文件)。
Deno 还支持工作空间(也称为 “monorepos”),可同时管理多个相关且相互依赖的包。Deno 工作空间支持从现有的 npm 包中使用 Deno-first 包,从而简化从 npm 工作空间的迁移。
开发人员可以从 dotcom-2.deno 安装生产版本。建议开发人员查看原发布说明,其中包括新增功能、改进和 Bug 修复的完整列表。Deno 是开源软件,采用 MIT 许可。开发人员可以通过 Deno 项目进行贡献,并应遵循 Deno 贡献指南。
原文链接:
https://www.infoq.com/news/2024/12/deno-2-released/\\"
","description":"最近,Deno 团队发布了 Deno 2。据该团队介绍,Deno 2 可以无缝地与传统的 JavaScript 基础设施进行互操作,并提供了稳定的标准库,用于跨运行时共享 JavaScript 库的现代注册表等。 据称,Deno 2 向后兼容 Node 和 npm。发布说明中写道:\\n\\nDeno 2 可以解析package.json、node_modules文件夹,甚至是 npm 工作区,这让你可以在任何使用 ESM 的 Node 项目中运行 Deno。如果有你需要的语法微调,可以使用deno lint --fix进行修复。\\n\\n上述兼容性使团队能够逐步采用 Deno…","guid":"https://www.infoq.cn/article/2itapaFwyWIGgsCSgrhf","author":"作者:Bruno Couriol","authorUrl":null,"authorAvatar":null,"publishedAt":"2025-01-09T08:00:00.949Z","media":null,"categories":["编程语言"],"attachments":null,"extra":null,"language":null},{"title":"百度视频搜索架构演进","url":"https://www.infoq.cn/article/fc7f6acc24f13f7efc87fc52f","content":"随着信息技术的迅猛发展,搜索引擎作为人们获取信息的主要途径,其背后的技术架构也在不断演进。本文详细阐述了近年来视频搜索排序框架的重大变革,特别是在大模型技术需求驱动下,如何从传统的多阶段级联框架逐步演变为更加高效、灵活的端到端排序框架。
过去近十年,搜索引擎的主流框架为多阶段级联框架,分为召回,粗排,精排几个阶段。在每个阶段中,系统会基于相关性、质量、时效性和点击率等维度独立建模,然后通过模型融合这些信号进行排序和截断,最终产出检索结果。随着以BERT、ERNIE和GPT为代表的预训练大模型技术的逐渐成熟,利用一套端到端框架解决信息检索问题变得越来越可行。同时,用户差异化,多样化,深层次信息需求越来越强烈, 为了满足这些需求,系统的算力需求也在不断增加。在这种技术及需求趋势的引导下,传统视频搜索排序架构如何演变,已经成为视频搜索最重要课题,同时也对排序架构提出了重大的挑战。
以大模型技术为主线,打造高性能,扩展灵活的视频搜索排序框架,同时完成存量排序系统的熵减治理,从而来大幅度提升排序系统的系统能力,降级系统长期运营治理成本。
架构功能如何解耦:视频搜索排序架构经历了多年的积累和发展,已经形成了策略、架构和产品逻辑高度耦合的局面。这种耦合导致排序模块承担了过多且复杂的功能,直接影响了研发效率,并频繁引发稳定性问题。此外,模块功能定位模糊,严重制约了新产品和业务的快速落地与迭代。面对这些挑战,我们亟需打破现有的陈旧框架,从更底层进行架构优化,以实现理想的业务和架构收益。系统效能如何提升: 目前核心排序模块缺少灵活高效的并行计算框架,制约系统资源使用率的提升。与此同时,系统流量低峰时段会存在大量空闲资源,没有得到充分使用,如何充分,高效挖掘这部分空闲资源资源,来满足业务对资源大量需求。端到端架构如何演进:在端到端大模型技术的引导下,排序策略的复杂性将逐步被模型内部化,现有策略实现可以得到极大的简化。传统多阶段级联排序架构如何演进升级,以适应这种新的排序模式,也是一个需要深入研究和探索的重要课题。
对上述问题和挑战,我们采取了一系列综合措施来加以解决。首先,为了解决架构耦合与复杂性问题,我们对核心排序模块进行了深度重构,将原本集成在其中的召回处理与摘要计算功能独立出来,从而实现系统分层的合理化。其次,采用支持串行、并行和数据并行的灵活框架,提升视频排序流程的可视化管理和并行计算能力,并基于弹性算力分配控制中心,高效利用系统空闲资源,最大化搜索视频业务收益。最后,在大模型端到端排序模式下,推动多阶段级联框架向单阶段端到端框架转变升级。下面详细介绍以上解决方案的设计思想:
核心排序功能解耦:视频核心排序模块是在线检索核心模块之一,之前承接排序和部分召回功能。累积了大量的视频独有的策略和业务逻辑,支持了视频搜索业务的不断发展。随着越来越多的策略、架构功能迭代,核心排序模块也越来越臃肿,接手、开发、维护等成本不断攀升。同时也面临例如不支持云原生、整体框架设计老旧、功能耦合严重等问题。
将排序模块中召回处理阶段独立分拆,整体功能迁移至新的视频召回模块。利用图引擎将多Query串行执行升级至Query全并行执行,包含请求构建,Cache读取,结果解析。常用架构,策略功能组件化,插件化,易于理解、开发和维护。
△新召回模块
为满足用户差异化,多样化查询需求,每次请求都需要重新进行召回,排序计算,摘要处理等阶段。如果全量穿透系统缓存,会带来巨大的资源,耗时增长,系统成本无法承担,所以需要考虑目前视频搜系统分层设计是否合理,是否需要重新设计。为解决视频个性化带来的资源,速度问题,我们对视频搜索核心排序功能进行重新分层设计:
核心排序系统结果返回和摘要获取解耦,视频排序系统有能力提供更多量结果集,弥补之前机制能力缺失的短板。新增个性化排序模块,优化传输协议,在核心排序模块返回更多结果基础上,同时穿透更多基础排序,供个性化排序使用。根据最终个性化排序结果集合,对Top N进行摘要处理计算,最后返回给上游模块。
△视频个性化排序演进
系统效能提升:当前的视频搜索排序框架采用单线多策略管理器的串行执行模式。这种单线程串行处理方式在吞吐量和延迟方面表现不佳。此外,框架缺乏灵活的并行化配置能力,依靠人工经验引入各种omp,bthread等并行组件,并且存在历史遗留的冗余计算逻辑,架构组件较为陈旧。为了设计出能实际解决业务需求的现代引擎框架,我们对主流图引擎的特性进行了调研总结:
驱动方式:排序层当有大量算子,上千维特征时,无论数据驱动,还是人工编排,可读性都很差。这种复杂性不仅增加了理解整个排序层架构的难度,还进一步影响了项目的研发效率。并行方式:目前主流job/processer算子并行方式,没有办法很好去支撑算子job内部并行,排序列队list/item-wise并行。排序数据通常含有多list, list内包含成百上千个item数据,这样数据处理模式需要job内部灵活的并行计算方案。
△驱动&并行方式
事实上,我们发现没有一套图引擎能够完全满足排序业务场景的需求。因此,我们提出了一种图框架引擎主张,灵活的支持搜索排序各个场景。
除了支持serial,paralle模式,常见的job 间的串,并行模式,框架还支持data_parallel模式。召回返回数据通常包含多list队列,list队列间要做排序,list内有成百上千个item,同样需要排序,常见并行模式不能很好解决这种排序需求,所以我们在框架层做了data_paralllel模式设计,让它契我们当前排序模式,支持list+item的混合排序模式,同时能满足各种并行场景使用需求。对业务阶段进行清晰的stage,sub_stage抽象,相对传统图引擎算子推导,缺少很好可读的效果,我们做了stage抽象,配置可读性更好,配置即可读,排序全流程可视化管理易读易接手,这也就是我们做编排配置及推导的主要目的。
△Rankflow框架
我们不仅要提升现有系统的并行计算能力,还优化资源的分配和使用方式,因为搜索系统的输入流量、资源消耗、响应时间等系统状态存在着周期性的波峰-波谷变动,而系统资源已经预先分配好。在波谷期,由于用户输入流量的减少,系统资源不会得到充分利用;而波峰期,随着用户输入流量的增多,系统往往面临着资源紧缺甚至不足的情况。于此同时,搜索系统的业务链路复杂,时常还会遭受某一中间节点的故障甚至是外部流量徒增等稳定性问题。架构方案:构建全局视角的弹性算力分配控制中心。通过对集群各种维度指标的获取、策略分析及周期性执行最适合当前机器负载状态的策略组合参数,实现其核心弹性算力分配决策。业务应用:目前支持视频搜索短小视频扩触发,高峰减载,系统异常处置等功能。
△智能弹性算力系统
端到端排序架构升级:视频核心排序模块主要分为粗排,精排级联两阶段,排序策略是依据这两阶段排序模式进行迭代升级,如粗排阶段完成初步相关性计算用于初步筛选,减少精排阶段系统计算量,精排阶段少量优质结果进行复杂计算。以大模型排序为核心的排序框架打破了原来多阶段级联模式,端到端排序框架需要对计算和数据方案进行重新设计。
精简精排前调权和挖掘队列策略,优化索引召回和模型计算选送逻辑,粗排和精排阶段统一为粗精排一体化排序阶段。由于缺少粗排模型提前初筛作用,端到端模型需要计算数量更多的候选结果集,计算候选集合从原来精排阶段的几十条增加到几百条。升级精排模块,利用Rankflow框架,高并发处理候选结果集数量增加带来的耗时问题。
△端到端排序架构
视频搜索排序框架通过系统分层优化、Rankflow框架引入及弹性资源复用等架构演进,显著提升了排序系统的性能与灵活性,提高研发效率,降低了长期运营成本。
在大模型技术趋势下,视频搜索系统如何更好提供RAG搜索增强功能。如何使视频与通搜端到端融合,达到搜索端到端理想态,都是我们后续探索研究的方向。
————END————
推荐阅读
如何定量分析 Llama 3,大模型系统工程师视角的 Transformer 架构\\"
微服务架构革新:百度Jarvis2.0与云原生技术的力量\\"
无需业务改造,一套数据库满足 OLTP 和 OLAP,GaiaDB 发布并行查询能力\\"
","description":"随着信息技术的迅猛发展,搜索引擎作为人们获取信息的主要途径,其背后的技术架构也在不断演进。本文详细阐述了近年来视频搜索排序框架的重大变革,特别是在大模型技术需求驱动下,如何从传统的多阶段级联框架逐步演变为更加高效、灵活的端到端排序框架。 过去近十年,搜索引擎的主流框架为多阶段级联框架,分为召回,粗排,精排几个阶段。在每个阶段中,系统会基于相关性、质量、时效性和点击率等维度独立建模,然后通过模型融合这些信号进行排序和截断,最终产出检索结果。随着以BERT、ERNIE和GPT为代表的预训练大模型技术的逐渐成熟,利用一套端到端框架解决信息检索问题变得越来越可行…","guid":"https://www.infoq.cn/article/fc7f6acc24f13f7efc87fc52f","author":"百度Geek说","authorUrl":null,"authorAvatar":null,"publishedAt":"2025-01-09T02:29:49.942Z","media":[{"url":"https://static001.geekbang.org/infoq/9f/9f4ed96c68b60ecce759fda8ef58b048.jpeg","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/60/60bba5c7a7d8100795a6ad8da6e36e61.jpeg","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/28/287e6c99d1bd5a5e1e7dbd1ef1485620.jpeg","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/7e/7ef986e2da36b3290acbe6747c884c61.jpeg","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/f1/f14591f19a7e1e73d673ba1671d17422.jpeg","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/c0/c0d3000e208c25cb59043103163f3435.jpeg","type":"photo","width":0,"height":0,"blurhash":""}],"categories":["音视频(后端)","百度","架构","视频"],"attachments":null,"extra":null,"language":null},{"title":"计算效率提升 10 倍,存储成本降低 60%,灵犀科技基于 Apache Doris 建设统一数据服务平台技术实践","url":"https://www.infoq.cn/article/sPx2c0aZQYVprUaVKfXq","content":"导读:灵犀科技早期基于 Hadoop 构建大数据平台,在战略调整和需求的持续扩增下,数据处理效率、查询性能、资源成本问题随之出现。为此,引入 Apache Doris\\" 替换了复杂技术栈,升级为集存储、加工、服务为一体的统一架构,实现存储成本下降 60%,计算效率提升超 10 倍的显著成效。
灵犀科技有限公司(简称灵犀科技)是奇点控股旗下的高科技企业,专注于为企业提供 SaaS 服务、定制化决策工具、智能匹配交易平台以及开放的大数据生态系统。灵犀科技深耕于企业产业分析,积累了大量相关信息,基于这些数据构建了独特的产业链结构,向政府和企业提供精准拓客服务,助力产业升级与招商。
灵犀科技早期基于 Hadoop 构建大数据平台,以 Hive、Clickhouse、Starrocks 搭建离线数仓,Flink、Redis 搭建实时数仓。2023 年随着公司的战略调整和需求扩增,数据处理效率、查询性能、资源成本问题随之出现。为了快速应对业务的发展需要,灵犀科技引入 Apache Doris 搭建了集存储、加工、服务为一体的统一架构,有效解决上述挑战,实现存储成本下降 60%,计算效率提升超 10 倍 的显著成效。
基于 Hadoop 体系的大数据平台架构如下图所示,分为实时及离线两条数据处理链路:
离线处理链路:在离线数据处理流程中,数据通过爬虫、埋点、业务系统和算法分析等多种方式被采集,通过 HDFS Put 命令和 SeaTunnel 工具被导入/同步到 Hive 的 ODS 层中。使用 Hive 对数据进行更新、清洗、聚合、主题构建。因 Hive 存在计算性能限制,又引入 ClickHouse 优化大规模数据集的多维聚合计算,引入 StarRocks 进行多源数据的 ID 映射。最终,处理后的数据通过 Seatunnel 同步到 TiDB,提供业务的实时查询需求。实时处理链路:在实时数据处理流程中,数据通过爬虫的方式写入 Kafka,Flink 读取 Kafka 的信息并根据系统下发在 Redis 的数据处理规则,完成数据的处理并最终写入 TiDB,提供实时的数据查询服务。
整体架构中,各组件的职能明确,并承载公司多年的数据服务工作。然而,随着 2023 年公司战略调整和需求扩大,数据处理效率、查询性能受到影响,架构疲态尽显。具体问题包括:
系统复杂:集成多种数据组件增加了系统的复杂性,导致系统维护和故障排除困难。数据一致性:在多个数据库和存储系统之间同步数据时,会导致大量数据冗余,同时容易出现数据一致性问题,使得数据排错变得困难。系统扩展性:随着数据量的增长,系统的可扩展性不足,扩展所需资源也随之增加。使用成本: 团队成员需具备多样化技能,以管理和维护复杂的系统组件。维护多样化的系统导致较高的使用成本,包括硬件及软件的成本投入。
为了快速应对业务发展需要,灵犀科技决定对架构进行升级。经过对多种大数据组件的对比,最终选择引入 Apache Doris 来构建公司新一代数据服务平台,Apache Doris 是一种低成本且能满足以下特性的架构:
架构简洁:架构简洁,易于部署维护,简化开发流程,提升工作效率;多源数据融合能力:能够集成 HDFS、Kafka、MySQL 等多种数据源,具备高效的数据融合能力;高效的数据建模能力:相较于多组件架构,能够高效率的执行 SQL,实现快速建模;具备实时数据处理能力:能够支撑分钟级延迟的数据生产;数据服务能力:能同时高效满足表报分析与常规的数据查询服务;稳定可靠:具备容灾恢复能力,确保数据存储的高可靠性。
新架构中,使用 Apache Doris 替代了原先架构中数据存储与数据分析引擎,实现集存储、形成集存储、加工、服务为一体的统一架构,依赖于 Apache Doris 的湖仓一体能力,实现数据的宽入->窄处理→宽出,具体来讲:
数据宽入: Apache Doris 提供多样化数据导入方式,结合 Multi-Catalog 能力,可实现多数据源的快速导入。具体来讲,使用 Broker Load 导入 HDFS 冷数据(历史数据),使用 Catalog 导入类 MySQL 静态数据,使用 Routine Load 导入埋点数据以及爬虫数据(增量实时数据),使用 Binlog Routine Load 导入业务应用数据(增量实时数据)。窄处理:利用 Doris 实现数据的统一存储及计算。Doris 采用列式存储,按列进行数据的编码压缩和读取,能够实现极高的压缩比,并利用 Doris 的极速计算引擎进行数据分析。数据宽出:Doris 提供各类异构数据源的查询和写入能力,支持用户将这些外部数据源统一到 Doris 的元数据映射结构上,当用户通过 Doris 查询这些外部数据源时,能够提供一致的查询体验。
在数仓建模上遵循维度建模思路。ODS 层采用明细模型(Duplicate Key),保证了数据完整变更链路的存储,数据不做任何的加工处理;DWD、DM、APP 层选用主键模型(Unique Key),在数据的录入过程中完成的数据更新。为确保一致性的数据服务,基于 Doris 提供统一的应用服务,避免多组件间数据传输导致数据孤岛,同时避免多组件繁重的数据存储和同步成本。
经过半年多使用,以 Apache Doris 为基石的数仓建设取得了显著成果:
从存储成本来看,同样的数据规模,原先架构需要 130+TB 磁盘资源,使用 Doris 后,仅需 60TB 即可,成本下降超过 60%。从计算性能来看,下图测试结果可清晰得知 Doris 显著优势,与 Hive 的数仓计算耗时相比,Doris 计算效率提升超 10 倍。
Doris 的多租户和资源隔离方案,主要目的是为了多用户在同一 Doris 集群内进行数据操作时,减少相互之间的干扰,能够将集群资源更合理的分配给各用户。
灵犀科技基于 Apache Doris 资源隔离方案对集群资源进行了租户级别的隔离。针对在线与离线任务,将节点资源划分为 Online 和 Offline 两个标签,并将 BE 节点均匀分配到这两个标签上。表数据依然以 3 副本的方式存储,其中 2 个副本存放在 Online 资源组,1 个副本存放在 Offline 资源组。Online 资源组主要用于高并发低延迟的在线数据服务,而一些大查询或离线 ETL 操作,则可以使用 Offline 资源组中的节点执行。从而实现在统一集群内同时提供在线和离线服务的能力。
同时,定义了多租户,并为每个租户分配不同的资源权限,通过租户级别的资源隔离,提高了资源使用效率,确保各业务模块按需获得计算与存储资源。在数据存储方面也进行了类似的划分,从而实现数据生产与业务应用的同时兼顾,提高了数据管理的可控性,降低了运维复杂度。
使用参考负载管理\\"文档
为了在确保集群稳定性的同时充分利用资源,我们将用户划分为多种角色,以应对不同时间段的资源需求。举例来说:
普通角色的用户(非生产性用户),仅使用 Offline 组的资源系统忙时(早上 8 点到晚上 8 点),生产用户可使用的资源仅为 Offline 组的资源系统闲时(晚上 8 点到第二天早上 8 点),生产用户可使用所有的服务资源处理数据应用系统用户,仅使用 Online 组的资源
资源划分确保了应用系统在高峰时段的资源不被挤占,同时也兼顾了夜间大批量数据处理的性能需求。
在一体化数仓建设中,集群需同时支持服务应用和数据生产,因此集群的稳定性显得格外重要。为此,灵犀科技采取了以下安全保障措施:
熔断机制:由于集群面向多种服务应用,常常会出现不规范的使用场景。为应对这种情况,我们引入了熔断机制。当 SQL 运行超过设定时长时,系统会及时报警并终止该查询,以实现熔断效果。
# 查询正常执行的查询\\nselect * from information_schema.active_queries\\n\\n\\n# 通过查询时长设置熔断,杀掉长查询\\nkill query {query_ID}\\n
监控报警:借助飞轮科技提供的 Doris Manager \\"进行巡检监控,及时上报集群的 CPU、内存状态,同时我们也建立了任务的异常报警机制,实现了问题监控和处理。通过 Doris Manager 的巡检监控,我们能够及时上报集群的 CPU 和内存状态。此外,我们还建立了任务异常报警机制,实现了对问题的监控与处理。
流量控制:针对常规的任务处理,控制整体的应用并发,合理利用闲时时间进行的数据的生产工作,确保能够在高峰期保持系统的高性能,同时在低峰期最大化资源的使用,提高了整体系统的生产效率。
公司依托详尽的企业信息,从多维度——包括企业类型、组织形式、经营范围以及产品服务等,构建了全面的企业产业链信息库。灵犀科技采用先进的数组结构来存储这些数据,并充分利用 Doris Array 数据结构以及强大的数据函数功能,精准分析企业间的相似度,以帮助企业更精准的招商引资。
原方案:
过往的方案中,采取每日将数据库中的新增数据同步至向量库,并转化为向量化数据进行存储。当用户发起请求时,将请求数据同样转化为向量,并查询向量库以获取相似企业的 ID 列表。随后,还需通过这些 ID 再次访问数据库,以获取并展示详细的企业信息。
这一流程存在显著弊端:数据冗余存储导致资源浪费,且数据不同步问题严重影响了结果的准确性。此外,每次页面请求都需要依次访问两个服务,不仅响应时间长,代码复杂度也较高,一旦出现问题,排查难度极大。
新方案:
为解决上述问题,引入 Doris 制定全新的方案。利用 Doris Array 的数据结构,承载企业所属产业、行业等相关信息,比如:一家企业的产业编码为 [\\"160\\", \\"208\\", \\"219\\", \\"399\\"],表示这家企业属于智能制造、汽车、新能源、物联网产业。然后运用数据相交函数 array_intersect计算两家企业在产业、行业之间的相交度,为企业相似度分析提供数据支撑。简化模型如下:
与之前方案不同的是,引入 Doris 之后,只需一次 SQL 请求即可完成相似度计算并返回企业详细计算,代码简单且流程缩短,接口响应时间稳定在 5 秒以内,较原方案快了 1 倍;同时,系统也无需进行冗余数据的存储及同步操作,避免了数据不一致的问题。
截至目前,灵犀科技基于 Apache Doris 建设的统一数据数据平台已上线并稳定运行,有效解决了数据孤岛问题,实现了数据整合与流通。在数据集成(ETL)、标准化、治理和可视化等方面取得显著进展,相较于原有的多组件架构,数据生产能力提升超过 10 倍、存储成本节省超 60%。未来,灵犀科技将进一步探索 Apache Doris 潜力,并在以下方面进行深入实践:
存算分离:进一步提升资源的利用率,精细化分配存储和计算资源。大模型 BI:将 Apache Doris 作为公司智能问答大模型的知识库,支撑大模型 BI 的查询。
","description":"导读:灵犀科技早期基于 Hadoop 构建大数据平台,在战略调整和需求的持续扩增下,数据处理效率、查询性能、资源成本问题随之出现。为此,引入 Apache Doris\\" 替换了复杂技术栈,升级为集存储、加工、服务为一体的统一架构,实现存储成本下降 60%,计算效率提升超 10 倍的显著成效。 灵犀科技有限公司(简称灵犀科技)是奇点控股旗下的高科技企业,专注于为企业提供 SaaS 服务、定制化决策工具、智能匹配交易平台以及开放的大数据生态系统。灵犀科技深耕于企业产业分析,积累了大量相关信息,基于这些数据构建了独特的产业链结构,向政府和企业提供精准拓客服务…","guid":"https://www.infoq.cn/article/sPx2c0aZQYVprUaVKfXq","author":"李冬梅","authorUrl":null,"authorAvatar":null,"publishedAt":"2025-01-08T09:08:19.813Z","media":[{"url":"https://static001.geekbang.org/infoq/ff/fff7a4fdd187c4694bdde832e2c5235f.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/ae/aed8da0ae818f35d209745a2937b6e37.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/d0/d01fa2b12bf2547c320cba10944d65f1.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/fa/faabd64425eeb0a0c5c25a139422b83c.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/e1/e15f5aac19c2e33f076c1b455baba450.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/b7/b74e046a473e6fe098514169c4814700.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/9f/9f442f63406839d4ca4e8038c12b5cbc.png","type":"photo","width":0,"height":0,"blurhash":""}],"categories":["数据库"],"attachments":null,"extra":null,"language":null},{"title":"数据库将成为下一波受 AI 影响最大的行业","url":"https://www.infoq.cn/article/WtzlLCYdKEaqvbHXGoko","content":"“很多业务的数据库分配它一个 CPU 都浪费,但是还不能停,我们内部大概有几百个这样的实例,隔离性是很好,但是成本太高了。”例如,OA 系统每天可能只有3个请求,但无法确定这3个请求什么时候会来,虽然这个系统很重要,却会占用多余资源,造成浪费。
这是某城商行在数据库应用过程中非常大的一个挑战,并且不是个例,很多不同行业的企业都面临着类似的问题。与此同时,除了资源利用率的困境之外,近年来,企业对数据库提出了越来越多的精细化需求,比如如何在不影响业务负载的情况下更快地扩容,再比如优先满足重要业务需求的前提下,如何将剩余资源合理分配给其它业务等等。
“十年前 TiDB 诞生的时候,是希望解决 MySQL 在面对数据量快速增长时所遇到的挑战,而现在的种种经验表明,客户的需求已经远远超越了这一要求,他们的关注点完全不一样了。”PingCAP\\" 联合创始人兼 CTO黄东旭在日前的媒体沟通会上表示。
回顾十年前TiDB 架构设计之初,黄东旭表示,当年最正确的决定就是做了分层设计。换言之,其计算引擎、分布式存储、存储介质之间是分层的,针对上述企业提出的一系列痛点时,可以迅速基于云技术满足其需求。
那么,在面对滚滚而来的AI浪潮时,TiDB的底层技术逻辑还是否同样具备这样的前瞻性?下一代数据库\\"内核又有哪些关键的设计要点呢?
“为了未来十年更好地发展,我们必须向前再迈进一步。”黄东旭强调。
在黄东旭看来,如今很多 AI 业务,其本质仍然是数据业务,虽然大部分的创新故事都聚焦于大模型和人工智能,但最终,在创新真正落地和应用过程中,都需要依靠数据技术来支撑和实现。
最近AI数据分析平台Databricks的百亿美元融资同样印证了这一点——据了解,Databricks99%的营收仍来自数据业务,Data+AI 的融合趋势超出业界预期。
自2023年ChatGPT横空出世之后,AI经历了从“Amazing”到“x Everything”的演变,业界开始不断思考并付诸实践,希望可以利用AI能力改造现有应用。那么,下一个阶段是什么样的呢?黄东旭认为,未来AI的核心在于From “AI” to “Your Own AI”,使 AI 能够访问并有效利用人与世界互动所产生的数据。“这里的关键不在于 AI 本身,而在于数据的来源、存储方式和使用策略。”
对此,黄东旭及其团队曾尝试使用高质量行业数据和个人数据,基于开源基础模型进行微调,探索数据增强和开发微调工具链的可能性,最终得出两个结论:第一,微调的方向是不可控的;第二,每一次微调的时间周期非常长,如果效果不佳就需要重新再来,迭代速度慢,且成本非常高。
经过一系列尝试,其证明了当下以及在可预见的未来,能够让大模型真正发挥作用的只有一条路,就是 RAG。“在 RAG\\" 的商业模式中,使用哪个大型语言模型并不重要。我们今天可以用 Llama,明天可以用 OpenAI,后天可以用 Databricks 的模型,这些模型本身并没有本质区别。真正宝贵的是什么?是数据。很快,整个世界将会发现,数据库将成为下一波受 AI 影响最大的一个行业。”
但是,旧瓶装不了新酒,大模型和RAG对数据基础设施也提出了新的要求:
一方面是向量索引,黄东旭指出,一个优秀的 RAG 应用需要整合向量搜索、检索、知识图谱等多种技术。2025 年主流的数据库都会支持向量索引类型,单独的向量数据库的市场增长会停滞。
另一方面,它还需要记录与系统的交互记录,包括公司文档、TiDB 产品文档以及结构化数据等,这些元素共同构成了 RAG 应用的核心,使其能够有效地理解和响应用户的查询。一个能够实现一站式服务的,多模态的数据库解决方案会越发流行。
为确保自己在新浪潮下“不掉队”,PingCAP近日发布了 TiDB 最新的长周期支持——TiDB v8.5 LTS。
意料之中的是,TiDB 8.5 引入了强大的向量搜索功能,适用于RAG、语义搜索、推荐系统等多种应用场景。并且,TiDB 的向量搜索 SQL 语法与 MySQL 语法风格一致,使得熟悉 MySQL 的开发者也能轻松构建 AI 应用。
事实上,早在 2019 年的 TiDB DevCon上,黄东旭就曾用下图(图1)指出未来5年TiDB 不仅要支持图索引,还要支持向量索引和全文索引。“虽然那时还没有大语言模型,但我们已经将向量搜索纳入了产品蓝图中。可以看到,如今我们也正沿着这个方向努力,最终这些功能都将由 TiDB 来提供。”
图1
图2
当然,向上支持AI应用只是数据库“职能”的一部分,作为基础设施,黄东旭强调下一代数据库还应当具备足够的可扩展性、灵活性、成本效益和简洁性。
以SaaS客户为例,很多企业向TiDB提出了支持创建上千万表、库的需求。这背后展示的不仅仅是数据量大小的可扩展性,而是更多数据维度的可扩展性,包括能保持的连接数,支持的表库数量,后台任务(例如 DDL)的扩展性,导入导出和 CDC 任务的速度和吞吐,多租户下的可观测性和运维性等等。
目前,TiDB 8.5 版本每个集群支持超过 100 万张表,并确保跨租户的一致查询性能。这项能力对于采用多租户架构和处理多样化工作负载的应用至关重要。
灵活性方面,进入AI时代发起数据请求的主体将从人变成 AI,这意味着数据库必须跳出过去的固有限制。“当需要提供千人千面的个性化服务时,就不能用固化的思路来解决问题,数据库本身的限制会反过来变成应用层面的限制。比如,你不能告诉AI,我的底层数据库只支持静态的表。”黄东旭表示。
与此同时,随着数据量和数据维度的爆发式增长,规模和灵活性两个因素叠加将带来指数级的复杂性。对此,PingCAP坚定地认为,未来的数据库一定是云原生与 AI 的结合,而下一代数据库内核关键的设计要点涉及两个方面:
第一,使用对象存储多OLTP引擎,借此可以规避分布式存储引擎带来的异常检测、数据搬迁等复杂性问题,同时最大限度地降低成本。黄东旭举例,过去的数据库是一个独立的软件,而今天在云上重新设计系统时,它们变成了一组微服务的组合,每个模块都在自我迭代,只需保持Serverless接口的稳定性。
第二,实现真正的多租户。“如今很多数据库厂商谈多租户时只谈隔离性,但隔离往往是容易解决的,其中最具挑战的问题是在多租户基础上实现资源共享。”正如文章开头举例,很多企业希望在保证重要业务100%安全可靠隔离的情况下,在逻辑上把资源分配给其它优先级更低的业务使用。黄东旭表示,这恰恰是TiDB独创的能力。
举例来说,TiDB 8.5 也增强了资源组的管理能力,允许根据不同业务应用的需求设置资源使用上限,并控制后台任务的资源消耗,确保在高并发情况下关键业务负载的服务质量得到保障。这也是TiDB能够帮助企业实现成本效益的重要抓手。
“对于新一代引擎,其重点在于未来3年内的持续迭代、创新和验证,最终,我们希望可以逐步演进到‘TiDB one’的状态。对于开发者而言,最大的挑战之一是如何用单一数据库解决各种复杂问题,如果能够有一个 All-in-one 的解决方案,将极大地简化开发者的工作。”黄东旭强调。
遵循“All-in-one”这一目标和愿景,PingCAP 研发副总裁唐刘透露,明年发布的 TiDB V9 版本将继续专注于内部的优化和能力增强。具体来说,将在以下几个方面发力:
第一,稳定性,持续改进 TiDB的内存控制机制,尽可能减少OOM(Out Of Memory)错误的发生,确保系统的稳定运行;
第二,自动执行优化,TiDB V9将引入类似于 Oracle SPN(Stored Procedure Native Compilation)的技术,实现自动化的性能优化;
第三,性能提升,TiDB V9将正式发布多模混合搜索(Hybrid Search)功能,进一步提升 TiDB 的搜索能力;
第四,Cascades优化器改进,确保在提升性能的同时,保持高度的稳定性;
第五,继续关注可扩展性,基于8.5版本的可扩展性基础,通过 TiCDC 和用户的业务生态进行对接,同时,基于海量数据加速批量 DDL,让整个业务的变得更加敏捷,支持企业业务的快速发展。
唐刘表示,过去十年的时间里,PingCAP始终在探索和实践,并且努力寻找一个问题的答案——什么才是“好的数据库”。如今他的答案是,一个“好的数据库”首先要具备广泛的全球化应用,拥有大量的全球客户,并且始终专注于产品最核心的基本能力,持续不断地为客户创造价值,真正帮助用户的业务实现持续增长。
而对于TiDB来说,从产品创建和社区建设初期,到规模化商业化和出海阶段,从全面拥抱云原生技术,再到如今又全面拥抱AI,可以看到,其正在不遗余力地朝着“All-in-one Database”的方向发展,提供全面的服务。这将是 TiDB打造下一阶段的“好数据库”的新方向和新起点。
","description":"“很多业务的数据库分配它一个 CPU 都浪费,但是还不能停,我们内部大概有几百个这样的实例,隔离性是很好,但是成本太高了。”例如,OA 系统每天可能只有3个请求,但无法确定这3个请求什么时候会来,虽然这个系统很重要,却会占用多余资源,造成浪费。 这是某城商行在数据库应用过程中非常大的一个挑战,并且不是个例,很多不同行业的企业都面临着类似的问题。与此同时,除了资源利用率的困境之外,近年来,企业对数据库提出了越来越多的精细化需求,比如如何在不影响业务负载的情况下更快地扩容,再比如优先满足重要业务需求的前提下,如何将剩余资源合理分配给其它业务等等。\\n\\n“十年前…","guid":"https://www.infoq.cn/article/WtzlLCYdKEaqvbHXGoko","author":"高玉娴","authorUrl":null,"authorAvatar":null,"publishedAt":"2025-01-07T08:52:06.028Z","media":[{"url":"https://static001.geekbang.org/infoq/37/378a4cd26251b7de3ef28594dd1a421f.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/1b/1bdceb2ace432eed68aa67238d124346.png","type":"photo","width":0,"height":0,"blurhash":""}],"categories":["AI&大模型","数据库"],"attachments":null,"extra":null,"language":null},{"title":"JavaScript 开发工具 JetBrain Webstorm IDE 现在可免费用于非商业目的","url":"https://www.infoq.cn/article/O1MTIlgVqkC46Mlvoa1P","content":"JetBrain 的 JavaScript IDE 现在可免费用于非商业用途。因此,Webstorm 已经与 RustRover(Rust IDE)和 Aqua(测试自动化 IDE)一样,成为 JetBrain 提供非商业许可模式的集成开发环境。非商业免费许可用户必须同意 JetBrain 收集有关使用情况的数据,才能享受与付费订阅用户相同的功能,包括基于 AI 的代码自动补全功能。
在发布说明中,JetBrain 列举了一些属于非商业用途类别的示例:
如果你出于非商业目的使用 [WebStorm],如学习、开源项目开发、内容创建或业余爱好开发,那么你现在可以免费使用了。
该公司称,他们的主要目的是让更多人采用其集成开发环境。非商业许可可能会吸引更多的临时开发者(在工作之余进行编码的开发者)和开源开发者。据 Stack Overflow 的一项调查估计,多达三分之二的开发人员是业余爱好者,约三分之一的开发人员是专业开发人员。
接受非商业许可条款的开发人员不能拒绝参与数据收集。但该公司表示,数据收集是匿名的,且仅限于使用情况数据:
我们收集的数据完全是匿名使用相关 IDE 功能的数据。数据主要集中在执行了哪些操作以及使用了 IDE 的哪些功能类型。我们不收集任何其他数据。
非商业许可用户可以使用与商业许可用户相同的产品和产品功能,但有一个例外。
非商业许可用户只能使用 Code With Me Community 功能,而不是付费用户可使用的 Code With Me 功能。Code With Me 旨在为开发团队提供安全的协作开发功能(如结对编程、代码审查)。虽然访客开发者无需许可即可加入 Code With Me 会话,但 Community 用户将在多个方面受到限制(如会话长度有限、访客数量有限、支持主要通过社区提供)。
非商业授权用户可以免费使用以前的付费 IDE 版本,尤其是可以使用现有的人工智能功能,如所谓的整行代码自动补全(Full Line Code Completion)。
在 Reddit/HackerNews 上,一些已经将 WebStorm 作为首选 IDE 的开发人员对数据收集条款可能产生的寒蝉效应表示了质疑。
以前没有使用过 JetBrains IDE 的开发人员询问改用 WebStorm 的理由,尤其是从微软的 Visual Studio Code 切换到 WebStorm 的理由。WebStorm 的拥护者似乎普遍认为,WebStorm 的重构和调试能力更胜一筹。其他方面更多的是褒贬不一,如代码导航、自动冲突解决,WebStorm 还默认提供了一些在其他编辑器中需要自定义安装质量参差不齐的插件才能使用的功能)。
开发人员可在线查看 JetBrains 隐私政策和非商业许可条款。
原文链接:
https://www.infoq.com/news/2024/12/jetbrain-webstorm-free-license/\\"
","description":"JetBrain 的 JavaScript IDE 现在可免费用于非商业用途。因此,Webstorm 已经与 RustRover(Rust IDE)和 Aqua(测试自动化 IDE)一样,成为 JetBrain 提供非商业许可模式的集成开发环境。非商业免费许可用户必须同意 JetBrain 收集有关使用情况的数据,才能享受与付费订阅用户相同的功能,包括基于 AI 的代码自动补全功能。 在发布说明中,JetBrain 列举了一些属于非商业用途类别的示例:\\n\\n如果你出于非商业目的使用 [WebStorm],如学习、开源项目开发、内容创建或业余爱好开发…","guid":"https://www.infoq.cn/article/O1MTIlgVqkC46Mlvoa1P","author":"作者:Bruno Couriol","authorUrl":null,"authorAvatar":null,"publishedAt":"2025-01-01T04:00:00.973Z","media":null,"categories":["编程语言"],"attachments":null,"extra":null,"language":null},{"title":"支持全量、增量迁移,YashanDB增量迁移组件研发实践解析","url":"https://www.infoq.cn/article/TbmSpeKWA3aOHcPp9wWS","content":"本文基于YashanDB高可用架构师-马志宏2024年11月在“2024年国产数据库创新生态大会”-“根”技术专场的演讲整理形成,本文将深入阐述YashanDB数据迁移流程,以及YashanDB增量迁移组件的实现技术原理。
崖山迁移平台YMP是YashanDB提供的数据库迁移产品,提供异构RDBMS与YashanDB之间进行迁移评估、数据迁移、数据校验的能力。
在最新发布的V23.3版本中,YMP新增增量迁移组件(以下简称“迁移组件”),具备异构数据库的在线全量迁移和增量迁移能力,且支持两者间的无缝衔接,真正实现业务无感知迁移,保障数据一致性及业务连续性。
迁移组件架构上由source,transform,sink三个模块组成。其中source模块负责从源端获取数据,transform模块负责数据转换,sink模块负责目标端数据导入。其具备以下关键能力:
支持一键式迁移,自动完成全量迁移到增量迁移的无缝衔接,无需用户介入。支持所有的常见数据类型,如CLOB和BLOB类型等。支持常用DDL操作,如建表、删表、增删列、rename table、增删主键等。支持无侵入式部署,不占用源端/目标端服务器资源。
完整的数据迁移过程包括元数据迁移、全量迁移及增量迁移三个阶段,接下来将会介绍每个迁移阶段的关键能力。
迁移组件在元数据迁移阶段具备以下几方面能力:
灵活配置需要迁移的对象。迁移组件可以指定某几个schema或table,或者同时指定schema和table,还可以配置table级黑名单,过滤掉不需要的表。提供对象名映射能力。如果源端数据库和目标端数据库的schema名或者表名不一样,迁移组件可以只映射整个schema,也可以对某几个表名做映射。在增量阶段,对增量DDL也做了对象名映射的适配,包括rename table的DDL。并行批量查询,加速元数据构建。迁移组件对元数据构建作了并行优化,通过多线程以及多表批量查询的方法,加速目标端元数据构建,节省迁移时间。多种冲突策略,自动处理元数据冲突。当目标端数据库存在与源端数据库相同的表名,这个表可能是原来就存在的,并且表中含有存量数据。针对此类情况,迁移组件提供多种冲突处理策略。当遇到相同名称的表时,可以truncate快速删除表中所有数据,也可以保留现有数据,或者报错等待用户介入。
全量迁移阶段,迁移组件对性能进行深度优化。
首先是多线程并行,按表并发,把每张表分配给一个线程去迁移。源端会启动多个线程进行查询,目标端也是多线程进行批量插入。每对线程之间有独立的缓冲队列,互不影响。
其次对大表进行拆分,均匀拆分成多个子表,分配给多个线程,进一步提高并发度。迁移组件采用rowid拆表算法,拆分耗时短,可以支持无主键表的拆分。
经过上述优化,全量迁移的性能可达到200M/s,满足主流场景的性能要求。
全量迁移结束后,将进入增量迁移。在此阶段需考虑全量迁移和增量迁移之前的无缝衔接。
基本要求如下:
业务连续性。业务不中断,尽量不影响业务运行。数据一致性。增量数据不能重复,也不能遗留,即所谓的无缝衔接。支持无主键表的无缝衔接。
迁移组件基于闪回查询实现全量迁移至增量迁移的无缝衔接。具体实施细节如下:
在全量迁移阶段,采用闪回查询确保全量数据处于一致性状态;通过增量数据解析,从最老活跃事务对应的Redo开始,保证活跃的事务不被遗漏;在增量迁移过程中,过滤闪回查询SCN之前的事务,该事务在闪回查询时已经包含,增量迁移只输出闪回查询SCN之后的增量事务,保证数据不重复。
增量迁移环节主要分为两部分,一个是从源端获取数据,另一个是在目标端入库。
迁移组件通过逻辑日志解析接口YStream获取源端增量数据。
YStream是 YashanDB数据库提供的一个日志解析服务,客户端可以通过YStream获取数据库逻辑日志,用于数据同步。YStream具备高性能、高可靠性、易使用等特点,主备部署环境下可以将其部署在备库,以减少主库压力。
迁移组件就是通过YStream获取增量逻辑日志,然后组装成SQL语法发送到目标库执行。
Redo日志的读取性能以及日志解析性能是影响逻辑日志获取性能的重要因素,YStream对此进行了深度优化。
YStream会优先从Redo buffer读取日志。一方面从buffer读取的速度很快,延迟很低;另一方面读Redo buffer不产生读IO,可以减少数据库压力。
正常情况下,数据库产生Redo的速度和YStream解析的速度一样,所以全部从Redo buffer读取,完全不产生IO。如果目标端背压高,导致YStream解析阻塞后,可能会从Redo文件读取。但当下次YStream解析追平Redo产生速度后,又会接着从buffer读取。
单个解析线程的性能无法满足并发业务产生的数据库Redo解析要求,因此YStream将Redo日志进行哈希分组,然后分配给多个线程进行独立解析。解析完毕后,再按照原始顺序进行聚合,生成原始逻辑日志进行事务组装和发送。
YStream在发送逻辑日志时,是以事务为单位发送的,且严格按照事务的顺序发送,用户无需关心回滚事务。当一个事务的所有逻辑发送完后,才会发送下一个事务,并且仅发送已提交的事务。
每条逻辑日志都有单调递增的position,使得客户端能够精确定位至特定的逻辑日志。在断点续传的时候,通过给服务端发送最后一次成功接收的position,可以让YStream从这个点开始发送后续数据,确保数据传输不会重复也不会遗漏。因为每条DML均有独立的position,YStream可以实现在事务中间的断点续传功能。
增量迁移过程中,增量DDL通常是一个难点,一方面是DDL语法较多,不同数据库之间不一定兼容,另一方面是从DDL原始语句里无法获取足够的信息。一般的CDC组件,对于DDL逻辑日志的只会输出DDL原始语句,不会有更多元数据信息。
YStream在解析增量DDL语句的时候,除了输出原始SQL语句,还会输出DDL类型以及表结构信息。包括表里有多少列,这次DDL涉及哪些列等。这样不需要解析SQL语句,直接从附带信息就知道表结构。
另外会附带主键等SQL语句无法获取的信息。比如上图中的建表语句,这条DDL没有指定主键约束名,执行时会自动生成一个约束名,这个约束名在DDL语句里看不到,但是YStream的逻辑日志会附带。
如果在目标端建表的时候执行原始DDL语句,那么会自动生成一个随机约束名,和源端约束名不一致。后面遇到一个指定约束名的DDL,目标端就会执行失败。比如源端执行DDL,drop指定的约束名,而目标端没有这个名字的约束(因为目标端自动生成的约束名不一样)。而YStream通过更详细的附带信息能解决这类问题。
从源端获取增量数据后,如何高效的把增量数据在目标端入库,也是增量迁移的重点内容。迁移组件支持表级和事务级两种并发模式,以提供数据入库效率。
介绍:按表并发是根据表的对象id将逻辑日志哈希分组,分配给不同的线程,写入目标库。即每个表的DML只属于一个线程。技术要点:为了进一步加速入库速度,迁移组件采用DML合并策略,按照一定规则将同一行数据的多个DML合并成一条DML,以此压缩DML数量。同时迁移组件将小事务合并成较大的事务,进行批量提交,以此减少事务提交次数。适用场景:按表并发模式对于表数量多的场景很友好。不过该模式只能支持最终一致性,因为它将事务做了拆分,所以不满足瞬时一致性。性能:按表并发模式的TPCC模型下,从YashanDB到Oracle的增量迁移,可以做到每秒8万条DML的迁移速度。该统计基于逻辑日志中的DML数量,每条DML只改一行。这个性能不算高,主要原因是TPCC模型下,只有一两张是热点表,导致采用按表并发模式难以提升并发度。
介绍:按事务并发,是指按事务进行哈希分配,把一个事务的所有DML分配一个线程进行入库。技术要点:因为事务之间可能存在先后依赖关系,若不遵循特定的顺序执行事务,会导致执行失败或数据不一致。所以先要对逻辑日志进行分析,将可以并发执行的事务进行分组,且保证同一组的事务相互独立、没有依赖,则该组事务就可以并行入库。待该组事务全部提交完成后,再并发执行下一组事务。适用场景:按事务并发模式可以做到瞬时一致。此外,在一组事务提交的时候,可以选择按照源端提交顺序依次提交,达到串行化的强一致效果,也可以不做限制,提高入库性能。性能:按事务并发模式的TPCC模型下,从YashanDB到Oracle的增量迁移,可以做到每秒13万条DML的迁移速度。该统计基于逻辑日志中的DML数量,每条DML只改一行。
断点续传是指增量迁移过程中,源端或目标端发生故障,导致事务传输中断后,可以重新从断点位置继续传输。为了提高增量迁移的可靠性,迁移组件实现“精确一次”的断点续传功能。
在迁移开始前,迁移组件在目标端创建一张辅助表,然后在往目标端迁移的事务中,同时更新辅助表中的position,这样事务提交后,这个position之前的数据就迁移成功了。
若在迁移过程中任意时刻发生故障,比如断网、数据库宕机等,只要在迁移组件重连目标库后,把辅助表里的position发送给YStream,YStream就可以从断点处发送后续数据,不会漏发,也不会重复发。
异构数据库之间的数据迁移,是一项较为复杂的工程。在不同的数据库产品,不同的部署拓扑结构下,会有较大差异的处理逻辑。目前YashanDB的迁移组件实现了数据迁移的常用功能,但是还有一些能力有待完善,未来我们将从以下几个方面进行优化加强:
丰富产品兼容性,适配更多的数据库。支持双向复制,解决循环复制问题。实现所有节点之间可以相互同步数据,达到一个多活的效果。全面提升数据质量管理,包括数据类型转换,数据的校验,增量和全量的校验,数据过滤和清洗功能。
","description":"本文基于YashanDB高可用架构师-马志宏2024年11月在“2024年国产数据库创新生态大会”-“根”技术专场的演讲整理形成,本文将深入阐述YashanDB数据迁移流程,以及YashanDB增量迁移组件的实现技术原理。 崖山迁移平台YMP是YashanDB提供的数据库迁移产品,提供异构RDBMS与YashanDB之间进行迁移评估、数据迁移、数据校验的能力。\\n\\n在最新发布的V23.3版本中,YMP新增增量迁移组件(以下简称“迁移组件”),具备异构数据库的在线全量迁移和增量迁移能力,且支持两者间的无缝衔接,真正实现业务无感知迁移,保障数据一致性及业务连续性。\\n\\n迁…","guid":"https://www.infoq.cn/article/TbmSpeKWA3aOHcPp9wWS","author":"马志宏","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-12-31T09:57:38.108Z","media":[{"url":"https://static001.geekbang.org/infoq/45/45268569abcf75901145c5fdabc2fd6b.png","type":"photo","width":931,"height":303,"blurhash":"LeD,oMLJAb=?D.rYwvNK4Zvi$LIt"},{"url":"https://static001.geekbang.org/infoq/4f/4f1b4126ad1242fddca023043d653e24.webp","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/97/97bce77f69e07386cd8d7655c9ee7dd0.webp","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/d8/d871f6f801946b3c566640dd22b2c381.webp","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/0a/0ae87df40960cf853003fa85d71e38c5.webp","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/4b/4bff85abb25942926b629f74dd372cd8.webp","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/d6/d6cadebf2065818ac6378dfec8336ad8.webp","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/9a/9a655d6beedb3561af4aa4c6b964edc2.webp","type":"photo","width":0,"height":0,"blurhash":""}],"categories":["数据库"],"attachments":null,"extra":null,"language":null},{"title":"数据规模超 1PB ,揭秘网易游戏规模化 TiDB SaaS 服务建设实践","url":"https://www.infoq.cn/article/JUuV6eTWSmijj8rFkGPI","content":"在网易游戏的数据库服务生态中,TiDB 当前已成为一个重要组成部分,支撑了游戏周边业务的服务运营。目前,TiDB 集群的数量超过 100+ 套,最大单集群节点数达到 60 个以上,数据总规模超过 1PB。本文作者田维繁,TiDB 社区的老朋友,在网易游戏负责包括 MySQL、TiDB 等关系型数据库的运维与平台开发工作,他在 TiDB 地区交流深圳站上分享了《网易游戏规模化 TiDB SaaS 服务建设》,深入探讨网易游戏在规模化 DB SaaS 服务运维方面的丰富经验,以及在处理高并发业务时的实践策略,本文根据其演讲实录进行整理。文章将从网易游戏 DB SaaS 服务的概览开始,详细介绍 TiDB SaaS 服务的具体实践,并深入讨论针对高并发请求业务的优化措施和问题解决方案。
我主要和大家分享网易游戏在规模化 TiDB SaaS 服务运维以及处理高并发业务方面的实践经验。我的介绍将围绕三个核心方面展开:
首先是对网易游戏 DB SaaS 服务的概览其次是我们在实施 TiDB SaaS 服务过程中的具体做法最后是针对高并发请求业务的优化措施和问题解决方案
我们为网易游戏及其周边服务提供一站式数据库管控服务:
平台服务层, DMS 负责数据维护和治理,DTS 负责数据库之间的数据迁移,比如 MySQL 到 TiDB 之间的迁移以及到 kafka 迁移等。DaaS,主要负责服务管理,包括调度和备份。在数据库服务层面,提供了包括 MongoDB、Redis、MySQL、TiDB 等在内的多种 数据库 SaaS 服务。根据最新的统计数据,TiDB 集群的数量已超过 100 套,TiDB 的数据总规模超过了 1PB,在网易游戏中的应用中已经达到了相当的规模和深度。
TiDB 在网易游戏的应用场景非常广泛和复杂。包括基础架构服务、云存储、内部管理和质量治理等 OLTP 场景;以及上游是 MySQL,下游 TiDB 作为读扩展的业务场景;重 OLAP 场景下的业务,比如使用 TiSpark 直接请求 PD 进行报表统计计算;利用 TiDB 的横向扩展能力, 进行数据归档。
针对多样化的业务场景,我们提供定制化的服务套餐,以满足不同计算和存储需求。我们的 SaaS 服务根据具体的业务需求,设计了多种专属套餐。
高并发请求的 OLTP 场景,如游戏服务,我们推出了高性能套餐。例如,18 核 CPU 和 180GB 内存的配置,专为满足高并发业务需求而设。高存储套餐,主要针对大型业务场景的数据归档需求,同时兼容 OLAP 业务需求。普通套餐适用于常规业务场景,常规的的 TP 和 AP 业务。测试套餐,采用较小规格 6C 主机或云虚拟机,以支持业务的测试和验证环境。
资源隔离有几个点需要考虑:
1. CPU 隔离
不同实例使用不同 cpu 资源,实例间使用 cpu 互不影响。
2. 内存隔离
不同实例使用不同的内存段,实例间使用内存互不影响。
3. 磁盘 IO 隔离
独占实例间使用不同的磁盘,独占实例间磁盘互不影响,独占实例可以动态进行扩容。
4. 虚拟节点请求独立
实例间的进程和数据互不可见,实例有独立的请求入口,实例间安装的依赖包互不依赖互不可见。
在实施套餐定制后,我们对节点进行虚拟化处理。在此过程中,资源隔离至关重要。我们采用轻量级 LXC 虚拟化技术,以实现 CPU 和内存的有效隔离。对于 IO 密集型节点,例如 TiKV 节点,我们在 SSD 盘上创建不同的 LVM,并将其挂载至不同虚拟机下,确保磁盘响应的独立性。至于网卡流量隔离,得益于多张万兆网卡的配置,通常流量不会成为限制因素。
平台支持套餐升级,以适应业务量的增长。如果需要从标准套餐升级至更高性能的套餐,会根据宿主机的资源情况,提供动态扩容服务。包括动态调整 CPU、内存和磁盘资源。若宿主机资源不足,后端服务将执行节点的增加和删除操作。虽然这一过程可能较长,但通过新增节点、负载均衡后再删除旧节点,确保整个升级过程的顺利进行。
在 TiDB SaaS 平台上,备份快照服务扮演着至关重要的角色。尤其在 OLTP 场景中,快速备份和恢复的能力对于数据回档等操作至关重要。用户可以通过简单的操作,在进行游戏维护或其他业务操作时,实现整个系统的完整备份,而不会对业务流程造成任何干扰。
快照服务使用 LVM 技术来创建 snapshot,用户只需一键操作,即可生成快照并继续进行其他任务,无需等待复杂的备份流程完成。根据需要,生成的快照可以被复制到备份盘,或者上传至 S3 存储,这一过程完全由用户自行选择。这样的设计使得备份过程轻量且快速,对业务的影响降到最低。
然而,快照备份作为一项可选操作而非默认备份方式,是因为它存在一些局限性。例如:
可能会造成一定的空间浪费,因为数据盘需要预留空间给 snapshot;不支持库表级别的备份;恢复时,必须在相同规模的 TiKV 节点集群中进行
尽管如此,快照备份仍然满足了一部分业务需求。
我们也提供 TiDB 官方的 BR 备份作为常规备份方式。BR 备份操作简便,直接备份至远程 S3 存储。我们广泛使用公有云服务,如 AWS、GCP、阿里云和微软云等,对于支持 S3 的云服务,我们直接备份至 S3;对于不支持的,则采用快照备份方式。
BR 备份的优点包括灵活简单的备份操作,支持库表级别的备份,以及稳定的 5.0 以上版本。此外,它无需预留数据盘空间,并且恢复过程相对灵活,无需指定同等规模的 TiKV 节点。
对于不同的备份方式,采取不同的恢复策略。
快照备份,我们会下载每个节点的备份,然后使用 TiDB 的 recover 工具将其恢复至 TiDB 集群。为防止数据覆盖,我们会为 alloc_id 赋予较大的值,确保恢复过程中数据的完整性。BR 备份的恢复则更为直接,只需从 S3 拉取备份并恢复至 TiDB 集群即可。
通过这些备份与恢复策略,确保了数据的安全性和可靠性,为用户提供了灵活的数据保护解决方案。
在 TiDB SaaS 平台中,我们经常需要在 TiDB 集群与 MySQL 之间进行数据同步。为此,我们提供了 DTS 服务,允许用户直接在 MySQL 中指定库表,并根据预设的规则进行同步,如同步特定表、更改库名等,通过我们封装的 DM 服务实现与 TiDB 集群的同步。若需反向同步,即从 TiDB 同步回 MySQL,用户可以通过 TiCDC 服务进行注册,实现指定表的反向同步,确保数据迁移的完整性和正确性。
此外,我们还支持异构数据的同步。通过 TiCDC,我们可以根据用户定义的规则,将增量或全量数据同步至 Kafka 集群,并进一步同步到其他非关系型数据库。提供了一个全面的异步数据同步解决方案,满足不同数据同步需求。
在我们使用的初期,在实际业务的应用中也遇到了很多问题,比如:
监控探测不够灵敏:发现探测不够灵敏,业务访问 TiDB 出现严重卡顿情况时,探测没有任何报警热点问题频发:业务热点问题频繁,没有很好的方式去打散,需要人工干预处理空间异常暴涨:长事务或者 TiCDC 异常导致,GC 清理异常,空间暴涨TiKV leader 频繁抖动:海量 region,PD 根据空间占比进行调度
针对这样的情况,我们也因此打造了定制化的监控调度服务。
我们实现了秒级的心跳探测机制,通过简单的写操作来实时监测实例状态,防止实例卡顿无法发现。同时,为了避免单点探测的不准确性,我们采用了多点多次探测策略,大多数情况下只有在多次探测均出现问题时才会触发报警,在一些特殊的业务实例中,我们也会根据敏感性来配置单次探测失败的告警。针对热点问题,我们采取了主动监控和自动处理的策略。监控 TiKV 的 CPU 使用情况,判断是否存在热点。一旦发现热点,会实时查询并尝试 split region。对于使用特定字段作为主键的业务场景,我们会主动打散热点,无需人工干预对于空间异常问题,我们通过监控 GC 的运行状态和长事务来预防空间暴涨。如果 GC 运行不正常或存在长期未提交的事务,我们会及时报警,避免空间异常。针对 TiKV leader 抖动问题,我们虽然不会直接处理,但根据各种可能存在的情况提供了一系列的解决方案。例如,优化 raft-base-tick-interval 参数,开启静默 region,或根据版本加大 region merge 的力度,以减少抖动现象。
接下来分享一些我们在高并发场景下的运维实践。
在处理高并发请求的场景中,我们积累了一系列运维实践经验。以网易内部某项目为例,在业务启动初期,我们预估并发量可能超过 10 万,而实际生产环境中,该业务已达到 36 万 QPS,高峰期甚至超过 40 万。同时,插入和更新操作的数量巨大,高峰期间的 I/O 需求极为严苛。此外,大规模数据的过期清理也对数据库性能构成了挑战。
因此,在真正投入使用前的设计阶段,我们就考虑到不仅要从数据库层面,也要从业务角度尽量去优化和避免这些问题。
针对大量写入,我们与业务团队合作,确保所有表使用 AUTO_RANDOM 策略来分散热点,减少单个热点的影响。实施了分区表策略,根据业务需求设定过期时间,定期清理过期数据表,以减轻 GC 压力。限制了单个 KV 的 region 数量,以避免过大的 region 导致的性能抖动。
在业务规划初期,我们遇到了几个主要问题:
使用 TiDB 5.1 版本时,GC 清理速度慢,导致数据堆积和空间异常增长,TiKV 节点不断增加,成本过高;单个 TiDB Region 过大,一些更新非常频繁的表单个 region 可达 300G 以上(正常的 region 大小不会超过 96M),影响了数据的备份和升级;以及高并发请求下的 raft 抖动问题,会导致业务的波动。
为解决这些问题,我们采取了以下措施:
1. 从 TiDB 5.1 升级至 TiDB 6.1.7 版本,优化了 GC 清理效率,减少了 1/4 的空间占用,并降低了成本。
2. 在面对庞大集群的升级任务时,我们无法通过建立新集群并进行数据同步的传统方法来实现。因此,我们采取了滚动升级的策略,确保在新版本经过充分验证后,逐步对集群进行升级。在此过程中,我们会先创建快照,以便在升级过程中出现问题时能够迅速回滚到升级前状态。针对因 Region 过大而无法进行 split 和备份的问题,通常会在业务流量较低的时段,创建一个新的表并将数据迁移过去。然后执行删除操作(drop table),以此来减少 Region 的大小,并允许正常的数据备份和升级流程进行。
3. 关于 raft 性能抖动,TiDB 6.1 版本会默认开启 raft engine,以降低 raft 平均时延,但随之而来的性能抖动是我们的业务难以接受的,所以我们选择关闭 raft engine,回归到 rocksdb 的默认写入方式,有效解决了性能抖动问题。
通过这些措施,我们确保了在高并发场景下的业务稳定性和数据库性能,为用户提供了更加可靠的服务。
","description":"在网易游戏的数据库服务生态中,TiDB 当前已成为一个重要组成部分,支撑了游戏周边业务的服务运营。目前,TiDB 集群的数量超过 100+ 套,最大单集群节点数达到 60 个以上,数据总规模超过 1PB。本文作者田维繁,TiDB 社区的老朋友,在网易游戏负责包括 MySQL、TiDB 等关系型数据库的运维与平台开发工作,他在 TiDB 地区交流深圳站上分享了《网易游戏规模化 TiDB SaaS 服务建设》,深入探讨网易游戏在规模化 DB SaaS 服务运维方面的丰富经验,以及在处理高并发业务时的实践策略,本文根据其演讲实录进行整理。文章将从网易游戏 DB…","guid":"https://www.infoq.cn/article/JUuV6eTWSmijj8rFkGPI","author":"田维繁","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-12-31T09:22:03.668Z","media":[{"url":"https://static001.geekbang.org/infoq/6c/6c3db2792ab106aaee6125d7835ec513.png","type":"photo","width":1080,"height":588,"blurhash":"LIQmI%~D-q_NohR+Wof8V#NZNZay"},{"url":"https://static001.geekbang.org/infoq/ad/ada2204b1e2ace850377a15caa508d1e.png","type":"photo","width":1080,"height":603,"blurhash":"LJQ]+v-;Rj~qRkR*t8WBIUM{xvWB"},{"url":"https://static001.geekbang.org/infoq/13/13f779284b801dc36698e0524327e083.png","type":"photo","width":1080,"height":598,"blurhash":"LQQv?xx.?GSt^,oNNGn,^-xcE1xc"},{"url":"https://static001.geekbang.org/infoq/56/567b0780ea409ec98b42ee3c7c0f3d0e.png","type":"photo","width":903,"height":514,"blurhash":"LGPa4%~q=}~W%hRoxss*-@xc$e$e"},{"url":"https://static001.geekbang.org/infoq/00/00690e83d6f875c7fe688f2faa65c569.png","type":"photo","width":799,"height":547,"blurhash":"LLQ]$l%M%MtRyZflt6X9MwRjfkt6"},{"url":"https://static001.geekbang.org/infoq/4f/4fa43629a611414651cc22da8691c00d.png","type":"photo","width":1080,"height":206,"blurhash":"LcQ0N{RQ~q_3ITRj%Mt7yBkBRQM{"},{"url":"https://static001.geekbang.org/infoq/67/67c8d0ba081218af524d7acd1c14444a.png","type":"photo","width":885,"height":270,"blurhash":"LgP?zLt7~q%fIUj[%3f8x[kBRQRj"},{"url":"https://static001.geekbang.org/infoq/c8/c8838c5e310f38580e522fc898633b47.png","type":"photo","width":1080,"height":321,"blurhash":"LHSY]i_NM{s;IBx]RQIURiogayWU"},{"url":"https://static001.geekbang.org/infoq/dc/dc1bf2a97ca0c2ab55d7f66d1ff88177.png","type":"photo","width":1080,"height":417,"blurhash":"LGSPX]_3t2Ri~pRhRixs_3D%In-:"},{"url":"https://static001.geekbang.org/infoq/53/532393a3c5cfb122c8bff800a5cc71da.png","type":"photo","width":944,"height":461,"blurhash":"LKR{#?~qt7oet7-;RjRiWBxuRjWC"},{"url":"https://static001.geekbang.org/infoq/3a/3a1e6b2e3e87846f70f863bbccb86080.png","type":"photo","width":1080,"height":487,"blurhash":"LARC}O_3-:~q?bxtj[R*%2Rkj[t7"},{"url":"https://static001.geekbang.org/infoq/a3/a32d2b0284122b64eab5fb0349cfbf7c.png","type":"photo","width":653,"height":236,"blurhash":"LASr$B~qyY~q=iogyDt7FObEt6of"},{"url":"https://static001.geekbang.org/infoq/05/0572900af4177cd4f3859e80a6ff2158.png","type":"photo","width":536,"height":234,"blurhash":"LCRfd{_NyD?v^4S2tlt7^%IAaet6"}],"categories":["数据库"],"attachments":null,"extra":null,"language":null},{"title":"提升数据库系统稳定性,OceanBase在vivo的应用实践","url":"https://www.infoq.cn/article/wYicgCtaKJ7ThXIXTxH8","content":"在日新月异的手机通讯行业中,vivo始终保持着先锋者的姿态,不断推动着技术的革新与进步。然而,随着业务的不断扩展和数据量的急剧增长,vivo互联网在数据库方面遇到了前所未有的挑战。原有的MySQL数据库逐渐无法满足业务需求,尤其是在处理海量数据和应对高并发场景时,显得力不从心。因此,vivo决定进行数据库替换,寻找一种更加高效、稳定且可扩展的数据库解决方案。vivo数据库工程师王翔分享了他们的数据库替换历程和实践经验。他提到,vivo在选择新的数据库时,充分考虑了业务需求、技术发展趋势以及成本效益等多个因素。经过深入的调研和对比,他们最终决定分布式选型OceanBase。
作者|王翔,vivo数据库工程师
vivo互联网主要负责为vivo手机的应用程序提供用户数据存储服务,包括消息推送数据的存储。从2018年至2024年,其数据库业务经历了显著的增长:
物理机数量从大约2000台增加至2024年的约5000台。实例规模从1万个扩展至2024年的近10万个,实现了十倍的增长。实例密度,即每台物理机可部署的实例数量,稳定在18至19个之间。
数据库运维规模增长趋势
这些数据清晰地展示了vivo互联网数据库业务在规模上的快速增长。但是,伴随着业务增长,我们同样面临着一系列挑战。
当前MySQL数据库的整体架构如下图所示,最上方client为业务访问的客户端,下方DNS服务主要为MySQL数据库提供域名。再往下,Proxy代理层主要负责日志记录、流量管控,实现读写分离的功能。继续深入,则是传统的MySQL核心部分一主两从架构。最底层的Agent组件,负责探活工作和高可用切换。一旦检测到主库出现故障,Agent会迅速进行高可用性切换,将新的主库信息更新到Zookeeper, 最终反馈到Proxy层,确保业务能够持续稳定地访问数据库。
当前MySQL数据库架构
基于上述架构,当前MySQL数据库面临两大痛点:
痛点1:MySQL的主从架构则存在局限性,无法实现真正的分布式。随着数据量的不断增长,单个MySQL集群受限于物理机的磁盘容量,磁盘容量达到上限时,不得不采取分库分表的策略。但随着数据量的持续增大,业务的复杂度和管理成本的成本也随之增加,这对我们的在线业务构成了显著痛点,成为当前业务发展的一个难题
痛点2:MySQL的逻辑复制机制也带来了挑战。在流量突增或执行批量任务时,大量的DML操作会导致主从复制延迟。若主库发生故障需要切换,必须等待从库追上主库的数据,确保数据一致性后才能完成切换。这不仅影响了主从切换的效率,还可能对从库的实时查询性能造成负面影响。
MySQL作为世界上最流行的开源数据库,以其简单易用和出色的性能而广受欢迎。然而,它在扩容和延迟方面存在的局限性促使我们寻找新的解决方案。
针对以上MySQL数据库架构存在的痛点,我们决定引入分布式数据库以解决问题。在对比了多种数据库后,我们选择了国产自主可靠的OceanBase分布式数据库。
分布式数据库有很多, 但随着我们对OceanBase 的深入研究, 最终OceanBase 以其多项显著优势脱颖而出 :
自主可控, OceanBase通过国家自主可控认可, 是蚂蚁集团自主研发的数据库,符合我们对数据安全性和自主可控的要求;灵活扩展能力,作为原生分布式数据库,OceanBase支持垂直和水平方向的灵活扩展,能够有效解决MySQL扩容受限的问题,同时其分区特性免去了MySQL分库分表改造,显著降低业务复杂度;OceanBase多租户功能,支持灵活分配租户资源,同时通过多租户资源隔离机制,减少资源争用,确保租户之间互不干扰,保障系统稳定运行;OceanBase的高压缩能力和多租户特性,能够节省60%以上的存储空间,同时大幅提升资源利用效率,从而有效降低数据存储成本;在高可用方面,OceanBase的三节点部署模式,支持在不增加资源消耗的情况下实现跨机房容灾,有效保障业务连续性。OceanBase对MySQL的高度兼容也是一大亮点,这使得业务从MySQL迁移到OceanBase时无需经过大量改造,即可实现无缝对接。同时迁移评估、反向同步等功能保障数据实现平滑且安全迁移。此外,OceanBase的HTAP能力也是我们关注的重点,一套系统同时支持OLTP和OLAP需求,为业务提供了更加灵活高效的数据处理方案。
在引入OceanBase数据库的过程中,我们着重进行了生态和平台的建设。我们内部已建立一套完善的数据库管理平台系统,该系统目前支持OceanBase的源数据管理以及数据变更操作。用户可以通过此平台进行表结构变更、数据增删改查等操作,并实现了OceanBase数据的归档功能。同时,我们正积极建设OceanBase的审计日志功能,以确保业务用户在从MySQL迁移到OceanBase后,能够继续享受与原有平台相同的安全策略和审计支持。
此外,我们还构建了常规的告警监控配置和备份恢复机制,以保障OceanBase数据库的稳定运行和数据安全。在下游,我们与大数据生态紧密集成;在上游,我们实现了透明加解密功能,为数据安全提供了额外保障。
2023年9月至10月,vivo互联网决定引入OceanBase数据库,并随即在10月至11月期间对OceanBase数据库进行了安全漏洞扫描。同年的12月,我们完成了环境部署,并建立了OceanBase相关的操作规范。
自引入OceanBase数据库之初,我们便开始着手构建告警监控系统,涵盖功能性和性能告警的监测,并持续完善相关文档。此外,我们在去年底时开始对OCP及OMS进行了高频测试,备份与恢复工作也开始持续进行。于此同时,我们测试了下游的oblogproxy工具,对比其日志格式与原生的Binlog是否存在差异,并进行了高可用性等关键特性的测试。
2024年3月,我们成功上线了首套OceanBase集群,并实现了与MySQL的双写功能。经过几个月的努力,今年7月,我们顺利完成了该集群的上线工作。其中,从6月份开始,我们陆续上线了多套MySQL集群,目前仍在持续进行中。
引入OceanBase数据库的进展情况
收益1:在线业务延迟大幅下降
在某个线上业务场景中,原本使用MySQL进行跑批业务。该业务并非持续运行,而是在短时间内需要处理大量数据操作,每秒需处理约4~5万行数据。然而,MySQL数据库在此高负载下性能严重受限,从库延迟高达10万秒,甚至持续攀升至百万秒,对数据库的高可用性和整体性能造成了极大影响。
针对此情况,我们将该业务的数据库从MySQL切换至OceanBase。在仅分配一个租户的情况下,OceanBase成功应对了每秒4~5万行的数据操作,且响应时间保持在约100毫秒左右,这一性能表现完全满足了业务需求。
下图为MySQL的监控图:
切换到OceanBase后,每秒40万行数据操作的事务响应时间:
OceanBase之所以成功解决了MySQL在高负载下出现的延时痛点。得益于其分布式架构,允许三个节点并行写入,这一特性显著提升了写入性能并降低了响应时间。
收益2:稳定性大幅增强, 延迟不再抖动
我们还成功将线上环境的某DB集群迁移至OceanBase数据库。迁移后,响应时间从原先不稳定的50毫秒显著降低至稳定的35毫秒,整体响应时间减少了约30%。上图中的黑色线条代表迁移前DB的响应时间,而蓝色线条则展示了迁移到OceanBase后的响应时间,表现出更加平稳且低延时的特点。
OceanBase的稳定性是我们非常重要的一个参考指标。在确保稳定性的基础上,再开发其他功能会更为理想。如果数据库缺乏稳定性,那么它就不会成为我们考量的选项之一。因此,当数据库稳定后,它对业务和用户访问将产生极为顺畅的影响,显著提升用户的体验。
收益3:超大表DDL 执行丝滑
在MySQL环境中,我们有一张不断增长的大表,由于业务上的限制无法拆分,最终达到了物理机磁盘容量的上限,无法继续存储数据。为了应对这一问题,我们选择了对这张大表进行压缩处理,并选用了Toku DB作为压缩工具。这是因为该表的查询量和访问量相对较低,适合在Toku DB上进行压缩。
将大表迁移到Toku DB后,数据量得以压缩至原来的四分之一,暂时缓解了物理机的磁盘容量压力。然而,随着表规模的不断扩大,数据量最终达到数百亿级,Toku DB已无法支持对该表进行DDL变更,这类操作对于如此庞大的表来说变得极为危险。
因此,我们决定将这张表再次迁移到OceanBase数据库上。迁移后,OceanBase同样实现了四倍的压缩率,有效解决了我们面临的存储和性能问题。
我们对400亿条记录的表在OceanBase上执行了DDL操作,用时仅为2小时18分钟,这一数据非常可观。这充分满足了业务上在不拆分大表的前提下,对大表处理的需求,是DDL操作效能提升的一个典型案例。
收益4:降本增效, 存储成本减少60%
接下来,我们实现了大规模集群的降本成效。将一套35TB的数据库迁移到OceanBase后,存储量降至26TB,节省了9TB空间。此外,我们还迁移了多套MySQL集群,总计20TB的数据迁移到后,存储量减至6.6TB,节省了13.4TB空间。这些迁移都显著降低了存储成本,实现了降本增效的目标。
接下来是关于OceanBase迁移案例的真实分享,分别总结了从某DB数据库和MySQL数据库迁移到OceanBase的实践经验。
本次迁移是从某分布式数据库迁移到OceanBase,迁移前进行了一系列前期准备。
首先,通过性能评估来确认压测结果是否符合预期。其次,检查原有系统在OceanBase上的兼容性,特别是表结构、SQL功能、账号等是否兼容。另外, 还需要考虑分区适应性。当业务使用分区表时,表结构需要做兼容性修改,查询SQL也要适配分区表,此时需要结合业务评估业务改造成本。
评估完成后,需关注一些迁移事项:
• 源与目标端字符集保持一致;
• 勿向TiCDC 同步使用的 Topic 中写数据,否则会导致 JDBC-Connector 异常,报空指针的错误;
• 确认OMS 对 DECIMAL、FLOAT 或 DOUBLE 等列类型的迁移精度是否符合预期;
• 变更目标端的唯一索引,需要重启增量同步组件,否则可能存在数据不一致的问题;
• OMS 进行增量数据同步时,必须部署 TxCDC+ Kafka,不然无法进行增量同步。
在使用OMS工具进行迁移时,有几点注意事项需特别关注。
首先,在进行源端迁移时应禁止执行库或表结构变更DDL操作,以确保数据一致性。其次,OMS不支持目标端存在Trigger OMS。另外,目前OMS支持的某DB数据库版本为4.x和5.4,且不支持迁移该DB数据库的无主键表,以及包含空格的数据至OceanBase 数据库 MySQL 租户。
另需注意,OMS仅支持TxCDC Open Protocol协议,不支持其他协议。这是在使用OMS进行迁移时必须考虑的一个重要因素,如果使用不支持的协议,会导致JDBC-Connector 异常,报空指针的错误
我们曾遇到一个问题,迁移的表虽有主键,但主键分布不连续,这导致迁移速度极慢。因为OMS在迁移时会根据主键分区,若主键不连续,则分区过小,严重影响迁移效率。为此,我们后期调整了分区策略,增大了主键分区范围,从而显著提升了迁移速度。
最初,迁移速度约为每秒5000行,经过优化后,最终达到了每秒50万行,提升是非常可观的。
某DB 迁移到 OceanBase 的OMS数据同步
接下来,关于迁移的同步过程,
首先需要创建一个数据源并配置某TxCDC+Kafka。完成配置后,就进入了常规的迁移流程;接着是前期的配置校验,确保账号数据的一致性;接着,对DDL操作进行表面高暂停修改;然后,切换应用的数据源名称,并处理剩余的数据库连接;此后,停止正向同步,并开启反向同步作为回滚机制,以备迁移不成功时使用。
某DB 迁移到 OceanBase 的迁移流程
对于MySQL到OceanBase的迁移,其流程与某DB的迁移大致相似,但相对更为简单:
首先也是进行可行性评估,随后使用OMS工具执行迁移。在迁移过程中,MySQL需要开启binlog,并创建相应的用户账号。
此外,还需关注以下几点:
• 确保源端和目标端数据库的Collation一致,不然可能导致数据同步不一致;
• VARCHAR 作为主键的表数据校验会不一致;
• 确认DECIMAL、FLOAT、DOUBLE 等列类型的迁移精度是否符合预期,可能发生截断现象,导致源端和目标端的数据不一致;
• 确保源端和目标端表结构一致,不然数据同步失败。
关于MySQL到OceanBase使用OMS进行的迁移,存在多种方案。
若连接主库进行迁移,可采取结构迁移、全量迁移、增量同步、全量校验,以及反向增量迁移的组合方式。而若连接备库,则主要进行全量迁移和全量校验。
考虑到直接从主库拉取数据可能带来风险或性能影响,一种优化的迁移模式是:从备库拉取全量数据,同时从主库拉取增量数据,实现主备库协同迁移。
这种迁移流程大致与上文所述相似,包括配置账号、一致性校验等步骤。最终,需将数据源切换到OceanBase,并停止OMS正向同步,开启反向同步以备不时之需。
展望未来,我们计划继续迁移更多对业务有痛点的MySQL集群至OceanBase数据库,并逐步将线上某分布式DB集群全部迁移至OceanBase。同时,我们将大力投入生态建设,针对公司内部MySQL的上下游工具,进行OceanBase工具的适配工作,确保业务迁移的顺畅性,让使用者几乎感受不到任何差异。
此外,我们将持续完善OceanBase数据库的工具体系,尤其是DaaS数据库平台,开发和完善慢日志、审计日志等功能,以及公司内部统一监控告警系统。我们也考虑将当前使用的OCP告警平台整合进公司统一的告警系统中,以提升运维的效率和便捷性。
","description":"在日新月异的手机通讯行业中,vivo始终保持着先锋者的姿态,不断推动着技术的革新与进步。然而,随着业务的不断扩展和数据量的急剧增长,vivo互联网在数据库方面遇到了前所未有的挑战。原有的MySQL数据库逐渐无法满足业务需求,尤其是在处理海量数据和应对高并发场景时,显得力不从心。因此,vivo决定进行数据库替换,寻找一种更加高效、稳定且可扩展的数据库解决方案。vivo数据库工程师王翔分享了他们的数据库替换历程和实践经验。他提到,vivo在选择新的数据库时,充分考虑了业务需求、技术发展趋势以及成本效益等多个因素。经过深入的调研和对比…","guid":"https://www.infoq.cn/article/wYicgCtaKJ7ThXIXTxH8","author":"王翔","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-12-31T06:39:45.297Z","media":[{"url":"https://static001.geekbang.org/infoq/a5/a5997bbae74b662af01576d21b4d9ded.png","type":"photo","width":1280,"height":549,"blurhash":"LRR3pE-:oex]~nt6azoe-iRlWEoe"},{"url":"https://static001.geekbang.org/infoq/cc/cca49802a2c5241ee524d870d4598d2d.png","type":"photo","width":844,"height":720,"blurhash":"LGR:NX~W~B-=?dofatjwtOkXxuRk"},{"url":"https://static001.geekbang.org/infoq/3b/3b4d84d87ed101aca5502ddc837f35cd.png","type":"photo","width":1280,"height":613,"blurhash":"LbLr7F%M%Lbx~mRnD;jY^#t3$_oe"},{"url":"https://static001.geekbang.org/infoq/72/72a13a84b6e9c42e558572567a05994c.png","type":"photo","width":1280,"height":521,"blurhash":"LFQmSN_2_2_3x_t6W?Iq~SM}RkxZ"},{"url":"https://static001.geekbang.org/infoq/92/928ef60c22e5b9416d3322321dbd8eba.png","type":"photo","width":1280,"height":547,"blurhash":"LGR3mA?boe_20sxYxXR-9NRnt4az"},{"url":"https://static001.geekbang.org/infoq/f0/f0ccc4bba3b7dfca6cea04b5c72f433e.png","type":"photo","width":1280,"height":247,"blurhash":"LzOg.=bvNbt7%LofoJX7~Cs:w^of"},{"url":"https://static001.geekbang.org/infoq/e7/e7632a41124c24e1dc6da30dd2015739.png","type":"photo","width":1280,"height":398,"blurhash":"LES6iB~D-V~p^+E1ofxb;AELSxoz"},{"url":"https://static001.geekbang.org/infoq/32/3275368b7d49639fe144ec53f35336e4.png","type":"photo","width":1280,"height":467,"blurhash":"LAQ]yh?vxu~qnOe-s.M{4-WXt7of"},{"url":"https://static001.geekbang.org/infoq/d7/d706bb2cc717b7f4a7b454968174091d.png","type":"photo","width":1254,"height":720,"blurhash":"LgQ]=~xttS?H~SRnR*RQIWWVWVRj"},{"url":"https://static001.geekbang.org/infoq/4a/4aab0088cdb976ff8e68dbfa30572d93.png","type":"photo","width":1280,"height":576,"blurhash":"LGP%n,5I^t~p0WE8%E-njMWH%J$_"},{"url":"https://static001.geekbang.org/infoq/93/93d316a7d9a77881bd0519b395d9f3df.png","type":"photo","width":1280,"height":623,"blurhash":"LKR{+3-p-.~qx^ofayxW-QV@R-Ny"},{"url":"https://static001.geekbang.org/infoq/8f/8f67794994fbc823aea02647504f1822.png","type":"photo","width":1280,"height":535,"blurhash":"LRPZ_%Iv~S%gNPRn${t5NNWZxpxV"},{"url":"https://static001.geekbang.org/infoq/fa/fa17b0041caeb9e322b476c6dcd5e7cb.png","type":"photo","width":1280,"height":618,"blurhash":"LIQA2G?a~n_3EXs+?9kCOdxtxTM{"}],"categories":["数据库"],"attachments":null,"extra":null,"language":null},{"title":"C++用了11年,仅17位贡献者代码提交超过10次,迁移到Rust后,再也不想回去了","url":"https://www.infoq.cn/article/t5QdUG6FZkcvrcjiUR59","content":"编者按: 本月初,Fish Shell 4.0正式进入beta测试阶段,主要变化就是从C++迁移至Rust。如今,随着大部分Fish Shell代码被成功转换为Rust(正式发布Fish 4.0 beta测试版,几乎百分之百由Rust代码构成),项目组日前也发布了一篇博文,回顾了他们在将大型C++代码库迁移至Rust过程中的种种心得与挑战。 Fish (英语:friendly interactive shell) 是一个Unix shell\\"。Fish旨在成为一个比其他shell交互性更强、用户体验更好的shell,并让其丰富的强大功能能够被用户轻松发现、记住并学以致用。它由 Axel Liljencrantz 于 2005 年创建。由于不符合 POSIX shell 标准,Fish的语法既不派生于Bourne shell也不派生于C Shell,故被分类为一种“外来”shell。有别于为节约系统资源而默认禁用部分功能的其他shell,Fish的全部功能都是默认启用的。 Fish Shell开发人员指出,他们遇到的一系列C++难题,促使其开始积极探索其他语言。最核心的难题体现在工具及编译器/平台差异、人体工程学与线程安全以及开发社区等。举例来说,Fish曾尝试用C++制作一个真正的多线程执行原型,整个过程对于该开源shell项目而言痛苦万分。 至于为何使用Rust语言,他们坦言“Rust很酷,也很有趣。”他们高度评价了Rust的工具、便捷设置、出色的人体工程学、更好的依赖项管理以及强大的发送与同步功能,这一切都使其非常适合线程处理类的应用场景。 开发人员们也承认,Rust语言仍存在一些不足,例如可移植性处理能力不佳、工具有时未能考虑到其他目标并存在某些本地化问题。有人指出,Cargo虽然特别适合构建需求,但在涉及安装的场景下Fish仍然选择了CMake。 Fish项目组在博文结尾写道: “整个迁移过程并非没有挑战,期间也出现了不少计划之外的状况。但总的来说,进展还算顺利。我们现在拥有一套我们非常喜爱的代码库,其中不乏如果沿用C++将很难实现的功能。另有更多功能正在开发当中,我们正在开发单独的3.7版本,期待能将更多酷炫的成果带给广大用户。” 本文将带大家回顾Fish Shell编程语言的迁移历程、经验心得、教训与不足,以及接下来的规划。
因为我们被C++折磨得不轻,包括:
工具与编译器/平台差异;人体工程学与线程安全问题;社区活力不足。
坦率地讲,C++的语言生态并不好。比如说,因为C++没有“rustup”、也没有在旧有操作系统上安装最新C++编译器的标准方法,所以我们在为LTS Linux和其他早期版本macOS发布最新Fish软件包时就遇到了麻烦。
Fish还被迫使用线程来实现广受好评的自动建议与语法高亮显示,添加并发性的计划也因为C++的自身局限而长期缺乏进展。
这里跟大家说个秘密:虽然外部命令能够并行运行,但FISH的内部命令(内置命令与函数)目前仍只能串行执行,而无法在后台运行。解除这一限制将实现异步提示和非阻塞补全等功能,同时提高性能表现。
POSIX shell选择用子shell来解决这个问题,但子shell是一种不完善的抽象,可能会在种种意想不到的情况下造成麻烦。我们希望尽量避免这些不可控的因素。
我们还尝试使用C++开发真正的多线程执行原型,但没能成功。比如说,其很容易意外跨线程共享对象,还得配合Thread Sanitizer等辅助工具才能防止此类问题。
C++的人体工程学也很糟糕——头文件很烦人、模板很复杂、经常触发编译错误,导致标准库中出现大量重载。许多函数使用起来不够安全,C++字符串处理非常冗长,许多方法的重载都容易引起混淆,因此很容易变成C样式的字符指针并引发安全风险。总而言之,C++是一种优先考虑性能、而非人体工程学的语言,这对开发者显然很不友好。
Curses这个C库则是C++开发实践中相当典型的案例。这是个用于访问终端功能的古老库,我们用它来访问terminfo数据库,后者负责描述终端功能与行为中的差异。
整个过程不仅相当麻烦、用起来也不够安全,而且感受上也很别扭——cur_term指针(有时是宏)可以为NULL,经常在意想不到的地方被取消引用,而且在源代码构建时也会引发大量问题。
最后得承认,C++对开发者的吸引力不强,贡献者们其实对它有点“嫌弃”。在FISH使用C++这11年里,只有17位提交量超过10次的贡献者。
所以值此离别之际,我们也想给C++社区提点感想:希望C++语言和工具的人体工程学及安全性能有所改进,这些改进其实比性能更重要。我们也希望C++编译器在实际系统上的升级过程能简单一点。
因为Rust很酷,也很有趣。
首先,FISH只是个业余项目,所以我们都是用爱发电来参与的。没人因为开发FISH而拿过一分钱报酬,因此趣味性就成了留住贡献者的关键。
Rust的工具生态也很出色,注重实用性且编译器错误机制出色。这可不是跟C++相比,而是Rust拥有绝对意义上优秀甚至卓越的错误消息机制,非常棒。
其安装体验也很好——Rustup堪称神奇,能够让大家快速上手、将root权限使用频度降到最低。相较于C++编译器那复杂到爆炸的升级流程,Rust这边只须使用rustup。
Rust具有出色的人体工程学——即使对于刚刚接触的新手来说,C++指针也是被碾压的一方。
Rust还有明确的使用系统,能够帮助开发人员确切了解哪个函数来自哪个模块,要比C++的#include好用很多。
Rust的依赖项添加体验也更好。现在我们可以轻松使用各种工具能够读取的特定格式,而Rust则顺畅支持YAML/JSON/KDL等主流选项。
从FISH shell的角度来看,Rust真正的王炸其实是Send和Sync,即静态执行线程规则。“无所顾虑地并发”太强大了,我们可以通过Send和Sync实现完全的多线程执行,并对其正确性充满信心。
当然,肯定也有其他同样适合的编程语言,只是我们没有那么多时间一一了解。我们相信Rust能够胜任这项任务,并果断开始行动。
网上有不少关于Rust平台支持力偏弱的讨论,但在我们这边没什么大问题——我们的macOS、Linux和BSD几大平台都受支持,Opensolaris/Illumos和Haiku也不在话下。反正我们是没听说过有人想在NonStop上运行FISH。
从Debian系统的流行度来估算,99.9995%的Debian设备都安装有Rust包。再结合Fish在Debian系统中1.92%的安装比例来看,预计每25万台设备中只有两、三台不受支持,完全可以接受。
跟很多网友的猜测不同,我们并不是为了支持原生Windows端口才转向Rust的。其实Fish本质上是一款UNIX shell,它不仅依赖于UNIX API,还依赖于其语义,并且在脚本语言中直接暴露。总之我们是搞UNIX的,开发的也是UNIX shell,跟Windows shell没啥关系。
我们唯一关注但缺乏支持的平台是Cygwin,很遗憾,但一点点妥协也完全可以接受。
我们决定以“忒修斯之船”的方式完成移植——即逐个组件迁移,直到C++代码被彻底替换掉。而且在过程中的每个阶段,项目都仍能正常运行。
这非常必要,因为如果不这样做,我们在几个月时间里就没有可以正常工作的版本。这不仅令人沮丧,还会影响大部分测试套件(即运行脚本或者伪终端交互的端到端测试)的正常运行。
闭门造车的问题就在这里——不光迁移可能根本没法完成,而且在测试阶段没准还要打回重来。此外,这种方式也让我们保持了C++代码结构的基本完整,这样我们可以比较迁移前后的情况,找出转译错误出现在哪里。
因此,我们使用autocxx生成C++与Rust代码之间的绑定,确保每次只移植一个组件。
移植的第一步从内置函数开始。这些函数本质上就是小型独立程序,拥有自己的参数、流、退出代码等。也就是说,只要有办法从C++这边调用Rust内置函数,就能轻松将它们与shell的其余部分拆解开来分别移植。
对于如何将函数接入主shell,我们使用了以下三种方法:
添加FFI胶水代码,使得Rust可以调用C++函数,这样就能先移植调用方、后移植被调用函数。将被调用函数迁移至Rust,如有必要则保证其可从C++处调用。编写被调用函数的Rust版本,并从移植后的调用方处调用,且继续保留C++版本。
例如,几乎每个内置函数都需要解析其选项。我们有自己的getopt实现,并在初始PR中用Rust进行了重新实现,但同时也将C++版本保留到了最后。若非如此,我们就得编写一个C++到Rust的桥接器,再调整C++调用方来使用,这显然就太麻烦了。
迁移工作大概就是这样有序推进,但最终我们还是遇到了更复杂的系统,这时必须选择更大的移植块,从而减少需要临时编写并终将被丢弃的FFI胶水代码的数量。比如说输入/输出“读取器”,作为FISH中最大的部分,其最终转换成了约1.3万行Rust代码。
在移植过程中,我们在autocxx上遇到了不少问题。有时候它理解不了特定C++ construct,我们只能花时间尝试解决。比如说,我们在C++端引入了一个打包C++向量的construct,但出于某种原因,autocxx总是弹出vector。为此我们不得不通过分叉添加了对wstring/wchar的支持。但请大家别误会,当初使用wchar就是个错误,只是年深日久确实不太好改了。
另外,因为autocxx生成了大量代码,所以某些辅助工具的表现也不如预期。比如rust-analyzer的运行速度就特别慢。
总之,虽然我们的代码库已经算是相当适合迁移至Rust(因为没怎么使用异常或者模板),但autocxx的使用体验确实一般。它能正常起效的确令人眼前一亮,也确实帮助我们完成了移植,但距离完美还差得很远。
初始PR发布于2023年1月28日,并于2023年2月19日合并。Fish 3.7.0是C++分支下的另一个版本,用于整理某些增量改进,于2024年1月发布。最后一点C++代码于2024年1月被彻底删除(残留的额外测试代码于2024年6月12日被移植至C)。首个移植后的beta测试版于2024年12月17日发布。
当初的移植计划本来打算在半年之内完成,最终显然没有达成,但大家对此并不失望。坦率地讲,14个月也是份相当不错的成绩了,毕竟我们在期间还发布了一个C++版本,就是说迁移工作甚至没有打乱我们的常规发布节奏。
大部分工作是由7位贡献者完成的(即至少提交过10次.rs文件的贡献者),同时也要感谢很多社区成员的热心参与。
造成延迟的原因主要有以下几点:
“最后10%需要翻倍的时间才能完成”——我们进行了全面测试,清除了大量bug。如果急于发布,那绝对是个极其糟糕的版本。不光是迁移,还要有新东西——用新代码做同样的事情没啥意义,一定要有所差别。所以我们推迟了发布,直到做出让人眼前一亮的成果。有时候,部分成员需要休息一段时间,这也是人之常情。
所以大家在评判之前,请先了解一个基本事实:我们只是一群志愿者,大家完全是在自发参与,能做成这样已经很不容易了。
必须承认,Rust并不完美,我们对它的某些状况也颇有微词。
最主要的一点就是Rust对于可移植性的处理方式。虽然它提供大量系统抽象,允许使用相同的代码指向多种系统,但在较低层级的系统上进行代码适配时,仍然完全依赖于手动枚举,即使用#[cfg(any(target_os = \\"freebsd\\", target_os = \\"netbsd\\", target_os = \\"openbsd\\"))]之类的检查。
这个办法明显有很多问题,可能会遗漏某些系统并忽略版本间的差异。据我们所知,libc能够能够为我们要使用的函数添加FreeBSD 12,但如果不经精心检查,在FreeBSD 11上直接调用则会触发失败。
但直接在代码中列出目标,实际上是在重复libc crate(在本项目中)已经完成的工作。所以要想调用libc::X(仅在系统A、B和C上定义完成),则需要单独为A、B和C添加该检查;如果libc添加了系统D,则需要额外添加。好在我们使用自己的rsconf crate在build.rs中实现了编译时功能检查。
假如Rust能有某种形式的“如果该函数存在,则将其编译”的功能——#[cfg(has_fn = \\"fstatat\\")],那情况就会好得多。这样libc create就能进行任何检查,而FISH则遵循其结果,帮助我们大大精简现有rsconf。现在的方案无法支持缺少某些功能的陈旧发行版,只能通过min_target_API_version cfg来解决。
我们还遇到了本地化问题——Rust往往依赖于在编译时检查的格式字符串,可遗憾的是这些内容无法转译。我们只能将musl移植为printf,这是我们内置printf函数运行所需,确保在运行时内复用预先存在的格式字符串。
迁移期间我们也遇到了不少错误。例如,我们最初使用一个复杂的宏以允许将字符串写为“foo”L,但其最终未能起效,所以我们将其删除并转而使用更常规的L!(“foo”) 宏调用。
libc crate中的弃用警告也经常让人摸不着头脑。它解释说“time_t”将在musl上转换为64位。我们曾尝试解决这个问题,添加了很多打包器,但最终发现其实没有实际影响,毕竟我们不会把从一个C库处获取的time_t传递到另一个C库。
有时对原始代码中细微差别的忽略也会引发bug,进而导致崩溃。比如我们使用了断言或者断言的现代实现“.unwrap()”。这通常就是转译C++的直接方法,但事实证明其准确性不足,有时需要替换成其他错误处理机制。
但总的来说,这些问题并不太难发现。而且出现之后,往往经常几次尝试和调整就能解决,所以就还好。
我们还因为开启了link-time-optimization并在CMake默认使用发布bulds(目前需要运行完整的测试套件)而引发了一些问题,导致构建时间意外超过预期。
虽然抱怨不少,但迁移至Rust的好处也随着时间推移而开始显现。
还记得我们之前提到的(n)curses问题吗?现在问题没了,因为我们压根就不使用curses。相反,我们转为使用一个Rust包,它唯一的功能就是访问terminfo并扩展其序列。这消除了尴尬的全局状态,用不着费心保证在系统上“正确”安装curses——cargo下载相应包并构建就行。
我们仍然会读取terminfo,就是说用户还是需要安装。但这个过程可以在运行时内完成,其已经预安装在所有主流系统之上;如果找不到,也只需使用xterm-256color定义的随附副本。
我们还高潮创建了“自安装”FISH包,其中包括FISH二进制文件在运行时写出的所有函数、补全及其他资产文件。如此一来,我们就能创建静态链接版本的FISH(在Linux上则使用musl,因为glibc总会崩溃且无法解决),这样我们就第一次拥有了能够在任意Linux上下载并顺利运行的单独文件(唯一需要注意的就是架构匹配)!
对于想要使用FISH,但有时候又需要以SSH接入服务器的朋友来说,这无疑是个巨大的福音。他们可能没有root访问权限来安装软件包,而现在一个scp就能解决所有问题。
我们当然也可以使用C23的#embed实现类似的效果,但Rust的办法更简单也同样有效。
我们没能成功完成的一项目标,就是在移植之后删除CMake。
这是因为Cargo虽然在构建方面表现出色,但在安装方面却过于简单粗暴。Cargo希望把所有内容都塞进几个简洁的二进制文件之内,但这对我们的项目并不适用。FISH拥有约1200个.fish脚本(961条补全,217条相关函数),外加约130页的说明文档(html及手册页面),外加web-config工具与手册页面生成器(均由Python编写)。
项目中还有一个测试套件,其在单元测试方面比重不大,主要关注端到端脚本和交互式测试方面。脚本测试通过我们自己的littlecheck工具运行,该工具会运行脚本并将输出结果与嵌入的注释进行比较。交互式测试由pexpect驱动,其会模拟终端交互并检查按下按钮时是否触发了正确的行为。
于是我们保留了精简版的CMake来完成上述任务,但将构建工作移交给了Cargo。
当然,也可以把这些都交给更简单的任务运行器,比如Just或者更常见的makefiles。但因为之前的设计运行良好,所以我们决定暂时保留,这样对于程序包来说构建过程并不会发生实质性改变。
我们暂时未将Cygwin列为受支持平台,因为Cygwin无法针对Rust构建二进制文件。我们希望这种情况未来会有所改变,但目前在Windows上运行FISH的唯一方法只有使用WSL。
我们这个巨大的迁移项目取得了成功,下面列举几个数字让大家直观感受一下:
变更文件达1155个,涉及110247次插入(添加)、88941次删除(削减),其中不包括转译。200多位贡献者共提交2604次。提交498个问题。近2年的工作周期。将57000行C++迁移为75000行Rust(外加400行C)。彻底清退C++代码。
目前的beta版本运行良好,性能整体上比之前的版本略好一些,内存使用量的下限比之前高、但上限比之前低——闲置时为8M,高于之前的7M;但即使是在运行高负载任务时也不会增加太多。当然,这些还有改进的空间,但对于初步迁移成果来说已经令人相当满意了。
必须承认,如今的FISH还是有点怪……作为一款Rust程序,它仍然会直接使用C API,也在沿用UTF-32字符串。希望接下来能找到更好的解决方案,但在迁移后的首个版本中,就不要求那么多啦。
移植过程的确充满挑战,很多工作也没能按计划进行。但总体来看,进展还算相当顺利。现在我们拥有了让人更加心情舒畅的新代码库,增添了不少在C++时代难以处理的功能,另有更多功能正在开发当中。
总之,Rust干得不错,我们很开心。
原文链接:
https://fishshell.com/blog/rustport/\\"
","description":"编者按: 本月初,Fish Shell 4.0正式进入beta测试阶段,主要变化就是从C++迁移至Rust。如今,随着大部分Fish Shell代码被成功转换为Rust(正式发布Fish 4.0 beta测试版,几乎百分之百由Rust代码构成),项目组日前也发布了一篇博文,回顾了他们在将大型C++代码库迁移至Rust过程中的种种心得与挑战。 Fish (英语:friendly interactive shell) 是一个Unix shell\\"。Fish旨在成为一个比其他shell交互性更强、用户体验更好的shell,并让其丰富的强大功能能够被用户轻松发现…","guid":"https://www.infoq.cn/article/t5QdUG6FZkcvrcjiUR59","author":"Fish Shell","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-12-31T06:21:08.010Z","media":null,"categories":["编程语言"],"attachments":null,"extra":null,"language":null},{"title":"Spring近期新闻:Boot、Security、Authorization Server和Session的新版本发布","url":"https://www.infoq.cn/article/If2eGh3CIbQFLmzIh8Xi","content":"最近,Spring 生态系统活动频繁,主要发布了Spring Boot、Spring Security、Spring Authorization Server、Spring Session、Spring Integration、Spring Modulith、Spring Batch、Spring AMQP、Spring for Apache Kafka、Spring for Apache Pulsar和Spring Shell的新版本。
Spring Boot\\"的3.4.1\\"版本和3.3.7\\"版本改进了文档、升级了依赖关系并解决了一些值得注意的问题,例如,由于Log4J2LoggingSystem类中定义的getShutdownHandler()方法持有对底层环境的引用,导致SpringApplicationShutdownHandlers接口的实现无法按确定的顺序运行;在启用虚拟线程的Java 21上启动 Maven shaded应用程序时出现UnsupportedOperationException异常。有关这些版本的更多详细信息,请参阅3.4.1版本\\"和3.3.7版本\\"的发布说明。
Spring Security\\"的6.4.2版本和6.3.6版本包含了缺陷修复、依赖关系升级和6.4.2版本中的新特性,例如,改进了AuthorizationManager接口错误信息的配置;新的WebAuthnWebDriverTests类可验证完整的端到端Web身份认证流程,包括默认登录和注销页面中打包的JavaScript代码。关于这些版本的更多详细信息,请参阅6.4.2\\"版本和6.3.6\\"版本的发布说明。
Spring Authorization Server\\" 1.4.1版本和1.3.4版本提供了缺陷修复、依赖关系升级和1.4.1版本中的新特性,例如,用emptyMap()方法取代unmodifiableMap()方法(这两种方法都定义在Java Collections类中),因为emptyMap()返回的是声明为final的Java Map实例;如果缺少参数,则使用一致的方法为令牌类(如OAuth2DeviceVerificationAuthenticationToken类)创建空 Map。有关这些版本的更多详细信息,请参阅1.4.1版本\\"和1.3.4版本\\"的发布说明。
Spring Session\\"的3.4.1版本和3.3.5版本分别对Spring Framework 6.2.1和6.1.16、Spring Security6.4.1和6.3.6、Spring Data 2024.1.1和2024.0.7以及Project Reactor 2023.0.13进行了依赖关系升级。关于这些版本的更多详细信息,请参阅3.4.1版本\\"和3.3.5版本\\"的发布说明。
Spring Integration\\"的6.4.1版本和6.3.7版本提供了缺陷修复、依赖关系升级和一项新功能,即在不需要回复的AbstractReplyProducingMessageHandler类实例未启用日志记录时,可避免记录消息。关于这些版本的更多详细信息,请参阅6.4.1版本\\"和6.3.7版本\\"的发布说明。
Spring Modulith\\"的1.3.1版本、1.2.7版本和1.1.12版本发布\\",提供了缺陷修复、依赖关系升级和功能改进,例如,Spring Boot兼容性矩阵;更新了Asciidoctor类,以增强应用模块画布的渲染;允许在调用ApplicationsModules类中定义的detectViolations()方法时过滤Violations类。关于这些版本的更多详细信息,请参阅1.3.1版本\\"、1.2.7版本\\"和1.1.12版本\\"的发布说明。
Spring Batch\\"的5.2.1版本和5.1.3版本发布\\",提供了缺陷修复、文档改进、依赖关系升级和一项新功能,即解决由于PostgreSQL数据库与DatabaseType枚举类中的EnterpriseDB引用之间关联缺失而导致的IllegalArgumentException异常。有关这些版本的更多详细信息,请参阅5.2.1版本\\"和v5.1.3版本\\"的发布说明。
Spring AMQP\\" 3.2.1发布,提供了缺陷修复、文档改进、依赖关系升级以及一项新特性,该特性提供了CachingConnectionFactory类与Spring Boot RabbitProperties类之间的兼容性。关于该版本的更多详细信息,请参阅RabbitProperties发布说明。
Spring for Apache Kafka\\"的3.3.1版本和3.2.6版本发布\\",提供了缺陷修复、文档改进、依赖关系升级和新功能,例如,与Kafka Client\\" 3.9.0 兼容;移除synchronized关键字,改用可重入锁,以确保这些方法对虚拟线程友好,从而避免阻塞和锚定(pinning);能够直接配置观测注册表,而不是从应用程序上下文中获取。这些版本分别包含在了Spring Boot 3.3.7和3.4.1中。关于这些版本的更多详细信息,请参阅3.3.1版本\\"和3.2.6版本\\"的发布说明。
Spring for Apache Pulsar\\" 1.2.1和 1.1.7发布\\",提供了文档改进和相应的依赖关系升级,例如,它们分别对应了Spring Framework 6.2.1和6.1.16、Micrometer Metrics 1.14.2和1.13.9以及Project Reactor 2024.0.1和2023.0.13。这些版本分别包含在了Spring Boot 3.3.7和3.4.1中。关于这些版本的更多详细信息,请参阅1.2.1版本\\"和1.1.7版本\\"的发布说明。
Spring Shell\\" 3.3.4发布\\",该版本将依赖关系升级到了Spring Boot 3.3.6和Apache Commons IO\\" 2.18.0。关于该版本的更多详细信息,请参阅发布说明\\"和更新日志\\"。
原文链接:
Spring News Roundup: Delivering Point Releases of Boot, Security, Authorization Server, Session\\"
","description":"最近,Spring 生态系统活动频繁,主要发布了Spring Boot、Spring Security、Spring Authorization Server、Spring Session、Spring Integration、Spring Modulith、Spring Batch、Spring AMQP、Spring for Apache Kafka、Spring for Apache Pulsar和Spring Shell的新版本。 Spring Boot\\n\\nSpring Boot\\"的3.4.1\\"版本和3.3.7\\"版本改进了文档…","guid":"https://www.infoq.cn/article/If2eGh3CIbQFLmzIh8Xi","author":"Michael Redlich","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-12-31T01:43:46.886Z","media":null,"categories":["编程语言"],"attachments":null,"extra":null,"language":null},{"title":"Java近期新闻:TomEE 10、Struts 7、Payara Platform、GlassFish、Commonhaus Foundation和Gradle","url":"https://www.infoq.cn/article/dBSx0TfggOyiHaUhLfNN","content":"JDK 24的早期访问构建版本\\"的Build 29\\"发布,该版本是对Build 28的更新\\",其中包括对各种问题\\"的修复。关于这个版本的更多细节可以在发布说明\\"中找到。
JDK 25的早期访问构建版本\\"的Build 3\\"发布,该版本是对Build 2的更新\\",其中包括对各种问题\\"的修复。关于这个版本的更多细节可以在发布说明\\"中找到。
对于JDK 24\\"和JDK 25\\",鼓励开发人员通过Java缺陷数据库\\"报告缺陷。
GlassFish\\" 8.0.0的第九个里程碑版本\\"包含了除Jakarta Data以外的所有Jakarta EE 11-M4规范。其他值得注意的变更包括:改进了EntityManagerFactoryWrapper类,删除了未使用的_logger字段并添加了serialVersionUID;删除了web.xml文件中的jakarta.faces.PARTIAL_STATE_SAVING属性,该属性在Jakarta Faces 4.1\\"中已被弃用。该版本还支持使用CDI进行Jakarta Persistence注入,并与GlassFish 7进行了同步。关于该版本的更多详细信息,请参阅发布说明\\"。
最近,Spring社区比较忙碌,各个团队先后发布了Spring Boot\\"、Spring Security\\"、Spring Authorization Server\\"、Spring Session\\"、Spring Integration\\"、Spring Modulith\\"、Spring Batch\\"、Spring AMQP\\"、Spring for Apache Kafka\\"、Spring for Apache Pulsar\\"和Spring Shell\\"的新版本。更多详情,请参阅InfoQ的新闻报道\\"。
Payara发布\\"了Payara Platform\\"的2024年12月版本,包括社区版6.2024.12、企业版6.21.0和企业版 5.70.0。这三个版本都解决了一些值得注意的问题,比如,在反序列化Jakarta Validation ConstraintViolation接口的实例时会出现ClassCastException异常;WebappClassLoader类会出现NullPointerException异常。社区版现在通过 Eclipse Krazo 3.0.1\\"支持了Jakarta MVC 2.1\\"规范,这是该规范的实现之一。有关这些版本的更多详细信息,请参见社区版6.2024.12\\"、企业版6.21.0\\"和企业版5.70.0\\"的发布说明。
本次发布还包含了Payara社区版7.2024.1的第三个alpha版本,该版本支持即将发布的Jakarta EE 11,并实现了Jakarta Security\\"规范。
IBM发布\\"了Open Liberty\\" 25.0.0.1-beta版本,该版本具有更强的密码加密功能,支持AES-256\\"密码加密;并更新了Open Liberty的功能,包括Batch API\\" (batch-1.0)、Jakarta Batch 2.0\\"(batch-2.0)、Jakarta Batch 2.1\\"(batch-2.1)、Java Connector Architecture Security Inflow 1.0\\"(jcaInboundSecurity-1.0)、Jakarta Connectors Inbound Security 2.0\\"(connectorsInboundSecurity-2.0),以支持InstantOn\\"。
Apache TomEE\\" 10.0.0发布\\",提供了缺陷修复、依赖关系升级和新特性,比如,Jakarta Security @OpenIdAuthenticationMechanismDefinition注解的实现;在TomEEMicroProfileListener类中添加了Jandex\\"索引缓存。关于此版本的更多详情,请参阅发布说明\\"。
Apache Struts\\" 7.0发布\\",提供了缺陷修复、依赖关系升级和新功能,比如,将JDK 17作为最小版本;支持Jakarta EE 9+,即从javax命名空间迁移到jakarta命名空间;实现更强的默认安全设置。关于该版本的更多详情,请参阅发布说明\\"。InfoQ将跟进更详细的新闻报道。
Apache Tomcat\\"团队披露了两个影响Tomcat 11.0.0-M1至11.0.1、10.1.0-M1至10.1.33以及9.0.0.M1至9.0.97版本的公共漏洞和暴露(Common Vulnerability and Exposure,CVE)(分别参见此处\\"和此处\\"):
CVE-2024-50379\\",Time-of-Check-Time-of-Use\\"漏洞,在该漏洞中,对于大小写不敏感的文件系统,启用写入功能的默认servlet可以绕过Tomcat的大小写敏感检查,并导致上传的文件被视为JSP,从而导致远程代码执行。CVE-2024-54677\\"漏洞,在该漏洞中,web应用程序示例未对上传的数据设置限制,从而引发OutOfMemoryError,导致拒绝服务。
建议开发人员升级到Tomcat 11.0.2+、10.1.34+和9.0.98+版本。
Infinispan\\" 15.1.0(代号为It Was All A Dream\\")发布\\",该版本提供了如下特性:新的Java Hot Rod客户端,取代当前的hotrod-client模块;支持基于地理条件进行地理化查询;嵌套实体连接,允许根实体和嵌入实体之间的嵌套关系,即非扁平化关系,以便连接它们的值进行查询。关于该版本的更多详细信息,请参阅发布说明\\"。
JBang\\" 0.122.0发布,其特性包括:为不需要集成的JBang项目添加了--no-integrations标志和相应的//NOINTEGRATIONS指令;在构建文件和ProjectBuilder类中的javac命令中默认添加-parameters标志。关于该版本的更多详细信息,请参阅发布说明\\"。
Commonhaus基金会\\"是一个致力于开源库和框架可持续发展的非营利性组织,该基金会宣布\\"了SlateDB\\"和Debezium\\"加入该基金会。红帽首席软件工程师Chris Cranford\\"在2024年11月初发表的一篇博客文章\\"中介绍了这两个项目加入基金会的情况:
Commonhaus因创新性的治理框架和对项目独立性的承诺而脱颖而出。这将使Debezium社区及其合作者从中受益,因为我们可以继续保持与现在相同的发布节奏和对卓越的承诺。我们很高兴能加入Commonhaus的其他著名项目,包括Hibernate\\"、Jackson和Quarkus\\"。
加入该基金会的其他知名项目包括JReleaser\\"、JBang\\"、OpenRewrite\\"、SDKMAN\\"、EasyMock\\"、Objenesis\\"和Feign\\"。
Gradle\\" 8.12.0发布\\",其特性包括:增强Problems API\\",通过汇总问题报告中的重复条目,提高了错误和警告报告\\"的可读性,在使用API引发构建失败时增强了控制台输出\\";对平台的增强\\",包括支持在Alpine Linux发行版上监视文件系统,以及支持构建和测试Swift 6应用程序。关于此版本的更多详细信息,请参阅发布说明\\"。
原文链接:
Java News Roundup: TomEE 10, Struts 7, Payara Platform, GlassFish, Commonhaus Foundation, Gradle\\"
","description":"JDK 24 JDK 24的早期访问构建版本\\"的Build 29\\"发布,该版本是对Build 28的更新\\",其中包括对各种问题\\"的修复。关于这个版本的更多细节可以在发布说明\\"中找到。\\n\\n \\n\\nJDK 25\\n\\nJDK 25的早期访问构建版本\\"的Build 3\\"发布,该版本是对Build 2的更新\\",其中包括对各种问题\\"的修复。关于这个版本的更多细节可以在发布说明\\"中找到。\\n\\n \\n\\n对于JDK 24\\"和JDK 25\\",鼓励开发人员通过Java缺陷数据库\\"报告缺陷。\\n\\nGlassFish\\n\\nGlassFish\\" 8.0.0的第九个里程碑版本\\"包含了除Jakarta…","guid":"https://www.infoq.cn/article/dBSx0TfggOyiHaUhLfNN","author":"Michael Redlich","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-12-31T01:39:48.039Z","media":null,"categories":["编程语言"],"attachments":null,"extra":null,"language":null},{"title":"Kotlin 首席设计师访谈:Kotlin 与 Java 的差距有多大?","url":"https://www.infoq.cn/article/RPS2Qw092ScP1AWEydvs","content":"Kotlin 语言由 JetBrains 开发,并在 Apache2.0 许可下 开源,于 2011 年开始作为 Java 在 JVM (Java 虚拟机)上运行的应用程序的替代品,但从那时起,它就已经发展成针对 JavaScript、移动平台、原生可执行文件和 WebAssembly 的语言了。
Kotlin 首席设计师 Michail Zarečenskij 向 DevClass 讲述了 Kotlin 与 Java 的关系以及该语言的未来。
他告诉我们:“Kotlin 语言是作为 Java 的替代品出现的,当时我们想解决 Java 的一些局限性和问题,比如可空性、检查异常、不变数组等。”。
他说:“多年来,Kotlin 不断发展,现在我们才有了 Kotlin 多平台的故事,我们可以针对多个平台,比如 iOS、安卓等,我们有了 Kotlin Notebook,我们有了 Compose,这是一个用 Kotlin 编写 UI 的框架,我们还有 build.gradle.kts,用于在 Kotlin 中编写 gradle 脚本,但 JVM 部分和 Java 对我们来说仍然非常重要,实际上也是至关重要的。我们仍然希望与 Java 互操作,因为我们完全明白 Java 还会陪伴我们很多年,我们不想完全取代 Java。这是不可能的,这也不是我们的目标。”。
在某些情况下,Kotlin 正在等待 Java 或 JVM 特性的实现。他说:“如果 Java 能够尽快发布 Valhalla 项目,我们会很高兴,因为 JVM 的所有用户都能从中受益。”。
Valhalla 项目将会为 JVM 带来值类型等更多特性。
“Vahalla 项目和值类很好地融入了 Kotlin,因为许多应用程序都是围绕数学来展开的。”Zarečenskij 说到。它还可以使 Kotlin 具有运算符重载,这样“你不编必编写.plus,但实际上需要编写 +”或其它标准符号。他说:“这就是 Kotlin 的闪光点,所以我们渴望在 JVM 上看到值类型,这样我们就可以采用这一特性,并使其在 Kotlin 中更具表现力。”。
Kotlin 团队是否与发展 Java 语言的委员会合作?Zarečenskij 告诉我们:“这实际上取决于特性。我们进行了沟通,我们正在密切关注值类等问题,因为它主要是一个 JVM 特性… 我们必须调整它的一些设计,并了解设计决策,以便 JVM 也能成功地优化 Kotlin 的值类。”
Java 最近实现了 虚拟线程,这是 Loom 项目的一部分,Kotlin 的协程也同样用于并发编程,这有什么影响?
“它们的目标略有不同,”Zarečenskij 说道。“Loom 项目仍然使用 Thread API。这是我们多年来一直使用的 API,具有所有的优点和缺点。在 Kotlin 中,我们有结构化并发,即协程之间的父子关系。因此,协程之间的通信、取消协程或当其中一个协程出现异常时处理错误更容易。如果你需要这种细粒度的并发,并且想编写一个新的应用程序,那么 Kotlin 协程可能会更好。”
他补充道,“Kotlin 协程的缺点之一是,如果你有一个挂起函数,它实际上在底层使用了 Thread API,我们仍然会使用物理线程。我们实际上想做的是为 Kotlin 协同程启用 Loom 项目,所以如果你必须使用线程,那么你将能够使用虚拟线程… 这样就可以两全其美了。”
由于谷歌将 Kotlin 作为安卓开发的首选语言,这推动了 Kotlin 的发展。这是 Kotlin 的主要用途吗?
“Kotlin 的大部分使用仍然是在安卓中,但大约有 40% 到 45% 的 Kotlin 用户正在编写服务器端应用程序。”Zarečenskij 解释道。“我们看到了正在增长的多平台故事。”
Kotlin 没有官方的 JetBrains 语言服务器协议(LSP)实现。非 JetBrains IDE(如 Visual Studio Code)使用它来在编辑器、调试等中启用智能编程语言支持。这是为了让开发人员留在 JetBrains IDE 家族系列中,还是将来会有所改变?
“LSP 的故事非常有趣,我认为在某种程度上,它对我们来说至关重要。”Zarečenskij 说道。“我们很想为 Kotlin 提供一个合适的 LSP,因为如果 Kotlin 可以在许多 IDE 上呈现并得到良好的支持,这对 Kotlin 来说是一个好处。但是,例如,LSP 的设计方式不允许在 Java 和 Kotlin 之间进行通信。我们的主要功能之一就是互操作性,但如果你从 Java 调用 Kotlin,就不可能进入 Java LSP 并导航到 Kotlin LSP。因此,我们没有来自 JetBrains 的合适 LSP。目前至少有两个开源实现,我看到开发这些实现的人正在开发一个新版本,该版本利用了 K2 API,因为它一个很好的 API 分析。
“我希望它能够流行起来,那么你将会拥有一个合适的 Kotlin LSP。但互操作性会存在问题。”
K2 是最近发布了新的 Kotlin 编译器 。
Kotlin 的下一步是什么?Zarečenskij 说道:“关键特性是不变性和新的错误模型。”。他预计会有大量的新语言特性。“因为 K2 已经完成,现在我们正在开发这种语言。”他还补充到。
原文链接:
","description":"Kotlin 语言由 JetBrains 开发,并在 Apache2.0 许可下 开源,于 2011 年开始作为 Java 在 JVM (Java 虚拟机)上运行的应用程序的替代品,但从那时起,它就已经发展成针对 JavaScript、移动平台、原生可执行文件和 WebAssembly 的语言了。 Kotlin 首席设计师 Michail Zarečenskij 向 DevClass 讲述了 Kotlin 与 Java 的关系以及该语言的未来。\\n\\n他告诉我们:“Kotlin 语言是作为 Java 的替代品出现的,当时我们想解决 Java 的一些局限性和问题…","guid":"https://www.infoq.cn/article/RPS2Qw092ScP1AWEydvs","author":"作者:Tim Anderson","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-12-30T09:00:00.903Z","media":null,"categories":["编程语言"],"attachments":null,"extra":null,"language":null},{"title":"作业帮基于 Apache DolphinScheduler 3_0_0 的缺陷修复与优化","url":"https://www.infoq.cn/article/ViygpyDTyBjejTRXHb3W","content":"基于 DolphinScheduler 搭建的 UDA 任务调度平台有效支撑了公司的业务数据开发需求,处理着日均百万级别的任务量。整个 UDA 的架构如下图所示,其中我们的引擎层主要基于 DolphinScheduler 的 Master 和 Worker 服务搭建,充分利用了 Master 节点优秀的高并发调度能力、worker 节点的分组隔离能力。我们通过一层适配层对 DolphinScheduler 对外暴露的接口进行了封装和增强来适配我们的业务场景。
图 1-1 UDA 任务调度平台架构
随着使用的深入,我们发现 DolphinScheduler3.0.0 版本中存在一些难以通过运维手段规避的问题,这些问题影响数据平台的稳定性,导致隔一段时间需要重启服务来使集群恢复正常,并且核心组件对外暴露的可观测性指标十分有限,导致问题的排查定位过程十分繁琐。我们认为一个可以稳定运行的调度引擎应该具备以下能力
反压与过载保护机制:当系统负载比较高的时候,能够自动推迟任务执行,以保护自己。任务分配均衡:保证任务分配的均衡性,避免任务倾斜问题。无副作用运行:调度引擎在运行过程中不应对自身产生“副作用”,确保能够持续的长时间稳定运行。集群可观测性:具备全面的可观测性指标,能够通过这些指标评估集群的健康状态。
在这些能力上,开源版 3.0.0 的 DolphinScheduler 尚存在一些问题,对此,我们进行了系列优化改造和修复,同时积累了丰富的运维经验。
在某次巡检的过程中,我们发现服务节点的线程数在过去一段时间呈明显的上升态势,根据经验判断,应该是程序中存在线程泄漏的地方,结合 metrics 发现泄漏速度为恒定速率,并且与任务并发量无关。
图 2-1 JVM 线程数不断增长
通过堆栈发现泄漏的线程主要是与 HDFS 相关,进一步将代码范围缩小至 HadoopUtils 之后,我们发现此处存在引发线程泄漏的代码逻辑。在 DS HadoopUtils 中存在一个 Cache,会以恒定的速率不断生成新的 HadoopUtils 实例,并放入 Cache,在 HadoopUtils 实例化的过程中会创建 HDFS FileSystem,但是却不会关闭原有的 FileSystem。
开源的 DS 在使用 HDFS FileSystem 时泄漏速度比较慢,不易发现。我们在生产环境中使用的是腾讯云提供的 CosFileSystem 插件,该插件中会使用多线程来加速文件的上传 / 下载操作。通过插件中的线程数目比对,与我们泄漏的线程数完全一致。
图 2-2 HadoopUtils 工作逻辑
至此,我们确定线程泄漏的原因是 HadoopUtils 在更新 Cache 的时候没有关闭 FileSystem,于是我们在更新 Cache 的时候关闭 FileSystem,并通过读写锁保证不会由于异步关闭导致文件操作失败,成功的解决了线程泄漏的问题。对比上线前后的 JVM 线程指标,修复之后线程数保持在一个小恒定范围内。
图 2-3 修复前后 JVM 线程数对比
在生产环境中,我们发现在任务量没有发生明显变化时,Master 服务随着运行时间越长,其 CPU 使用率出现增长趋势。
图 2-4 Master 服务 CPU 使用率不断增长
通过分析火焰图,我们发现 Master 中存在一处代码逻辑,随着程序的运行时间越久,这段代码逻辑对 CPU 的消耗会越来越高。
图 2-5 任务事件处理器 CPU 使用占比很高
通过梳理代码逻辑,我们发现 DolphinScheduler 的 Master 服务在运行工作流时采用事件驱动的方式,每个任务实例在运行过程中会生成一个对应的 TaskExecuteRunnable 对象,任务在运行过程中产生的生命周期事件会存放在 TaskExecuteRunnable 对象中。会有一个后台线程轮询当前服务中存活的 TaskExecuteRunnable 对象,然后提交事件处理任务到事件线程池。
不过,当任务运行结束之后,TaskExecuteRunnable 并不会被释放,还会存放在任务事件线程池中,这就会导致任务事件处理线程空转时间越来越长。
通过分析堆栈,我们的判断得到了验证,TaskExecuteRunnable 的确会泄漏,不过由于 TaskExecuteRunnable 占用内存很少,因此很难从内存中反应出来。我们的集群中有 4 台 Master,任务实例数一天百万左右,因此对于单台 Master 一天会泄漏大约 25w TaskExecuteRunnable,随着时间的积累会拖慢引擎的事件处理。
图 2-6 Master 堆内存 TaskExecuteRunnable 对象泄漏
于是我们进行了代码修复,在任务执行结束之后,移除内存中的 TaskExecuteRunnable 对象。对比修复前后的 JVM CPU 指标,修复之后,Master 的 CPU 指标随着运行时间始终维持在一个小的恒定范围内。
图 2-7 修复前后 Master 服务 CPU 使用变化
DolphinScheduler 中任务分为两类,分别为以 dependent 为代表的逻辑任务和以 Shell 为代表带的物理任务,其中逻辑任务在 Master 中执行,物理任务在 Worker 中执行。不管是逻辑任务还是物理任务在 Master 处理过程中都会经历以下阶段。
图 2-8 Master 中任务处理流程
逻辑任务和物理任务的区别在于 Dispatch 和 Run 阶段的实现不同,对于逻辑任务不需要触发真正的 Dispatch,Run 阶段运行在 Master 中。而物理任务在 Dispatch 阶段会将任务分发给 Worker,Run 阶段运行在 Worker 中。
无论是哪种任务,当 Dispatch 阶段执行成功之后,会注册到 StateWheelThread 中,该组件会定时的每隔 5 秒钟为每个任务生成一个 TaskStateChangeEvent,提交到任务的事件队列中,TaskStateChangeEvent 被处理的时候会触发 Run 任务,对于逻辑任务会不断的通过 TaskStateChangeEvent 触发执行。
图 2-9 StateWheelThread 生产消费模型
这里是一个典型的生产消费模型,生产者以固定的速率(每隔 5 秒)生成事件写入队列,消费者异步的从队列中消费事件。
因此当消费者处理的速度小于生产者生产的速度时,这里就会出现事件堆积。
而实际情况下,由于生产者生产事件的时候是纯内存计算,没有任何 io 阻塞,而消费者处理事件的时候需要多次查询 db。对于 Dependent 这类逻辑任务的运行时间通常都很长,因此如果达到一定的并发量,这里极大概率会出现事件积压,导致整个 master 中所有任务的状态事件处理出现延迟、增加数据库压力,严重的话还会导致 Master OOM 服务宕机。
在我们的测试环境中,单台 Master 服务,事件线程池大小为 100,Dependent 并发数超过 500,此时就 Master 中的 StateEvent 就会出现堆积的情况。
图 2-10 修复前 StateEvent 变化情况
我们发现堆积的事件都是用来触发逻辑任务 Run 阶段,并且对于同一任务实例存在多个重复的触发事件,我们通过对事件去重从而修复堆积的情况。在修复之后,事件的堆积情况得到解决,一旦事件的消费速度低于增长速度,事件的堆积量最多为任务的并发数,不会出现一直积累的情况。
图 2-11 修复后 StateEvent 变化情况
Master 在分配任务给 Worker 的时候,会使用负载均衡策略,使任务的分配尽量均衡。默认的均衡策略是 LOW_WEIGHT,该策略会通过 Worker 的心跳信息来计算一个负载量,会将任务分配给负载量最低的 worker。
图 2-12 Worker 通过 Heartbeat 暴露自身负载情况
在实际的使用过程中我们发现在大多数情况下,这种负载策略会出现严重的任务分配不均衡的情况,在同一个 WorkerGroup 下,不同的 Worker 被分配到的任务量可能会相差几十倍。
图 2-13 Worker 任务分配失衡
究其原因我们发现主要是由两个方面导致
负载计算的值无法代表负载情况
在计算 Worker 节点的负载时,Master 会对 Worker 的 CPU、内存、Load、等待任务数分别加一个权重来做归一化,但是针对各资源加权值和归一化算法表达不严谨。导致计算出来的负载值实际上并不能正确的反应 Worker 的真实负载情况,并且实际生产很难通过调节权重得到一个真实的值。
负载计算不是实时的
Worker 的心跳上报是定时上报,Master 在分发任务时使用的 Worker 心跳数据并不能反映当前 Worker 的真实情况,这会导致某个时刻一旦出现一个负载量偏低的 worker,master 在接下来一段时间中可能会将大量的任务都发送给这台 worker,从而导致任务倾斜。
分析完原因之后,我们决定使用 RANDOM 策略来分发任务,保证 Master 在分发时绝对均衡,然后由 Worker 自己通过自身负载决定是否要接受 Master 的分发请求。对比修复前后同一个 worker 分组下不同 Pod 接收的任务,发现修复后不同的 pod 接收的任务变得均衡,不再出现任务倾斜的情况。
图 2-14 修复前后 Worker 接收任务对比
在生产环境中,我们发现 Master 的 CPU 持续升高,通过服务日志发现 Master 一直在处理某个事件,并且伴随异常,我们猜测此时出现了事件死循环的情况。通过研究 DolphinScheduler3.0.0 中 Master 事件驱动流程我们发现在该版本中存在三类事件。
WorkflowStartEvent
WorkflowStartEvent 是工作流启动事件,该事件是由一个单独的后台线程产生,并且由一个单独的后台线程处理,用于启动工作流,工作流的元数据出现异常时会导致 WorkflowStartEvent 执行出现异常,此时异常的 WorkflowStartEvent 会一直重试并阻塞后面其他事件,直到在数据库中对元数据进行修复。
图 2-15 WorkflowStartEvent 处理流程
StateEvent
StateEvent 是工作流和任务执行相关的事件,用于驱动 DAG 拓扑执行。
StateEvent 有以下事件类型:工作流状态变更、任务状态变更、工作流超时、任务超时、TaskGroup 中的任务被唤醒、任务重试、工作流阻塞。
对于一个工作流来说,里面所有的 StateEvent 都存储在一个队列中,事件按照进入队列的先后顺序被执行。并且采用的是 DFS 的方式被线程池消费,即一个队列被 fire 的时候会被分配给一个线程,该线程直到处理完队列中的所有事件才会退出,如果一旦有某个队列在处理时无法退出,那么线程会被一直占用。
图 2-16 StateEvent 处理流程
TaskEvent
当任务实例在运行时发生了变化会生成 TaskEvent,即该事件是由 Worker 发送的任务数据所转换而来,以下情况都会生成 TaskEvent,TaskEvent 处理流程和 StateEvent 类似。
任务实例被分发成功了,那么会触发 Dispatch 类型的 TaskEvent。任务实例延迟执行了,那么会触发 Delay 类型的 TaskEvent任务实例开始运行了,那么会触发 Running 的 TaskEvent任务实例运行结束了,会触发 Result 类型的 TaskEvent
值得注意的是以上三种事件都采用死信队列的方式存放,即只有当事件被处理成功才会将事件从队列移除,社区最初这么设计是希望在某些情况下由于基础设施故障,例如 db 抖动等不会影响到事件的处理,但实际上有很多其他的意外情况会导致事件处理失败,例如数据库存在非正常数据,事件发送过程中出现乱序等。
我们认为对于引擎来说,需要避免由于某一个工作流事件处理出现问题,从而影响到引擎的稳定性。因此,我们移除了这里的死信队列,当事件处理失败的时候,会直接抛弃事件,并将工作流快速置为失败,由上层进行重试,并结合 Metrics 监控各类事件的处理情况。修复后,Master CPU 保持稳定,服务日志也不再出现一直重复处理某个事件。
图 2-17 三种事件监控情况
目前 DolphinScheduler 中 Master 执行工作流的时候会将工作流实例的元数据存储在内存,然后通过事件驱动的方式去进行状态流转,直至工作流中所有的任务都结束然后将工作流实例从内存卸载。在某些情况,例如网络原因导致事件丢失,或者事件在处理过程中由于状态机 bug 处理失败从而丢失,此时会导致工作流实例处理流程卡住,从而导致工作流实例成为孤儿实例,即永远不可能结束。
此时如果发现了可以在上层通过 kill 的方式去停止工作流实例,从而卸载,不过这种方式存在两个问题。一是依赖业务方自行检测,需要业务方定期的巡检整个系统,当业务方发现问题时往往业务已经受到了影响。二是处理的方式很繁琐,一旦运行的工作流实例数比较多的时候,逐个操作成本比较高。我们希望调度引擎能够有自检功能,能够自己检测工作流实例是否已经变成僵尸实例,并且自动上报,自动做恢复操作。
对此,我们进行了优化,在 Master 中添加一个组件 WorkflowInstanceHealthCoordinator,该组件用于定期对当前 Master 运行中的每个工作流实例执行健康检查。在健康检查的时候会通过 HeartbeatEmitter 去触发工作流实例的心跳检测,当连续多次的心跳检测失败之后,会通过 DeadWorkflowInstanceHandler 去清除该工作流实例,并上报 metrics。
图 2-18 健康检查流程
整个检测主要是由 WorkflowInstanceHealthCoordinator 负责,该组件在每个 Master 中采用单例的形式,里面包含一个后台线程,和 EventExecuteService 工作模式类似,当一个工作流实例被加载到 Cache 之后,会同时在 WorkflowInstanceHealthCoordinator 中注册自己,当工作流实例执行结束从 Cache 中移除的时候也会同步从 WorkflowInstanceHealthCoordinator 移除。
图 2-19 WorkflowInstanceHealthCoordinator 处理流程
WorkflowInstanceHealthCoordinator 中有一个后台线程会定期的(默认 5min 一次,可自定义配置检测间隔)对注册进来的工作流实例做健康检查。
健康检查的方式是通过对工作流实例中所有未结束的任务做心跳探测,如果探测成功,则表明该工作流实例是存活的,如果探测失败,则表明该工作流实例可能已经出现了异常。对一个工作流实例如果探测失败的次数超过了阈值,我们认为该工作流实例已经成为僵尸工作流实例,我们目前会进行告警,由运维同学介入,当前我们尚未实现自动故障恢复,因为此类僵尸实例发生的情况不会很多,后续我们会考虑实现对僵尸实例自动运维。
DolphinScheduler 中 Worker 主要职责是接受任务,执行任务,上报任务事件。
其中任务事件在上报的时候存放在内存中的一个死信队列中。
图 2-20 Worker 上报任务事件流程
整个过程为
任务执行过程中生成任务事件,并将事件提交到死信队列,每个任务会有一个单独的死信队列Worker 中有一个后台线程会定期轮询死信队列,当事件达到重试间隔之后会重新发送事件给 masterMaster 在处理完事件之后会发送对应事件 ACK 给 worker,worker 收到 ACK 之后会清除事件,当死信队列中所有事件都为空,并且任务执行结束,此时会卸载死信队列。
这样做的好处是能够避免因为网络抖动或者 master 因为故障而导致某段时间内事件上报不成功从而丢失事件,不过这样也会导致可能出现内存泄漏的问题。例如,如果 master 发生容错,那么会进行工作流容错,容错的时候会先 kill 任务,然后重新提交,在 kill 的时候如果发送 RPC 给 worker 失败了,此时 worker 中的任务事件将永远不会被清除,并且由于工作流实例发生了容错,此时某些任务事件可能无法发送给容错后的 master,即会一直重试,变成僵尸消息。
即一旦消息的目的地发生了变化,但是 worker 感知不到,那么会导致消息泄漏到内存。
一旦发生泄漏,可能会导致重试线程中堆积大量的无效事件,这会占用线程资源,导致有效事件发送出现延迟,并且这类无效事件永远不会被释放,会造成内存泄漏,影响服务稳定性。
对此,我们在事件中添加了 TTL,每个事件在创建的时候会带有 createTime,如果 currentTime-createTime>ttl,那么表明事件在给定的时间内没有发送成功,此时说明事件可能已经出现了泄漏,会在 prometheus 中打点,并自动从死信队列队列中清除。
图 2-21 事件添加 TTL 检测
随着系统使用时间的增长,数据库和磁盘数据逐渐积累,会影响服务运行和数据库稳定性。实际运维中我们发现,数据库中增长的主要是一些实例元数据,这些数据的积累会导致数据库压力越来越大,同时会伴随慢查询越来越多。磁盘中增长的主要是任务实例日志和任务实例工作目录,这些数据的积累会导致磁盘可用容量和 inode 变得越来越少。
我们希望程序能够自动的清理无用的历史数据。例如,在数据库中仅保留最近一个月的运行实例数据。磁盘上保留最近一周的临时文件,超出保留期限的数据则自动删除,以减少人工运维的工作。
由于 DolphinScheduler 原生的删除接口在做数据清理的时候是按照工作流实例的维度,即清理历史数据的时候需要先找出工作流实例下的任务实例,然后分别清理每个任务实例的数据,这个过程涉及大量的数据库操作和 RPC 操作,并且执行批量删除操作的时候会给服务带来很大的压力,不适用大批量数据的清理。为此,我们分别在 Master 和 Worker 中添加了 InstanceDBPurgerThread 和 TaskFilePurgerThread 两个后台线程组件,分别负责数据库实例数据和磁盘文件的定期检查、上报与清除工作。
数据库方面主要清理工作流实例、任务实例和告警事件等数据。磁盘方面,主要是清理 exec 目录下的临时文件夹,log 目录下的任务实例日志等数据。同时,通过暴露相关的 metrics 对这些数据量进行监控。将数据库和磁盘的清理分开可以极大的加速历史数据的清除速度。
图 2-21 实例变化情况
为了确保系统稳定运行,我们不仅配置了大量告警,还定期进行日常、周、月巡检。通过巡检,我们能够提前发现潜在问题,不断的完善自动化运维流程。我们目前发现的大多数问题都是通过巡检提前发现,避免了对业务造成实际影响。
同时,巡检也帮助我们不断优化我们的监控大盘和告警项。目前我们从集群、项目、WorkerGroup 和 Pod 等维度搭建了监控面板和告警,以辅助巡检工作。
图 2-22 不同维度的监控面板
图 2-23 Cluster 维度部分面板
图 2-24 项目维度部分面板
图 2-25 WorkerGroup 维度部分面板
在日常巡检中,我们主要关注集群、项目、WorkerGroup 三个维度下的指标。在集群维度上,关注 Master Slot 变化、集群水位、并发量、资源使用等稳定性指标。在项目和 WorkerGroup 维度,关注异常任务、任务量的同比变化,WorkerGroup 下 Slot 使用率及业务运行情况。Pod 维度则用于周巡检和问题排查。
目前 DolphinScheduler3.0.0 已经在我们的生产环境中稳定运行,我们针对使用场景中发现的问题,在不进行大规模架构调整的前提下做出了修复和优化,并且沉淀出了一套适用于当前业务场景的运维手段。社区在后续版本中对某些问题进行了更完善的修复,如针对逻辑任务事件阻塞的问题,重构了整个逻辑任务执行流程;针对状态机卡住问题,重构了状态机模型等。未来,随着业务量和使用场景的扩展,我们会考虑版本升级到 3.2+ 版本,以尽可能与社区保持同步,并将我们所做的一些优化项反馈至社区。
","description":"基于 DolphinScheduler 搭建的 UDA 任务调度平台有效支撑了公司的业务数据开发需求,处理着日均百万级别的任务量。整个 UDA 的架构如下图所示,其中我们的引擎层主要基于 DolphinScheduler 的 Master 和 Worker 服务搭建,充分利用了 Master 节点优秀的高并发调度能力、worker 节点的分组隔离能力。我们通过一层适配层对 DolphinScheduler 对外暴露的接口进行了封装和增强来适配我们的业务场景。 图 1-1 UDA 任务调度平台架构\\n\\n随着使用的深入,我们发现 DolphinScheduler3…","guid":"https://www.infoq.cn/article/ViygpyDTyBjejTRXHb3W","author":"文:作业帮大数据团队(阮文俊、孙建业)","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-12-27T04:00:00.660Z","media":[{"url":"https://static001.geekbang.org/wechat/images/bd/bd72cd6d6d307b6814d7c13c1a7420b6.png","type":"photo","width":1080,"height":1550,"blurhash":"L8Q]+w_3?b~q_3ofRjayxut7RjWB"},{"url":"https://static001.geekbang.org/wechat/images/af/af7bcefac2d9367b447e965bcb8b293e.png","type":"photo","width":1080,"height":252,"blurhash":"L13u$Uj]D$oz-rayD$j[_3kBD$kC"},{"url":"https://static001.geekbang.org/wechat/images/c1/c160efcb9a990a78eaaf4f3bec5676c8.png","type":"photo","width":1080,"height":840,"blurhash":"LAR:HG?b_3~q?b9FIURjayWBM{of"},{"url":"https://static001.geekbang.org/wechat/images/82/823db2fa363dcb639889e7b9aafcb7ef.png","type":"photo","width":1080,"height":316,"blurhash":"L03SCVjcMxtQR9V[MxjuMkj@M_ju"},{"url":"https://static001.geekbang.org/wechat/images/40/40a30a7aa53d16c185918eea24f5ee09.png","type":"photo","width":1080,"height":187,"blurhash":"L142SJofWBog_Nayofof-@j[fiof"},{"url":"https://static001.geekbang.org/wechat/images/7a/7a24e2e36894a9b883177877ab9b66a4.png","type":"photo","width":1080,"height":58,"blurhash":"LSMtEK~oIBxt+@D*%2ay@KVtoyn+"},{"url":"https://static001.geekbang.org/wechat/images/9c/9c45b7476cb3829240e7b8109f66c870.png","type":"photo","width":1080,"height":601,"blurhash":"L16*dh~qof_3~qR*ofj[?bRjofRj"},{"url":"https://static001.geekbang.org/wechat/images/d0/d06ae09805e837e671fd03649ab1c0b7.png","type":"photo","width":1080,"height":185,"blurhash":"L24C9iOZxWSj.mt6R-xt,@VsafjF"},{"url":"https://static001.geekbang.org/wechat/images/79/79d0f749d717c699cca79e7773fa5678.png","type":"photo","width":1080,"height":503,"blurhash":"LESY{q~q%M?b?bWBRjxuayt7j[t7"},{"url":"https://static001.geekbang.org/wechat/images/22/22ec4af48cb14199a8b4b5ccf4fb28a4.png","type":"photo","width":1080,"height":301,"blurhash":"LESigQ?bt7?b%MfQj[j[~qofWBof"},{"url":"https://static001.geekbang.org/wechat/images/d8/d8074d828dd7e6e884641724fc5b7370.png","type":"photo","width":1080,"height":348,"blurhash":"L038|=%Nxv%NWCtRtRt7%MkBayay"},{"url":"https://static001.geekbang.org/wechat/images/dd/ddf09a95e68a4be1502f3a158d47d529.png","type":"photo","width":1080,"height":371,"blurhash":"L02~ZG%gxv%Mj]ogt7t7xuogofj["},{"url":"https://static001.geekbang.org/wechat/images/98/9842c1f2df61b0c572c665b9af645697.png","type":"photo","width":1080,"height":669,"blurhash":"LESigQ~qj[_3_3oft7M{?bj[ofM{"},{"url":"https://static001.geekbang.org/wechat/images/21/21fa9f6c160684f4e323be9b1f7cf6ca.png","type":"photo","width":1080,"height":361,"blurhash":"LC8MXINwJ7sm1Is.xGWqsDoLs.oL"},{"url":"https://static001.geekbang.org/wechat/images/37/37509dcf1e4687b3242c5640cedb3acb.png","type":"photo","width":1080,"height":231,"blurhash":"L13up1s;Mxt7NIWBMxj]?vazMxs;"},{"url":"https://static001.geekbang.org/wechat/images/b3/b39feb8cef0c802ebbd86371548198fd.png","type":"photo","width":1080,"height":509,"blurhash":"LCSs50~qWB?bayt7WBRjt7WBj[of"},{"url":"https://static001.geekbang.org/wechat/images/37/37f0373a5deab904ec20ececd5859d51.png","type":"photo","width":1080,"height":355,"blurhash":"LHSigQ-;of-;?bj[ayj[~qt7WBof"},{"url":"https://static001.geekbang.org/wechat/images/b5/b56da5957969a605d1cf78d84038d6c4.png","type":"photo","width":1080,"height":180,"blurhash":"L13lN@IAkCxu.9IAkCozHsRiflj["},{"url":"https://static001.geekbang.org/wechat/images/aa/aa45c65fc17fafde728194f861839b12.png","type":"photo","width":1080,"height":251,"blurhash":"L13bp_s-fko#?bR*M{Ri_NoKa{kC"},{"url":"https://static001.geekbang.org/wechat/images/e5/e5ac4be0aa70a46b5fe6c2b2a169a154.png","type":"photo","width":1080,"height":179,"blurhash":"L74f8ctlkCaetRt8j[aeHXi_jsa}"},{"url":"https://static001.geekbang.org/wechat/images/1b/1b59136b8fdefaeac9f4143d6d5ef0e5.png","type":"photo","width":1059,"height":542,"blurhash":"LJR:KR-,9G-;~pE2t6obx@RSobWV"},{"url":"https://static001.geekbang.org/wechat/images/9c/9c3169f47ea63973589f7f4d4c9629b9.png","type":"photo","width":1080,"height":328,"blurhash":"LDRfkB?bof?b~qRjM{of%MRjj[WB"},{"url":"https://static001.geekbang.org/wechat/images/a6/a6e6be2845df5463e9e7a19ab394ffc9.png","type":"photo","width":1080,"height":397,"blurhash":"LARp8-?bRj_3~qayj[j[_3M{j[xu"},{"url":"https://static001.geekbang.org/wechat/images/be/beba21bec981dac49a5738a08b8aa4bb.png","type":"photo","width":1080,"height":567,"blurhash":"LHRysi-;?Y-=?wt6--WC%Nt7t2M|"},{"url":"https://static001.geekbang.org/wechat/images/53/530710907bf98cab29cca50a97cd324d.png","type":"photo","width":1080,"height":157,"blurhash":"LB864eoxkBoxR8afj[ayHbWBj[ae"},{"url":"https://static001.geekbang.org/wechat/images/14/14c4cda5f265843da87ea5eca5de5f0d.png","type":"photo","width":1080,"height":338,"blurhash":"L17x2bRjxu%M?vRjofRjWBt7Rioz"},{"url":"https://static001.geekbang.org/wechat/images/85/85cb6f964ee3d96c0210ada9cf510547.png","type":"photo","width":1080,"height":465,"blurhash":"L84yS_V[Vue=RRj[kBfjHboxo{kB"},{"url":"https://static001.geekbang.org/wechat/images/05/05a411b1af5a0303470aa8d709b297c4.png","type":"photo","width":1080,"height":526,"blurhash":"L02~ZExuofkCoytRjtRjMyozkCja"},{"url":"https://static001.geekbang.org/wechat/images/63/635ef282901e63d028c38e9d1a04ede7.png","type":"photo","width":1080,"height":536,"blurhash":"L35Ev$V@0JtRnnWBInofabbIxwjE"},{"url":"https://static001.geekbang.org/wechat/images/24/2478aac8fe3ac764d9711e11e304a7a5.png","type":"photo","width":1080,"height":251,"blurhash":"L54fEXVvMMj[y,VuMgoyVuj[Vuo{"}],"categories":["后端"],"attachments":null,"extra":null,"language":null},{"title":"资源节省超 50%!作业帮 Spark 全面替换 Hive 的技术实践","url":"https://www.infoq.cn/article/IgfpikEX0XCAx5ssVyry","content":"作业帮历史数据计算引擎主要依赖 Apache Hive 2.3.7,主要用于数仓建设、即席查询、算法特征分析、实验效果统计等方面。虽然 Hive 在数据管理和计算方面有自己的优势,但随着湖技术、云原生、引擎向量化等技术发展,以及业务对成本敏感程度的变化,Hive 逐渐暴露出一些局限性,主要体现在引擎生态、资源利用效率和系统稳定性方面。
Spark 作为计算引擎基本已经成为行业大数据标配。能力上不仅有 SQL,还有 ML、Steaming、GraphX,以及对各种编程语言的支持。在 Catalyst 优化器、内存计算等资源利用效率方面明显优于 Hive。同时官方支持除 Yarn 部署模式外还支持 K8S,为在离线资源峰谷互补提供支持。Spark 作为事实上的标配,也吸引了很多外围开源项目的深度适配,较 Hive 的简单支持在性能、功能方面差异很大,例如 Apache Iceberg、Apache Kyuubi。
Hive 由 hive metastore 和 hiveserver2 两部分组成,metastore 主要解决 Hive 表数据管理,也是目前行业的主流方案,hiveserver2 主要用于接收 SQL 任务请求转为物理执行计划提交给 Yarn 等资源执行。随着湖相关技术的不断成熟,Databricks、Snowflake、公有云 EMR 等商业组织积极推广。Databricks 收购 Iceberg 背后公司 Tabular 后,Unity Catalog、Apache Gravitino 等元数据技术更是被提到了新的高度,用于统一解决 Data + AI 的数据管理,Hive metastore 也将会被逐渐替代。而 hiveserver2 抛开 Hive 计算引擎本身的没落,自身稳定性不足也比较突出,尤其在资源隔离、限流控制等方面。
在行业技术趋势以及业务需求上考虑,我们期望通过计算引擎迭代,实现规模性降本、整体架构可长期演进,系统性提高服务稳定性。
总体架构
结合作业帮当前 Hive 应用情况,Spark SQL 替换 Hive 在技术架构上核心需要考虑 SQL 提交、认证和鉴权、以及数据开发平台适配。
SQL 提交开源解决方案主要有 Apache Kyuubi、Spark Thrift Server。STS 是 Spark 主导的 SQL 解析和优化器,兼容了 HiveServer2 的 Thrift 通信协议,但是 Thrift Server 和 Driver 在同一个进程内,所有 SQL 都由这个 Driver 负责编译、执行,此阶段资源消耗高,高并发情况容易造成服务节点异常。Kyuubi 则更加灵活,兼容了 STS 服务能力,Kyuubi Server 基于 ZooKeeper 实现服务发现机制保障高可用,针对 ETL、即系查询等不同应用场景设计灵活、可选的 Engine 共享级别。具体对比如下图 (引自 Apache Kyuubi 微信公众号)
认证和鉴权部分在平台(调度 / 即系等系统)和客户端(beeline)访问处理逻辑并不统一,解决起来会稍微麻烦些。为了兼顾项目效率我们采用了与 HiveServer2 类似的鉴权逻辑。如下图简单举例说明整体流程。
Beeline 客户端访问时,通过 Kyuubi 实现信息透传 Spark App,二次开发 Hive Metastore 实现认证,结合 Ranger Hive Metastore Plugin 实现鉴权。相对来说,平台实现会简单些,系统直接和公司内部 IPS 系统对接实现认证。服务入口获取相应 SQL 并解析,在通过 AuthServer 权限服务进行权限校验,较 Client 方式执行速度更快,不需要等待资源创建 Kyuubi Engine。认证鉴权完成后会以超级用户继续走后续流程。本质上账号体系是两套,为了实现一次授权双向可用,用户名必须统一。
迁移和优化
任务迁移
整体迁移大概分为两个阶段,一是部门内部流量数仓由 Hive 迁移到 Spark SQL + Iceberg,同时沉淀平台能力。这部分主要为提供基础能力,人工执行迁移动作,规模性验证收益效果。此处不多介绍,可参考 https://www.infoq.cn/article/SXZhixk65MjUfEecrhGu\\"。二是全面推广 Spark 引擎,规模性迁移快速拿到收益。
开始考虑仍然以业务人工自主迁移的方式进行,历史存量 Hive 任务有 1W+,牵扯多个组织角色和团队,少量团队结合当前成本压力意愿度较高,但从全局视角看节奏远低预期。整体上可投入精力有限,新引擎学习、迁移流程复杂(SQL 转换、双跑对数)、遇到问题后迁移意愿降低是主要影响因素。
为尽快拿到收益,以工具化迁移替代人工,大概流程如下图。首先通过调用离线调度平台接口获取 Hive SQL,替换 SQL 中时间等变量占位符,形成可执行 Hive SQL。解析可执行 Hive SQL 基于规则转换为 Spark SQL,同时在测试库下创建目标表,并替换输出结果到测试表,再做 explain 校验。资源低峰期执行 Spark SQL 任务,对比 Hive 产出数据结果(对比方式见下文)。对比收集 Yarn Application 中 Aggregate Resource Allocation 资源消耗指标。数据准确且资源收益为正,持续双跑一段时间无异常后切换为 Spark 引擎,并关注迁移任务接下来一周异常情况,迁移首天出现异常可自动回滚。整个过程当出现超预期问题时,人工分析具体原因迭代转换规则、优化集群和任务参数。经过几轮迭代,可迁移任务覆盖率逐步提高。
迁移工具流程图
基础类型对数 sum(hash(xxx)) 即可,复杂类型需要做些特殊处理,例如
array类型:sum(hash(array_sort(array())))\\nmap类型:sum(hash(array_sort(map_entries(map())))) \\narray类型:sum(hash(array_sort(flatten(transform(array(map()), x -> map_entries(x))))))
在控制增量任务时,用户视角主要关注以下情况,一是平台功能是否对齐;二是 SQL 语法是否存在差异;三是是否稳定;四是新引擎的收益。在平台功能上,主要是即席查询、例行调度、表 / 任务血缘、语法 / 语义检测、自定义 UDF、Holo/ES 外表查询等方面,随着存量任务迁移能力已补充。SQL 语法差异上,虽说两个引擎语法差异不大,但是明显感觉 Spark SQL 3.3.2 较 Hive 2.7 语法校验上更严谨,在应用上还是会有小的差别,例如 map 类型不支持 group by、distinct、join key;数据类型自动转换、空值做 map key 等异常情况下的输出表现存在差异等等。针对这部分主要以培训宣贯、整理用户使用手册的方式解决。稳定性问题在存量任务双跑阶段基本已经覆盖了绝大头,主要通过调整相关参数解决。切换 Spark 后的收益已有论证,不存在争议。总体上,为避免用户反馈太过强烈,平台能力具备后并没有急于做任务的增量控制,仍然以迁移存量任务和宣贯优势为主。当存量任务覆盖率占绝对优势后,修改默认计算引擎逐步关闭 Hive 入口。
稳定和性能
1. 内存控制不合理导致任务异常
在 Spark 应用中,OOM 问题一直比较突出,随着自身内存管理的不断发展和迭代已有明显改善,但在一些场景中仍然有这种风险。默认情况下,Executor 数据和计算过程所用内存资源主要在 JVM 管理的 On-Heap Unified Memory Pool 中,而 JVM 内对象通常是其原始数据的 2-5 倍,这种高内存占用主要因为封装为 JVM Object 时一些额外开销。加持数据内容、存储格式和文件存储压缩比差异,想要准确预测一个任务需要多少内存资源比较合理是件很难的事情。
为了兼顾迁移进度、稳定性、性能多方面因素,我们提供了两版参数。一是集群级别默认参数,兼顾绝大多数任务性能和稳定性。二是针对稳定性要求较高,允许一定性能损失的参数。以上参数工具化迁移阶段基本覆盖。部分异常 case 整理如下
Broadcast Join 时,广播数据阈值是通过 spark.sql.autoBroadcastJoinThreshold=10M 控制的,当压缩比较高时,需要申请较多的 On-Heap Storage Memory 内存,会导致等待资源时间长或者 OOM 问题,需要禁用或调低阈值才能解决。
执行窗口函数、开启向量化读时,缓存在内存中数据条数默认都为 4096 行,单行记录过大时会导致 OOM,适当调低阈值、避免扫描非必要的大字段可解决。
Kyuubi 提交 Spark SQL 任务时,Driver 会额外加载一些类、启动一些线程,默认的 Spark spark.driver.memoryOverhead 内存 10% 或 384M 总体偏小,导致任务 Driver 使用内存超限被 yarn kill,利用 jmcd 简单分析 Driver 内存消耗,这部分资源使用相对固定的,适当增加后解决。
针对 Spark 内存管理划分整理如下图,结合 Spark UI Metric 可用于辅助分析内存情况。
2. 大规模并发提交 Spark 任务优化
离线任务中有很多用户设置整点调度,同时任务实例数也比较多。Kyuubi 是通过线程数量来控制提交任务并发的,如果线程数较低,会产生 Yarn 资源空闲但是任务提交限流情况。如果线程数调高,高并发时瞬时产生大量 SparkSubmit 进程,消耗 Kyuubi 节点 Cpu、Mem 资源,Kyuubi 服务有稳定性风险。我们在 Kyuubi engine 启动后释放 startupProcessSemaphore 可以解除并发限制,Kyuubi 节点资源利用率较之前提高 70%,Yarn 资源也可以打满。相关 PR 地址 https://github.com/apache/kyuubi/pull/6463\\"
3. 结果集返回慢和乱序问题
在部分场景中(例如算法特征数据同步到 GPU 节点、业务数仓结果同步到 OLAP 引擎用于 B 端系统),对任务稳定性、结果集拉取速度比较敏感。Kyuubi 在处理结果集返回有多种方式,但针对我们的场景使用每种方式都有些缺陷。首先是大结果集返回时,因为 Kyuubi 默认使用的方式是 resultDF.collect(),这样会把所有的数据拉取到 Driver 的内存中再返回给 kyuubi Server,数据量大容易发生 OOM 问题。之后测试串行拉取 kyuubi.engine.spark.operation.incremental.collect=true 解决了内存问题,但是拉取速度上会比较慢,尤其是遇到 scan + filter 这种简单查询时。最后 kyuubi.operation.result.saveToFile.enabled=true,结果集大于 minSize 后会将结果存储到 hdfs/cos 等文件系统,但是会触发 Kyuubi 的小文件优化,用户 order by 后获取的结果集仍然乱序,最后优化 Repartition 小文件合并判断逻辑后问题解决。
4. 复杂类型开启向量化读,性能显著提升
日志数据在 Hive 表存储中占比非常高,为了保障日志打点的灵活性表设计一般都会包含嵌套类型(StructType、ArrayType、MapType),数仓在构建 DWD、DWS 层表时也会延续这种设计方式。而针对这种嵌套类型查询时会因为嵌套解析、未做 projection pushdown、逐行操作等原因导致资源消耗较多。Spark 在 3.4 版本默认开启嵌套类型向量化读,而我们引用的是 3.3.2 主要因测试覆盖度问题默认未开启。结合我们批量工具迁移逻辑及定向任务性能测试判断无风险有收益。开启向量化后效果非常显著,详细见下图。
SQL\\nspark.sql.orc.enableNestedColumnVectorizedReader=true\\nspark.sql.parquet.enableNestedColumnVectorizedReader=true
5. 默认 jvm GC 并行度高导致 CPU 负载高
历史情况,大数据离线主要采用腾讯云定制高 CPU 核数和内存的大规格机型,高峰期 cpu idle 几乎为 0。明显感受处理数据吞吐能力下降,偶尔出现因 CPU 高导致的节点卡死、网络超时等异常情况,与腾讯 EMR 团队配合针对这种情况定向分析。节点高峰时定位消耗 cpu 较多的 yarn container,利用 async-profiler 分析 cpu 占用,发现瓶颈在 jvm gc。利用 jstack 分析 jvm gc 线程情况,发现相关线程数和 cpu 核数有关,有小几百个线程。一个节点 192c,跑 100 多个 container,jvm 线程总共约小几万个,大批量数据处理情况下,内存频繁分配和释放 GC 表现更明显。调整参数 ParallelGCThreads=8 限制 jvm gc 并行度,cpu 使用率变化情况如图。
https://docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/g1_gc_tuning.html#g1_gc_tuning\\"
总体收益
总体上看,从平台能力建设 -> 内部少量任务灰度沉淀平台能力、验证整体效果 -> 存量任务规模化迁移 -> 关闭 Hive 增量入口,通过平台和工具化手段完成,整个迁移过程对业务影响很小。Spark 任务覆盖量从 0 到 1.5W,占例行任务约 80%,资源节省约 54%(同逻辑、同数据),收益超预期。同时未来 Spark on K8S 弹在线资源、基于 Kyuubi 做计算网关收口等技术演进提供了基础。
","description":"作业帮历史数据计算引擎主要依赖 Apache Hive 2.3.7,主要用于数仓建设、即席查询、算法特征分析、实验效果统计等方面。虽然 Hive 在数据管理和计算方面有自己的优势,但随着湖技术、云原生、引擎向量化等技术发展,以及业务对成本敏感程度的变化,Hive 逐渐暴露出一些局限性,主要体现在引擎生态、资源利用效率和系统稳定性方面。 Spark 作为计算引擎基本已经成为行业大数据标配。能力上不仅有 SQL,还有 ML、Steaming、GraphX,以及对各种编程语言的支持。在 Catalyst 优化器、内存计算等资源利用效率方面明显优于 Hive…","guid":"https://www.infoq.cn/article/IgfpikEX0XCAx5ssVyry","author":"作者:作业帮大数据团队(孙建业、常庆琳)","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-12-26T04:00:00.322Z","media":[{"url":"https://static001.geekbang.org/wechat/images/72/72d2e56f2463ed8141f5681743bd981a.jpeg","type":"photo","width":1080,"height":381,"blurhash":"LUQ0XGx_RO%M_4$|NIjbyBrtNZaK"},{"url":"https://static001.geekbang.org/wechat/images/ee/ee55ae9026e64392d069f45c0ab40084.png","type":"photo","width":1080,"height":415,"blurhash":"LESPFU%%ys#S?bofjZj[cDMyHst,"},{"url":"https://static001.geekbang.org/wechat/images/c1/c157e21c56cf97ea1b36ce5e58f3ed7e.png","type":"photo","width":1080,"height":206,"blurhash":"LBSPX{~q4n_3D%R*D%j[D%M{M{of"},{"url":"https://static001.geekbang.org/wechat/images/81/8160d9a8de687c767fa0ac7912cb2e18.png","type":"photo","width":1080,"height":883,"blurhash":"L6Q,O90$^l~W9ZRn+[EM?J^OMHE*"},{"url":"https://static001.geekbang.org/wechat/images/26/2634b895b4b8518548c7d8c1b1836af8.jpeg","type":"photo","width":1080,"height":131,"blurhash":"LJQcr8xvf6%N~AoMs:s.NLofR+WB"},{"url":"https://static001.geekbang.org/wechat/images/bf/bf5382e845ff5d5f9270ba5eae1df9a9.png","type":"photo","width":1080,"height":502,"blurhash":"LHQ].--=-U?G~WadV@t7-;WBf6f+"},{"url":"https://static001.geekbang.org/wechat/images/22/22cc2162aba301b2118260d69a76a84c.jpeg","type":"photo","width":1080,"height":260,"blurhash":"LlS$cKxuazxu.Tj]j@j]Mcaya|ay"}],"categories":["数据库"],"attachments":null,"extra":null,"language":null},{"title":"AISuite:一个新的开源Python库,提供了统一的跨LLM API","url":"https://www.infoq.cn/article/rKNXWEgBXvy1y7hK59js","content":"吴恩达(Andrew Ng)最近宣布, aisuite 的目标是围绕目前最流行的大语言模型(LLM)提供一个类似 OpenAI 的 API,使开发人员可以轻松地尝试并比较结果,或者在不更改代码的情况下从一个 LLM 切换到另一个 LLM。
根据吴恩达的说法,在同一个应用程序中使用多个 LLM 提供程序可能会很麻烦,而 aisuite 的目标是对其进行简化,只需在实例化其主组件时更改单个字符串即可选择所需的 LLM 提供程序。例如,要使用 OpenAI GPT-4o,你需要将“openai:gpt-4o”作为 model 参数传递到调用中,以创建一个 aisuite 聊天完成智能体代理。下面的代码片段进一步展示了这一点:
import aisuite as ai\\nclient = ai.Client()\\n\\n\\nmessages = [\\n {\\"role\\": \\"system\\", \\"content\\": \\"Respond in Pirate English.\\"},\\n {\\"role\\": \\"user\\", \\"content\\": \\"Tell me a joke.\\"},\\n]\\n\\n\\nresponse = client.chat.completions.create(\\n model=\\"openai:gpt-4o\\",\\n messages=messages,\\n temperature=0.75\\n)\\nprint(response.choices[0].message.content)\\n\\n\\nresponse = client.chat.completions.create(\\n model=\\"anthropic:claude-3-5-sonnet-20240620\\",\\n messages=messages,\\n temperature=0.75\\n)\\nprint(response.choices[0].message.content)
要安装 aisuite ,只需运行 pip install aisuite 。该库还提供了安装 LLM 提供程序库的快捷方式。例如,你可以运行 pip install \'aisuite[anthropic]\' 来安装基础库和 Anthropic 支持。
几位 X 用户回复了吴恩达的公告,他们也表达了同样的感受,即 aisuite 确实解决了部署 LLM 时的实际痛点。Reddit 用户将 aisuite 等代理库的可用性与数据库的抽象层进行了类比,这些抽象层能够从测试中的 sqlite 切换到生产中的另一个数据库。
虽然总体反响普遍积极,但一些 X 和 Reddit 用户强调了 aisuite 的一些局限性,包括它尚不支持流媒体,也不支持速率限制、token 令牌使用监控等其他细节。同样,目前还不清楚 aisuite 对使用自定义云部署的 LLM 的支持程度如何。无论如何,值得记住的是,该库仍处于起步阶段,正在积极的开发中。
aisuite 并不是目前唯一可用于解决 LLM 交叉兼容性问题的解决方案。具体来说,LiteLLM 似乎是一种更成熟、功能更齐全的解决方案,可以使用相同的类似 OpenAI 的 API 调用多个 LLM,包括支持按项目逐个限制费率和预算。同样值得一提的是 OpenRouter,它还进一步提供了自己的基于 Web 的 UI。
aisuite 目前支持 OpenAI、Anthropic、Azure、Google、AWS、Groq、Mistral、HuggingFace 和 Ollama。该库是用 Python 编写的,要求开发人员拥有他们想要使用的任何 LLM 提供商的 API 密钥。该库使用每个 LLM 提供商发布的 API 或 SDK 来最大限度地提高稳定性。目前,它主要专注于聊天完成,但其维护人员表示,未来会涵盖新的用例。
Sergio De Simone 是一名软件工程师,已经拥有超过 25 年的工作经验了。他曾供职各种不同的项目和公司,包括西门子、惠普和小型初创公司等不同的工作环境。在过去的十多年里,他一直专注于移动平台和相关技术的开发。他目前在就职于 BigML, Inc.,负责 iOS 和 macOS 的开发。
查看原文链接:
https://www.infoq.com/news/2024/12/aisuite-cross-llm-api/\\"
","description":"吴恩达(Andrew Ng)最近宣布, aisuite 的目标是围绕目前最流行的大语言模型(LLM)提供一个类似 OpenAI 的 API,使开发人员可以轻松地尝试并比较结果,或者在不更改代码的情况下从一个 LLM 切换到另一个 LLM。 根据吴恩达的说法,在同一个应用程序中使用多个 LLM 提供程序可能会很麻烦,而 aisuite 的目标是对其进行简化,只需在实例化其主组件时更改单个字符串即可选择所需的 LLM 提供程序。例如,要使用 OpenAI GPT-4o,你需要将“openai:gpt-4o”作为 model 参数传递到调用中,以创建一个…","guid":"https://www.infoq.cn/article/rKNXWEgBXvy1y7hK59js","author":"作者 | Sergio De Simone","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-12-26T02:00:00.760Z","media":null,"categories":["编程语言"],"attachments":null,"extra":null,"language":null},{"title":"都推进到95%了,为什么curl还是放弃基于Rust开发了四年的HTTP后端替代","url":"https://www.infoq.cn/article/ojYSKkjEuNywPHcNC93K","content":"“实验结束了。我们努力了,但还是失败了。”
近日,知名开源项目 curl 的创始人 Daniel Stenberg 正式发文宣布,将放弃对基于 Rust 编写的 Hyper HTTP 后端的支持,并彻底移除相关代码。
“四年前,我们开始在 curl 中添加对另一种 HTTP 后端的支持。它将使用一个基于 Rust 编写的库,名为 Hyper。我们的想法是引入一种替代的 HTTP 内部实现,让 curl/libcurl 使用它来代替本地实现。”Stenberg 在博客中写道。然而,这场实验在历经四年的努力后,以失败告终。
这一尝试始于 2020 年,由 ISRG(Let’s Encrypt 背后组织)资助。当时的目标是通过 Rust 的内存安全特性,为 curl 用户提供一个更安全的 HTTP 后端实现。Stenberg 在早期的博客中写道。“通过 Hyper,我们能够让更多代码运行在内存安全语言中,而非完全依赖 C。”
尽管实验已经推进了一大半,甚至让 Hyper 后端通过了几乎所有测试用例,但如同 Stenberg 在最新的博文中所述,“我们完成了 95% 的开发工作,然而,最后那‘百分之几’的挑战,还是让我们不得不认输,放弃这个实验。”
目前来看,实验失败的两大关键原因如下:
几乎没人有这需求:curl 的用户对 Hyper 没有兴趣;Hyper 的用户也不太关心让它兼容 curl。缺乏同时精通 C 和 Rust 的开发者来推进:Hyper 是用 Rust 写的,而 libcurl 库(curl 背后的“引擎”)是用 C 写的,需要一个“胶水层”来把它们连接起来。这需要开发者不仅对两种语言精通,还要深入理解它们的架构和协议,但目前没有合适的人去做这件事。
此外,早在 2020 年开始这个实验时,Stenberg 就提到过“Hyper 没有 C API”是一个棘手的挑战。
在今年 4 月的另一篇推文中,Stenberg 就预示过这次实验的结局,他提出了发人深省的问题:“Hyper 支持是否值得继续?”——当时,Hyper 后端的开发工作已陷入停滞,过去半年内几乎没有人主动对其进行功能改进或优化。与此同时,用户对 Hyper 的需求仍然冷淡。
技术上,Hyper 后端的开发过程中还出现了多次反向调整。例如,例如,由于对 Hyper API 集成方式的理解偏差,而不得不移除对 HTTP/2 的支持,这直接导致无法正确实现 HTTP/2 的功能。
更大的问题在于,社区用户的需求和兴趣严重失衡:当下 Rust 用户更愿意直接使用 Hyper,而不是帮助让它支持 C 项目;而 curl 的现有用户对 Hyper 几乎没有兴趣。
社区中这两类用户的交集太小,已经无法为 Hyper 后端的持续开发提供足够的支撑。
面对多重困难,Stenberg 开始反思:“Hyper 的支持是否已经从一种探索创新的尝试,变成了拖累改进的负担?”显然,继续维护这一功能的成本已经超过了它的实际价值。
既然在短、中期内都看不到完成的希望,与其继续耗费资源,不如果断放弃——移除这部分代码,不仅可以大幅简化项目结构,还能提高整体的灵活性,为 curl 的未来发展留出更多空间。
或许会有人提问,当初为什么不直接用 Rust 重写 curl 呢?Stenberg 早就明确表示,这从来不在他们的计划之中。
一方面,curl 是一个老牌开源软件,已经运行了 25 年。对于 libcurl 用户来说,稳定的接口(API)、应用二进制接口(ABI)、一致的行为,以及文档中定义的所有功能选项,都是不可动摇的基础。重写代码不仅意味着要重新开发所有功能,还需要确保新版本完全兼容旧版,这对任何项目来说都是一项巨大而复杂的挑战。即使是那些考虑过这样做的大型企业,最终也都放弃了这个想法。
与此同时,Stenberg 等人也深知,curl 必须不断引入新功能,才能跟上技术的发展步伐。于是,Hyper 后端支持方案成为他们探索的方向。
虽然 Hyper 实验以失败告终,但它对 curl 和 Hyper 项目都带来了积极影响。Stenberg 表示,curl 在与 Hyper 集成的过程中,改进了自身对 HTTP 的严格性,并优化了代码结构,而 Hyper 则通过与 curl 的合作获得了宝贵的反馈,进一步提升了自身的稳定性和性能。
他强调:“虽然 Hyper 已被移除,但我们依然对未来引入 Rust 或其他语言的安全后端持开放态度。与 2020 年那会相比,我们现在已经拥有了更好的内部架构可供借鉴。只要用户需求足够明确,并且有足够的资源支持,我们还可能会重新尝试类似的整合。”
尽管 Hyper 被放弃,curl 仍然在推进对两个 Rust 编写的后端的支持::rustls(用于 TLS)和 quiche(用于 QUIC 和 HTTP/3),它们被认为比 Hyper 更易于维护。
据悉,Hyper 的相关代码已于 2024 年 12 月 21 日从 curl 的代码库中删除,并将在 2025 年 2 月发布的 curl 8.12.0 版本中完全失效。
参考链接:
https://daniel.haxx.se/blog/2024/12/21/dropping-hyper/
https://daniel.haxx.se/blog/2020/10/09/rust-in-curl-with-hyper/
https://curl.se/mail/lib-2024-04/0021.html
","description":"“实验结束了。我们努力了,但还是失败了。” 近日,知名开源项目 curl 的创始人 Daniel Stenberg 正式发文宣布,将放弃对基于 Rust 编写的 Hyper HTTP 后端的支持,并彻底移除相关代码。\\n\\n“四年前,我们开始在 curl 中添加对另一种 HTTP 后端的支持。它将使用一个基于 Rust 编写的库,名为 Hyper。我们的想法是引入一种替代的 HTTP 内部实现,让 curl/libcurl 使用它来代替本地实现。”Stenberg 在博客中写道。然而,这场实验在历经四年的努力后,以失败告终。\\n\\n完成 95% 的工作只是开始?\\n\\n这一尝试始…","guid":"https://www.infoq.cn/article/ojYSKkjEuNywPHcNC93K","author":"罗燕珊","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-12-25T09:11:33.819Z","media":null,"categories":["后端","开源"],"attachments":null,"extra":null,"language":null},{"title":"Oracle 推出 GraalVM Java JIT 编译器,但仅限于自己的 JDK","url":"https://www.infoq.cn/article/wmxEBSSVlYH4i0ZsPC7m","content":"2024 年 9 月,甲骨文公司在其 OpenJDK 发行版 Oracle JDK 23 中添加了一项实验性功能GraalVM JIT 编译器。GraalVM JIT 编译器比标准 OpenJDK JIT 编译器更快,也更易于维护。甲骨文的这一举动引起了争议,因为他们曾研究过将 GraalVM JIT 编译器纳入所有 OpenJDK 发行版,而不仅仅是他们自己的发行版。这项研究的状态目前尚未可知。
Java 需要 JIT 编译器,因为 HotSpot JVM 会在运行时解释与机器无关的 Java 字节码。与 C++ 等语言相比,这个过程要慢得多,因为 C++ 的超前(AOT)编译器会在构建时创建机器代码。在 Java 中,JIT 编译器会在运行时将常用方法(“热点”)的字节码转换为机器代码。
GraalVM JIT 编译器是 Oracle 实验室项目 GraalVM 的成果之一。这是一个面向 Java、JavaScript、Python 和 Ruby 等 JVM 语言的高性能运行时。GraalVM JIT 编译器可以在名为 HotSpot JVM 的标准 OpenJDK 虚拟机中运行。此外,它也可以在 GraalVM JDK(基于 Oracle JDK 的 Java 发行版)中运行。
标准 OpenJDK HotSpot JIT 编译器是一个由 C1 和 C2 编译器组成的分层编译器。这两种编译器都是用 C++ 编写的,并且自 2000 年以来就一直是默认的编译器。与 HotSpot 相比,GraalVM JIT 编译器有一些技术优势,而且是用 Java 编写的,比 C1 和 C2 的 C++ 代码更易于维护。甲骨文发现,使用 GraalVM JIT 编译器运行其云业务软件 NetSuite 时,CPU 消耗一般可降低 6-7%,在某些工作负载中可降低 13%。
GraalVM 还有一个 Java 编译器:本地镜像 AOT 编译器,它将编译和尽可能多的初始化工作转移到构建时。它生成的本地可执行文件可立即启动,并且没有 JIT 编译器。甲骨文表示,借助性能分析引导优化(PGO),本地镜像的峰值性能接近 JIT 编译器,在某些情况下甚至超过了 JIT 编译器。
使用 GraalVM 本地镜像的代价是,可能会出现一些对大多数 Java 应用程序没有影响的限制,而且故障排查的成本会增加不少。多年来,Helidon、Micronaut、Quarkus 和 Spring Boot 等应用程序框架一直都支持 GraalVM 本地镜像。有些库,尤其是比较老的库,并没有提供开箱即用的支持,但通常只要补充下本地镜像的配置数据,就能正常工作。
甲骨文于 2022 年 12 月提出了 OpenJDK 项目 Galahad。其目标是将 GraalVM JIT 编译器和 GraalVM 本地镜像 “贡献给 OpenJDK 社区,并为可能在 JDK 主线版本中孵化它们做好准备”。该项目已于 2023 年初获得批准,但此后几乎没有任何公开活动。
今年 6 月,甲骨文公司的 Douglas Simon表示:“Galahad 项目的目标是使 GraalVM 项目与 OpenJDK 和 Oracle JDK 更好地保持一致。Galahad 主要是为了协调两个团队之间的开发流程,应该不会对 GraalVM 发行版中用户可见的功能产生任何重大影响”。截至 2024 年 11 月,关于 Galahad 项目是否会导致 GraalVM JIT 和 AOT 编译器被纳入未来的 OpenJDK 主线版本,以及何时纳入,均没有明确的消息。目前,也没有明确的消息说明 OpenJDK 主线中的 GraalVM JIT 编译器与 Oracle OpenJD 发行版中的 GraalVM JIT 编译器有何不同。
InfoQ 曾向甲骨文公司咨询过相关问题,但甲骨文公司并未给予答复。
Azul Systems 公司副首席技术官 Simon Ritter 很高兴地回答了有关 JIT 编译器的问题。
Simon Ritter: 要明确地回答这个问题很难。JIT 编译器的作用是在运行时将 Java 字节码转换为本地机器指令。与单纯解释字节码相比,这样做的好处是大大提高了应用程序的性能。
作为 HotSpot 虚拟机的一部分,C1 和 C2 JIT 编译器早在 JDK 1.2 版本中就已引入,为的是解决 Java 运行速度慢的问题。使用 C1 快速编译代码立即就可以获得性能的提升。之后,使用 C2 重新编译代码,根据收集到的性能分析数据生成最优的本地指令。
替换 C2 可以生成优化程度更高的本地指令,从而提高应用程序的性能。在很大程度上,提升程度取决于代码的实际操作。如果应用程序比较简单,则不太可能有任何性能上的改进,而如果应用程序比较复杂,比如数值密集型应用程序,则可能会有很大的性能提升。归根结底,最好的方法是测试各种替代方案,并确定哪种方案最适合您的应用程序。
Ritter:Falcon 是 C2 JIT 编译器的替代品,基于开源的 LLVM 编译器项目。LLVM 是可重用模块化编译器和工具链技术的集合。它的大部分工作是将编译生成的代码的中间表示与性能分析数据相结合,生成最优的本地机器指令。利用这一点,Azul 将其集成到了 JVM 中,与垃圾收集器、类加载器等协同工作。这项工作随后又被贡献给了 LLVM 项目。
使用 LLVM 进行 JIT 编译可以获得不同的性能特征。它使用的技术包括更激进的推测优化和更好的自动矢量化,仅举两例。通常,这能带来两位数的性能提升。
Ritter:C2 是 1998 年推出的,其设计是一体的,很难通过修改来提高性能。Falcon 基于 LLVM,它是模块化的,添加新的编译功能要容易得多。
Graal JIT 编译器是用 Java 编写的。同样,修改代码生成方式和改进优化都更简单。目前,Graal JIT 编译器并未包含在 OpenJDK 中,而仅在 Oracle JDK 中作为实验性功能提供。
Ritter: 这个问题也很难给出一个明确的答案。我能想到的最好的回答是,与.NET 和 JavaScript 相比,基于 JVM 的应用程序在服务器端更受欢迎。JVM 具有令人难以置信的可扩展性和健壮性,这也是几乎所有企业关键任务应用程序都选择这一平台的原因。
查看原文链接:
https://www.infoq.com/news/2024/12/oracle-jdk-graalvm-jit-compiler/\\"
","description":"2024 年 9 月,甲骨文公司在其 OpenJDK 发行版 Oracle JDK 23 中添加了一项实验性功能GraalVM JIT 编译器。GraalVM JIT 编译器比标准 OpenJDK JIT 编译器更快,也更易于维护。甲骨文的这一举动引起了争议,因为他们曾研究过将 GraalVM JIT 编译器纳入所有 OpenJDK 发行版,而不仅仅是他们自己的发行版。这项研究的状态目前尚未可知。 Java 需要 JIT 编译器,因为 HotSpot JVM 会在运行时解释与机器无关的 Java 字节码。与 C++ 等语言相比,这个过程要慢得多,因为 C+…","guid":"https://www.infoq.cn/article/wmxEBSSVlYH4i0ZsPC7m","author":"作者:Karsten Silz","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-12-25T00:05:05.885Z","media":null,"categories":["编程语言"],"attachments":null,"extra":null,"language":null},{"title":"装机超1500万节点,适配超96000软硬件,开源操作系统OpenCloudOS又向前迈了一大步","url":"https://www.infoq.cn/article/8acNHZtU3pRhRPPE5gWI","content":"12月21日,记者从2024 开源操作系统OpenCloudOS社区年会上获悉,截至目前, OpenCloudOS装机量突破1500万节点,已经在娱乐、政务、医疗、银行、保险、证券等各行各业实现落,同时,OpenCloudOS社区上下游共建企业达800家,触达超15万开发者,适配的软硬件超过96000款。
会上,OpenCloudOS社区还正式发布了城市联盟计划,并成立了OpenCloudOS社区行业发展委员会。城市联盟计划将在北京、上海、深圳、广州、杭州五个城市率先开始试点,通过与当地软件行业头部企业的合作,加速OpenCloudOS的全行业、全场景落地。社区行业发展委员会则将推动行业标准制定、促进OpenCloudOS在细分行业的应用加入和技术发展。
中国电子技术标准化研究院研究室主任杨丽蕴表示,如今,操作系统、云计算、大数据等各类开源软件,正逐渐成为软件领域技术创新的主导力量。随着国际开源生态竞争的日趋激烈,中国开源事业发展也面临着一些新的挑战,希望OpenCloudOS开源社区和企业能够把握住机遇,群策群力,推动软件迭代创新,技术演进升级,共同促进中国开源软件的高质量发展。
腾讯云副总裁、OpenCloudOS社区技术监督委员会(TOC)主席郭振宇表示,在OpenCloudOS社区成立以来的三年时间里,通过技术适配、社区活动、生产高质量内容以及培养高校人才等机制,不断加快与生态厂商共建OpenCloudOS的步伐。未来,围绕“全链路自研创新”目标, OpenCloudOS还会在技术研发、生态建设等方面进一步发力,与合作伙伴携手创造更繁荣的OS生态。
近些年,随着数字化和智能化浪潮的持续推进,操作系统作为连接硬件与软件的桥梁,在现代产业中的重要性也愈加凸显。
2021年12月,腾讯、宝德、飞腾、浪潮、龙芯中科等20余家操作系统上下游企业共同发起成立了OpenCloudOS操作系统开源社区,致力打造全面中立、开放、安全、稳定易用、高性能的操作系统,构建健康繁荣的操作系统生态。目前,OpenCloudOS社区已经成为国内三大服务器操作系统根社区之一,实现了从源社区、商业版到社区稳定版的全链路覆盖。
作为社区的主要发起方之一,腾讯将在操作系统领域超十年的技术积累全部贡献到了OpenCloudOS社区。在过去一年中,包括腾讯在内的多家社区企业投入L1到L3版本研发,不断迭代升级,提升OpenCloudOS在AI、云原生等场景下的稳定性、安全性和技术领先性,为各行业的数字化升级提供更加好用、易用的解决方案和服务。
OpenCloudOS发行版研发负责人及腾讯操作系统发行版研发负责人陶松桥介绍,在产品迭代方面,基于OpenCloudOS 7、8、9的各个LTS版本,OpenCloudOS不断演进并发布了新的版本,装机量达到了1500万,同源可支持X86_64、ARM64、龙芯、RISC-V四种架构。
此外,OpenCloudOS还进一步推动了AI在研发全流程的应用,比如自动化更新和打包、自动化review等,将软件包升级效率提升80%以上,AI助手实现了智能问答与智能运维等,为企业提供了更加高效、智能化的服务。
今年3月,OpenCloudOS还重磅开源云原生OS玄湾,为容器安全运行提供了轻量级云原生解决方案,进一步打破了传统镜像构建与升级的局限。
目前,经过在真实业务场景中千万级节点的长时间验证,0penCloudOS可用性高达 99.999%,与CentOS 7和其他开源社区版本相比,故障率降低超 70% ,且在典型业务场景中性能提升超50%。
以娱乐行业为例,趣丸科技是一家集兴趣社交、电子竞技、人工智能于一体的创新型科技企业,为了支撑业务的快速发展以及直播场景的需求,趣丸科技采用OpenCloudOS开源操作系统,结合业务特点将容器化集群平均利用率提高到了50%左右,高峰利用率达80%,降本增效的同时,满足了不断增长的业务需求。
","description":"12月21日,记者从2024 开源操作系统OpenCloudOS社区年会上获悉,截至目前, OpenCloudOS装机量突破1500万节点,已经在娱乐、政务、医疗、银行、保险、证券等各行各业实现落,同时,OpenCloudOS社区上下游共建企业达800家,触达超15万开发者,适配的软硬件超过96000款。 \\n\\n会上,OpenCloudOS社区还正式发布了城市联盟计划,并成立了OpenCloudOS社区行业发展委员会。城市联盟计划将在北京、上海、深圳、广州、杭州五个城市率先开始试点,通过与当地软件行业头部企业的合作,加速OpenCloudOS的全行业…","guid":"https://www.infoq.cn/article/8acNHZtU3pRhRPPE5gWI","author":"李冬梅","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-12-24T08:39:03.168Z","media":[{"url":"https://static001.geekbang.org/infoq/68/68f8d95476142156305ddc232c0f8513.png","type":"photo","width":1592,"height":1042,"blurhash":"LSEoMikDE2s:~Uf6Rka#w?adt6WC"},{"url":"https://static001.geekbang.org/infoq/96/967b8112ea50d380ae73102b17f9461d.png","type":"photo","width":1592,"height":1042,"blurhash":"LUM6h[$Y-=Mv~UnfNMM}M_WXs:a$"},{"url":"https://static001.geekbang.org/infoq/a7/a7077f10eea9b92fe99fcdecb64a714d.png","type":"photo","width":1592,"height":1042,"blurhash":"LKGH_fNF0LifD~%3t6XN0JWA?Hxu"},{"url":"https://static001.geekbang.org/infoq/44/447c9a5aacb04e4722e6b1d363f61c54.png","type":"photo","width":1592,"height":1042,"blurhash":"LLCs8vS6V=s*~CWnbdkEs*xuWCRk"}],"categories":["腾讯","操作系统"],"attachments":null,"extra":null,"language":null},{"title":"机器比人靠谱!Meta 耗时4年半,将Java 代码转成Kotlin:进度刚过半,真正难搞的还没开始","url":"https://www.infoq.cn/article/ECShuXrDetidmYD33GvE","content":"自2020年以来,Meta公司的Android开发就一直以Kotlin为先,这一编程语言也在公司内部得到了开发人员们的普遍好评和支持。
然而,早期采用并不涉及遗留代码转换。对于大部分其他企业,常见的作法仅仅是直接用Kotlin编写一切新代码,同时继续保留原有Java代码。或者也可以更进一步,只转译最重要的原有代码文件。但相反,Meta认为充分发挥Kotlin价值的唯一方式就是全力以赴推进转译,而这也意味着必须构建自有基础设施以大规模实现转译自动化。
为此,Meta的工程师们在几年前就决定用Kotlin重写约千万行本已完好、运行顺畅的Java代码。另外,Meta还必须解决转译以外的各种问题,例如构建速度慢以及linter测试不足等。
为了最大限度提高开发人员的生产力与null安全性,Meta的目标是转译几乎所有正在积极开发的代码,以及依赖项图谱中的全部核心代码。可以想见,这涉及Meta的大部分代码,累计达到数千万行之巨,其中涉及不少极其复杂的文件。
直观来讲,如果想要最大限度提高生产力,Meta必须转译其积极开发的代码部分。除此之外,能够提供增量null安全优势的部分也在需要转译的范畴之内。简而言之,任何遗留的Java代码都可能引发null混乱,特别是不具备null安全保障的部分。如果既涉及null安全、又属于依赖项图谱的核心,自然成为转译工作的重中之重。
Meta还希望尽量减少混合代码库的缺点。只要还拥有大量Java代码,Meta就必须继续支持并行工具链。另外一个备受诟病的问题就是构建速度较慢:Kotlin的编译速度本身就不及Java编译,但同时编译二者才最是影响性能。
与业内的大多数企业一样,Meta的迁移之旅同样是从反复单击Intellij IDE中的功能按钮开始。这项操作将触发Intellij的翻译工具,即大家熟悉的J2K。但Meta工程师们很快发现,这种方法无法扩展至规模庞大的代码库:为了转译Meta的Android代码库,工程师们必须先点击按钮、然后等待几分钟后才能恢复运行,而这样的操作几乎要重复达十万次。
考虑到这一点,Meta开始着手推动转换过程自动化,并尽量减少对于开发人员日常工作的干扰。结果就是,Meta围绕J2K构建了一款名为Kotlinator的工具,其具体操作现在包含以下六个阶段:
“深度”构建:对要转译的代码进行构建有助于IDE解析所有符号,特别是涉及第三方依赖项或者所生成代码的情况。预处理:此阶段建立在Mea的自定义工具Editus之上,其中包含约50个具体步骤,涵盖可空性、J2K解决办法、通过变更支持自定义DI框架等等。无头J2K:还是那个大家熟悉且喜爱的J2K,但对服务器更加友好。后处理:此阶段在架构上与预处理部分类似,其中包含约150个针对Android特定变更的步骤,以及更多可空性变更及调整,以确保生成的Kotlin代码更加自然地产。Linter测试:使用自动修复运行linter测试,保证Meta能够以有利于弥合转换diff及常规diff的方式实现永久修复。构建基于错误的修复:最后,Kotlinator会根据构建错误执行进一步修复。如果刚刚转译完成的代码遭遇构建失败,该工具会解析错误并应用进一步修复。
第一步是创建一个能够在远程设备上运行的无头版J2K——考虑到J2K与Intellij IDE其余部分的紧密耦合,这项工作并不容易。
Meta的工程师们尝试了几种方法,包括使用类似于Intellij测试环境的设置运行J2K等。但在与JetBrains的J2K专家Ilya Kirillov交谈之后,他们最终决定采用更类似于无头检查的方法。为了实现这种方法,工程师们开发出一款Intellij插件,其中包含一个用于扩展ApplicationStarter的类,并直接调用JavaToKotlinConverter类——IDE中的转换按钮同样会引用该类。
除了不会阻塞开发人员的本地IDE之外,无头方法还使得一次性转译多个文件成为可能,同时消除了一系列有用但却耗时的步骤,例如接下来详述的“构建与错误修复”流程。尽管总体转换时间变长(典型的远程转换现在需要大约30分钟才能运行完成),但开发人员投入的时间却大幅缩短。
当然,无头转换带来了另一个难题:如果开发人员不亲自点击按钮,那么该由谁来决定转译什么、如何审核以及能否发布?
答案其实很简单:Meta拥有一套内部系统,允许开发人员设置一项实质上属于cron作业的任务,其会根据用户定义的选择标准每天生成一批diff(Meta版的pull request)。该系统还能帮助选择相关度最高的审阅者,以确保测试及其他验证顺利通过,而后经人工批准再发布diff。Meta还为开发人员提供一套Web UI,用于触发针对特定文件或者模块的远程转换;在后台,整个运行过程与cron作业完全相同。
至于选择转译的内容和时间,除了优先考虑正在积极开发的文件之外,Meta不强制规定任何顺序。目前的Kotlinator足够复杂,可以处理外部文件中所需要的大多数兼容性变更(例如将Kotlin依赖项的foo.getName()引用更改为foo.name),因此无需根据依赖项图谱对转译做出排序。
由于Meta拥有的代码库规模极大且须使用自定义框架,原始J2K生成的绝大多数转换diff都无法构建。
为了解决这个问题,Meta在转换过程中添加了两个自定义阶段,即预处理与后处理。这两个阶段均包含数十个步骤,具体涵盖接收正在转译的文件、执行文件分析(有时也须分析文件的依赖项及从属项),并在必要时执行Java到Java或者Kotlin到Kotlin的转换。Meta的部分后处理转换方法已经开源(https://github.com/fbsamples/kotlin_ast_tools\\")。
这些自定义的转译步骤建立在内部元编程工具之上,该工具利用到了Jetbrains的Java以及Kotlin PSI库。与大多数元编程工具不同,其并不属于编译器插件,因此可以分析两种语言中的损坏代码,而且运行速度极快。这种速度优势对于后处理阶段尤其重要,因为其通常会在存在编译错误的代码上运行,执行各类需要配合类型信息的分析。对于一部分涉及依赖项的后处理步骤,往往需要解析数千个无法构建的Java及Kotlin文件中的符号。例如,Meta的一个后处理步骤通过检查其Kotlin实现程序并将重写的getter函数更新为重写属性以协助完成接口转换。
但这款工具的速度和灵活性也存在一定缺点,导致其有时无法提供关于类型信息的答案,特别是难以解析第三方库中定义的符号。在这种情况下,该工具会直接放弃,避免在不确定的情况下仍然执行转换。尽管其生成的Kotlin代码可能仍无法构建,但余下的修复工作量对于工程师们来说已经完全在可接受范围之内(只是较为枯燥)。
Meta最初添加这些自定义阶段的目的,在于帮助开发人员减少工作量。但随着时间推移,Meta也开始利用这些阶段降低开发人员造成的不可靠问题。与普遍观点相反,Meta发现将最微妙的转换留给机器反而更加安全。有些并非绝对必要的修复会在后处理过程中自动执行,因为Meta希望最大限度减少人为干预(这也是大部分错误的根源)。其中一例就是压缩长链中的null检查:生成的Kotlin代码并不一定正确度更高,但也更少受到善意开发人员们意外丢弃的影响。
在Meta的代码转换过程中,工程师们注意到有相当一部分时间被用于根据编译器的错误信息反复构建及修复代码。理论上,当然可以在自定义后处理阶段修复大部分此类问题人,但这样做要求重新实现Kotlin编译器中所嵌入的大量复杂逻辑。
因此,Meta决定在Kotlinator中添加新的收尾步骤,以与人类工程师相同的方式利用编译器提示的错误消息。与后处理阶段一样,这些修复同样通过可分析无法构建代码的元编程以实现执行。
在预处理、后处理与生构建阶段之间,Kotlinator工具共包含200多个自定义步骤。可遗憾的是,某些转换问题根本无法通过添加更多步骤来解决。
Meta最初将J2K视为一种黑箱——尽管已经开源,但其代码仍非常复杂且并未积极开发;而深入研究并为其提交PR贡献似乎又太过耗时耗神、价值有限。这种情况在2024年初有所变化,当时JetBrains开始着手改造J2K以使其与新的Kotlin编译器K2相兼容。Meta借此机会与JetBrains合作改进了J2K,一举解决了困扰多年的各种问题,例如override关键字消失。
与JetBrains的合作,还让Meta有机会在J2K中插入hook,以使得Meta等客户端能够在转换前后直接在IDE中运行自己的自定义步骤。考虑到已经编写了大量自定义处理步骤,此举似乎无甚必要,但切实带来了以下好处:
改进符号解析。Meta的自定义符号解析虽然快速且灵活,但在精确性上仍不及J2K,这一点在解析第三方库中定义的符号时体现尤其明显。对一系列预处理及后处理步骤进行移植以利用J2K扩展点,不仅有助于提升其准确性,也允许工程师们使用Intellij提供的更为复杂的静态分析工具。降低开源与协作难度。Meta的某些自定义步骤由于高度针对Android而无法被纳入J2K,但其功能本身往往同样符合其他公司的需求。遗憾的是,其中大多数都依赖于Meta自定义的符号解析机制。通过将这些步骤移植到依赖J2K的符号解析当中,Meta将这部分成果进行了开源,此举也使其能从社区的共同努力中获益。
为了在避免到处产生null指针异常(NPE)的前提下实现代码转译,Meta首先需要保证null安全(所谓null安全,是指由Nullsafe或者NullAway等静态分析器对代码进行检查)。Null安全虽然不足以彻底消除发生NPE的可能性,但至少是个很好的起点。可遗憾的是,代码的null安全一直是个说起来容易、做起来难的大麻烦。
即使是null安全Java代码,偶尔也会抛出NPE。
其实经常接触null安全Java代码的朋友都清楚,虽然其可靠性要远超原始Java代码,但触发NPE的几率仍然不低。遗憾的是,静态分析只在100%代码覆盖率下才能让人彻底安心,而这样的覆盖率在任何与服务器及第三方库交互的大规模移动代码库中都不现实。
下面就是一个看似无害的典型变更案例,其很有可能触发NPE:
@Nullsafe\\npublic class MyNullsafeClass {\\n \\n void doThing(String s) {\\n // can we safely add this dereference?\\n // s.length;\\n }\\n}
假设有十几个依赖项均须调用 MyNullsafeJava::doThing。单一非null安全依赖项可能传入一个null参数(例如MyNullsafeJava().doThing(null)),这时如果在doThing的主体中插入取消引用,则会导致NPE。
当然,虽然无法通过百分之百的null安全覆盖率彻底消除Java中的NPE,但仍可以大大降低其发生频率。在上面的例子中,当只有一个非null安全依赖项时,触发NPE的情况往往相当罕见。但如果有多个传递依赖项均未经null安全,或者其中某个更加核心的依赖节点不具备null安全,则NPE风险会高得多。
Null安全Java与Kotlin之间的最大区别在于,在跨语言边界的Kotlin字节码中存在运行时验证机制。这种验证虽不可见但却功能强大,因为其允许开发人员信任自己正在修改或者调用的任何代码中所声明的可空性注释。
让我们重新回到之前的MyNullsafeClass.java示例,在将其转译为Kotlin之后,则会得到类似以下形式的内容:
MyNullsafeClass.kt\\nclass MyNullsafeClass {\\n \\n fun doThing(s: String) {\\n // there\'s an invisible `checkNotNull(s)` here in the bytecode\\n // so adding this dereference is now risk-free!\\n // s.length\\n }\\n}
现在,在doThing主体开头的字节码中存在一个不可见的checkNotNull(s),意味着我们可以安全添加对s的取消引用。因为如果s可空,则此代码将崩溃。大家可以想见,这种确定性将使得开发更加顺畅且安全。
在静态分析层次上也存在一些差异:在并发方面,Kotlin编译器会强制执行比Nullsafe略为严格的一组null安全规则。具体来讲,Kotlin编译器可能会因为取消对另一线程中设置为null的类级属性的引用而抛出错误。这个差异对Meta来说并不重要,但其确实会导致null安全代码的转译过程中出现更多问题。
也没那么简单。相信大家都清楚,歧义的由多转少对应着大量成本。对于像MyNullsafeClass这样的情况,尽管在转译为Kotlin之后能够大大降低开发难度,但相应的也必然有人要承担起初始风险——即为那些确切不可为null的参数有效插入非null断言。而承担风险的“人”,只能是最终负责Kotlin转换工作的开发人员或者机器人。
我们当然可以采取一些措施为尽量减少转换过程中引入新NPE的风险,其中最简单的办法就是在转换参数及返回类型时偏向“更可空”。仍然以MyNullsafeClass为例,Kotlinator会使用上下文线索(在此例中,doThing主体中没有任何取消引用)来推断String s是否应被转换为s:String?。
在审查转换差异时,Meta要求开发人员高度关注的变更之一,就是在预先存在的取消引用之外添加!!。有趣的是,Meta所担心的并不是像foo!!.name这样的表达式,因为其在Kotlin中引发崩溃的可能性并不比Java这边更高。相反,像someMethodDefinedInJava(foo!!)这样的表达式倒更值得关注,因为someMethodDefinedInJava可能只是在其参数上缺少@Nullable,盲目添加!!反而会不必要地引发NPE。
为了避免在转换过程中添加不必要!!之类的问题,Meta运行有十几种互补的代码模块。它们会认真检查代码库,查找可能缺失的@Nullable参数、返回类型及成员变量。在整个代码库中(即使是那些永远不可能转译的Java文件中)实现更准确的可空性不仅有助于提高安全水平,同时也能大大改善转换成功率,这一点对于转译项目的收尾部分显得尤其重要。
当然,Java代码中剩余的最后一点null安全问题往往会长期存在,其解决难度也是最高的。以往解决这些问题的尝试主要是依赖静态分析,因此Meta决定借鉴Kotlin编译器的基本思路,即创建一款Java编译器插件来帮助收集运行时可空性数据。这款插件允许Meta收集一切接收/返回null值,且未被注释为null值的返回类型及参数数据。无论其属于来自Java/Kotlin互操作还是在本地级别注释错误的类,Meta都可以借此确定最终事实来源并使用codemods对相应注释进行修复。
除了null安全风险之外,还有其他几十种可能性都会威胁到转换过程中的代码完整性。在交付了超过4万次转换之后,Meta已经从这段艰难的旅程中吸取到诸多教训,目前也设置了多层验证加以预防。下面分享几项重点举措:
// Incorrect!\\nval name: String = getCurrentUser().name\\n \\n// Correct\\nval name: String\\n get() = getCurrentUser().name
// Original\\nif (foo != null && !foo.isEnabled) println(\\"Foo is not null and disabled\\")\\n \\n// Incorrect!\\nif (foo?.isEnabled != true) println(\\"Foo is not null and disabled\\")\\n \\n// Correct\\nif (foo?.isEnabled == false) println(\\"Foo is not null and disabled\\")
截至目前,Meta的Android Java代码中已经有超过半数被成功转译为Kotlin(在少数情况下也可能被直接删除)。但这只是其中比较简单的一半!真正艰难的部分仍在后面,而且越来越棘手。
Meta希望通过添加并改进自定义步骤以及为J2K项目做出贡献以最终实现更多完全自动化的转换流程。更重要的是,Meta还希望通过对Kotlinator的改进顺利且安全地交付余下几千个半自动转换流程。
Kotlin 在 Android 开发中占有重要地位。目前 Android 上 80% 的应用都使用 Kotlin。
Kotlin 的开发与 Java 密不可分。JetBrains 于 2010 年开始开发 Kotlin,以摆脱内部对 Java 的过度依赖。Kotlin 的早期开发者之一 Dmitry Yeremov早在 2011 年就指出\\",从 Java 到 Kotlin 的转变将逐步进行。
获得 Google 等巨头的官方支持是让 Kotlin 像 Java 一样受欢迎(甚至更受欢迎)的重要一步。2017 年,当谷歌宣布 Kotlin 将作为 Android 官方语言时,现场观众欢呼雀跃。
Kotlin 在 Google 的编程生态系统中占有重要地位,主要应用于 Android 应用开发。不过根据 Analytics Insight数据,谷歌最重要和使用最广泛的顶级编程语言则是Python、C++、Java 和 Golang。
Python 是 Web 开发、数据科学、人工智能和自动化等各种应用的理想选择,其活跃的社区确保了持续的改进和支持。Python 的多功能性使开发人员能够快速制作原型并实施解决方案,使其在学术研究和行业应用中都具有很高的价值。谷歌在各种项目中对 Python 的支持,包括 TensorFlow 等机器学习框架,进一步巩固了其作为顶级编程语言的地位。
C++\\" 主要用途是大多数现代浏览器的核心Chromium,例如 Chrome、Mozilla、Brave 等。Java 可以创建复杂的 Web 应用程序,用于 Gmail 功能、Stadia 以及更重要的 Google Document Suite 中。Golang 主要用于基于 Web 的应用程序,包括 Google Cloud 微服务、地图管理、Gmail 服务等,几乎每个微服务都可能使用 Golang 语言。
但实际上,Kotlin 在 Android 之外也越来越受欢迎,Kotlin 现在用于后端开发、全栈开发、Web 应用程序,甚至数据科学。
得益于 Ktor 和 Spring Boot(完全支持 Kotlin)等框架,Kotlin 在后端开发中的应用越来越广泛。该语言的简单性和富有表现力的语法使其成为构建 RESTful API 和微服务的理想选择。Kotlin 既可用于服务器端开发,也可用于客户端开发,从而减少了对堆栈内多种语言的需求。借助 Kotlin/JS,开发人员可以编写编译为 JavaScript 的Kotlin 代码\\",从而实现全栈 Kotlin 应用程序。Kotlin Multiplatform 则允许跨平台共享代码,使开发人员更容易使用单一代码库维护 Android、iOS 和 Web 应用程序。今年5月谷歌宣布将在安卓平台支持 JetBrains 旗下 Kotlin Multiplatform 技术。
尽管 Kotlin 在某些方面已经取代了 Java,但它并没有在各个方面都超越这门旧语言。例如,Java 的 IDE 体验仍然被认为是更优,其文档更为详尽。与Rust 一样,Kotlin 用户也抱怨其编译时间过长。
但正如一位经验丰富的Java开发人员所说,“尽管我过去很喜欢Java,但在经历了这样一个实用且富有成效的语言之后,现在我看到了新的可能性。”
参考链接:
https://www.analyticsinsight.net/programming/googles-top-programming-languages-in-2024\\"
https://www.analyticsinsight.net/software-developers/future-of-kotlin-what-developers-need-to-know\\"
https://engineering.fb.com/2024/12/18/android/translating-java-to-kotlin-at-scale/\\"
","description":"自2020年以来,Meta公司的Android开发就一直以Kotlin为先,这一编程语言也在公司内部得到了开发人员们的普遍好评和支持。 \\n\\n然而,早期采用并不涉及遗留代码转换。对于大部分其他企业,常见的作法仅仅是直接用Kotlin编写一切新代码,同时继续保留原有Java代码。或者也可以更进一步,只转译最重要的原有代码文件。但相反,Meta认为充分发挥Kotlin价值的唯一方式就是全力以赴推进转译,而这也意味着必须构建自有基础设施以大规模实现转译自动化。\\n\\n \\n\\n为此,Meta的工程师们在几年前就决定用Kotlin重写约千万行本已完好、运行顺畅的Java代码。另外…","guid":"https://www.infoq.cn/article/ECShuXrDetidmYD33GvE","author":"核子可乐,褚杏娟","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-12-24T07:19:56.080Z","media":null,"categories":["编程语言"],"attachments":null,"extra":null,"language":null},{"title":"亿级订单系统的数据库查询性能优化之路","url":"https://www.infoq.cn/article/a9O4pyXDm40uEIm0gW26","content":"随着京东供应链业务数十年的发展,作为第一环节的采购系统(BIP)俨然在业务复杂度、订单数据量上达到了前所未有的规模,随之而来的数据库查询性能问题屡见不鲜。本文主要介绍了研发团队在面对海量订单场景下,为了提升用户体验、降低系统技术风险,所做的真实优化案例。
•系统概要:BIP 采购系统用于京东采销部门向供应商采购商品,并且提供了多种创建采购单的方式以及采购单审批、回告、下传回传等业务功能。
•系统价值:向供应商采购商品增加库存,满足库存周转及客户订单的销售,供应链最重要的第一环节。
•JED:京东自研的基于 MySQL 存储的分布式数据库解决方案
•JimKV/JimDB:京东自研的新一代分布式 KV 存储系统
采购系统在经历了多年的迭代后,在数据库查询层面面临巨大的性能挑战。核心根因主要有以下几方面:
•复杂查询多,历史上通过 MySQL 和 JED 承载了过多的检索过滤条件,时至今日很难推动接口使用方改变调用方式
•数据量大,随着业务的持续发展,带来了海量的数据增长
•数据模型复杂,订单完整数据分布在 20+张表,经常需要多表 join
引入的主要问题有:
•业务层面:
◦订单列表页查询/导出体验差,性能非常依赖输入条件,尤其是在面对订单数据倾斜的时候,部分用户无法查询/导出超过半个月以上的订单
◦查询条件不合理,1.归档筛选条件,技术词汇透传到业务,导致相同周期的单子无法一键查询/导出,需要切换“是否归档”查询全部;2.无法区分“需要仓库收货”类的单子,大部分业务同事主要关注这类单子的履约情况
•技术层面:
◦慢 SQL 多,各种多表关联复杂条件查询导致,索引、SQL 已经优化道了瓶颈,经常出现数据库负载被拉高
◦大表多,难在数据库上做 DDL,可能会引起核心写库负载升高、主从延迟等问题
◦模型复杂,开发、迭代成本高,查询索引字段散落在多个表中,导致查询性能下降
业务层面:提升核心查询/导出体验,加强查询性能,优化不合理的查询条件
技术层面:1.减少慢 SQL,降低数据库负载,提高系统稳定性;2.降低单表数据量级;3.简化数据模型
提升海量数据、复杂场景下的查询性能!
•采购订单系统 VS C 端销售订单系统复杂度对比:
\ufeff
\ufeff
基于历史数据、业务调研分析,采购订单只有 8%的订单属于“需要实际送货至京东库房”的范围,也就是拥有完整订单履约流程、业务核心关注时效的。其余订单属于通过客户订单驱动,在采购系统的生命周期只有创建记录
\ufeff
基于以上结论,在与产品达成共识后,提出新的业务领域概念:“入库订单”,在查询时单独异构这部分订单数据(前期也曾考虑过,直接从写入层面拆分入库订单,但是因为开发成本、改动范围被 pass 了)。异构这部分数据实际也参考了操作系统、中间件的核心优化思路,缓存访问频次高的热数据
执行流程
\ufeff
\ufeff\ufeff
•“入库”订单数据打标
◦增量订单在创建订单完成时写入;存量订单通过离线表推数
◦需要订单创建模块先完成改造上线,再同步历史,保证数据不丢
◦如果在【数据解析模块】处理 binlog 时无法及时从 JimKV 获取到订单标识,会补偿反查数据库并回写 JimKV,提升其他表的 binlog 处理效率
•binlog 监听
◦基于公司的【数据订阅】任务,通过消费 JMQ 实现。其中订阅任务基于订单号进行 MQ 数据分区,并且在消费端配置不允许消息重试,防止消息时序错乱
◦其中,根据订单号进行各个表的 MQ 数据分区,第一版设计可能会引起热分区,导致消费速率变慢,基于这个问题识别到热分区主要是由于频繁更新订单明细数据导致(订单(1)->明细(N)),于是将明细相关表基于自身 id 进行分区,其他订单纬度表还是基于订单号。这样既不影响订单数据更新的先后顺序,也不会造成热分区、还可以保证明细数据的准确性
•数据同步
◦增量数据同步可以采用源库的增量 binlog 进行解析即可,存量数据通过申请新库/表,进行 DTS 的存量+增量同步写入,完成 binlog 生产
◦以上是在上线前的临时链路,上线后需要切换到源库同步 binlog 的增量订阅任务,此时依赖“位点回拨”+“数据可重入”。位点回拨基于订阅任务的 binlog 时间戳,数据可重入依赖上文提到的 MQ 消费有序以及 SQL 覆盖写
•数据校对
◦以表为纬度,优先统计总数,再随机抽样明细进行比对
◦目前入库订单量为稳定在 5000 万,降低 92%
•考虑到异构“入库”订单到 JED,虽然数据查询时效性可以有一定保障,但是在复杂查询能力以及识别“非入库”订单还没有支持
•其中,“非入库”订单业务对于订单数据时效性要求并不高(1.订单创建源于客户订单;2.没有履约流程;3.无需手动操作订单关键节点)
•所以,考虑将这部分查询能力转移到 ES 上
ES 数据异构过程
\ufeff
•首先,同步到 ES 的数据的由“实时+归档”订单组成,其中合计 20 亿订单,顺带优化了先前归档 ES 大索引(所有订单放在同一个索引)的问题,改成基于“月份”存储订单,之所以改成月份是因为根据条件查询分两种:1.一定会有查询时间范围(最多 3 个月);2.指定单号查询,这种会优先检索单号对应的订单创建时间,再路由到指定索引
•其次,简化了归档程序流程,历史方案是程序中直接写入【归档 JED+归档 ES】,现在优化成只写入 JED,ES 数据通过【数据解析模块】完成,简化归档程序的同时,提高了归档能力的时效性
•再次,因为 ES 是存储全量订单,需要支持复杂条件的查询,所以在订单没有物理删除的前提下,【数据解析模块】会过滤所有 delete 语句,保证全量订单数据的完整性
•接着,为了提升同步到 ES 数据的吞吐,在 MQ 消费端,主要做了两方面优化:1.会根据表和具体操作进行 binlog 的请求合并;2.降低对于 ES 内部 refresh 机制的依赖,将 2 分钟内更新到 ES 的数据缓存到 JimKV,更新前从缓存中获取
•最后,上文提到,同步到入库 JED,有的表是根据订单号,有的表是根据自身 id。那么 ES 这里,因为 NoSQL 的设计,和线程并发的问题,为了防止数据错误,只能将所有表数据根据单号路由到相同的 MQ 分区
优化前,所有的查询请求都会直接落到数据库进行查询,可以高效查询完全取决于用户的筛选条件是否可以精准缩小数据查询范围优化后,新增动态路由层
•离线计算 T-1 的采销/供应商的订单数据倾斜,将数据倾斜情况推送到 JimDB 集群
•根据登陆用户、数据延迟要求、查询数据范围,自动调度查询的数据集群,实现高性能的查询请求
查询调度
\ufeff
\ufeff
1.主/备 ES 可以通过 DUCC 开关,实现动态切换,提升数据可靠性
2.结合公司的业务监控,完成订单数据延迟监控(数据同步模块写入时间-订单创建时间)
3.开启消息队列积压告警
1:1ES 集群进行互备,应急预案快速切换,保证高可用
\ufeff
\ufeff
•第一步,优先上线数据模块,耗费较多时间的原因:1.整体数据量级以及历史数据复杂度的问题;2.数据同步链路比较长,中间环节多
•第二步,预发环境验证,流量回放并没有做到长周期的完全自动化,根因:1.项目周期相对紧张;2.新老集群的数据还是有一些区别,回放脚本不够完善
•第三步,用户功能灰度,主要是借助 JDOS 的负载均衡策略结合用户 erp 完成
•第四步,对外接口灰度,通过控制新代码灰度容器个数,逐步放量
\ufeff
平稳切换,无线上问题
•主动监控层面,新增按照天纬度进行数据比对、异常告警的能力,提高问题发现率
•优化数据模型,对历史无用订单表进行精简,降低开发、运维成本,提升需求迭代效率
•精简存储集群
◦逐步下线其他非核心业务存储集群,减少外部依赖,提高系统容错度
◦目前全量订单 ES 集群已经可以支持多场景的外部查询,未来考虑是否可以逐步下线入库订单 JED
•识别数据库隐患,基于慢日志监控,重新梳理引入模块,逐步优化,持续降低数据库负载
•MySQL 减负,探索其他优化方案,减少数据量存储,提升数据灵活性。优先从业务层面出发,识别库里进行中的僵尸订单的根因,进行分类,强制结束
•降级方案,当数据同步或者数据库存在异常时,可以做到秒级无感切换,提升业务可用率
•为什么没考虑 Doris?因为 ES 是团队应用相对成熟的中间件,处于学习、开发成本考虑
•未来入库的 JED 相关表是否可以下掉,用 ES 完全替代?目前看可以,当初设计冗余入库 JED 也是出于对于 ES 不确定性以及数据延迟的角度考虑,而且历史的一部分查询就落在了异构的全量实时订单 JED 上。现在,JED 官方也不是很推荐非 route key 的查询。最后,现阶段因为降低了数据量和拆分了业务场景,入库 JED 的查询性能还是非常不错的
•因为项目排期、个人能力的因素,在方案设计上会有考虑不周的场景,本期只是优化了最核心的业务、技术痛点,未来还有很大持续优化的空间。中间件的使用并不是可以优化数据库性能的银弹,最核心的还是要结合业务以及系统历史背景,在不断纠结当中寻找 balance
","description":"随着京东供应链业务数十年的发展,作为第一环节的采购系统(BIP)俨然在业务复杂度、订单数据量上达到了前所未有的规模,随之而来的数据库查询性能问题屡见不鲜。本文主要介绍了研发团队在面对海量订单场景下,为了提升用户体验、降低系统技术风险,所做的真实优化案例。 0.前言\\n\\n•系统概要:BIP 采购系统用于京东采销部门向供应商采购商品,并且提供了多种创建采购单的方式以及采购单审批、回告、下传回传等业务功能。\\n\\n•系统价值:向供应商采购商品增加库存,满足库存周转及客户订单的销售,供应链最重要的第一环节。\\n\\n•JED:京东自研的基于 MySQL 存储的分布式数据库解决方案\\n\\n•Jim…","guid":"https://www.infoq.cn/article/a9O4pyXDm40uEIm0gW26","author":"京东零售技术","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-12-23T09:53:58.077Z","media":[{"url":"https://static001.geekbang.org/infoq/70/700e897664ea33c3e62bd6e4a72e4236.jpeg?x-oss-process=image%2Fresize%2Cp_80%2Fauto-orient%2C1","type":"photo","width":626,"height":290,"blurhash":"LCSPU:_3pI?v_NofMxax-pjZxaof"},{"url":"https://static001.geekbang.org/infoq/9a/9aecc4f91241ab3df7b2369f9c161bc8.png","type":"photo","width":1082,"height":634,"blurhash":"LCSF*5?vpI-B?^sAiwtlw_ozX8nO"},{"url":"https://static001.geekbang.org/infoq/55/558c206105e864a7802040fbd52cf5b1.png","type":"photo","width":1320,"height":732,"blurhash":"LCR{uwsrxZ-=~VobNHt5.Sxus;xa"},{"url":"https://static001.geekbang.org/infoq/ca/ca2cd9f25439389a102862c235234f9c.jpeg?x-oss-process=image%2Fresize%2Cp_80%2Fauto-orient%2C1","type":"photo","width":961,"height":521,"blurhash":"L8S$ov~qxu_3_3g3t7jFVtWBkCs:"},{"url":"https://static001.geekbang.org/infoq/64/64213f49f05fc9cce627ce603c18c8ae.jpeg?x-oss-process=image%2Fresize%2Cp_80%2Fauto-orient%2C1","type":"photo","width":984,"height":515,"blurhash":"LESF;K%eV?-q~UVpnMnh?Fw@jDxt"},{"url":"https://static001.geekbang.org/infoq/cf/cfc9dd9adf90dec9f2f743aff39370fa.jpeg?x-oss-process=image%2Fresize%2Cp_80%2Fauto-orient%2C1","type":"photo","width":1051,"height":531,"blurhash":"LHSidJ~qxu%M_2Rkofs:%Ns9S1WX"},{"url":"https://static001.geekbang.org/infoq/04/0485d08cebda71c9e91419269be441f5.jpeg?x-oss-process=image%2Fresize%2Cp_80%2Fauto-orient%2C1","type":"photo","width":961,"height":462,"blurhash":"LJSY]g-pxs-n?wkDt7x]%3kDR-WF"},{"url":"https://static001.geekbang.org/infoq/86/86ec96bd62f0878204447bfa0e5bb14d.png","type":"photo","width":1615,"height":284,"blurhash":"LAS$ln~q-;_3.St7-;WBIpt7%MRj"},{"url":"https://static001.geekbang.org/infoq/c8/c8492232b8a8758a20884417815dd261.png","type":"photo","width":1612,"height":262,"blurhash":"L8SiaA~p-;_4_Nxu-;t6K%M{-:xu"},{"url":"https://static001.geekbang.org/infoq/88/8833b36601f07e6b81f1e4f0743b4783.jpeg?x-oss-process=image%2Fresize%2Cp_80%2Fauto-orient%2C1","type":"photo","width":1991,"height":812,"blurhash":"LESidI~pM{_3?Haft7W;aJWBt6Rj"}],"categories":["数据库"],"attachments":null,"extra":null,"language":null},{"title":"共建操作系统开源生态,OpenCloudOS社区上下游共建企业达800家","url":"https://www.infoq.cn/article/YpFQBMbQvoooajV1xQIA","content":"12月21日,2024 OpenCloudOS年会在京举办,会上,OpenCloudOS社区正式公布了最新合作成果与创新实践案例。目前,OpenCloudOS社区上下游共建企业已经达到800家,触达超15万开发者,装机量突破1500万节点,完成超90万核CentOS替换,可兼容适配96000+软硬件,实现了从源社区、商业版到社区稳定版全链路覆盖。
据了解,2024 OpenCloudOS年会由OpenCloudOS社区主办,腾讯云、海光、中科方德、飞腾、Intel、龙芯中科等社区伙伴共同举办,以“稳建基石,共创新篇”为主旨,聚集了业界顶级技术专家与行业领袖,邀请超300位企业伙伴及用户,共同分享OpenCloudOS的科研成果与实践,探讨下一代操作系统的建设与未来。
作为国内三大服务器操作系统根社区之一,OpenCloudOS沉淀了腾讯及多家厂商在软件和开源生态的优势,在云原生、稳定性、性能、硬件支持等方面均有坚实支撑,可以平等全面地支持所有硬件平台。
现场,OpenCloudOS社区进一步公布了新的技术创新成果与重要进展。
腾讯云副总裁、OpenCloudOS 社区技术监督委员会(TOC)主席郭振宇表示,2024年,OpenCloudOS社区加深了与南北向厂商的开源共建,并建立起长期有效的沟通合作机制,使OpenCloudOS的多个版本在安全和稳定性方面的能力持续提升。未来,希望能有更多新的企业、个人加入,携手创造更繁荣的OS生态。
OpenCloudOS发行版研发负责人及腾讯操作系统发行版研发负责人陶松桥介绍,过去几年,OpenCloudOS的各项技术SIG都在稳步向前,软硬件适配呈现出更加繁荣的生态,在经过千万级节点的长时间验证,OpenCloudOS可用性已经高达99.999%,下一步,社区将持续提升OS性能、共建OS行业标准、加速全行业及全场景替换,打造真正安全可靠、高性能、广泛应用的新一代OS。
OpenCloudOS Stream SIG Maintainer陈晓杰分享了OpenCloudOS云原生OS版本的优势,他表示,目前云原生OS版本已经具备完善的基础功能,可用于部署k8s集群node节点,未来,社区将持续对云原生OS启动流程、运维容器、配置管理等多个维度进行优化开发,面向云场景打造更加轻量化、安全可靠的云原生操作系统。
针对企业数字化过程中面临的跨版本升级迁移的挑战,OpenCloudOS Stream SIG Maintainer夏存舜则介绍了OpenCloudOS跨大版本升级迁移的完整落地方案,通过OpenCloudOS upgrade-oc + rpm-check + Leapp + WebUI解决方案,企业可以更加高效丝滑的实现跨版本迁移。
OpenCloudOS kernelSIG Maintainer郝信则分享了OpenCloudOS在云原生数据库场景下的优化实践与探索,目前优化版本已经上线,服务了外部多个客户,综合优化效果整体QPS提升了超30%
除了在技术层面的进展,会上,来自整机、芯片、存储、安全等12大领域的操作系统上下游的多位生态伙伴、专家学者还分享了与OpenCloudOS技术合作的实践成果。
比如,在开源共建方面,中科方德副总裁胡昆剖析了中科方德在OpenCloudOS社区FoundUI、安全机制和安全供应链相关的成果和应用实践,他表示,“作为基础软件底座,操作系统正在面临安全威胁、供应链风险等多重挑战,中科方德作为社区的深度共建者,将积极携手社区伙伴,共建安全联盟以及可靠稳定的供应链安全管理平台,打造安全可靠的操作系统生态。”
海光生态技术总监李伟则聚焦海光C86指令集及体系架构,介绍了海光在OpenCloudOS社区中的技术贡献,特别是与OpenCloudOS合作打造的性能优化联合解决方案,并分享了SIG共建的案例。
在架构版本打造方面,龙芯中科操作系统研发总监王洪虎分享了龙芯中科与社区共同解决LoongArch架构在OpenCloudOS上的移植适配难题的经验。他认为,现在是发展中国计算机事业和关键核心技术的黄金时期,龙芯团队将全力投入开源社区建设,持续支持多样化的指令集和算力架构,与社区伙伴共同推动OpenCloudOS社区建设成为有国际影响力的操作系统社区。
在技术合作与应用落地方面,趣丸科技基础架构负责人黄金介绍,为了支撑业务的快速发展以及直播场景的需求,趣丸科技采用OpenCloudOS开源操作系统,结合业务特点将容器化集群平均利用率提高到了50% 左右,高峰利用率达80%,降本增效的同时,满足了不断增长的业务需求。
中南民族大学信息化建设管理处信息技术部主任高杰欣分享了学校如何借助OpenCloudOS开展数字化转型的成果,他表示,结合学校对教育信息化数字基座的管理、应用供给以及教学实验对数字基座的整合与资源统筹,基于OpenCloudOS成功实现了国产化硬件上搭建计算资源池,迁移应用,开发应用服务,打造了轻量虚拟化平台技术方案,并将继续围绕人才培养,产学研协同等领域与OpenCloudOS开展合作。
网易有道AI解决方案总监冯江涛则介绍了网易有道开源的 AI 知识库问答平台 QAnything 与 OpenCloudOS 操作系统的集成,为 OpenCloudOS 用户提供了一键部署 AI 知识问答库的能力。
此外,在圆桌对话环节,OpenCloudOS社区 TOC副主席王佳、奇安信天擎事业部总经理李常坤、飞腾软件技术方案部总监郑俊普、英特尔研发经理贾培、北京大学软件与微电子学院副教授荆琦等专家学者,针对“新时代操作系统的挑战与机遇”议题展开了深度讨论,为推动操作系统生态发展提供了方向与参考。
值得一提的是,会上,OpenCloudOS社区还正式发布了城市联盟计划,并成立OpenCloudOS社区行业发展委员会。其中,城市联盟计划预计于2025年在北京、上海、深圳、广州、杭州五个城市试点建设城市联盟,通过与当地软件行业头部企业的合作,推动OpenCloudOS的集成、技术共建和用户市场拓展;行业发展委员会则更聚焦某一垂直行业或领域,计划推动行业标准制定、促进OpenCloudOS在细分行业的应用加入和技术发展、提供企业支持和培训,以及联合开展市场推广活动等。
未来,OpenCloudOS社区将持续开源,携手更多社区伙伴打造健康繁荣的操作系统生态,将更多领先技术、产品方案、优质服务开放给千行百业,为开发者和企业提供丰富、坚实的“装备”。
*所有内容根据嘉宾实际演讲调整
","description":"12月21日,2024 OpenCloudOS年会在京举办,会上,OpenCloudOS社区正式公布了最新合作成果与创新实践案例。目前,OpenCloudOS社区上下游共建企业已经达到800家,触达超15万开发者,装机量突破1500万节点,完成超90万核CentOS替换,可兼容适配96000+软硬件,实现了从源社区、商业版到社区稳定版全链路覆盖。 \\n\\n据了解,2024 OpenCloudOS年会由OpenCloudOS社区主办,腾讯云、海光、中科方德、飞腾、Intel、龙芯中科等社区伙伴共同举办,以“稳建基石,共创新篇”为主旨…","guid":"https://www.infoq.cn/article/YpFQBMbQvoooajV1xQIA","author":"腾讯云","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-12-23T02:48:29.191Z","media":[{"url":"https://static001.geekbang.org/infoq/6a/6aa192089b86d9a3ffeaded35f1505a9.png","type":"photo","width":1080,"height":720,"blurhash":"LiMGFuR7R:xu~oMzWEt7%dM{M|R-"},{"url":"https://static001.geekbang.org/infoq/d0/d0e816c25cb825e818f6934815b810d9.png","type":"photo","width":1081,"height":720,"blurhash":"LLG8W,R%4.igISxvoeXN0JV[?Hxu"},{"url":"https://static001.geekbang.org/infoq/1e/1ecaee87a1948cfb6022c70dc780a756.png","type":"photo","width":1080,"height":720,"blurhash":"LKCPeyNGV;oI~CS1W@a#s+t8RkR*"},{"url":"https://static001.geekbang.org/infoq/a6/a6a4ba3b2cbb15103d36926d99e593e5.png","type":"photo","width":1081,"height":720,"blurhash":"LfHd$]0Lxok7^inhNHtR$fsTWFt7"},{"url":"https://static001.geekbang.org/infoq/14/14430e360a98408164951fffaa535e82.png","type":"photo","width":1080,"height":720,"blurhash":"LZFO$bWA0JM_i^Rjxut8D$flxuoz"},{"url":"https://static001.geekbang.org/infoq/b7/b7c13ebaaaf4b4af086fa6e0c2e100e4.png","type":"photo","width":1079,"height":720,"blurhash":"LLIDzax^DN?a-;aeITx[56V@-oob"},{"url":"https://static001.geekbang.org/infoq/ff/fff676d39391dda0db11544ed3c9c2f4.png","type":"photo","width":1080,"height":720,"blurhash":"LYGRPkVV8_xa+pN#kYoHi]I?t7t7"},{"url":"https://static001.geekbang.org/infoq/7e/7e53d099d3b83809bdfb000d40b54040.png","type":"photo","width":1079,"height":720,"blurhash":"LKGu5@ot9Fx^yB-Wo2-;DNI:xYV?"},{"url":"https://static001.geekbang.org/infoq/69/69bb000e59119e9ef50a3d310b2457fb.png","type":"photo","width":1080,"height":720,"blurhash":"LVEnV5whR5$K}?I=IpbF$eI:R.og"},{"url":"https://static001.geekbang.org/infoq/2a/2a2b5df8654c51b75fbf7f2a47b45fb3.png","type":"photo","width":1080,"height":720,"blurhash":"LoKwCM~UoY-m-qoJRjWAoLayWBWC"},{"url":"https://static001.geekbang.org/infoq/3d/3d4eb7c07b363f3762a2c4a27f3690ba.png","type":"photo","width":1081,"height":720,"blurhash":"L9CO,~4,BpS#~CM{ROkCAANE$Mxa"},{"url":"https://static001.geekbang.org/infoq/19/197cb6249d855666a304dc8fad1ace6c.png","type":"photo","width":1080,"height":720,"blurhash":"LuNmEA8w?GkE?aaeIUozt3RiM{f*"},{"url":"https://static001.geekbang.org/infoq/5c/5ceba008aa6c5cd29b8d98dfcec570c4.png","type":"photo","width":1081,"height":720,"blurhash":"LKEe[rxbIoRj~Wt7NFWBw=obWBae"},{"url":"https://static001.geekbang.org/infoq/ff/ff10b1842ee1e8d4c1ac6dd6619657a0.png","type":"photo","width":1080,"height":720,"blurhash":"LVEx-HogE3s.~BjsRka#x9adt6WC"},{"url":"https://static001.geekbang.org/infoq/16/16baeede960199d49d30f4df42423584.png","type":"photo","width":1079,"height":720,"blurhash":"LqGRuOt7Rjof~UoeWBof$xj?oLj?"}],"categories":["操作系统"],"attachments":null,"extra":null,"language":null},{"title":"Java 近期新闻:JDK 24 进入 Rampdown 阶段、JDK 25 专家组、Jakarta EE 11 Core Profile、Spring Cloud","url":"https://www.infoq.cn/article/er0UuiE1MPtPJkEodYZS","content":"这一周的 Java 新闻综述要点:JDK 24 进入 Rampdown 第一阶段;JDK 25 专家组成立;Jakarta EE 11 Core Profile 和 Spring Cloud 2024.0.0 发布;以及 GlassFish、Open Liberty、Quarkus 和 Apache Camel 的新版发布。
JDK 24 早期版本\\" 的 Build 27\\" 已于上周发布,其中包含 Build 26\\" 以来的更新和对各种问题\\"的修复。有关此版本的更多细节,请参阅发行说明\\"。
根据 JDK 24 的发布时间表\\",Oracle Java 平台组首席架构师 Mark Reinhold 正式宣布 JDK 24 已进入 Rampdown 第一阶段。这意味着主线源代码存储库已分叉到 JDK 稳定存储库\\",并且不会为 JDK 24 添加任何额外的 JEP。因此,2025 年 3 月 GA 版本的最终 24 个特性集将包括:
JEP 404\\":分代 Shenandoah(实验性)
JEP 450\\":紧凑对象标头(实验性)
JEP 472\\":准备限制 JNI 的使用
JEP 475\\":G1 的后期屏障扩展
JEP 478\\":密钥派生函数 API(预览)
JEP 479\\":删除 Windows 32 位 x86 端口
JEP 483\\":提前类加载和链接
JEP 484\\":类-文件 API
JEP 485\\":流收集器
JEP 486\\":永久禁用安全管理器
JEP 487\\":范围值(第四个预览)
JEP 488\\":模式、instanceof 和 switch 中的原始类型(第二个预览)
JEP 489\\":矢量 API(第九个孵化器)
JEP 490\\":ZGC:删除非生成模式
JEP 491\\":同步虚拟线程而不固定
JEP 492\\":灵活的构造函数主体(第三个预览)
JEP 493\\":链接运行时映像而不使用 JMOD
JEP 494\\":模块导入声明(第二个预览)
JEP 495\\":简单源文件和实例主方法(第四个预览)
JEP 496\\":基于量子抗性模块格的密钥封装机制
JEP 497\\":基于量子抗性模块格的数字签名算法
JEP 498\\":在 sun.misc.Unsafe 中使用内存访问方法时发出警告
JEP 499\\":结构化并发(第四个预览版)
JEP 501\\":弃用 32 位 x86 端口以移除
JSR 400(Java SE 25\\")于上周获得批准,正式宣布了 JDK 25 的四人专家组,即 Simon Ritter(Azul Systems)、Iris Clark(Oracle)、Andrew Haley(Red Hat)和 Christoph Langer(SAP SE)。Clark 将担任规范负责人。当前的其他关键日期\\"包括 2025 年 6 月至 8 月的公开审查和 2025 年 9 月的 GA 版本。
JDK 25 早期访问版本\\"的 Build 0\\" 和 Build 1\\" 也于上周发布,其中包含解决一些初始问题\\"的更新。
对于 JDK 24 和 JDK 25,鼓励开发人员通过 Java Bug 数据库\\"报告错误。
Eclipse 基金会 Jakarta EE 开发倡导者 Ivar Grimstad 在其每周的 Hashtag Jakarta EE 博客中提供了 Jakarta EE 11 的最新进展\\",他写道:
Jakarta EE 11 Core Profile\\" 的投票已经完成!这意味着该规范已获得批准并可以发布。这在多个层面上都是一个里程碑。首先,我们在 2024 年发布了 Jakarta EE 11(至少是部分)。其次,我们独立于 Platform\\" 和 Web Profile\\" 规范发布了 Core Profile 规范。这是我们一直想做的事情,也验证了我们能够充分解耦依赖关系以使其成行。 Jakarta EE 11 Platform 和 Jakarta EE 11 Web Profile 规范的投票仍有一丝希望,投票将在年底前开始。
Jakarta EE 11 之路包括四个里程碑版本、核心配置文件的发布,以及在 2025 年 1 季度平台和 Web 配置文件的 GA 发布之前根据需要发布的候选版本。
GlassFish 7.0.20 是第二十个维护版本\\",它提供了依赖项升级和对一些值得注意的问题的解决方案,例如:由于 Jakarta Faces ViewExpiredException\\",在管理控制台中会话超时后无法重定向到主页或登录页面;以及在更新 logging.properties 文件时创建无限数量的日志泵线程。有关此版本的更多细节,请参阅发行说明\\"。
Oracle Labs 发布了 Native Build Tools 0.10.4 版\\",这是一个 GraalVM 项目,由用于与 GraalVM 原生映像互操作的插件组成。最新版本提供了一些值得注意的变化,例如:确保在 AgentConfiguration\\" 类中定义的 accessFilter 输入流是线程安全的;以及对原生映像 SBOM 生成的改进。有关此版本的更多细节,请参阅变更日志\\"。
Oracle 实验室还发布了 Graal Development Kit for Micronaut 4.6.0.6 版本,与 Micronaut 4.6.0 保持一致。Graal Development Kit for Micronaut 以前称为\\" Graal Cloud Native,它提供了一组精选的 Micronaut 框架模块,可简化云应用程序开发。其发行说明\\"仅涵盖了针对特定操作系统的下载、Oracle Maven 中的 GDK 工件列表以及使用 macOS Catalina 及更高版本的开发人员如何删除隔离属性的说明。
在 Spring Cloud 2023.0.4(代号为 Leyton)发布\\"后不到一周,Spring Cloud 2024.0.0(代号为 Moorgate)已发布\\",其中包含错误修复和对一些子项目的重要更新:Spring Cloud Kubernetes 3.2.0;Spring Cloud Function 4.2.0;Spring Cloud OpenFeign 4.2.0;Spring Cloud Stream 4.2.0 和 Spring Cloud Gateway 4.2.0。此版本基于 Spring Boot 3.4.0。有关此版本的更多细节,请参阅发行说明\\"。
Spring Tools 4.27.0 版已发布\\",其中包含错误修复、Eclipse 2024-12 更新以及新特性,例如:支持 Spring Boot @ConditionalOnProperty\\" 注释,包括完成、导航到定义和查找引用;以及支持在 Spring Data JPA @Query\\" 注释内连接字符串以进行数据查询。有关此版本的更多细节,请参阅发行说明\\"。
IBM 发布\\"了 Open Liberty 24.0.0.12 版,其特点是:支持 MicroProfile 7.0;持续改进 SameSite 并改进处理 SameSite=None cookie 值,而无需担心破坏某些客户端版本;以及对 CVE-2024-7254\\" 的解决方案,该漏洞影响 IBM 的 grpc-1.0 和 grpcClient-1.0 特性,攻击者可能会在解析不受信任的协议缓冲区数据时破坏嵌套组/一系列 SGROUP 标签。有关 MicroProfile 7.0 和 Open Liberty 的更多细节,请参阅 IBM Liberty Cloud Native 架构师 Emily Jiang 的这篇博客文章\\"。
Quarkus 3.17.3 是第二个维护版本\\"(由于回落而跳过了 3.17.1),包含了依赖项升级和对以下重要问题的解决方案:由 SmallRye Config PropertyName\\" 类引起的,来自 BuildTimeConfigurationReader\\" 类中定义的 mappingToNames() 方法的 NullPointerException;使用 JDK 23 和 JDK 24 的 JLine\\" 控制台启动时间的回归,通过添加 -Djdk.console=java.base 标志解决了该问题。有关此版本的更多细节,请参阅变更日志\\"。
Apache Camel 4.9.0 的发布\\"提供了错误修复、依赖项升级和新特性,例如:支持 OAuth2 在 Camel HTTP\\" 组件中缓存和刷新令牌;以及将 Smooks Camel Cartridge\\" 迁移到主代码库。有关此版本的更多细节,请参阅发行说明\\"和新特性\\"页面。
Java Operator SDK 5.0.0 的第一个测试版\\"附带一些新特性,例如:Kubernetes 服务器端应用\\"已提升为一等公民,并采用默认方法修补状态资源;以及 EventSource\\" 接口的职责发生变化,以监控资源并处理访问缓存资源、过滤和曾经由 ResourceEventSource\\" 子接口维护的其他特性。有关此版本的更多细节,请参阅变更日志\\"。
Keycloak 26.0.7 是第七个维护版本\\",它修复了大量错误,改进了文档,并将依赖项升级到 Infinispan\\" 15.0.11。有关此版本的更多细节,请参阅发行说明\\"。
Ktor 3.0.2 是第二个维护版本\\",它解决了一些值得注意的问题,例如:当服务器发送无效标头 cache-control: max-age: 120(其中应在 max-age 后使用等号)时,使用 HttpClient\\" 的 HttpCache 插件时出现 IndexOutOfBoundsException;以及使用 FileItem\\" 类中定义的已弃用的 streamProvider() 方法(该方法没有实现)时应用程序会崩溃。有关此版本的更多细节,请参阅发行说明和新特性\\"页面。
原文链接:
Java News Roundup: JDK 24 in Rampdown, JDK 25 Expert Group, Jakarta EE 11 Core Profile, Spring Cloud\\"
","description":"这一周的 Java 新闻综述要点:JDK 24 进入 Rampdown 第一阶段;JDK 25 专家组成立;Jakarta EE 11 Core Profile 和 Spring Cloud 2024.0.0 发布;以及 GlassFish、Open Liberty、Quarkus 和 Apache Camel 的新版发布。 JDK 24\\n\\nJDK 24 早期版本\\" 的 Build 27\\" 已于上周发布,其中包含 Build 26\\" 以来的更新和对各种问题\\"的修复。有关此版本的更多细节,请参阅发行说明\\"。\\n\\n \\n\\n根据 JDK 24 的发布时间表\\",Oracle…","guid":"https://www.infoq.cn/article/er0UuiE1MPtPJkEodYZS","author":"Michael Redlich","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-12-23T02:27:00.777Z","media":null,"categories":["编程语言"],"attachments":null,"extra":null,"language":null},{"title":"如何使用编程规则和指南","url":"https://www.infoq.cn/article/OLjqhMbiaCu6xkTUGDfC","content":"根据 Arne Mertz 的说法,使用编程规则和指南有助于开发人员协同工作,因为它们可以产生更一致、更好的代码。然而,如果使用不当,则会产生相反的结果——代码难以阅读,或者以次优甚至错误的方式解决问题。
Arne Mertz 在 NDC Tech Town 发表了关于编程规则和指南的演讲。
Mertz 解释了规则和指南之间的区别:
规则或多或少是绝对的。无论规则应用在哪里,都必须遵守,违反规则通常是不可接受的。指南是一种最佳实践或合理的默认做法——我们可能有产生分歧的理由,但这没关系。
了解这种差异是很重要的,因为将指南解释或陈述为规则会导致开发人员破坏代码,而不是破坏指南本身,Mertz 认为:
指南的本质是,在某些情况下,它们并不适用,并且在这种情况下,试图坚持应用它们往往会导致代码变繁琐、可读性变差,甚至导致完全的错误。
Mertz 说,对于开发人员来说,严格的规则似乎更方便。编译器对其接受的内容非常严格。我们有太多复杂的问题需要解决,盲目遵循一套规则会让我们负担过重。
在他的演讲中,Mertz 探讨了一些规则和指南。他解释了“不要使用异常”(“don’t use exceptions”)规则的由来:
近二十年来,我看到“不要使用异常”规则(或指南)在各种情况下出现。当你追溯它的起源时,你会发现它是来自谷歌风格指南,其中说到“我们不使用异常”。
Mertz 表示,这种微小的差异非常重要,因为它表明谷歌不使用异常。该风格指南阐述了原因;这并不是因为异常被认为是不好的,而是因为在谷歌,有很多代码在编写时并没有考虑异常。对这样的代码库引入异常会带来引入未定义行为的风险,并且需要重新编写其现有代码库的大部分内容,正如 Mertz 所解释的那样:
Mertz 说道:“谷歌是出于必要才采用了这一指南的,而且,据我从在谷歌工作过的人那里了解到的情况看,并不是所有地方都遵循了这一指南。”。
Mertz 表示,在项目中应用这一指南时,指出它的起源以及它是针对旧的大型项目这一事实可能会导致该指南被弃用;当然,除非到那时,这个有问题的项目也已经发展了多年,并且没有考虑异常,而引入异常到这些项目中会导致与谷歌采用该指南同样的问题,他补充道。
Mertz 探索的另一条规则是“每个函数都应有一个返回(return)语句”。该规则是几组指南和规则的一部分,例如 MISRA C 和 MISRA C++ 规则。正如 Mertz 所解释的那样,制定这一规则的原因各不相同:
一些人认为长函数的可读性更高,但反驳的观点是首先应该缩短函数。在像 C 这样的语言中,过早返回可能会意外忽略资源清理,这样是很糟糕的。
Mertz 提到,当你将 C++ 与 RAII 类一起使用,该论点并不适用,因为编译器能通过析构函数来保障资源的清理。
InfoQ 就遵循编程规则和指南可能产生的影响采访了 Arne Mertz。
Arne Mertz:异常是 C++ 语言报告错误的核心特性。不经常使用异常会导致过多地使用错误返回码和输出参数,从而使代码变得更难阅读和推理。像 std::expected 这样的现代库解决方案可以在一定程度上缓解这些问题,但我从未见过它们被用于因谷歌指南而避免异常的项目中。
我推测,尤其是在 21 世纪初,谷歌作为一家软件公司是一个时髦的榜样,所以人们都想要效仿他们。他们在完全不同的代码库中采用了这一指南,而没有质疑它的必要性。
Mertz:遵循该规则通常会导致“retVal”变量的某些变体,这些变体通常会被初始化为一个无意义的值,希望稍后能被赋值为实际的返回值。此外,我们经常看到用一个变量来跟踪我们是否在一条正确的道路上,或者跟踪一个深度嵌套的控制流。所有这些模式都会使代码变得更加复杂,并降低可读性。
Ben Linders 是一位来自荷兰的敏捷、精益、质量和持续改进方面的独立顾问。他著有《从敏捷回顾中获得价值(Getting Value out of Agile Retrospectives)》、《Waardevolle 敏捷回顾(Waardevolle Agile Retrospectives)》、《是什么推动了质量(What Drives Quality)》、《敏捷自我评估游戏(The Agile Self-assessment Game)》、《问题?什么问题?(Problem? What Problem?)》以及《持续改进(Continuous Improvement)》。并且是许多敏捷辅导工具的创建者,例如敏捷自我评估游戏。作为一名顾问、教练和培训师,他通过部署有效的软件开发和管理实践来帮助组织。他专注于持续改进、协作和沟通以及专业发展,为客户提供商业价值。Ben 是敏捷、精益和质量网络的活跃成员,也是一位经常演讲和写作的人。他在一个双语博客(荷兰语和英语) 中分享自己的经验,并在 InfoQ 担任敏捷方面的编辑。可以通过 @BenLinders 在推特上关注他。
查看原文链接:
https://www.infoq.com/news/2024/11/programming-rules-guidelines/\\"
","description":"根据 Arne Mertz 的说法,使用编程规则和指南有助于开发人员协同工作,因为它们可以产生更一致、更好的代码。然而,如果使用不当,则会产生相反的结果——代码难以阅读,或者以次优甚至错误的方式解决问题。 Arne Mertz 在 NDC Tech Town 发表了关于编程规则和指南的演讲。\\n\\nMertz 解释了规则和指南之间的区别:\\n\\n规则或多或少是绝对的。无论规则应用在哪里,都必须遵守,违反规则通常是不可接受的。指南是一种最佳实践或合理的默认做法——我们可能有产生分歧的理由,但这没关系。\\n\\n了解这种差异是很重要的,因为将指南解释或陈述为规则会导致开发人员破坏代码…","guid":"https://www.infoq.cn/article/OLjqhMbiaCu6xkTUGDfC","author":"作者:Ben Linders","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-12-20T00:04:08.853Z","media":null,"categories":["编程语言"],"attachments":null,"extra":null,"language":null},{"title":"Python、生成式 AI 和全球开发者社区的崛起:来自 GitHub Octoverse 2024 的见解","url":"https://www.infoq.cn/article/Py4lDmYpODOldycJXydz","content":"最近,GitHub Octoverse 2024 报告显示,Python 已超越 JavaScript 成为 GitHub 上最受欢迎的语言,这主要是由于其在数据科学、机器学习和科学计算等领域的主导地位。生成式 AI 在软件开发中继续占据重要地位,GitHub 上对生成式 AI 项目的贡献大幅增加。
GitHub 工作人员发表了一篇博客文章总结了 Octoverse 报告。它指出,GitHub 上对生成式 AI 项目的贡献增加了 59%,新项目增加了 98%。开发人员越来越多地将 AI 模型融入到应用程序中,涉及的场景也不止限于代码生成,他们还在探索新的用例,如 AI 代理和更小、更高效的 AI 模型。
报告强调,Python 现在是 GitHub 上使用最多的语言,超过了 JavaScript。Jupyter Notebooks 的崛起(增长 92%)也进一步强调了它在数据科学家和研究人员中的吸引力。关于 Python 在 GitHub 上的整体受欢迎程度,博客文章引用了 Python 软件基金会执行董事 Deb Nicholson 的话:
我们的目标是让 Python 成为一个伟大的工具,帮助不断增长的开发社区构建他们设想的世界。我们很高兴得知 Python 在 GitHub 上的受欢迎程度持续上升,而且这还伴随着 Jupyter Notebooks、数据分析、AI 和开源技术的使用率的增长。
GitHub X 上的官方帖子提到了 Octoverse 2024 报告的这一发现,并获得了大量参与,在撰写本文时有 79,000 次浏览、157 次转发和 598 次点赞。除了在 GitHub 上崛起之外,Python 还在其他各种平台上占据主导地位,包括 TIOBE 编程社区指数。
另外,全球开发社区经历了显著增长,预计到 2028 年,印度将超过美国成为最大的开发者群体。印度开发社区同比增长 28%。尼日利亚(增长 28%)和巴西(27%)也是增长最快的地区之一。在亚太地区,印度尼西亚(23%)和菲律宾(29%)等国家也经历了快速增长。
开源仍然是 GitHub 创新的基石,2024 年向公共存储库的贡献量接近 10 亿。报告提到,商业支持的项目和生成式 AI 计划吸引了最多的活动。GitHub Copilot 等工具大大帮助了首次贡献者,同时保持了贡献的高质量。home-assistant/core 和 flutter/flutter 等框架仍然是贡献者的首选。
报告还指出,人们对需要较少计算能力但仍能提供强大性能的小规模 AI 模型的兴趣日益浓厚。从 ollama/ollama 等项目的兴起就可以看出这一趋势,该项目专注于本地运行的大型语言模型。开发人员越来越多地尝试将这些模型用于学术研究或嵌入式系统等特殊用例。
报告讨论了 Copilot Autofix 等工具,它可以帮助开发人员比手动方法更快地识别和修复漏洞,从而增强软件安全性。开发人员也越来越依赖 GitHub Actions 处理 CI/CD 管道,使用量同比增长近 30%。
本报告基于 2023 年 10 月 1 日至 2024 年 9 月 30 日期间从 GitHub 收集的匿名用户和产品数据。读者可以通过 GitHub Innovation Graph 访问其他数据,这是一个专为有兴趣探索 GitHub 上的全球软件开发趋势的组织和个人设计的资源中心。
查看原文链接:
https://www.infoq.com/news/2024/11/github-octoverse-2024/\\"
","description":"最近,GitHub Octoverse 2024 报告显示,Python 已超越 JavaScript 成为 GitHub 上最受欢迎的语言,这主要是由于其在数据科学、机器学习和科学计算等领域的主导地位。生成式 AI 在软件开发中继续占据重要地位,GitHub 上对生成式 AI 项目的贡献大幅增加。 GitHub 工作人员发表了一篇博客文章总结了 Octoverse 报告。它指出,GitHub 上对生成式 AI 项目的贡献增加了 59%,新项目增加了 98%。开发人员越来越多地将 AI 模型融入到应用程序中,涉及的场景也不止限于代码生成…","guid":"https://www.infoq.cn/article/Py4lDmYpODOldycJXydz","author":"作者 :Aditya Kulkarni","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-12-17T01:53:43.667Z","media":null,"categories":["编程语言"],"attachments":null,"extra":null,"language":null},{"title":"从“追赶”到“并驾齐驱”,统信系统800万装机量达成,正式开启“亿级规模”五年计划","url":"https://www.infoq.cn/article/h8Bc7ETFbQTW1v9X6VjC","content":"12月10日,2024中国操作系统大会在北京中国大饭店盛大启幕。作为操作系统行业高规格的年度盛会和信息技术应用创新产业的风向标,大会已迈入第五届。本届大会以“创变·求真”为主题,旨在探讨以生成式AI为代表的虚拟技术为操作系统和基础软件领域带来的深刻变革,以及这些变革为各行各业带来的切实影响。
作为大会创始主办方之一,统信软件已连续5年将中国操作系统创新技术、落地经验和产业洞察同与会者分享。
2024年是统信软件第一个五年计划的收官之年,自主研发的统信UOS操作系统发展进入了规模化阶段,国产平台装机量已超800万套,服务客户超50000家,遍及党政及关基行业,服务体系深入全国2800多个区县,全球个人用户超百万;软硬件生态适配数超700万,生态伙伴规模即将突破80万,基于统信UOS的原生应用已上架15000余款,是我国最大的自主生态,在开放市场上也是占有率最高的中国操作系统品牌。
“过去五年,统信软件最显著的成绩,就是让中国拥有了自己可用、好用的操作系统,在易用性、稳定性、安全性等方面表现出色。现在,又承担起研发下一代操作系统的历史使命,在智能、云化、安全、跨设备融合、生态扩展和开放性等方面,构建起国际领先的技术优势。”中国工程院院士孙家广在致辞中表达了对统信软件的认可与鼓励。
五年来,统信软件完成了中国基础软件自主化建设的需求,初步建立起中国操作系统生态,成为具备一定实力和知名度的中国操作系统品牌。未来五年,公司将瞄准‘亿级’用户规模,打造具备国际主流水平的操作系统产品和具备国际影响力的中国操作系统品牌。
纵观国际,AI与云、AI与多端的深度融合成为全球操作系统厂商竞争下一代操作系统的主战场。一年前,统信软件前瞻性提出了智能化、云化、多端的产品战略,意图与国际竞争者站在同一起跑线上。
“我国整个操作系统产业正在进入一个正向循环的阶段,”第二个五年战略发布之际,统信软件总裁刘闻欢表示:“随着生成式人工智能浪潮席卷全球,中国操作系统有望实现从‘追跑’到‘并跑’”
统信软件总裁刘闻欢
在刘闻欢看来,产品与创新能力达到国际水平,桌面端最显著的趋势是AIOS。本届大会,统信软件发布UOS AI 2.0,带来3大系统级交互感知、AI效率办公全家桶,以及AIOS生态的全面升级,正式开启原生AIOS时代。
所谓AIOS,是指全面融合硬件的多种AI算力,通过端云结合的方式为用户提供系统级、全场景智能化体验,并提供丰富的智能体生态和原生AI能力,是智能时代的新型生产力平台。统信软件产研平台副总经理王耀华表示,统信AIOS将聚焦两大核心场景,一是生产力场景,功能上围绕生产力提升和生产效率提升;二是AI生态场景,面向底层硬件构建AIOS底座和硬件生态,面向上层,构建AI应用生态,统一服务,统一赋能。
统信软件产研平台副总经理王耀华
大会发布的UOS AI 2.0,带来AI搜索、AI随航、AI任务栏3大系统级交互感知,意味着AI不再是操作系统体验的附加值,不再以助手为AI能力的单一入口,而是真正意义上的全局赋能、无处不在;并推出AI效率办公全家桶,覆盖AI绘图、AI海报、AI PPT、AI数字员工4类个人办公场景,以及AI会议、AI文档中台2类协同办公场景;此外,大会基于AIOS的创新生态构建,发布《统信AIOS白皮书》(2024),从硬件算力层,到推理框架层、AI模型层、模型服务层、智能应用层五个方面进行了总体性设计,为AIOS生态共建提供指引。
此白皮书在中国操作系统行业尚属首次。
北京通明湖信息城发展有限公司副总经理谭畅与统信软件产研平台副总经理王耀华共同发布《统信AIOS 白皮书》(2024)
安全,是信息技术应用创新产业的底色,新兴技术带来的重重挑战,使得“安全”在新时代下有了新叙事。会上,统信软件基于安全的最新洞察,发布了统信服务器操作系统安全增强版。
统信软件高级副总裁、CTO张磊
统信服务器操作系统安全增强版拥有三大关键技术:首先是内核漏洞安全防护技术(简称KVSP),可以实时监控和阻断已知和未知内核漏洞利用链路,提供运行时保护,同时具有后渗透漏洞利用检测能力,并且具备自防护能力; 其次以安全编程语言重新开发的核心组件,在保障了功能、性能基线的前提下,提供了更强的安全,能有效消除缓冲区溢出和悬空指针等内存安全风险,并且实现了相关组件的全自主演进;最后是升级优化后的强制访问控制模块(简称USEC),该模块进一步提升了易用性,而且其策略下发可通过系统安全软件一键完成,并且预置了一系列场景配置基线,降低了安全配置的复杂度。
在实现自身产品安全的同时,统信软件还构建了生态安全和供应链安全体系。生态方面,围绕UAPP 打造了快速高效的安全应急响应,并联合200余位成员UAPP伙伴推广安全接口规范和应用治理体系,为产业生态提供坚实的安全基础;供应链方面,将deepin深度社区打造成为中国最活跃的开源操作系统根社区之一,着力解决供应链源头问题,同时,由SBOM治理为起点,加强软件组件的溯源、分析和治理,积极联合清华、北航等高校打造安全实验室,多方面保障操作系统供应链安全。
在活动采访的最后,InfoQ对统信软件高级副总裁、CTO张磊进行了一次访谈,在问及过去一年统信操作系统所取得的成就时,张磊表示,“团队致力于将去年推出的UOS AI产品升级至2.0版本,并成功发布了一系列实用的AI功能。
UOS AI 2.0的核心亮点包括三个方面:一是优化三大系统级交互感知入口。
AI搜索功能重大更新:去年我们已经推出了AI搜索,今年在此基础上进行了重大升级。以往在没有AI辅助的情况下,查找资料需要深思熟虑搜索关键词,而现在,用户可以直接通过图片、文档甚至文档内容进行提问,AI搜索能够一键总结答案,极大提升了搜索效率。AI随航:作为系统级交互感知入口,AI随航功能可在操作系统的各种场景中发挥作用。无论是浏览信息、聊天交流还是自由创作,用户只需划选文字,即可唤醒AI随航能力。例如,在聊天软件中划选消息,AI随航便以浮窗形式出现,提供专业解释、文本转译、长文总结等便捷功能。AI任务栏:在统信桌面环境中,任务栏扮演着重要角色。UOS AI 2.0将AI功能融入任务栏,用户只需将文档拖拽至任务栏,即可展现对应的AI功能,实现一拖即用的便捷操作。
二是实用智能体助力“一句话办公”。UOS AI 2.0秉持“一句话办公”的理念,为用户提供了一系列简单、高效、全能的智能体。其中,AI数字员工便是典型代表,它能帮助用户或企业实现“一句话完成任务”,构建高效、自动化的智能工作流。
三是端侧模型UOS LM(有容)及云端模型的自由切换。今年9月,统信推出了自己的端侧模型UOS LM(有容)。UOS AI 2.0支持用户自由切换云端模型和端侧模型,满足不同场景的需求。此外,市场上100多个热门大模型均可通过接口方式接入第二代UOS AI,实现协同工作。
张磊称,“随着产品影响力的不断扩大,我们有信心UOS AI 2.0将受到更多用户的喜爱。”
国家网络与信息系统安全产品质量检验检测中心与统信软件合作签约
基于长期以来的安全技术积累和操作系统在产业链的关键站位,统信软件与国家网络与信息系统安全产品质量检验检测中心签署合作协议,围绕信创网络安全产品兼容适配验证、自动化检测、信创漏洞检测等关键技术展开联合技术攻关。此外,双方联合发起“网络安全信创适配实验室”(筹建)工作,共同致力于促进网络安全产业的健康、创新发展。
“桌面端进入AIOS 1.0时代,服务器端呈现性能、安全性、运维和AI融合多头并进,是2024年中国操作系统最显著的技术创新趋势。”中国信息通信研究院云计算与大数据研究所政企数字化转型部主任徐恩庆表示:“统信软件通过持续积累和不断深入实践,逐渐突破了发展中的难点,在一些新兴领域取得了可喜的创新成果,为中国操作系统发展注入了内生活力。”
","description":"12月10日,2024中国操作系统大会在北京中国大饭店盛大启幕。作为操作系统行业高规格的年度盛会和信息技术应用创新产业的风向标,大会已迈入第五届。本届大会以“创变·求真”为主题,旨在探讨以生成式AI为代表的虚拟技术为操作系统和基础软件领域带来的深刻变革,以及这些变革为各行各业带来的切实影响。 作为大会创始主办方之一,统信软件已连续5年将中国操作系统创新技术、落地经验和产业洞察同与会者分享。\\n\\n2024年是统信软件第一个五年计划的收官之年,自主研发的统信UOS操作系统发展进入了规模化阶段,国产平台装机量已超800万套,服务客户超50000家,遍及党政及关基行业…","guid":"https://www.infoq.cn/article/h8Bc7ETFbQTW1v9X6VjC","author":"李冬梅","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-12-13T14:00:51.197Z","media":[{"url":"https://static001.geekbang.org/infoq/1b/1b5daa228fcf09e56f1816a7bccfd2f0.png","type":"photo","width":1079,"height":720,"blurhash":"L+H:B:oLR+oztRWAj=ogDNWAafa#"},{"url":"https://static001.geekbang.org/infoq/fc/fc29e2a4d36dcdee20fa2b720dc1e826.png","type":"photo","width":1079,"height":720,"blurhash":"LRLFLD%%t+0L~DM|$~t9EVMyMxt9"},{"url":"https://static001.geekbang.org/infoq/c9/c9805a0220bb5721a9ba71c07360e34c.png","type":"photo","width":1080,"height":720,"blurhash":"LCD0DtxuD*x^.ARht8xv~qs+WYV@"},{"url":"https://static001.geekbang.org/infoq/70/70043286fe942cf9a575aed2eed458a7.png","type":"photo","width":1079,"height":720,"blurhash":"LUB4FXI7Rhx^RUt0obaixbt8oMae"},{"url":"https://static001.geekbang.org/infoq/74/7420dcbb7d66e19474246b49f806c15b.png","type":"photo","width":1079,"height":720,"blurhash":"LfEpypxtV@WZXAf5RikCMHWEofoe"},{"url":"https://static001.geekbang.org/infoq/39/393cda6b246b7e8c5140509be8a0c137.png","type":"photo","width":1079,"height":720,"blurhash":"LiCaKL%LRRtRRaayahj?Qkoht3Mz"}],"categories":["操作系统"],"attachments":null,"extra":null,"language":null},{"title":"1620天后,Redis之父强势归来:开始着手修复社区裂痕,并布局下一代向量数据库","url":"https://www.infoq.cn/article/keyQoFMZkUj081kAFAD5","content":"Redis的创始人Salvatore Sanfilippo,更为人熟知的绰号是 Antirez,昨日宣布回归 Redis 社区。
2020年Antirez辞去了 Redis 维护者的职务,此后1620 天,他再也没有看过源代码、提交消息或任何与 Redis 相关的东西。但现在他注意到Redis社区出现了分裂,这让他感到担忧,因此,他考虑重返Redis生态系统,修复企业对于Redis社区的态度,帮助将后续的开发重点再次放在Redis的核心身上。
2020年,Antirez在告别帖中表示\\",他辞去Redis开源项目的维护者,是因为希望有更多时间去探索新的领域。虽然他并未明确指出对项目现状的不满,但“处理项目”挤占了太多时间这一表述,间接反映了他想做出改变的心态。
他将Redis“交给Redis社区”,标志着项目治理模式的转变。Redis公司解释说,这一变革是为了超越传统的“终身仁慈独裁者”(BDFL)模式。
现在,Antirez突然宣布重返Redis。在博文中,Antirez提到最近几年生活并不宽松,他想给女儿创造更好的生活,因此萌生了重返纽约并找份兼职工作的想法。此前,他在一次视频通话中向新任Redis CEO Rowan Trollope表达了这个意向,并得到了对方的积极回应。
不过,外界对Antirez的回归充满了各种猜测。很多人认为,除了家庭原因,一定还有其他更深层次的动机,比如巨额薪资、私下协议,甚至是对Redis更改许可证的不满。
Antirez本人对此进行了澄清。他表示,是自己主动联系了Redis,而不是公司挖角。他拿到的薪资也是“常规水平”,并没有获得额外的特殊待遇,但仍然会获得跟以前一样的Redis股票期权。
而对于Redis切换许可证的决定,他解释说虽然他自己可能会选择别的不同许可证,“毕竟我已经远离项目一线多年了,不太能感受得到业务端的压力”,但总的来讲,他完全可以理解这个决定。
2020年,Antirez离开后,Redis社区风波不断。
Redis曾以宽松的BSD 3条款许可而广受开发者欢迎。然而,从7.4版本开始,Redis转而采用更严格的RSALv2和SSPLv1双重许可。这一变化引发了社区的广泛关注和争议,部分开发者认为Redis正在逐渐“闭源”。
这一变化还导致社区涌现出多个分支,包括 Redict 、以及由Linux基金会支持的 Valkey 分支。AWS、Google 和 Oracle 等公司也迅速加入了 Valkey 分支。随着资金充裕的 Valkey 支持者不断壮大,其势头逐渐强劲。
今年9月份,Linux 基金会宣布发布Valkey 8.0之后,有报告称Valkey项目正在逐渐蚕食Redis的市场份额。虽然Redis仍然是键值存储领域的霸主,使用率高达67%,但Valkey已经引起了广泛关注:63%的受访者从一开始就了解Valkey项目,其中约8%的人已经在使用它,而12%的人正在使用其他Redis替代品。此外,还有60%的受访者正在考虑或测试Valkey。
2024年,Redis替代方案一览
上个月,Redis 试图接管社区 OSS Redis 库的事件\\",更是激起了社区维护者们的愤怒。
这些纷争,Antirez 实际上都看在眼里,并在 Hacker News 等平台上有所留言和回应。
因此,Antirez表示他希望与Trollope一道修复企业跟社区的关系,重新引导代码库的发展方向:
我看到Redis社区正在分裂,即使是以纯粹局外人的身份来看,我也对此深感忧心。 所以我想到,也许我可以回归Redis生态系统,修复企业对于Redis社区的态度,甚至可以帮助将后续的开发重点再次放在Redis的核心身上。总之,我可以扮演某种“布道者”的角色——虽然我个人很不喜欢这种称呼。也就是说,我一方面充当企业和社区之间的桥梁,同时也可以开发编程演示、发明和讲解新的模式,兼顾撰写文档、制作视频和博文。这些跨越新旧两个时代的成果既符合我的兴趣,也对Redis的未来发展有所助益。
Antirez认为,Redis的成功离不开开源社区的共同努力,依赖的是开源领域的“侠义精神”。
在Redis发展的初期,Antirez为了寻求商业化的可能性,曾探索过多种模式:一种是让它以闭源产品的形式出现,但能够以某种方式帮助用户运行Redis,另外一种是尝试某种开放核心的方法;还有一种是考虑将新代码的BSD许可证推迟六个月,以便为付费用户创造一定的领先优势。
最终,得益于VMware和Redis Labs的慷慨支持,Antirez得以全身心地投入到开源社区。
这是 Redis 发展初期的一个故事。当时,Antirez 的工作还没有什么回报,直到有一天,他接到了来自 VMware 的电话。VMware 表示愿意在经济上支持 Redis,并提出希望雇用他。当 Antirez 询问需要为他们做什么时,VMware方面表示只需Antirez继续目前的工作,他们会提供报酬,并希望Antirez能在个人网站上注明Redis项目得到了VMware的赞助。
VMware以及后来的Redis Labs,他们做的并不只是付一份工资。如果大家快速浏览一下代码仓库的贡献历史,就会发现位列第二的贡献者是Oran Agra(来自Redis),第三位则是Pieter Noordhuis(来自VMware)。
Antirez认为,过去12年间,Redis在BSD协议下专注于用户需求的发展取得了巨大的成功。而新的许可证虽然引发了社区的讨论,但并非核心矛盾。实际上,新的许可证解决了几个长期存在的问题:
鼓励开发者为核心代码做出更多贡献,而不是将新功能都塞进模块中。防止云服务商在不提供回报的情况下,粗暴地复制粘贴Redis代码库并出售相关服务。确保Redis核心功能的持续发展,并让全球开发者都能参与其中。为更多的开发者提供了通过贡献代码获得报酬的机会。
“这是我希望帮助公司达成的目标之一,我也必将为此而努力。我们定会让许可证转换对用户群体和项目功能产生良好影响,至少我自己坚定秉持着这样的理念。”
百倍工程师的回归,实际上是社区和技术上的双赢。
Antirez本人对开发向量功能越来越感兴趣,并支持将AI融入编程。
Antirez 表示,他每天都会关注 Hacker News,并看到一大帮不喜欢AI、拒绝接受新发展的技术人员。他发现,许多人甚至不愿意深入体验最新的模型(他特别提到 Claude AI 的表现十分突出),仍然认为这些模型毫无用处,但在他看来,情况完全不是这样。
Antirez 一直对神经网络充满兴趣。他在2003年编写了自己的第一个神经网络库,对整个概念的强大和功能的酷炫深感震惊。而到了 2024 年底,他终于看到了该领域爆发出的惊人成果。几年前还像是科幻小说中的桥段,如今已经成为现实。他提到 Claude AI 是他最近最好的推理、编辑和编码助手,借助它,他能够完成比以往更多的工作,生产效率显著提高,成果的质量也远超过去。他还分享了最近的一次经历:他为一家意大利出版商撰写了一篇科幻短篇小说。由于 Claude 对部分内容的批评,他决定重写结尾,最终创作出了更优秀的作品。
Antirez 提到,近期他需要评估使用 8 位量化向量计算点积的速度。他向 Claude 描述了自己特定的基准设计要求,而它两分钟之后就给出了测试方案、加以修改并评估其是否具有实际价值。
近年来,RAG相关的数据库曾一度风靡一时,而现在我们有了与主流数据库的插件集成方案。Antirez对此也分享了一些他的新思路,希望能改进目前的向量设计,显然社区对此充满了期待。
总的来说,Antirez希望通过引入新的向量数据类型,将Redis打造成一个高效、灵活的向量搜索引擎,并为开发者提供一个高度可定制的平台,以满足各种各样的AI应用需求:
我坚信无论RAG有多受欢迎,它一定不会成为主流应用,也不可能是最具未来意义或者实用价值的应用方式——因为模型上下文正变得越来越臃肿,而未来的主流模型必须配备具有线性复杂性的注意力机制。我相信通过学习获得的嵌入仍将存在,而向量搜索则将是Redis的核心优势。下此论断的理由如下:首先因为向量索引属于数据结构,特别是慢数据结构,这样的数据结构往往在内存内运行效果更好。第二,则是因为我自认为找到了完美的API来加以公开。 在Redis项目的设计工作当中,我总会表现出一些自我矛盾的倾向。比如我总是会对某些看起来非常适合项目需求的事物说不(比如Lua脚本、哈希字段过期等等,顺带一提,现在它们都成了Redis的组成部分),但与此同时,我又会在看似不合时宜的时候将它们添加进来。比如Lua脚本功能、Redis的内部解释器,似乎跟上下文无关的Pub/Sub功能,还包括数据流甚至是计算机科学专著中都不存在的合成数据结构(比如排序集)。因为对我来说,判断一项新功能适不适合被引入Redis主要考虑两个方面:用例和与内部设计的契合度。对我来说,Redis更像是做给程序员们的乐高积木,而不是真正的“产品”。 所以最近开始,我觉得排序集可以启发出一种新的数据类型,其中的得分实际就是一个向量。在跟Rowan交流回归的同时,我开始编写设计文档,而后着手对这种新型数据结构做概念验证,以Redis的方式从头开始重新实现HNSW(之所以没有选择现成的库,是因为我想一点点做调整)。其实我自己也不确定这项工作什么时候才能完成,目前仍处于编程的早期阶段,但如果提案最终得到大家的认可,也许我会再次开始贡献代码。 我实现的模块(稍后将被合并到核心内,但出于简单起见,现在它还只是个模块)实现了直接操作嵌入的新命令。下面我给大家稍微展示一下: VSIM top_1000_movies_imdb ELE \\"The Matrix\\" WITHSCORES1) \\"The Matrix\\"2) \\"0.9999999403953552\\"3) \\"Ex Machina\\"4) \\"0.8680362105369568\\"5) \\"Akira\\"6) \\"0.8635441958904266\\"7) \\"District 9\\"8) \\"0.8631418347358704\\"9) \\"The Martian\\"10) \\"0.8608670234680176\\"11) \\"The Bourne Ultimatum\\"12) \\"0.8599717319011688\\"13) \\"The Bourne Supremacy\\"14) \\"0.8591427505016327\\"15) \\"Blade Runner\\"16) \\"0.8585404753684998\\"17) \\"Metropolis\\"18) \\"0.8572960793972015\\"19) \\"Inception\\"20) \\"0.8521313071250916\\" 这里已经有了VSIM、VADD、VCARD等现成的指标,而这就是排序集的概念,但同时还涉及多维得分(也就是嵌入)跟K-NN的匹配。当然,除此之外还有很多实现技巧能够进一步提高效率。但毕竟现在这还只是概念验证代码,我还需要再多研究一下。我正在探索如何实现线程、降维、量化等等。说实话,这个过程真的很有趣。 可以看到,这里并没有提到混合搜索——也就是最近关于向量存储的流行词汇。而这也正是我们Redis的行事风格:让开发人员发挥作用并自行做出权衡,毕竟只有他们才知道自己正在为什么建模。每个键都有一个向量索引,这样就像程序员使用排序集时做的那样,他们会自行发明出各种有趣的拆分策略、新模式、Lua脚本、模式以及用例建模所需要的一切。 再有,虽然关联项大多只是一小段字符串或者文档ID,但我们也完全可以让它变得更复杂,比如带上可以稍后再过滤的元数据(我个人持怀疑态度)。我只是觉得很多用例实际上并不需要复杂的服务器端过滤,采用预分区数据进行建模就可以了。 另一个让我感到兴奋的点就是增加了潜在的STORE选项,即将结果存储在排序集内、而非直接将其返回给用户。当然,其中的得分代表相似度。所有这一切将对效率、可扩展性、使用脚本的能力等产生复杂且有趣的影响,我希望在未来几周乃至几个月中通过系列文章与大家分享更多发现和心得。 我觉得可能这些才是真正的重点,毕竟只有新思路才格外让人感到兴奋。
参考链接:
https://antirez.com/news/144\\"
https://news.ycombinator.com/item?id=42378488\\"
","description":"Redis的创始人Salvatore Sanfilippo,更为人熟知的绰号是 Antirez,昨日宣布回归 Redis 社区。 \\n\\n \\n\\n \\n\\n2020年Antirez辞去了 Redis 维护者的职务,此后1620 天,他再也没有看过源代码、提交消息或任何与 Redis 相关的东西。但现在他注意到Redis社区出现了分裂,这让他感到担忧,因此,他考虑重返Redis生态系统,修复企业对于Redis社区的态度,帮助将后续的开发重点再次放在Redis的核心身上。\\n\\n \\n\\n创始人重返Redis:百倍工程师的回归\\n\\n \\n\\n2020年,Antirez在告别帖中表示\\",他辞去Redis开源项目…","guid":"https://www.infoq.cn/article/keyQoFMZkUj081kAFAD5","author":"Tina,核子可乐","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-12-13T08:48:23.013Z","media":[{"url":"https://static001.geekbang.org/infoq/b8/b857a0553f487c0d7533e7b0383c3592.jpeg","type":"photo","width":609,"height":244,"blurhash":"LGQmCs%Mx]?b?bM{jaa{~qRjWBWB"},{"url":"https://static001.geekbang.org/infoq/92/92db222a369d6fdd8fe7ab4fe4f98217.png","type":"photo","width":1024,"height":528,"blurhash":"LCR{#?~qWA_2?bxv%2s,%Mj^xuf5"},{"url":"https://static001.geekbang.org/infoq/59/59486fe1f5abfe212fd7eb421fc0fdc3.jpeg","type":"photo","width":1566,"height":398,"blurhash":"LBP?p:?Hx]_3:4MxS1WB*_o}ofoM"},{"url":"https://static001.geekbang.org/infoq/74/744a277c019db141fd7c9d2eb922f5be.png","type":"photo","width":1540,"height":662,"blurhash":"LKP?t4-Bxu?^ZMm,W=t,H?wJkBb]"},{"url":"https://static001.geekbang.org/infoq/bc/bc59d054b411a1041b59f60204f6351d.jpeg","type":"photo","width":782,"height":293,"blurhash":"LCQ]+w?b%M~q_3M{j[j[~qIUM{WB"},{"url":"https://static001.geekbang.org/infoq/2f/2f9a89278a92fc2df04018d1e8cdb69b.jpeg","type":"photo","width":1614,"height":183,"blurhash":"L8QmFt_2j[~p~qj[ayt7IUIUWBof"},{"url":"https://static001.geekbang.org/infoq/7c/7c6991f1e70fb7e56d539125e91cfcc5.jpeg","type":"photo","width":1622,"height":319,"blurhash":"L7P?]q%LWB~q~pj[RjofD%IURjtQ"},{"url":"https://static001.geekbang.org/infoq/49/49355c2f0526e8f6ce6c5a08822a64a3.png","type":"photo","width":1557,"height":151,"blurhash":"LNR3TQ%May-:?aj[ayj[~qofj[j["}],"categories":["数据库"],"attachments":null,"extra":null,"language":null},{"title":"Java 24减少对象头的大小并节省内存","url":"https://www.infoq.cn/article/VNqG9IDeJ2XswbyfLeqZ","content":"
JEP450(Compact Object Headers,紧凑对象头)已经成为 JDK 24 的交付目标,并且已合并到了主版本中。
这个目前处于实验阶段的特性通过缩小 HotSpot 中强制对象头的大小来优化堆利用率。这应该会减少整体堆的大小,提高部署密度,并增加数据局部性。
HotSpot 将所有对象存储在 Java 堆中,Java 堆是进程的“C 堆”的连续区域。在 Java 中始终是通过引用来处理对象,例如:
引用对象的局部变量包含从 Java 方法的堆栈帧到 Java 堆的指针。引用类型的对象字段从一个 Java 堆位置指向另一个位置。
Java 引用的目标地址始终是对象头的开始处(这在当前版本的 HotSpot 中是强制性的)。
每个对象上都有标头(数组还有一个额外的 32 位标头来存储数组的长度)。标记字是前 64 位,用于特定于实例的元数据,即支持以下特性:
垃圾回收——存储对象的年龄(以及可能的转发指针)哈希码——存储对象的稳定身份哈希码锁——存储对象的锁 / 监视器
在某些情况下,标记字将被覆盖并被替换为指向更复杂数据结构的指针。这会使紧凑对象头的实现稍微复杂一些。
在标记字之后是类(或 klass)字,用于计算指向此类类型的每个对象所共享的元数据的指针。这用于方法调用、反射、类型检查等。
klass 元数据(或 klass)保存在元空间中,元空间位于 Java 堆之外,但在 JVM 进程的 C 堆之内。由于它们存在于 Java 堆外,因此 klass 不需要 Java 对象头,而且它们与反射中使用的类对象(真正的 Java 对象)不同。
klass 字最初是标头的一个完整机器字,但这在 64 位的架构上是很浪费的,因此引入了一种称为“压缩类指针”的技术。这将类指针编码为 32 位(通过使用缩放和偏移方法),适用于加载小于 4GB 类文件的任何应用程序。
因此,除了极端情况外,64 位版本的 HotSpot 上的非数组对象要支付 96 位的“标头税”。相比之下,这是轻量级的:直到最近,Python 的标头税还是 308 字节,但 JEP 450 的目的是为了做得更好,将标头的总大小减少到 64 位。
这个新实现是作为 OpenJDK 的“Project Lilliput”的一部分开发的,它减少了两个目标 64 位平台(x64 和 AArch64)上的对象头大小。
总体目标是:
将目标平台上的吞吐量和延迟开销限制在 5% 内,并且只有在极少数情况下才能达到这一限制不会在非目标平台上引入可测量到的吞吐量或延迟开销
事实上,目前的测试只显示了极少数的回归(JDK 24 正在对它们进行修复)。到目前为止,亚马逊(Amazon)的测试表明,许多工作负载实际上在吞吐量方面受益,有时甚至会有大幅提升——一些工作负载的 CPU 利用率下降了 30%。
该项目试图利用观察到的事实,即许多 Java 工作负载的平均对象大小较小,只有 32 到 64 字节。这相当于约 20% 的标头税。因此,即使对象头大小略有改进,也可以显著减少堆的占用空间。反过来,这可以提高数据局部性并减少 GC 压力,从而带来进一步的潜在性能优势。
为了实现这种标头的减小,标记字和类字被组合成一个 64 位字,布局如下:
我们应该注意到以下几个方面:
现在有 22 位(而不是 32 位)用于标识对象类类型。这意味着我们可以加载到 JVM 进程中的不同类类型的数量约为 400 万个。哈希码的大小不会变。锁定操作不再覆盖标记字。这将保留压缩的类指针。为了保持对压缩类指针的直接访问,GC 转发操作变得更加复杂。有 4 个未使用的位保留用于未来的增强(例如 Valhalla 项目)
如果 Java 锁存在争用,那么新的实现需要查找保存锁信息的 辅助数据结 构的地址。这种方法称为“对象监视表”,已经在 JDK 22 中实现了,并由默认启用的新开关 UseObjectMonitorTable 激活。紧凑对象头依赖于此机制。
如果没有发现任何阻碍问题,这一特性将作为 JDK 24 的一部分发布(最初是一个实验特性),发布时间预计在 2025 年 3 月。长期的目标是使该机制成为受支持平台上唯一的标头表示,但这可能需要更多的版本。它还取决于对实际工作负载的广泛测试,目前缺乏性能和其他回归。甚至还有正在进行的探索性工作,以查看是否有可能将标头大小减小到 32 位。
一旦该特性在 JDK 24(测试版或最终版)中可用,应用程序团队可以通过命令行开关 -XX:UseCompactObjectHeaders 来激活该新特性以测试他们的工作负载,并寻找与之相关的性能差异,从而为长期目标提供帮助。
原文链接:
https://www.infoq.com/news/2024/11/compact-headers-java24/\\"
","description":"JEP450(Compact Object Headers,紧凑对象头)已经成为 JDK 24 的交付目标,并且已合并到了主版本中。 这个目前处于实验阶段的特性通过缩小 HotSpot 中强制对象头的大小来优化堆利用率。这应该会减少整体堆的大小,提高部署密度,并增加数据局部性。\\n\\n当前的实现情况概述\\n\\nHotSpot 将所有对象存储在 Java 堆中,Java 堆是进程的“C 堆”的连续区域。在 Java 中始终是通过引用来处理对象,例如:\\n\\n引用对象的局部变量包含从 Java 方法的堆栈帧到 Java 堆的指针。引用类型的对象字段从一个 Java…","guid":"https://www.infoq.cn/article/VNqG9IDeJ2XswbyfLeqZ","author":"作者:Ben Evans","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-12-13T00:00:00.625Z","media":[{"url":"https://static001.geekbang.org/wechat/images/b8/b8dc7a05efa6dd284f7ffcd0762a395b.png","type":"photo","width":1080,"height":280,"blurhash":"LMPQjT?HR+%N~q%1R*WXv{$%azay"}],"categories":["编程语言"],"attachments":null,"extra":null,"language":null},{"title":"敢不敢尝试:MVA 困境","url":"https://www.infoq.cn/article/Egwq8u4q7ER5OduwYIrJ","content":"本文要点技术雷达是一种常用的描述技术采用风险的方法。技术雷达可以帮助团队针对他们正在构建的解决方案及其架构进行实验。每个产品发布都是或应该是关于团队提供的价值及解决方案的可持续性的实验。这些实验必须以业务的利益相关者能够理解和支持的方式来平衡业务和技术风险。发布的版本应着眼于学习最多的经验,而不是特性的数量或交付的技术深度,但如果新版本的实验规模过大或次数过多,就会变得“大到不能倒”,不再是实验了。
开发一个产品的新增量(也称为最小可行产品,MVP)的团队往往面临着艰难的处境:他们必须在很短的时间内开发和交付他们希望其能有价值的产品增量。他们还需要为这个 MVP 开发一个最小可行架构(MVA),以满足其质量目标——也称为质量属性要求(QAR)。
这两种力量之间的这种紧张关系造成了一个两难境地:团队是依赖久经考验但可能无法完全满足其需求的技术,还是探索可能更适合,但实施起来风险更大的新的和陌生的技术?团队及其组织如果一直坚持使用久经考验的技术,往往会在短期内将风险降至最低,但从长远来看,继续使用不再适合应对组织所面临挑战的那些旧技术会增加风险。
技术雷达(TR)是组织汇总和交流其在使用各种技术时所获得的经验的一种方式,如图 1 所示。
图 1:Thoughtworks 的一个技术雷达示例
在这个流行的表示中,技术雷达在一个圆圈的象限中显示了四个不同的技术领域,当然这里的技术领域可以多放一些,也能少放一些。在这个圆圈内,根据编制者的经验,需要建议团队是否应该:
采用 该技术,因为它已被无可争议地证明具有普遍用途;试用 该技术,因为尽管一些团队已经成功使用了该技术,但每个团队都需要根据自己的情况做出自己的决定;评估 该技术,因为虽然该技术看起来很有趣,但它还没有得到广泛的应用,不足以值得推荐;暂停 使用该技术,因为该技术领域有更好的解决方案。这个环中的产品可能曾经被推荐采用过,但它们被推荐使用的机会可能已经减少了。
组织对风险的亲和力也会影响技术决策,如图 2 所示。
图 2:技术采用因团队技能和风险承受能力而异
这张表使用 Everett Rogers 的创新扩散模型将技术成熟度映射到了组织风险承受能力上。从这个角度来看,如果你的团队认为在构建某个 MVA 时使用某种特定技术会很有用,你需要问自己“我们的组织是否符合该技术采用者的形象?”例如,如果你想使用自动机器学习(AutoML)技术,那么你的组织是否真的符合“创新者”形象?你的组织能否吸引精通该技术的人才?当这些实验可能没有回报时,你的组织是否依旧愿意进行实验?
在上一篇文章中,我们谈到了每次产品发布都是一个增量式最小可行产品(MVP),它有着对应的最小可行架构(MVA),可确保 MVP 的价值能够长期维持。在这个模型中,每个 MVP 都是一个探索那些客户认为有价值的东西的实验,每个 MVA 都是一个关于如何可持续地支持该价值的实验。
这些实验为团队提供了尝试新技术的机会;为了实现发布的目标,团队可能必须使用一些新技术。他们面临的挑战是平衡技术实验和业务实验。业务利益相关者不会接受仅由技术实验组成的产品版本,如果技术实验失败,他们也可能会担心新版本将业务实验置于风险之中。团队必须协商解决这一问题。
但是……技术实验可能是实现业务实验所必需的。有时业务实验可能会失败并拖累技术实验,但如果技术实验不能满足迫切的业务需求,它也永远不会成功。
无论如何,如果团队想要在发布版本中加入技术实验,就需要与业务和运营利益相关者进行富有挑战性的讨论。业务利益相关者必须以他们熟悉的方式了解技术实验的好处,了解该技术如何更好地满足客户需求。
运营利益相关者需要确信该技术是稳定且可支持的,或者至少稳定性和可支持性是用于评估该技术的一部分标准。
完全避免技术实验通常是一件坏事,因为它可能会错过以更好的方式解决业务问题的机会,从而导致解决方案的效果不如其他方法。随着时间的推移,这可能会增加技术债务。
正如我们在最近的一篇文章中所写,承担技术债务(TD)是一种学习事物的方式,可以让你避免对那些你可能尚未完全理解的问题的解决方案做过度投资。在引入新的、不熟悉的技术作为 MVA 的一部分时,有意承担 TD 可能不是一件坏事。假设新技术成功满足了团队的需求,使 MVA 达到或超过其 QAR;这也可能适用于试图解决类似问题的其他团队,因此增加的 TD 可能不需要“偿还”。
但如果新技术未能兑现承诺,无法满足团队的需求,则应迅速终止实验,从而消除 TD 问题。这里的危险在于,你也许会假设在新技术上花费更多时间和精力可能会扭转局面。一旦确定 MVA 无法满足其 QAR,就应立即终止实验,无需在实验上花费更多时间和精力。小心落入“确认偏见”陷阱!
此外,如果实验规模太大而不能失败,或者实验失败会被视为坏事,那么它就不是实验。只有在实验没有提供任何有用信息的情况下,它才会是失败的;你要记住,一项技术,甚至一项特性就算没有提供预期的结果也并不是失败,你只是获得了相关信息而已。
团队在这方面犯的一个错误是,在不知道技术是否会产生预期结果的情况下,投入过多精力实施新技术。当他们不确定时,他们应该将发布分解为一些较小的版本,以便更快交付,从而获得反馈。
同样,开发团队及其业务利益相关者都应避免对价值做出假设,而是将复杂而昂贵的解决方案分解为一些较小的部分,这样他们就能更快、更轻松地进行评估。换句话说,如果“实验”太大而不能失败,那么他们需要将其分解为一些较小的实验。
团队及其利益相关者首先必须就 MVP/ 新版本发布的业务范围达成至少是初步的协议。达成协议后,开发团队必须做出预测,判断他们需要做多少工作才能实现发布目标。这里他们就必须开始做出技术选择了,因为不同的技术会改变团队需要做的工作量和性质。
使用图 1 所示的技术雷达,团队将首先调查“采用”类别中列出的技术,并评估这些技术是否有某些选项可以帮助他们实现发布目标。如果他们只需要使用“采用”类别中的技术,他们的工作通常会更简单,风险更小。不过,这些更“成熟”的技术并不总是能完成团队需要做的所有事情,因此他们可能需要考虑“试用”类别中的技术,等等。
在做出这些决策时,团队会权衡各种技术风险,如图 3 所示。
图 3:团队权衡多种技术风险
这些权衡受到两个简单事实的制约:开发团队没有太多时间获取和掌握新技术,且他们不能因为采用未经证实或不可持续的技术而将新版本的业务目标置于风险之中。这通常会导致团队坚持使用久经考验的技术,但这种策略也存在风险,最明显的是锤钉式风险,即团队无论如何都会使用不适合新问题的旧技术,例如使用关系数据库来存储类似图形的数据结构。
任何新版发布的第一步规划工作是就发布的目标达成一致。关于这一点,最重要的决定是就团队或组织需要多快获得实验反馈达成一致。为此,他们需要了解应运行哪些实验。他们总要平衡至少两种实验:
他们需要决定应进行哪些有关业务价值的实验。这些实验将成为 MVP 的重点。换句话说,业务利益相关者对“他们的客户或用户需要什么或会发现什么”有一些想法,但这些想法通常未经证实。很多时候,测试这些想法的唯一方法是构建和发布某些东西。他们需要决定应做出哪些技术决策来持续支持业务价值实验,如果实验成功的话。这些决策的一部分可能涉及采用新技术。类似于图 1 和图 2 的技术雷达可以帮助他们做出决定。对于每一种候选技术,他们需要问自己组织是否能接受与新技术相关的风险?业务实验和相关技术实验的业务案例是否合理?组织如何知道这一点?考虑到组织的专业知识和资源,技术是否可支持 / 可持续?组织如何知道这一点?技术是否满足团队的需求?如何知道这一点?
对于每一种实验,团队及其利益相关者都需要就如何判断实验是否成功达成一致。此外,如上所述,如果实验规模过大或数量过多,团队及其利益相关者将需要缩小发布范围,以保持在新版本的反馈周期目标之内。
开发 MVP 的团队只有很短的时间来开发和交付他们希望有价值的产品增量,以及创建 MVA 来支持该 MVP。他们可以依赖久经考验的技术,但这些技术可能无法完全满足他们的需求,也可以探索可能更适合但会增加技术风险的新的和不熟悉的技术。技术雷达是一种描述这种风险的流行方式,可以帮助团队对他们正在构建的解决方案及其相关的 MVA 进行实验。
产品发布是对团队提供的价值以及解决方案的可持续性而做的实验。这些版本发布应着眼于尽可能学习经验,而不是特性数量或交付的技术深度。发布中体现的实验必须以业务利益相关者和开发团队可以理解和支持的方式来平衡业务和技术风险。
实验规模过大或次数过多的版本会变得“大到不能倒”,不再是实验。快速和早期的反馈非常关键,可以防止过度投资于客户或用户不想要或不需要的东西,还可以防止产品架构变得臃肿和无效,并防止依赖不可持续的技术。
原文链接:
https://www.infoq.com/articles/mva-dilemma-experiments/\\"
","description":"本文要点技术雷达是一种常用的描述技术采用风险的方法。技术雷达可以帮助团队针对他们正在构建的解决方案及其架构进行实验。每个产品发布都是或应该是关于团队提供的价值及解决方案的可持续性的实验。这些实验必须以业务的利益相关者能够理解和支持的方式来平衡业务和技术风险。发布的版本应着眼于学习最多的经验,而不是特性的数量或交付的技术深度,但如果新版本的实验规模过大或次数过多,就会变得“大到不能倒”,不再是实验了。 开发一个产品的新增量(也称为最小可行产品,MVP)的团队往往面临着艰难的处境:他们必须在很短的时间内开发和交付他们希望其能有价值的产品增量。他们还需要为这个…","guid":"https://www.infoq.cn/article/Egwq8u4q7ER5OduwYIrJ","author":"作者:Pierre Pureur, Kurt Bittner","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-12-10T00:00:00.788Z","media":[{"url":"https://static001.geekbang.org/wechat/images/ab/abfad78efd293eafc133f07f95ec0c71.webp","type":"photo","width":1080,"height":1170,"blurhash":"LCR:NU_3NK?b.Tj^soW9NeWER+WU"},{"url":"https://static001.geekbang.org/wechat/images/a5/a53a4664c201cee427583f579e37b157.webp","type":"photo","width":1080,"height":630,"blurhash":"LQRMby-?Or=_%%W8nNSj%2WAogX8"},{"url":"https://static001.geekbang.org/wechat/images/b0/b02087edc43914f8a9ca3fe365e09951.webp","type":"photo","width":770,"height":1015,"blurhash":"LFRfg~~QI?%%?bRPjrj[?a9Zs,tQ"}],"categories":["后端"],"attachments":null,"extra":null,"language":null},{"title":"Spring近期新闻:Boot、Security、Auth Server、Integration和Modulith交付GA版本","url":"https://www.infoq.cn/article/6ksJXcohIZCWxINC1DNi","content":"最近,Spring生态系统活动频繁,主要发布了如下项目的GA版本:Spring Boot、Spring Security、Spring Authorization Server、Spring Integration、Spring Modulith、Spring AMQP、Spring for Apache Kafka和Spring for Apache Pulsar。
Spring Boot\\" 3.4.0发布\\",该版本提供了依赖关系升级和新特性,比如,支持结构化日志,内置了对Elastic Common Schema\\"、Graylog Extended Log Format\\"和Logstash\\"的支持;扩展了对虚拟线程的支持,现在允许Micrometer OtlpMeterRegistry类和Undertow\\" Web服务器使用虚拟线程。关于该版本的更多详细信息,请参阅发布说明\\"。
InfoQ发布了关于Spring Boot 3.4和Spring Framework 6.2的详细报道\\",其中包括对Broadcom的高级员工工程师兼Spring Framework项目负责人Juergen Hoeller\\"和Broadcom主软件工程师兼Spring Framework核心提交者Sébastien Deleuze\\"的采访。
代号为Kilburn的Spring Cloud\\" 2022.0.9版本发布\\",主要特性是对子项目的依赖关系进行了升级,即Spring Cloud Contract\\" 4.0.9、Spring Cloud Netflix\\" 4.0.7和Spring Cloud OpenFeign\\" 4.0。该版本兼容Spring Boot 3.0.18和3.1.14。
Spring Security\\" 6.4.0版本发布\\",提供了缺陷修复、依赖关系升级和新特性,比如,支持Passkeys\\"和一次性令牌;通过弃用原有配置方法并替换为新方法,简化了OAuth 2.0的配置。例如,DefaultAuthorizationCodeTokenResponseClient类已被弃用,取而代之的是RestClientAuthorizationCodeTokenResponseClient类。关于该版本的更多详细信息,请参阅发布说明\\"和新功能页面\\"。
Spring Authorization Server\\" 1.4.0发布\\",提供了依赖关系升级和新特性,比如,改进了使用Spring Security HttpSecurity类中定义的with()方法配置身份验证服务器的支持;通过OidcLogoutAuthenticationProvider类,自定义OpenID Connect 1.0 RP-Initiated注销请求的验证和成功处理的功能。关于该版本的更多详细信息,请参阅发布说明\\"。
Spring Integration\\" 6.4.0发布\\",提供了缺陷修复、依赖关系升级和新特性,例如,通过新的ControlBusCommandRegistry类实现了新的Control Bus交互模型;在AmqpInboundChannelAdapter类中添加了一个新的选项,以覆盖默认的amqp_batchedHeaders名称。关于该版本的更多详细信息,请参阅发布说明\\"和新功能\\"页面。
Spring Modulith\\" 1.3.0发布\\",提供了缺陷修复、依赖关系升级和新特性,例如,在核心抽象中嵌套应用模块的能力;新的ApplicationModuleSourceFactory接口,用来声明根包(root package),以便于“扫描显式的应用模块基础包,并且可选择性地自定义应用模块探测策略,用于声明的根包”。这个新版本还升级到了Spring Boot 3.4和Spring Framework 6.2。关于该版本的更多详细信息,请参阅发布说明\\"和新功能\\"页面。
Spring AI\\" 1.0.0的第四个里程碑版本\\"包含了缺陷修复和新特性,比如,支持Bedrock Converse API\\",为AI聊天模型提供了统一的接口;通过FunctionCallback构建器接口改进对Java Function、Supplier和Consumer接口的支持,从而允许直接调用这些函数和方法类型。根据路线图\\",Spring AI团队计划在2024年12月发布第五个里程碑版本,随后在2025年1月发布候选版本和最终的GA版本。
Spring AMQP\\" 3.2.0发布\\",该版本提供了缺陷修复、文档改进、依赖关系升级和一项新特性,即因为RabbitMQ 4.0\\"发布后x-death头信息不再有效,所以在向死信队列交换机(Dead Letter Exchanges,DLX)\\"队列重新发布消息之前,需要调用MessageProperties类中的incrementRetryCount()方法。关于该版本的更多详细信息,请参阅发布说明\\"。
Spring for Apache Kafka\\" 3.3.0发布\\",提供了缺陷修复、文档改进、依赖关系升级和新特性,比如,泛型优化,以修复MessagingMessageListenerAdapter类中定义的testTransactionReplicationFactor()方法中的警告;在使用嵌入式Kafka代理@EmbeddedKafka注解进行测试时,为事务主题提供了副本因子的默认最小值。关于该版本的更多详细信息,请参阅发布说明\\"。
Spring LDAP\\" 2.4.4和3.2.8版本发布\\",解决了\\"CVE-2024-38829,大小写比较时,Spring LDAP敏感数据暴露(Spring LDAP Sensitive Data Exposure for Case-Sensitive Comparisons)\\"的漏洞,该漏洞影响了3.2.0 - 3.2.7、3.1.0 - 3.1.7、3.0.0 - 3.0.9和2.4.0 - 2.4.3版本。在这些版本中,使用Java String中的toLowerCase()和toUpperCase()方法会引发Locale相关的异常,这些异常可能会导致查询预料之外的列。关于这两个版本的更多详细信息,请参阅3.2.8版本\\"和2.4.4版本\\"的发布说明。
Spring for Apache Pulsar\\" 1.2.0发布,提供了多项依赖关系升级,值得注意的包括Spring Framework 6.2.0、Project Reactor 2024.0.0、Micrometer Metrics 1.14.1和Micrometer Tracing 1.4.0。有关该版本的更多详情,请参阅发布说明\\"。
原文链接:
Spring News Roundup: Delivering GA Releases of Boot, Security, Auth Server, Integration, Modulith\\"
","description":"最近,Spring生态系统活动频繁,主要发布了如下项目的GA版本:Spring Boot、Spring Security、Spring Authorization Server、Spring Integration、Spring Modulith、Spring AMQP、Spring for Apache Kafka和Spring for Apache Pulsar。 Spring Boot\\n\\nSpring Boot\\" 3.4.0发布\\",该版本提供了依赖关系升级和新特性,比如,支持结构化日志,内置了对Elastic Common Schema\\"、Graylog…","guid":"https://www.infoq.cn/article/6ksJXcohIZCWxINC1DNi","author":"Michael Redlich","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-12-09T08:07:15.031Z","media":null,"categories":["后端"],"attachments":null,"extra":null,"language":null},{"title":"Java 近期新闻:以 JDK24 为目标的最新一批 JEP,Quarkus 3.17,Maven 4.0-RC1,Kotlin 2.1","url":"https://www.infoq.cn/article/bFf3XYDz2MgzM8bbS1iM","content":"以下 JEP 已成功完成各自的审核,现在以 JDK 24 为目标。
JEP 501\\":弃用 32 位 x86 端口以进行删除 [公告\\"]JEP 499\\":结构化并发(第四个预览版)[公告\\"]JEP 498\\":对 sun.misc.Unsafe 中使用内存访问方法的行为发出警告 [公告]
所有这些 JEP 的细节,请参阅这篇 InfoQ 新闻\\"。
JDK 24 早期访问版本\\"的 Build 26\\" 已于上周发布,其中包含对 Build 25 的众多更新\\",和对各种问题的修复。有关此版本的更多细节请参阅发行说明\\"。
对于 JDK 24\\",鼓励开发人员通过 Java Bug 数据库\\"报告错误。
Spring Cloud Stream Applications\\" 2022.0.1 的发布\\"带来了一些显著的变化,例如:在 org.springframework.cloud.fn:function-test-support 依赖项\\"中添加了缺失的 test 范围;以及对多个 Spring 项目的依赖项升级。此版本与 Spring Boot 3.1.12 和 Spring Cloud 2022.0.5 兼容。有关此版本的更多细节,请参阅发行说明\\"。
Spring Cloud 2023.0.4(代号为 Leyton)已发布,其中包含一些错误修复和对子项目的显著更新:Spring Cloud Kubernetes 3.1.4;Spring Cloud Function 4.1.4;Spring Cloud OpenFeign 4.1.4;Spring Cloud Stream 4.1.4;和 Spring Cloud Gateway 4.1.6。此版本基于 Spring Boot 3.2.12 和 3.3.6。有关此版本的更多细节,请参阅发行说明。
值得注意的是,上述 Spring Cloud Gateway 4.1.6 已更新为使用 Spring Framework HttpHeaders\\" 类中定义的 headerSet() 方法,以更好地与 MultiValueMap\\" 接口及其迭代方法的原生实现保持一致。此更改需要 Spring Framework 6.1.15 及更高版本。
Quarkus 3.17.0 的发布\\"提供了错误修复、依赖项升级和新特性,例如:将 OpenTelemetry 规范集成到 WebSockets Next\\" 扩展;在 MicroProfile 7.0 中提供MicroProfile Rest Client 4.0 规范的实现;以及新的 @PermissionChecker\\" 注释,允许在 CDI bean 上创建权限检查器方法。有关此版本的更多细节,请参阅发行说明\\"。
两天后,第一个维护版本\\" Quarkus 3.17.2(由于回归而跳过了 3.17.1)解决了一些值得注意的问题,例如:由于在 Jakarta Persistence @ManyToOne\\" 注释中使用 optional=false 作为参数而导致的 Hibernate FetchNotFoundException\\";以及与 @AuthorizationPolicy\\" 注释和 Kotlin Suspend 函数\\"不兼容。有关此版本的更多细节,请参阅发行说明\\"。
Hibernate Search\\" 7.2.2.Final 的发布\\"提供了对 Hibernate ORM 6.6.3.Final 和 Elasticsearch 8.15.4 的依赖项升级,还解决了一些值得注意的问题,例如:当单个和多值投影混合在单个长字段路径中时的投影基数问题;以及当使用 Hibernate ORM 6.6.3.Final 处理索引嵌入对象时使用 Jakarta Persistence @IdClass\\" 注释的潜在问题。有关此版本的更多细节,请参阅发行说明\\"。
Eclipse Vert.x 5.0 的第二个候选版本\\"有以下特性:一个新的 VerticleBase\\" 类,它用新的面向未来的模型取代了 Vert.x 以前版本中使用的回调异步模型。版本 5.0 将通过显式模块支持 Java 平台模块系统(JPMS)。已为有兴趣入门的开发人员提供了 JPMS 示例\\"。有关此版本的更多细节,请参阅发行说明\\"和弃用与重大更改\\"。Vert.x 团队预计在 2024 年 12 月 GA 版本发布之前会发布更多候选版本。
JDKUpdater\\" 14.0.67+100 版于上周发布,该实用程序可让开发人员跟踪与 OpenJDK 和 GraalVM 版本相关的更新。该版本由 Azul 首席工程师 Gerrit Grunwald 于 2024 年 3 月中旬推出,包含以下新特性:现在,软件包类型气泡弹出窗口会显示 JDK/JRE 版本是长期支持(LTS)还是短期支持(STS)版本;如果可用,软件包类型气泡弹出窗口现在还会显示特定 JDK/JRE 版本的终止日期。有关此版本的更多细节,请参阅发行说明\\"。
Kotlin 2.1.0 的发布\\"提供了错误修复和新特性,例如:对 K2 编译器的更新,包括编译器检查的额外灵活性;以及对 Kotlin Multiplatform\\"、Kotlin Native\\" 和 Kotlin Wasm\\" 的改进。有关此版本的更多细节,请参阅发行说明\\"和这里的 YouTube 视频。InfoQ 将跟进更详细的新闻报道。
Apache Maven 4.0.0 的第一个候选版本和第五个测试版本提供了许多依赖项升级和显著的变化,例如:在详细模式下添加命令行和终端信息;以及解决损坏的 Maven enc 子命令。有关这些版本的更多细节,请参阅版本 4.0.0-RC1\\" 和版本 4.0.0-B5\\"。
原文链接:
Java News Roundup: Last of the JEPs Targeted to JDK 24, Quarkus 3.17, Maven 4.0-RC1, Kotlin 2.1\\"
","description":"OpenJDK 以下 JEP 已成功完成各自的审核,现在以 JDK 24 为目标。\\n\\n \\n\\nJEP 501\\":弃用 32 位 x86 端口以进行删除 [公告\\"]JEP 499\\":结构化并发(第四个预览版)[公告\\"]JEP 498\\":对 sun.misc.Unsafe 中使用内存访问方法的行为发出警告 [公告]\\n\\n \\n\\n所有这些 JEP 的细节,请参阅这篇 InfoQ 新闻\\"。\\n\\nJDK 24\\n\\nJDK 24 早期访问版本\\"的 Build 26\\" 已于上周发布,其中包含对 Build 25 的众多更新\\",和对各种问题的修复。有关此版本的更多细节请参阅发行说明\\"。\\n\\n \\n\\n对于 JDK 24…","guid":"https://www.infoq.cn/article/bFf3XYDz2MgzM8bbS1iM","author":"Michael Redlich","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-12-09T00:00:00.929Z","media":null,"categories":["编程语言"],"attachments":null,"extra":null,"language":null},{"title":"优化 Uber 的搜索基础设施:升级至Apache Lucene 9.5","url":"https://www.infoq.cn/article/30Tr8Qtilq23YJCyuTVe","content":"最近,Uber 工程团队宣布升级其搜索基础设施,从 Apache Lucene 8.0 升级到 9.5 版本。此次升级提高了 Uber 各项服务的搜索能力、性能和效率。
在一篇博文中,来自 Uber 搜索平台和数据工程团队的 Anand Kotriwal、Aparajita Pandey、Charu Jain 和 Yupeng Fu 详细阐述了本次升级工作。Uber 搜索平台有一个可靠的架构,包括服务层(读取路径)和摄取层(写入路径),以及用于离线处理的组件。
服务层负责处理用户查询,并从 Lucene 索引中检索信息。它主要包含两个部分:路由服务和搜索服务,前者将传入的查询定向到适当的搜索节点,并管理负载均衡;后者查询 Lucene 索引,实时检索结果。
当数据发生变化时,摄取层会更新 Lucene 索引。基于 Apache Flink 的摄取服务会处理实时更新,确保搜索索引保持最新。
对于离线处理,Uber 使用离线作业。这些 Apache Spark 作业可以处理批量索引创建和重建,高效地处理大量数据,构建或重建 Lucene 索引。
图片来源:Lucene:Uber 搜索平台版本升级
工程团队修改了一个单独的特性分支,单体存储库中受影响的文件有 400 多个,而这些文件与当前的代码库并不兼容。为了解决这个问题,团队选择了分阶段上线 Lucene 更新。首先,他们将其部署到优先级较低的内部用例中,然后再逐步扩展到更高的层级上。
整个过程耗时约 6 个月,包括全面的代码审查、验证、与客户团队合作以及合并分支前的分级推广。
Apache Lucene 是一个基于 Java 的搜索引擎库。它支持各种搜索需求,包括结构化搜索和全文搜索、分面搜索、最近邻搜索、拼写纠正和查询建议。它还有一个子项目 PyLucene,为 Lucene Core 提供 Python 绑定。
最近,他们发布了第 10 个版本,新增一个预取 APIIndexInput(支持对文档值做稀疏索引),并升级了 Snowball 字典,进而改进了分词。
本次升级提高了 Uber 的搜索速度和效率。搜索运行速度更快,使用的资源更少,也就是说应用程序用户可以更快地获得搜索结果。按照该团队的说法,有些搜索现在比以前快了 30%,使用该应用的乘客和司机都可以获得更好的体验。
这次升级的另一个好处来自对 Uber 基础设施的影响。Uber 的搜索请求严重依赖 CPU 能力,因此降低 CPU 使用率至关重要。这有助于削减基础设施成本,使 Uber 能够减少为多个客户提供服务所需的机器数量。
Uber 升级 Lucene 版本凸显了在技术驱动的大规模运营中保持核心技术与时俱进的重要性。
原文链接:
https://www.infoq.com/news/2024/11/uber-search-infra-lucene-upgrade/\\"
","description":"最近,Uber 工程团队宣布升级其搜索基础设施,从 Apache Lucene 8.0 升级到 9.5 版本。此次升级提高了 Uber 各项服务的搜索能力、性能和效率。 在一篇博文中,来自 Uber 搜索平台和数据工程团队的 Anand Kotriwal、Aparajita Pandey、Charu Jain 和 Yupeng Fu 详细阐述了本次升级工作。Uber 搜索平台有一个可靠的架构,包括服务层(读取路径)和摄取层(写入路径),以及用于离线处理的组件。\\n\\n服务层负责处理用户查询,并从 Lucene 索引中检索信息。它主要包含两个部分:路由服务和搜索服务…","guid":"https://www.infoq.cn/article/30Tr8Qtilq23YJCyuTVe","author":"Aditya Kulkarni","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-12-09T00:00:00.151Z","media":[{"url":"https://static001.geekbang.org/wechat/images/dd/dd95e59e24fe9e06817ea4fa302429cf.png","type":"photo","width":1024,"height":854,"blurhash":"LCS6Su?b%1?b~qxuIVxa?HWBIVR*"}],"categories":["后端"],"attachments":null,"extra":null,"language":null},{"title":"优步借助 MyRocks 差异备份显著节省了存储成本","url":"https://www.infoq.cn/article/cewR0BIjuEkvC7cW5xFG","content":"据其博客的文章介绍,优步(Uber)已经成功地为其分布式数据库实施了一个新的差异备份(Differential Backup)系统,该系统使存储成本降低了 70%。
优步(Uber)工程师开发这一解决方案,是为了应对优步(Uber)将其 Schemaless 和 Docstore 服务的存储迁移到基于 RocksDB 的 MySQL 存储引擎 MyRocks 后出现了存储成本上升和备份完成时间过长的问题。
在优步(Uber),Schemaless 和 Docstore 分布式数据库处理数十 PB 的运营数据,每秒处理数千万个请求。这些数据库对优步(Uber)的全球运营至关重要,用以支持各种业务功能并确保业务的连续性。
当优步(Uber)团队将存储平台迁移到 MyRocks 时出现了问题,尽管 MyRocks 针对写入操作和存储效率进行了优化,但缺乏对增量备份(Incremental Backup)的支持。这种限制意味着每个数据库分区每次都需要进行完全备份(Full Backup),这导致了大量的重复数据存储并增加了 blob 存储成本。
新的差异备份(Differential Backup)系统利用了 MyRocks SSTable 文件的不可变特性,这些文件在连续备份之间通常保持不变。系统不会在每次备份期间复制所有文件,而是维护一个共享的 SSTable 文件池,并且只将新创建的文件添加到该共享池中。清单文件通过记录包含的文件列表来定义每个备份,因此可以在需要时进行高效地恢复。
Adithya Reddy 在一篇 技术博客 中详细介绍了该解决方案,该系统的工作原理是首先执行初始的完全备份,将所有元数据和 SSTable 文件存储在 blob 存储区内的共享池中。后续差异备份仅将新的 SSTable 文件添加到共享池中,同时重用之前备份中的现有文件。
备份清单文件以 JSON 文档的形式实现的,用以跟踪基本信息,包括备份类型、成功状态、计时详细信息和文件校验和。该清单用作备份的索引,并为恢复过程提供必要的信息。
新系统由一个称为 Backup Scheduler 的无状态服务管理。Backup Scheduler 根据分区备份状态确定备份的时间和频率。实际的备份过程由临时备份容器处理,当需要使用 Percona XtraBackup 工具执行备份时,这些容器就会被激活。
虽然系统主要执行差异备份,但在某些情况下仍需要完全备份,例如:
当备份在生产环境中首次运行时当上一个分区节点变得不适合使用时在 MyRocks 版本升级之前当现有备份池达到差异备份上限时
备份系统继续使用已建立的 Percona XtraBackup 工具进行备份和恢复过程,在添加新的差异备份功能的同时保持与现有系统的兼容性。这种方法使优步(Uber)能够在不需要对其更广泛的数据库基础设施进行大量更改的情况下实施改进。
尽管存在这些限制,但改进仍然很显著。优步(Uber)报告称,大多数实例的数据存储平均减少了 45%,一些较大的实例的每次差异备份的存储成本减少了 70% 或更多。备份过程的速度也得到了显著的提高,完全备份的完成速度比以前快两倍,差异备份的完成时间缩短了五倍。
MyRocks 最初是由 Facebook(现在的 Meta)开发的,目的是为 RocksDB 添加复制和 SQL 层。2016 年,Facebook 将其用户数据库迁移至 MyRocks。RocksDB——MyRocks 背后的底层存储引擎——也被其他组织采用,一些用户声称性能提高了三倍,Percona 发布的基准测试也显示,它的性能与 InnoDB 相比有了显著的改进。然而,对于某些用例,有报道称 RocksDB 在检索方面的表现不如 InnoDB。
Matt Saunders 是 Adaptavist 的首席技术官 DevOps 主管。他帮助团队使用 DevOps、平台工程和云原生工具和技术,快速高效地交付质量可靠的软件,同时将压力降到最低。他曾与复杂的企业、小型初创企业、中小企业以及介于两者之间的所有企业合作过。还联合组织了伦敦 DevOps 聚会小组,该小组拥有 10000 多名成员,每月举办一次非常受欢迎的行业活动。
查看原文链接:
https://www.infoq.com/news/2024/11/uber-myrocks-backups/\\"
","description":"据其博客的文章介绍,优步(Uber)已经成功地为其分布式数据库实施了一个新的差异备份(Differential Backup)系统,该系统使存储成本降低了 70%。 优步(Uber)工程师开发这一解决方案,是为了应对优步(Uber)将其 Schemaless 和 Docstore 服务的存储迁移到基于 RocksDB 的 MySQL 存储引擎 MyRocks 后出现了存储成本上升和备份完成时间过长的问题。\\n\\n在优步(Uber),Schemaless 和 Docstore 分布式数据库处理数十 PB 的运营数据,每秒处理数千万个请求。这些数据库对优步(Uber…","guid":"https://www.infoq.cn/article/cewR0BIjuEkvC7cW5xFG","author":"作者:Matt Saunders","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-12-05T00:03:04.641Z","media":[{"url":"https://static001.geekbang.org/wechat/images/a0/a0c73feb6c4bb1d169f7c5caaeaf3d59.png","type":"photo","width":1080,"height":719,"blurhash":"LSRx[mv~*JxGx]aKMdV@yrVsHrkq"}],"categories":["数据库","性能优化"],"attachments":null,"extra":null,"language":null},{"title":"Linux迎来重要转折点!Rust驱动将全面进军内核核心","url":"https://www.infoq.cn/article/jeiFQpEtCg47ZWBK8IJ3","content":"11 月 30 日,除了之前合并到 Linux 6.13 内核开发窗口的 USB 更新和大型 staging 分支更新外,“char/misc”模块的更改也被采纳。作为内核中汇总各种改动的模块,“char/misc”合并中引入了一些重要更新,这对希望用 Rust 编程语言编写内核驱动的开发者来说尤其值得关注。
Linux 内核关键维护者Greg Kroah-Hartman 表示,随着这些改动的引入,Linux 6.13 现在可以支持更多基于 Rust 的内核驱动开发。
在“char/misc”合并中,他解释道:“Rust 中的 misc 驱动绑定和其他改动使得开发 misc 驱动成为可能。我认为这是一个转折点,有了这些绑定,未来会有更多 Rust 驱动出现。希望在下一个合并窗口中,我们能够实现 PCI 和平台驱动的功能,从而全面支持几乎所有驱动子系统接受(或至少尝试使用)Rust 驱动。这是许多开发者共同努力的成果,祝贺大家取得这样的进展。你们用可运行的代码证明了我们许多人的质疑是错误的 :)。”
这位资深内核开发者预测,未来我们将看到越来越多的上游 Rust 驱动程序。
除了“char/misc”子系统,Rust for Linux项目负责人 Miguel Ojeda 还于11月26日提交了一组针对 Linux 6.13 holiday kernel 内核的大规模 Rust 基础设施和工具链更新,一夜之间让Linux增加了3000行Rust代码。
Linux 6.13 的合并窗口预计将于今天(12 月 1 日)结束,同时发布 Linux 6.13-rc1。Linux 6.13 正逐步成为一个重要的内核版本,稳定版本预计将在 1 月底左右发布。
从这次版本发布中,我们可以得出两个重要信息:一是Greg Kroah-Hartman承认,包括他在内的部分人曾质疑 Rust,但这是“错误”的,他认为Rust for Linux维护者用实际可行的代码证明了 Rust 在内核开发中的潜力。二是尽管此前Rust for Linux维护者宣布退出内核开发,但实际上,将 Rust 代码引入 Linux 的进展并未受到太大影响。
今年9月份的时候,微软工程师、 Rust for Linux维护者之一 Wedson Almeida在Linux 内核邮件列表上宣布退出该项目。他离开的原因是,“在过去四年的工作当中,我发现自己的精力和热情已经被严重消磨,越来越抗拒回应那些跟技术无关的废话。所以这份任务,最好是留给那些仍然抱有这份热情的成员。”
C 和 Rust 两派的分歧一直很大。一些现有的 C 语言程序员对 Rust 作为第二语言的引入持抵触态度,担心这会增加他们的工作复杂性,或迫使他们学习 Rust 而感到压力。英特尔 Linux 核心内核架构团队成员 Dan Williams 也曾指出,Rust 在 Linux 内核中的应用面临一个问题:“内核维护者往往非常保守。” 他们对 C 语言非常熟悉,可以说了如指掌,但对 Rust 却并不了解。因此,他们“不知道该如何审查这些代码,也不知道如何调试那些代码,因为他们并不理解这些代码。”
在 Linux 缔造者 Linus Torvalds 看来,这场争议“几乎上升到了带有宗教战争色彩的信仰之争层面”。而对于不少人因此断言 Rust 的融合之路已经失败的观点,Linus评论道,“我们已经在这方面探索了几年,所以目前下结论还为时过早。但我也认为,哪怕是失败了(虽然我并不支持这种失败论),这也是学习经历的一部分。所以我觉得推广 Rust 是有积极意义的,可争论过程中的很多人似乎并不这么看。”
作为Rust for Linux 项目的首席维护者,Miguel Ojeda 则将 Wedson 的辞职描述为该项目“黎明前最黑暗”的时刻。
“对我来说,这当然非常困难,”Ojeda 表示,“但从积极的角度看,这或许是黎明前最黑暗的时刻……我想向大家保证,项目正在继续前进。”
不久前,Miguel Ojeda 在 RustConf 2024 主题演讲中回顾了 Rust for Linux 项目的历史。
早在 2013 年就有人提出了为内核编写out-of-tree Rust模块的想法,那时 Rust 还未正式发布 1.0 版本。然而,Rust for Linux 并不仅限于out-of-tree模块的开发,其目标是将 Rust 的支持集成到 Linux 主线中,使其能够用于 C 能完成的所有内核任务。值得说明的是,一般情况下,稳定且常用的驱动都是 in-tree 的,它们位于内核源代码树的对应目录下。
2019 年夏天,Miguel Ojeda创建了 Rust for Linux GitHub 组织,但直到 2020 年才真正投入使用。同年 7 月,Nick Desimone 发起了一封关于对 Rust 感兴趣的邮件,随后大家意识到有不少人希望这件事能够成真。
“那时,这仍然只是一个白日梦”,但Miguel Ojeda认为让大家在同一目标下独立工作会很有意义,于是他提交了第一个 Rust 拉取请求,后来越来越多的人加入了这个项目。经过多次协作,最终在两年后,Rust 支持被合并至内核的 6.1 版本。
Rust for Linux旨在为 Linux 内核引入对 Rust 编程语言的支持,目标是实现对 Rust 的一流支持,即在内核中任何可以用 C 实现的功能都可以用 Rust 实现。
他们的最终目标并不仅仅是out-of-tree模块,而是in-tree,以及用 Rust 编写核心 API 和子系统,这不仅限于内核空间代码,还包括宿主和用户程序。
Miguel Ojeda强调项目的关键目标一直都是“将这些支持集成到主线内核中”。并且就像他之前总结的那样:“Rust 现在处于有利地位。”
参考链接:
https://www.phoronix.com/news/Linux-6.13-char-misc-More-Rust\\"
https://www.youtube.com/watch?v=FRMJzNYut4g\\"
","description":"11 月 30 日,除了之前合并到 Linux 6.13 内核开发窗口的 USB 更新和大型 staging 分支更新外,“char/misc”模块的更改也被采纳。作为内核中汇总各种改动的模块,“char/misc”合并中引入了一些重要更新,这对希望用 Rust 编程语言编写内核驱动的开发者来说尤其值得关注。 \\n\\n Linux 内核关键维护者Greg Kroah-Hartman 表示,随着这些改动的引入,Linux 6.13 现在可以支持更多基于 Rust 的内核驱动开发。\\n\\n \\n\\n在“char/misc”合并中,他解释道:“Rust 中的 misc…","guid":"https://www.infoq.cn/article/jeiFQpEtCg47ZWBK8IJ3","author":"Tina","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-12-03T03:35:41.634Z","media":[{"url":"https://static001.geekbang.org/infoq/7e/7e8c5f273e9d4282b74e8944542b1305.jpeg","type":"photo","width":760,"height":687,"blurhash":"L8Q]+x01?b_3~q%Mt7of?bWBIUxu"},{"url":"https://static001.geekbang.org/infoq/47/4774ef8a5f73934a12ff39500f838c80.jpeg","type":"photo","width":1762,"height":876,"blurhash":"LQRMb$%Mt7-;~qWBWBayRjRjRjWB"},{"url":"https://static001.geekbang.org/infoq/ce/ce6527259dbe2de881981e0ed37255b0.jpeg","type":"photo","width":1762,"height":894,"blurhash":"LNRMb$%M%M-;~qRjayj[D%RjWBWB"}],"categories":["操作系统"],"attachments":null,"extra":null,"language":null},{"title":"基于 Java 的无代码和低代码应用程序引导工具","url":"https://www.infoq.cn/article/rYZYML80tjkhZfKSI3EV","content":"
在过去几年中,有几种无代码和低代码平台越来越受开发人员欢迎。有研究预测,到 2025 年,70% 的新增应用程序将使用此类平台开发,而在 2020 年,这一比例还不到 25%。此外,根据 Gartner 的估计,云原生产品将几乎完全占据新增应用的市场份额。随着 LLM 人工智能模型使用量的增加,这种趋势可能只会加快。
但究竟什么是无代码或低代码平台呢?
这些工具有助于为产品开发提供一个共用的基础,避免重复的开发任务。这类平台使用了众所周知且经过验证的框架和架构。有了这个坚实的基础,开发人员就不必再费力设计安全系统了。
使用无代码或低代码平台有利于避免常见的错误和陷阱。对于非开发人员(如业务分析师)来说,这些平台也可以为他们进行系统建模及创建系统概念验证提供很大的帮助。
本文比较了几种比较受欢迎的平台,读者朋友们可以根据自己的需求和资源情况进行选择。
JHipster 是一款著名的开源工具,于 2013 年首次发布,现在已比较成熟。它是一个 Web 应用和微服务应用程序生成器。它可以帮助开发人员在后端创建 Spring Boot 项目,而前端则通过 Yeoman 工具搭建,并且支持 HTML5、Angular、React 和 Vue。它还可以将这些框架与 Thymeleaf 等模板引擎搭配使用。整个技术栈既可以在本地设置,也可以在云中设置,因此,这个工具很容易上手。
JHipster 示例:Motorsports Database
要使用最新版的 JHipster,需要安装 JDK(实际版本取决于 JHipster 的版本以及你是否需要 Spring Boot 2 或 3)、Git、NodeJS 和 Yeoman。
JHipster 可以在线上或本地生成应用程序项目,也可以使用 Docker 镜像生成。
让我们看下第二个选项,因为利用 Docker 镜像在线生成项目可以达到相同的效果,而且最方便。要在本地运行 JHipster,需要安装 JDK 17+ 和 NPM。
在 Linux 系统上,JDK 可以手动安装,也可以通过非常易用的 SDKman 工具安装。安装过程非常简单。
要安装 SDKMAN,只需运行以下命令即可:
curl -s \\"https://get.sdkman.io\\" | bash\\nsource \\"$HOME/.sdkman/bin/sdkman-init.sh\\"
安装完成后,你就可以很轻松地安装 Java 了。例如,安装 OpenJDK 17:
sdk install java 17.0.0-open
NPM 可通过 NVM 工具进行安装和管理。安装方法与 SDKMAN 的安装方法非常类似:
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.3/install.sh | bash\\nsource ~/.nvm/nvm.sh
安装 npm,只需运行以下命令:
nvm install --lts
在 Windows 上,安装 JDK 和 NPM 最简单的方法是从 Oracle 或 OpenJDK 和 NodeJS 网站获取预编译的二进制文件。
最后,执行以下命令就可以运行了:
npm install -g generator-jhipster
然后,JHipster 会引导你回答一系列有关应用程序的问题,包括以下选项:
应用程序类型:单体或微服务构建自动化:Maven 或 Gradle身份验证模型使用的数据库更多信息
JHipster Online 和 Docker 可以帮助你回答这些问题并自动生成实际的应用程序,从而简化这一过程。
使用mvnw(或gradlew)完成构建后,就可以运行应用程序了。JHipster 提供了一些开箱即用的功能,如用户访问管理和度量指标。最酷的是,当在集成开发环境中编辑应用程序时,它支持对前端和后端进行热重载,使得开发过程更加流畅。
虽然它提供了许多强大的功能,但也有自己的优点和缺点。让我们一起来看看。
优点:
减少了模板代码简化了项目初始设置
缺点:
与一些比较新的低代码平台相比,它的学习曲线较长生成的项目有时会包含额外的依赖项
总的来说,JHipster 最适合用于:
创建复杂的 Spring 项目构建面向微服务的应用程序
Openkoda 是一个全新的开源开发平台,旨在以较低的资源占用加速业务应用程序的创建。它省去了 Spring Boot 的设置过程,提供了内置的用户 - 角色 - 组织管理,让你可以专注于业务。它能在运行时使用动态创建的实体和模型,大大加快了应用程序的创建速度。因此,你不需要重新构建 / 重新编译应用程序就能实现完整的 CRUD 功能。当然,与其他工具一样,它也提供标准的 CMS 功能。
Openkoda 主要侧重于提供安全、相互隔离的数据工作流,并通过扩展支持各种多租户模型。
当在 Openkoda 中开发应用程序时,对于前端的仪表盘和小部件,你会用到 Thymeleaf 模板引擎以及 JavaScript 和 CSS。特别有趣的是,在后端执行的代码可以完全用 JavaScript 编写,作为经典技术栈 Spring Boot+Hibernate 的原生部分,你也可以用 Java。
Openkoda 还为触发和处理后台事件以及管理 cron 作业提供了基础。后端功能和前端小部件的结合使该平台能够执行更多的 Web 应用任务,几乎可以完全专注于后端和底层操作。
Openkoda 是一个开源项目,因此你可以轻松地获取源代码,并通过运行.NET Framework 2.0 或更高版本来构建它:
mvn -f openkoda/pom.xml clean install spring-boot:repackage -DskipTests
为了方便起见,还可以选择使用 Docker 镜像。使用docker-compose.yml(可从 Github 上获取)或Dockerfile。
对于喜欢托管服务的用户,Openkoda 的托管云提供了一个高级选项。不过,无论选择哪种方法,你都可以将应用程序作为 Maven 项目导出 / 导入。
让我们来看下 Openkoda 的优缺点。
优点:
开箱即用的 CRUD 和 CMS 功能在运行时动态创建模型和实体内置许多扩展 Spring Boot 的功能
缺点:
对非技术用户来说可能比较难用
最适合:
多租户应用程序的快速模型开发,将其作为模板使用,可避免从头开始编码
Appsmith 通常被称为开源低代码平台,非常适合于开发数据工作流。不过,这个平台也适合那些掌握一定的 JavaScript 和 SQL 技能,并了解如何使用 API 创建更复杂的定制化应用程序的工程师 / 设计师。
Appsmith 提供了超过 18 个本地数据源连接器。类似地,它还提供了与第三方服务和 SaaS 的集成。你可以通过拖放和内置模板及组件(超过 50 个)来创建仪表盘。你还可以使用内置的 JS 编辑器插入自定义代码,并根据自己的需要定制应用程序,使其功能更加强大。你还可以共享自定义小部件,不过需要审批通过才行。
此外,在运行时,该平台还提供了直观的用户体验(UX)和强大的集成开发环境。当你深入研究编码时,就会发现一个突出的特性:它允许你捕捉组件内的事件。
你可以选择免费版,并使用自托管或是云版本,也可以选择付费版。后者提供了更好的可扩展性,并且不限制数据源、自定义品牌等。
Appsmith 主要提供了两个选项:使用云版或使用 Docker、Kubernetes 或 AWS 运行自托管实例。
使用基于云的选项,只需在 Appsmith 云中创建一个账户。然后,配置好数据源(可以是数据库、API 或 SaaS)就可以开始使用了。你可以从可视化地编辑应用程序开始,为通过预先配置好的数据源创建访问数据的表格。之后,你就可以按需调整数据并开发应用程序了。
如果你决定使用本地托管的容器化实例,如 Docker,则只需使用 Appsmith 在安装手册中提供的docker-compose.yml,你可以像使用云版本一样使用它。
让我们来看下 Appsmith 的优缺点。
优点:
出色的可拖放的用户体验设计能力支持快速开发提供多种开始方式
缺点:
相当耗费资源用户体验定制有点受限
最适合:
构建由各种数据源支持的低代码用户界面 CRUD 和工作流应用程序
Wavemaker 不是一个开源平台,但它基于开放的技术栈。它提供了一个可视化开发环境,你可以在其中设计 Web 应用程序(Java、Angular 和 React 栈),可以编码,也可以不编码。它可以利用 Figma 设计导入自动生成 Angular 和 Reactive 移动应用程序。它以生成式人工智能为基础,并且做了许多集成,在快速开发方面应该是非常强大。
Wavemaker 的强项之一是,平台开发环境既可以将在其中创建的项目导出为兼容 Maven 的项目,也可以导入兼容 Maven 的项目。
Wavemaker 一个最突出的特点是集成了 SAP、Salesforce 和微软的 Office 生态系统服务。无疑,这些服务有助于快速创建业务应用,但需要注意的是,Wavemaker 仅提供 PaaS 服务;在应用程序非常特别或后台操作密集时,估计其扩展能力可能会有点不足。
虽然 Wavemaker 不提供免费版,但了解功能的话,你可以申请试用。
进入 Wavemaker 集成开发环境后,就可以开始创建页面、拖放组件和小部件了。之后,你通常需要使用现有的 API 或开发自己的 API 来作为页面或表格的数据源,这里你可以使用平台的导入 / 导出功能。
在管理方面,除了管理外部数据源、API 或集成外,你还可以启用各种安全选项,例如使用 OWASP 工具扫描应用程序中最常见的安全漏洞。
让我们来看下 Wavemaker 的优缺点。
优点:
出色的用户体验设计能力直观的应用程序开发流程支持快速开发
缺点:
对于小型项目来说可能比较昂贵无免费或自托管版本
最适合:
在 PaaS 模式下进行可视化富企业应用程序开发
如果不实际试用,则很难从上述工具中选择出适合自己的。因此,建议读者朋友们下载或创建账户,直接试用。上述平台的优势、方法、整体复杂性、资源要求和价格各不相同,但它们都能提高你的工作效率。
查看原文链接:
https://www.infoq.com/articles/java-no-code-bootstrapping-tools/\\"
","description":"1. 前言 在过去几年中,有几种无代码和低代码平台越来越受开发人员欢迎。有研究预测,到 2025 年,70% 的新增应用程序将使用此类平台开发,而在 2020 年,这一比例还不到 25%。此外,根据 Gartner 的估计,云原生产品将几乎完全占据新增应用的市场份额。随着 LLM 人工智能模型使用量的增加,这种趋势可能只会加快。\\n\\n但究竟什么是无代码或低代码平台呢?\\n\\n这些工具有助于为产品开发提供一个共用的基础,避免重复的开发任务。这类平台使用了众所周知且经过验证的框架和架构。有了这个坚实的基础,开发人员就不必再费力设计安全系统了。\\n\\n使用无代码或低代码平台有利于避免…","guid":"https://www.infoq.cn/article/rYZYML80tjkhZfKSI3EV","author":"作者:Michał Boroński","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-12-03T01:19:38.031Z","media":[{"url":"https://static001.geekbang.org/wechat/images/53/53062ebcb0d0a0fd4f9ec2701c7183cd.jpg","type":"photo","width":560,"height":315,"blurhash":"L#OM{VtMBlt74TW9O=WBS4jvr?ju"},{"url":"https://static001.geekbang.org/wechat/images/4e/4e0a4069be699aaea4df9f09ac07defb.jpg","type":"photo","width":1080,"height":686,"blurhash":"L[NdK|t8WBof~qofWBj[IUaxayj]"},{"url":"https://static001.geekbang.org/wechat/images/72/728f9f06e5bf0ec557b1df30b2e1e02d.jpg","type":"photo","width":1080,"height":554,"blurhash":"LCR:Wv~q-p?b_3a$xus.?GjFt7R*"},{"url":"https://static001.geekbang.org/wechat/images/e0/e0b893922da99f47a592bb5e7a659c63.jpg","type":"photo","width":1080,"height":554,"blurhash":"LVQmL^0KD%?btRaea{t7-:%Mt7WB"},{"url":"https://static001.geekbang.org/wechat/images/29/29ca0be7ecde4e8bcb72adea6a5c967f.jpg","type":"photo","width":1080,"height":705,"blurhash":"LvOW+_R*xtWV00Rjt7Rj9FV@ofWB"},{"url":"https://static001.geekbang.org/wechat/images/8b/8bef89b3afb7b22ef3931fa5ec6dfe0f.jpg","type":"photo","width":1080,"height":462,"blurhash":"LHPjx=}=,C-=.8%1-o%M}=IsIpV@"},{"url":"https://static001.geekbang.org/wechat/images/a2/a2f06543502375e3188563a0cd3b54fa.jpg","type":"photo","width":1080,"height":593,"blurhash":"LmLqeB009FIUIUt7t7WB9Fxuoft7"}],"categories":["编程语言"],"attachments":null,"extra":null,"language":null},{"title":"Apache Doris 在 Cisco WebEx 数据平台的技术升级实践","url":"https://www.infoq.cn/article/95i8blSyayfSXZafbiMf","content":"导读:Cisco WebEx 早期数据平台采用了多系统架构(包括 Trino、Pinot、Iceberg 、 Kyuubi 等),面临架构复杂、数据冗余存储、运维困难、资源利用率低、数据时效性差等问题。因此,引入 Apache Doris 替换了 Trino、Pinot 、 Iceberg 及 Kyuubi 技术栈,依赖于 Doris 的实时数据湖能力及高性能 OLAP 分析能力,统一数据湖仓及查询分析引擎,显著提升了查询性能及系统稳定性,同时实现资源成本降低 30%。
WebEx 是 Cisco 推出的远程、实时的网络会议平台。全球财富 500 强公司中约有 95% 的公司采用 WebEx 来作为视频会议工具,日均会议次数突破 150 万次,全球业务市场超过 160 个。随着市场规模的扩大及使用者持续增加,亟需一个数据平台提供全面的数据及处理分析,以支持故障排查、批量和实时的分析、BI 和大模型的应用、可观测性与数据治理等需求。
在此背景下,WebEx 数据平台从早期的多系统架构(包括 Trino、Pinot、Iceberg 、 Kyuubi 等)改造为基于 Apache Doris\\" 的统一架构。使用 Doris 替换了 Trino、Pinot 、 Iceberg 及 Kyuubi 技术栈,统一数据湖仓及查询分析引擎。显著提升了查询性能及系统稳定性,同时实现资源成本降低 30%。新架构目前已应用于 CCA Peak Ports 项目、Dashboard 系统、统一认证授权等业务场景中。
为适配复杂的业务需求,早期架构融合了多种技术栈。数据源通过 Kafka 进行数据抽取,由 UDP 调度系统(Unified Data Platform:调度 ETL/Spark/Flink 等数据处理任务的平台)将数据调度并存储到湖仓层的 Iceberg 中。Trino、Kyuubi 收到查询请求后提供查询服务,Pinot 主要用于 OLAP 分析。
由于该架构技术栈多样、结构复杂,在实际应用中引发了诸多问题:
运维困难: 多种数据库并存,运维管理工作也变得繁琐且困难。资源利用率低:数据冗余严重,查询入口不统一,难以实现 CPU 和内存资源的高效利用。数据一致性问题频发:多个技术栈中数据独立计算,计算口径不一致,常常引发用户负面反馈。数据治理挑战: 元数据来源多样且格式各异,数据的准确性和一致性难以保障,直接影响了数据治理的效率。
因此迫切需要统一技术栈、降低技术架构的复杂度,同时希望实现性能提升、降低使用成本及简化运维。经过调研,他们发现 Apache Doris 具备的特性能够很好满足这些需求。具体如下:
数据湖能力: Apache Doris 支持 Multi-Catalog 多源数据目录,通过扩展 Catalog 和存储插件,无需将数据物理集中至统一的存储空间,仅借助 Apache Doris 即可实现多个异构数据源的统一联邦分析。目前支持 Hive、 Iceberg、Hudi、Paimon、Elasticsearch、MySQL、Oracle、SQL Server 等主流数据湖、数据库的连接访问。实时写入: Doris 支持直接从 Kafka 等数据源进行数据订阅和导入,避免了复杂的 ETL 过程,提高了数据的实时性。简单易用:Doris 提供统一的架构,减少了对多种技术栈的依赖,降低了系统的复杂性,运维难度及工作量均较低,结合多数据源目录,可实现低成本快速迁移。高性能查询: Doris 采用列式存储和高性能查询引擎,能够快速处理大规模数据集,实现低延迟的查询响应。
基于上述优势,采用 Apache Doris 替换了原先数据湖仓 Iceberg ,统一了查询引擎 Trino、Kyuubi 以及 OLAP 分析引擎 Pinot。依托于 Doris Multi-Catalog 数据湖能力,无需进行数据传输即可直接查询底层引擎中数据;借助其 OLAP 能力,显著提升了数据分析的效率。
具体收益如下:
降低架构复杂性:由 Doris 替换多个技术栈,简化系统架构,减少组件间的依赖和集成工作。简化 ETL 流程:原先数据传输需要经过一系列 ETL 与 Spark Load 转换,流程复杂且需要维护大量计算任务。而 Doris Routine Load 能够直接订阅 Kafka 数据,简化了 ETL 流程。提升资源利用率: 1 个 Doris 集群即可替代原来多个集群,数据无需在多个数据库冗余存储,资源利用率大幅提升,成本节约 30%。降低运维及使用成本:架构及 ETL 流程的简化,大幅降低潜在故障点的发生次数,系统稳定性得到较大的提升。
CCA Peak Ports 项目用于在基于 Peak Ports 套餐的计费模式下,计算 WebEx 与 Partner 之间的对账报表。该项目所采用的技术栈较为传统,数据处理链路较长,系统维护工作量较大,因此作为第一批基于 Doris 改造项目。
原方案:
首先,依赖于 Oracle 数据库中的原始表作为数据源,通过一系列存储过程进行计算,生成中间结果。接着,Java 编写的定时任务进一步处理中间结果,并最终写入 Kafka 消息队列。最后,通过 Spark Job 将 Kafka 中数据同步到 Iceberg 中提供报表服务。
在上述流程中,一旦数据计算过程中出现问题,排查和调试就会变得相当复杂和繁琐。特别是在 Oracle 存储过程的调试,往往不够直观和便捷,增加了解决问题的难度。同时也由于该流程过于复杂,对数据的实时性也产生了一定的影响。
新方案:
基于 Doris 进行改造,将 Oracle 的存储过程改造到 Spark 与 Doris UDF 中,并使用 Doris 替换了 Iceberg,借助 Doris 高效存储和分析能力直接提供数据服务。具体流程如下:
首先,所有数据已预先存储在 Kafka 中。接着,通过 Doris 提供的 Doris-Kafka-Connector\\" 插件,通过 Routine Load 可直接将 Kafka Topics 中数据写入 Doris 中,并将数据整合到明细表中构成 DWD 层。最后,提前部署好的 Spark 作业会对明细数据进行深入的分析与处理,最终将结果写入 DWS 层,由 Doris 提供业务侧数据分析和报表生成的需求。
CCA Peak Ports 项目在基于 Doris 的改造下,整体技术栈风格更为统一,简化了数据处理链路,数据处理更加高效。 在时效性方面,报表更新周期从 T+2 缩短至 T+1;在查询效率方面,报表生成时间由原先 10 分钟缩短至 5 分钟,查询效率至少提升 1 倍多。
Dashboard 系统主要用于展示数据治理的全貌,特别是关于 WebEx 的数据资产概况和分析指标,为管理团队的业务决策提供坚实的数据支撑。
在早期数据治理平台中,依赖 Spark 定期任务提取数据进行 Schema 分析和 Lineage 分析。分析后的结果发送至 Kafka,随后由 Pinot 实时摄取,以便后续的处理展示。这种分散的处理方式可能使得数据治理的整体效率和效果受到限制。不同组件之间的数据交换和同步可能会带来额外的开销和延迟,同时也不利于数据的统一管理和优化。
为解决该问题,使用 Doris 替换了 Pinot ,并基于 Doris Multi-Catalog 能力对底层引擎分别建立了 Catalog,使用 Doris 定时任务抽取引擎中数据。抽取的数据被写入上层的主键模型和聚合模型表中。依赖于 Doris SQL 抽取能力以及其提供的数据模型,完全能够满足 Governance Dashboard 的数据需求。
这一方案的节省了原先 11 个 Spark 作业的维护工作,整个 Data Pipeline 都能够在 Doris 中创建和管理,处理流程更加清晰、简单、高效。同时,降低了 UDP 对 CPU 和内存资源的依赖,避免了偶发的因资源不足导致 Job 无法启动的问题。此外,尽管 Doris 相比 Pinot 查询性能并无巨大提升,但在执行相同的查询时,Doris 消耗的资源更少,更能保证查询正常返回。
在早期认证授权场景中,面临查询入口不统一、用户查询复杂度各异的挑战。这不仅会导致资源利用率低下,还可能引发单个资源密集型查询对其他用户查询性能的严重干扰。
除上述问题外,从用户角度来说,他们需要管理多个系统之间的链接关联,加之各平台密码更新周期的不统一,反复申请认证授权等问题也消耗了大量的时间与精力。
为了解决这些问题,结合 Doris 实现了统一查询服务,整体框架下图所示:
使用 Doris 替换实现了统一的查询服务,依托于 Doris Multi-Catalog 能力,对底层 Trino、Iceberg 和 Pinot 引擎构建 Catalog。 所有应用和作业可以通过查询网关接入 Doris,直接对底层引擎中数据进行查询。
为便于用户使用,还为所有用户创建了 Query Book 服务,以便统一访问湖中数据。此外,结合 Apache Ranger 构建了 Web Auth 服务,将统一认证授权同步至 Doris。原先,用户和平台管理员原先需要在 3 个不同的平台(LDAP/Ranger/DB)中申请和审批权限,现在只需访问 WAP Auth 即可,降低多平台管理负担。还在 Web Auth 中开发了 SQL 规则集模块,支持将规则集的定义同步到 Doris,对高风险 SQL 进行拦截,避免潜在资源滥用。
作为一个在全球范围内分布应用的在线会议产品,WebEx 面临各个国家、各个地区不同隐私数据保护的法案和相关要求,所以数据治理环节至关重要。
为确保企业数据资产的质量、安全和可用性,需要对 WebEx Data Platform 进行数据治理。在引入 Apache Doris 后,也需将其纳入数据治理体系中。这涉及到元数据融合、数据授权与审计、合规检查、质量检查的融合。为支撑这些融合点,需要构建元数据流、血缘数据流、审查数据流。
元数据流作用在于确保元数据顺利同步。Schema Registry 可轻松地将元数据推送至 MetaHub,实现集中存储与管理。Doris 提供了丰富的元数据 API 接口,能够无缝接入大量有价值的元数据,增强 MetaHub 的数据完整性和实用性。
血缘数据流整合有两部分:
静态信息拉取:从 Doris 数据库提取定义好的作业信息(如 Routine Job),反映数据从 Kafka 流向 Doris 表的路径。同时获取 Catalog 信息(部分 Catalog 条目对应外部表,Table 直接存储在 Doris 中),以确保捕获外部表的真实血缘关系。动态数据血缘生成:当新 Job 读取或写入 Doris 时,生成新的数据血缘关系。为管理动态血缘开发了 Client Library,在平台调度 Job 时,Library 以 Sidecar 的形式注入 Job ,Client Library 解析 Job 的 DAG,并基于此生成数据血缘信息,并将信息发送到 MetaHub。
通过结合静态和动态数据血缘的方法,能够全面追踪数据的流动和变化,从而为数据治理和分析提供坚实的基础。
数据流审查主要集中在数据审计、合规性检查和质量监控三个方面。在数据审计方面,直接从 Doris 系统中提取 Audit_log 数据,实现高效审计。在合规性和质量监控上,采用定时任务主动扫描并验证 Doris 中的数据,以确保其合规性和质量达标。
在实时生成并写入 Doris 新数据时,可以利用 Client Library 提供的嵌入式功能,持续监测新生成或正在处理的数据,这一机制不仅提升了数据处理效率,还增强了数据管理的安全性与可靠性。
截至目前,WebEx 数据平台所部署的 Doris 集群近 5 个,总节点数十台。当前已支持在线服务的平均每日查询总数量已超过 10 万,存储总量 40TB+,实时导入的日增数据量高达 5TB+。Doris 的引入不仅带来了诸多降本增效的助力,也驱动其在更大范围内的业务发展探索改造思路与方向:
扩大 Doris 应用范围: 逐步迁移更多数据湖仓中的业务与数据应用层 App 进入 Doris。增强数据平台功能与性能: 基于 Doris 构建高性能数据分析平台,逐步替代应用自建的分析性存储方案,如 TiDB,Kylin 等。探索更多应用场景: 探索 AI on Doris 以及 Doris on Paimon 的场景。
","description":"导读:Cisco WebEx 早期数据平台采用了多系统架构(包括 Trino、Pinot、Iceberg 、 Kyuubi 等),面临架构复杂、数据冗余存储、运维困难、资源利用率低、数据时效性差等问题。因此,引入 Apache Doris 替换了 Trino、Pinot 、 Iceberg 及 Kyuubi 技术栈,依赖于 Doris 的实时数据湖能力及高性能 OLAP 分析能力,统一数据湖仓及查询分析引擎,显著提升了查询性能及系统稳定性,同时实现资源成本降低 30%。 WebEx 是 Cisco 推出的远程、实时的网络会议平台。全球财富 500…","guid":"https://www.infoq.cn/article/95i8blSyayfSXZafbiMf","author":"SelectDB","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-12-02T10:36:43.570Z","media":[{"url":"https://static001.geekbang.org/infoq/95/959366570d8aa74db4c9354c59e36598.png","type":"photo","width":1280,"height":1206,"blurhash":"LBQT7k_3xb_N~Wj[WXofv:V[oyV["},{"url":"https://static001.geekbang.org/infoq/64/64de73e84c05d632d0244ed2c6c2a008.png","type":"photo","width":1280,"height":1206,"blurhash":"LBQvzn_M%3~q~Woeogt6rfV[oyV["},{"url":"https://static001.geekbang.org/infoq/00/00670b2a57964990989649c98e88a831.png","type":"photo","width":1280,"height":714,"blurhash":"LNRC[K^~?TM:~kD,IX%JxnM|M}xs"},{"url":"https://static001.geekbang.org/infoq/e1/e16184ba3c87c5de4d640109689a2a23.png","type":"photo","width":1280,"height":1109,"blurhash":"LY84QOoiIjRiM{ayogfRWEj]axj["},{"url":"https://static001.geekbang.org/infoq/54/54804bf41e4a4cfca098d4b506d408d1.png","type":"photo","width":880,"height":720,"blurhash":"L88#mTVYQnND3NR5MJtPLIiyQn%h"},{"url":"https://static001.geekbang.org/infoq/f1/f1e3e90fab7d55d757f6660322f0e020.png","type":"photo","width":838,"height":720,"blurhash":"LA7V1YyEHsM+CEpIMJRQ*6XNv+w_"},{"url":"https://static001.geekbang.org/infoq/ed/ede72d76078014d42798a11a118cb9fe.png","type":"photo","width":1280,"height":712,"blurhash":"LDQ]?2I}sj?c~S-,t7ob?Fs.%gRj"},{"url":"https://static001.geekbang.org/infoq/13/13fe0585183d497a2627027bb59982a0.png","type":"photo","width":1280,"height":578,"blurhash":"LMB:wE?sbRxgV=DkD%WjtRt8oyfg"},{"url":"https://static001.geekbang.org/infoq/0e/0eab4f99c8e643778be17ade497a0770.png","type":"photo","width":1280,"height":1065,"blurhash":"L$FGUuofoMofj]a{a{fQ?]ofj@of"},{"url":"https://static001.geekbang.org/infoq/1b/1b088929d79e011e6afd2368407e8b3d.png","type":"photo","width":1280,"height":781,"blurhash":"LMQT4i%P^]~n_1ouRVRn?Q%LD-IX"},{"url":"https://static001.geekbang.org/infoq/e9/e96e265139705a549ade11ba060b9d91.png","type":"photo","width":1038,"height":688,"blurhash":"LKQcoGxf%I~n_1xrRpIX%E%LfORQ"},{"url":"https://static001.geekbang.org/infoq/e0/e06b63cde655d42763a005e31fa93115.png","type":"photo","width":1280,"height":239,"blurhash":"LbQ9?1-;-%%Mt6t7ayof~fWFIEa#"}],"categories":["数据库"],"attachments":null,"extra":null,"language":null},{"title":"OceanBase在科大讯飞三大场景下的应用实践","url":"https://www.infoq.cn/article/AhvDxCH2ielPZ1zqk7zC","content":"作者|李梦嘉,科大讯飞技术中心数据库方向负责人。
作为亚太地区知名的智能语音和人工智能上市企业(股票代码:002230),科大讯飞自成立以来一直从事智能语音、自然语言理解、计算机视觉等核心技术研究并保持了国际前沿技术水平。2023年,我们的某个AP业务进行数据库方案替换,上线了OceanBase数据库。本文分享这一年来OceanBase在科大讯飞的应用场景和运维经验。
2023年,我们上线了一个全新的业务,短短几月,数据增长就远远超出了上线初的预测,以至于底层数据库MySQL支撑出现瓶颈。对此,运维侧和业务侧提出了不同的诉求。
首先,业务侧希望数据库具备HTAP能力和多模能力。
HTAP能力。MySQL数据库在我们生产环境中被广泛使用,既支持TP类在线业务,又处理AP类业务的数据统计与分析。众所周知,MySQL对复杂SQL的优化能力较弱,当数据达到一定规模时就会出现性能瓶颈,这时开发人员需要找到一款性能更强的数据库,经过改造让其适配MySQL。为了减少改造成本,我们希望有一款数据库既兼容MySQL协议,又能支持HTAP 混合负载,最好一套系统代替 TP+AP 两套系统,无需分库分表,同时支持列存和行列混存及查询优化,以保障良好的查询性能。
多模能力。随着科大讯飞业务的多元化与复杂化,我们使用的数据库类型也越来越多,对开发、运维都是一种挑战。我们希望有一款数据库能够统一接口处理结构化、非结构化数据,简化我们的技术栈。另外,最好支持 NoSQL 功能,比如HBase、Redis、向量等产品形态。
其次在运维侧,我们对数据库的诉求主要包括两方面:数据迁移、白屏运维。
数据迁移。由于我们使用的数据库类型较多,DBA日常工作涉及在各个数据库集群中迁移、同步数据的操作,而使用的迁移工具、迁移方案也多种多样,因此,我们希望能有一款数据库支持 MySQL、HBase、Redis 、PostgreSQL等多种数据库的数据迁移、同步,同时具备数据校验能力。
白屏运维。我们的运维工作也涉及平台化建设,在该平台尚未完成数据流转生命周期的覆盖时,就无可避免通过命令行黑屏去操作。进而产生误操作,给业务带来稳定性风险。我们希望通过白屏化运维包括安装部署、升级、备份恢复,以及集群巡检、故障分析、SQL优化建议等功能,实现数据流转全生命周期的覆盖。
在做产品调研时,OceanBase作为单机分布式一体化、TP与AP一体化的数据库吸引到了我们,其兼容MySQL协议和部分语法,稳定性与性能已经过市场验证,近年来也拥有了多模能力。同时,OceanBase拥有丰富的生态工具,在数据迁移和白屏运维方面页满足我们的要求。因此,我们决定引入OceanBase(对选型和测试、上线过程感兴趣的朋友可以查看博文:亿级规模大表数据,查询性能快40倍|科大讯飞HTAP探索实践)。
在业务上线OceanBase后,主要的应用情况体现在三类场景中。
起初业务数据量很小,在线业务和统计业务共用一套MySQL集群,没想到上线不久后业务量猛增,增速远超产品侧的预测。
该业务有三个典型特点。第一,数据量大,核心表上亿级,最大的表超百亿规模;第二,增长快,核心表每天新增千万级数据,每年数据的存储量增加5TB以上,且不能删除,产品策略要求永久保存数据;第三,基于海量数据进行实时的多维度统计分析,要求秒级返回,并通过大屏进行实时展示(涉及报表40+)。
这三个业务特性使MySQL面临两个支撑难点,一是大规模数据的迅速增长已经超出MySQL的承载力,二是MySQL在统计查询方面较弱,无法满足业务需求。为了解决这两个问题,我们对系统进行改造和拆分。
首先,为了解决MySQL单集群的容量问题,我们将与核心业务关联较低的表拆分到单独的MySQL集群中,再把纯用户文本类的大字段的表单独拆分到MongoDB集群,相当于缓解了MySQL容量瓶颈和水平扩展问题。
其次,把数据拆分到多个集群后,出于统计分析的需求,业务侧仍然需要将数据进行汇总,一种可行的办法是将数据抽取到大数据平台,通过平台进行查询。但是,这种方法的缺陷在于查询是异步进行,无法满足秒级查询和展示的需求,同时,数据流向大数据平台,也需要经过开发和改造。
为了减少开发改造的工作量,同时更好地解决问题,我们找到了兼容MySQL协议的单机分布式一体化数据库OceanBase,并在2023年将其应用于海量数据统计场景。因为OceanBase支持水平横向扩容,所以容量不会成为业务发展的阻碍。同时,OceanBase的HTAP特性,无论是TP场景的性能还是AP场景的统计分析都能够满足业务秒级查询的要求,在不同的统计SQL 场景,相比MySQL,OceanBase的OLAP性能提升7~40倍。
最终,我们通过数据同步工具将MongoDB和MySQL多个集群的数据统一汇总到OceanBase,在不改变业务逻辑的情况下,满足了业务统计查询报表的需求。
对于一些规模较大的集群,我们在前期使用分库分表方案进行水平拆分,实际是将数据打散在多个分片上。比如将最大的表分成16个分库共256个分片。
在这样的架构下,做统计查询就比较困难。因为分库分表中间件对跨分片的关联和汇聚查询能力较弱,所以无法直接在中间件查询。如果采用人工查询和汇聚的方式,面对单表256个分片,耗时较长。另外,在进行SQL统计分析时,涉及亿级数量的表扫描,可能导致集群性能抖动,影响业务稳定性。
基于上述背景,我们将多个经过分片的数据汇聚到同一个查询库里进行统计,这是一个过渡方案,本质是使用MySQL多元复制的能力将多个分片的数据汇聚到一个MySQL汇总查询库,可以暂时满足业务需求。
但是,这个方案的数据同步链路非常复杂,因为我们业务环境中使用的是MySQL 5.5,复制能力较弱,一些业务原因导致数据库版本无法升级和改造,所以数据必须经过一个临时的中转库,再结合MySQL 5.7的多元复制及replicate DB功能,把多个分片汇聚到一张表中。同时,每个分片都需要一个单独的同步链路,任何一个链路有问题,中转库及最终的数据查询汇聚库都要进行数据修复,导致整体链路出故障时难以修复。尤其是当线上需要变更表结构时。经过的每一个分片都要执行变更操作,致使汇聚链路中断,此时只能依靠人工修复链路。
更让人头疼的是,我们采用MySQL的源生同步,不支持数据校验,缺乏对已汇聚数据和源库原表的完整性校验的机制。如果同步链路中出错,我们只能选择忽略错误,继续保持链路的进度。因此,我们无法判定汇聚后的数据一致性和准确性,如果发现问题,只能重建同步链路,整个过程耗时又耗人。
为了解决上述痛点,我们使用了OceanBase的数据同步工具OMS,代替中转库的方案。
OMS对MySQL各版本兼容良好,可以让我们将数据从MySQL一步汇聚到OceanBase,同步链路被极大地简化。由于OMS的监控和数据校验功能完善,可以监控各种数据延迟,便于我们及时获取同步动态,当数据出现冲突或丢失时,我们也可以借助工具快速进行修复。另外,上文提到每一个分片都是单独的链路,我们可以复制链路原子化,如果单一链路出现问题,也不会影响其他链路的数据同步。
下图是MySQL源生复制和OMS同步的功能对比,可以看到OMS占据很大的优势。比如支持断点续传、数据同步校验、同步延迟监控,以及当数据发生冲突时可以根据配置选择跳过还是覆盖。同时OMS也支持同步链路重建,当出现同步故障时,我们可以通过数据抽取快速恢复链路。
这是一个在线爬虫类业务,需要下载客户请求端的网页,并返回数据。该业务的并发很高,生产端和消费端的并发量均为1.5万个进程,同时业务对应用请求响应的时延要求是毫秒级,因此我们最初选择使用Redis去解耦生产端和消费端,使二者互不影响。
通过 lpush 和 rpush 把待下载网页的URL 数据存入 redis 的 list key。通过 lpop 和 rpop 来获取待下载的网页URL。
由于爬虫的数据量特别大,整个Redis集群使用三台服务器,共42个实例,最大的单实例内存约60GB,整个集群规模占内存约2TB,这为系统埋下了隐患。
第一,Redis主从复制是基于内存中的复制积压缓冲区,如果业务爬虫的瞬时写流量大,会把积压缓冲区的内存覆盖,导致内存不足,进而 Redis主从复制中断,重建频繁失败。这时只能人工介入。
第二,由于爬虫数据的分布不均,整个集群中会存在热 key,业务对部分 key 请求频率过高时(>2w/s),会使集群负载不均。而且因为业务逻辑,我们没办法针对热key进行拆分。
第三,无论是生产还是消费,业务的并发量都很高,但Redis本身是单线程的,如果业务出现偶发 o(n) 操作就会导致单线程阻塞 :如 hgetall,scan, lrange 0-1 等。
因此,我们需要重新选型数据处理方案以解决上述难题。
OBKV是构建在分布式存储引擎上的NoSQL产品,继承了OceanBase 的分布式、多租户、高性能、高可靠等基础能力。其分为OBKV-HBase和OBKV-Redis,后者正是我们当前选择的新方案,原因是:
OBKV-Redis 完全兼容 Redis 协议,业务侧不需要修改。OBKV-Redis 持久化key 到磁盘,解决内存不足或使用过多的问题。OBKV-Redis 针对热 key底层通过表分片进行了优化。OBKV-Redis 利用OBServer多线程处理,无单线程阻塞问题。OBKV-Redis 无特殊运维,只需运维OceanBase集群。OBKV-Redis 的 P99 在 10 ms 以内,满足业务需求。
在上线前,我们针对OBKV和Redis进行了读写方面的压测,为了保证公平性,规格统一限定为12核20GB。从下图可见,在读场景,二者的性能、延时相近。而在写场景,OBKV写性能与Redis存在一定差距,但满足业务负载;OBKV写延迟比Redis略高,但都在10ms以内,满足业务需求。
使用OBKV-Redis后,虽然性能与延时并未提升,但解决了此前Redis主从复制容易中断,产生热 key、单线程阻塞等问题。
除了上述应用场景外,OceanBase丰富的工具体系为我们提供了极大便利。
本文开头提到复杂的运维操作促使我们寻找一个白屏化的运维平台,以管理数据库全生命周期。OceanBase运维平台——OCP基于 Web 的可视化白屏管理,将黑屏运维管理工作标准化、自动化,我们可以通过页面操作进行数据库运维,提升运维效率。
OCP具有几项典型功能:
资源管理。提供 OceanBase 集群,租户,主机等资源对象的全生命周期管理,包括管理,安装、运维、 性能监控、配置、升级等功能。监控告警。全局监控及告警设置,支持所有资源对象不同维度,实时、准确地监控告警需求,支持自定义告警。备份恢复。支持集群和租户表级全量备份、增量备份及日志备份,支持在备份周期内任意时间点的恢复,支持多种云平台介质的备份恢复。自治服务。自动化处理 “发现-诊断-定位-优化/应急”链路,极大地降低用户运维的成本。
从下面OCP平台的截图可以看到,无论是集群管理还是租户管理,我们部可以通过白屏化进行操作。在很大程度上简化了运维工作,降低了我们的运维投入。
OceanBase成功解决了我们在业务侧和运维侧的难题,在运维OceanBase一年后,我们也积累了一些运维经验,供大家借鉴。
当我们在业务侧推广OceanBase时,通常业务侧会关心应该使用哪个版本,这时我们需要对各版本有较为全面的了解。OceanBase的版本号通常有三类:
Va.b.c_CE,如V4.2.1_CE;Va.b.c_CE_BP1,如V4.2.1_CE_BP1;Va.b.c_CE_BP1_HF1,如V4.2.1_CE_BP1_HF1。
在上述版本号中:
a表示主要的大版本,一般会有架构升级或较大的新功能发布。b表示计划迭代版本,含有重要功能或特性更新和提升。c表示发布更新版本,对已知问题进行修复,一般无功能或特性变更。BP:表示是第 X 个 Bugfix 版本,通常每个月发布一次,用于修复一些重大的 bug,引入一些小功能特性。HF:表示是第 X 个 Bugfix 版本的第 Y 个 Hotfix,如果在BP发布期间发现了重大的 bug,就通过 HF 来修复。
目前,OceanBase 4.x的长期支持版本有OceanBase 4.2.1和OceanBase 4.2.5,我们使用的是OceanBase 4.2.1。对于初次选择OceanBase的企业,我们推荐使用长期支持版本的最新BP或最新HF版本。
在MySQL的日常运维工作中,Online DDL操作或大表DDL操作对我们来说是一大痛点。OceanBase对Online DDL操作进行了增强,目前MySQL 中大表分钟级的DDL操作,在OceanBase中秒级完成,且不锁表,完全不会阻塞业务。不过,对于秒级完成的Offline DDL :操作,其原理是新建一张临时隐藏表,后台将原表的数据补全到隐藏表,最后重命名临时表为原表并删除旧表,在这个过程需要锁表,对业务有损。
下图是OceanBase目前已经支持的DDL操作,相信随着版本的快速演进,Online DDL操作会越来越多,Offline DDL:操作会越来越少。
此外,值得一提的是,为了解决Offline DDL锁表的问题,OceanBase提供了一个功能——ODC 无锁结构变更。其本质是依赖OMS、OCP解决问题,首先创建临时表并改变表结构,其次全量拷贝数据并做增量同步和校验,最终切换新旧表。
下图是ODC 无锁结构变更支持的变更范围。
在进行无锁结构变更操作时,我们需要注意:
表必须有主键或非空唯一键;需要操作对象至少 2 倍的磁盘空间;无锁结构变更期间,其它关于该表的 DDL 变更将导致任务失败。
根据我们的实测数据,线网5亿单表(200GB)修改列类型耗时约 5 小时,但经过我们和官方技术人员分析,耗时较长的原因是 ODC 依赖的 OMS 同步效率慢,可以通过参数调优实现加速。
优化器是数据库SQL执行的关键,但往往无法正确选择准确的执行时间。当优化器选择了错误的执行计划时,就需要通过Hint指定执行计划。Hint 是一种 SQL 语句注释,用于将指令传递给数据库优化器,使优化器生成指定的执行计划。一般情况下,优化器会为用户查询选择最佳的执行计划,不需要用户使用 Hint 指定。
下面来看一个简单的SQL在是否增加Hint的执行效率对比。该表的全量数据为600万行。虽然有围绕条件,但过滤条件不是很好,没有办法走索引。经过扫描,结果集也是600万,可以判定为全局扫描。
数据量:
obclient [oceanbase]> select count(1) from chat_req_uid_doctype_daily;
count(1)|
--------+
6097816
obclient [oceanbase]> select count(1) from chat_req_uid_doctype_daily where doctype in (\'0\', \'1\', \'2\', \'3\', \'1100\');
count(1)|
--------+
6025383
在不用Hint的情况下,初始SQL执行需要6s,为了优化性能,我们为该SQL加入Hint,执行效率提升至了1s,效果较为显著。我们线网一般是把OceanBase作为一个AP类的场景去使用。所以说它的并发不是特别高。所以说在为了提升查询效率的情况下,我们一般会建议业务适当增加Hint,因为Hint并不是越多越好,达到一定并行量后,性能提升效果会受限。
原SQL(6s):
obclient [oceanbase]> select count(distinct uid) as uidcnts
from chat_req_uid_doctype_daily
where doctype in (\'0\', \'1\', \'2\', \'3\', \'1100\');
添加Hint的SQL(1s):
obclient [oceanbase]> select /*+ parallel(4) */
count(distinct uid) as uidcnts
from chat_req_uid_doctype_daily
where doctype in (\'0\', \'1\', \'2\', \'3\', \'1100\');
不同版本的优化器,对SQL性能会产生不同的影响。举个例子,某SQL的条件列中是一个条件中的一个非相关子查询,最初我们使用OceanBase 4.1.0版本时,该SQL的执行时间为0.3s,当我们升级为OceanBase 4.2.1版本后。执行时间退化到了50s。
经过测试,发现问题在于条件列的子查询,如果把这个子查询换成子查询返回的固定日期,它的查询时间会恢复到0.3s。这是由于数据库版本之间优化器的变化导致的,最终我们通过添加Hint并修改执行计划,使该SQL的执行效率重回0.3s。
OceanBase的优化器是基于规则优化和代价优化相结合,在一般情况下通过代价进行查询优化,可能会产生错误的执行计划,这时就需要通过Hint基于规则进行“修剪”实现优化。
目前OceanBase还在不断演进,其研发人员无法神通广大地覆盖所有SQL场景,还是要依赖于用户在生产场景不断发现问题、反馈问题,而官方的响应和改进也非常快速。期待OceanBase能够越做越好。
作者简介:
李梦嘉,科大讯飞技术中心数据库方向负责人。10年以上DBA经验,对数据库的架构设计、优化、问题诊断、故障处理、数据恢复等有深刻地理解和实战经验。推动了讯飞数据库标准化、自动化运维、运维流程规范体系、高可用架构设计等建设。
","description":"作者|李梦嘉,科大讯飞技术中心数据库方向负责人。 作为亚太地区知名的智能语音和人工智能上市企业(股票代码:002230),科大讯飞自成立以来一直从事智能语音、自然语言理解、计算机视觉等核心技术研究并保持了国际前沿技术水平。2023年,我们的某个AP业务进行数据库方案替换,上线了OceanBase数据库。本文分享这一年来OceanBase在科大讯飞的应用场景和运维经验。\\n\\n数据库选型需求\\n\\n2023年,我们上线了一个全新的业务,短短几月,数据增长就远远超出了上线初的预测,以至于底层数据库MySQL支撑出现瓶颈。对此,运维侧和业务侧提出了不同的诉求。\\n\\n首先…","guid":"https://www.infoq.cn/article/AhvDxCH2ielPZ1zqk7zC","author":"李梦嘉","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-12-02T10:32:11.090Z","media":[{"url":"https://static001.geekbang.org/infoq/fb/fb40fd43d9b8b407d7f2ba8808bda056.png","type":"photo","width":832,"height":412,"blurhash":"LOPZ+N0M^*~V%MM|xZa#NLofWBRj"},{"url":"https://static001.geekbang.org/infoq/81/8154441327dd22fb17d7b894ff05cae4.png","type":"photo","width":832,"height":356,"blurhash":"LGLq^oxvV@-=4|a#j[WB03WXj[WB"},{"url":"https://static001.geekbang.org/infoq/89/89d8f211dd008ad26db939c4962cbfb9.png","type":"photo","width":832,"height":382,"blurhash":"LdPGz0kDxtWZbJazWBR*~Vt6M|of"},{"url":"https://static001.geekbang.org/infoq/bb/bb87f927112a1655d6ef390d7da1cca3.png","type":"photo","width":832,"height":930,"blurhash":"LLO4PUbd~V%g0MxtRjRjE2M|WBWC"},{"url":"https://static001.geekbang.org/infoq/44/44f12f582cca2609497639488a269a09.png","type":"photo","width":832,"height":874,"blurhash":"LUM@.qbc~Vt8xvxtM|xa9aR*t7WB"},{"url":"https://static001.geekbang.org/infoq/3b/3b4f6d067d29617f97d61a1a28797aa1.png","type":"photo","width":832,"height":360,"blurhash":"LQLhJca#axxuEVRkt6WB0Nogodof"},{"url":"https://static001.geekbang.org/infoq/ae/ae80c5b5c5d461e902bcc8273d794364.png","type":"photo","width":832,"height":372,"blurhash":"LLO|njIW01NM%NIVM|of^*aeRkt7"},{"url":"https://static001.geekbang.org/infoq/9e/9e38451b30d4a90c0d376497cb82c9fe.png","type":"photo","width":832,"height":518,"blurhash":"LDR{uu.8.T~q_3WBxtt7o#WBV@fR"},{"url":"https://static001.geekbang.org/infoq/2c/2cfb6ef00db8f0553f19cb163793404b.png","type":"photo","width":832,"height":436,"blurhash":"LCSijZ~qIU~q~qt7WCa|IVofayjZ"},{"url":"https://static001.geekbang.org/infoq/01/0141fa0fadaa09eaebdf078307a5c496.png","type":"photo","width":832,"height":314,"blurhash":"LIO|kY0O%i?cE9t7xtRj02adRPWB"},{"url":"https://static001.geekbang.org/infoq/03/03fb7c4ecebf711e00bb235c93fbb055.png","type":"photo","width":332,"height":366,"blurhash":"LQO;0z9cR;_4E9oft6R*4=s.kBRj"}],"categories":["数据库"],"attachments":null,"extra":null,"language":null},{"title":"Java近期新闻:OpenJDK和Jakarta EE 11更新、Payara平台、Vert.x、Log4j、JobRunr","url":"https://www.infoq.cn/article/GI9kOZYSLh7OwqyK6eCc","content":"本期Java新闻综述主要包括以下新闻:处于JDK 24 Targeted和Proposed to Target状态的OpenJDK JEPs;Jakarta EE 11核心配置文件处于发布审查中;2024年11月Payara平台发布;Vert.x 5.0的第一个候选版本;以及Log4j 2.24.2和JobRunr 7.3.2的小版本。
以下JEP已经成功地完成了各自的审查,现在已处于JDK 24的Targeted状态。
JEP 497,基于模格的抗量子数字签名算法\\" [公告\\"]JEP 496,基于模格的抗量子密钥封装机制\\" [公告\\"]
以下JEP已提升为JDK 24的Proposed to Target状态。它们的审查预计于2024年11月25日和2024年12月26日结束(JEP 499)。
JEP 501:弃用32位x86端口以进行删除\\" [公告\\"]JEP 499:结构化并发(第四次预览)\\"[公告\\"]JEP 498:在sun.misc.Unsafe使用内存访问方法时发出警告\\" [公告\\"]
更多关于这些JEP相关的详细信息,请参阅InfoQ的这篇新闻报道\\"。
JDK 24早期访问构建版本\\"的Build 25\\"于上周发布,其中包含针对Build 24的更新\\",其中包括对各种问题\\"的修复。有关该版本的更多详细信息,请参阅发布说明\\"。
对于JDK 24\\",鼓励开发人员通过Java Bug数据库\\"报告缺陷。
Eclipse基金会的Jakarta EE发人员倡导者 Ivar Grimstad\\"在其每周Hashtag Jakarta EE\\"博客中提供了Jakarta EE 11的最新情况\\",他写道:
一些令人兴奋的消息!Jakarta EE Core Profile 11\\"终于进入发布审查阶段了。由于WildFly和Open Liberty都通过了TCK,因此有两种兼容的实现可用。投票最迟将于12月4日结束,但如果所有成员都投票了,投票可能会提前结束。希望不久我就能与大家分享关于Jakarta EE Platform 11\\"和Jakarta EE Web Profile 11\\"同样令人兴奋的消息。对TCK进行现代化和重构的工作仍在进行中。
通往Jakarta EE 11的道路上包括四个里程碑版本,在2024年第4季度发布GA版本之前,可能会根据需要发布候选版本。
对于Spring来说,本周是非常忙碌,因为各个团队已经发布了预期中的GA版本,包括Spring Boot\\" 3.4、Spring Security\\" 6.4、Spring Authorization Server\\" 1.4、Spring Integration\\" 6.4、Spring Modulith\\" 1.3、Spring AMQP\\" 3.2、Spring for Apache Kafka\\" 3.3.0和Spring for Apache Pulsar\\" 1.2。更多详细信息请参阅InfoQ的这篇新闻报道\\"。
Payara发布\\"了2024年11月版的Payara Platform\\",其中包括社区版6.2024.11、企业版6.20.0和企业版5.69.0。除了缺陷修复和依赖项升级外,所有这三个版本都提供了新特性:支持Tom的Obvious Minimal Language\\",即更广为人知的TOML,用在MicroProfile Config规范中;以及在自动化部署组(Automated Deployment Groups\\")中添加自动命名功能,从而简化了集群管理操作。有关这些版本的更多详细信息,请参阅社区版6.2024.11\\"、企业版6.20.0\\"和企业版5.69.0\\"的发布说明。
本次发版还包含Payara社区版7.2024.1的第二个alpha版本,该版本支持即将发布的Jakarta EE 11,并实现了Jakarta EE 11除了Jakarta Authentication和Jakarta Data之外的Jakarta EE 11平台规范。
IBM发布\\"了Open Liberty\\"的24.0.0.12-beta版,该版本在其Jakarta XML Web Services\\"规范的实现中增强了入站SOAP消息验证,从而简化了消息调试,并提供了更具弹性的Web服务和客户端应用程序。可以将新属性( enableSchemaValidation 、 enableDefaultValidation 和 ignoreUnexpected elements )添加到 server.xml 文件中的 webService 和 webServiceClient 元素中。
Micronaut基金会发布\\"了Micronaut Framework\\" 4.7.1版本,其中包含了Micronaut Core 4.7.6\\",并对以下模块进行了缺陷修复和补丁更新:Micronaut Security\\"、 Micronaut JAX-RS\\"、Micronaut Data\\"、Micronaut OpenAPI/Swagger Support\\"和Micronaut Micrometer\\"。有关该版本的更多详细信息,请参阅发布说明\\"。
JobRunr\\" 7.3.2的发布提供了缺陷修复和增强功能,例如:确保 Interval 类是幂等的,以防止从 BackgroundJobServer 类实例化的 JobZooKeeper 类的实例在关键启动任务失败时启动;以及在IoC容器关闭时捕获和转换 JobActivatorShutdownException 。有关该版本的更多详细信息,请参阅发布说明\\"。
Apache Log4j\\" 2.24.2的发布\\"主要解决了Log4j API初始化代码中的一个严重缺陷,该缺陷有可能导致LogManager类中定义的 getLogger() 方法在某些条件下返回 null 。其他值得注意的修复包括:由于 StackTraceStringResolver 类中的“off-by-one”(或fencepost错误)导致的 ArrayIndexOutOfBoundsException ;以及由于2.24.1版本中的日志记录器损坏而导致的 NullPointerException 。有关该版本的更多详细信息,请参阅发行说明\\"。
Eclipse Vert.x 5.0的第一个候选版本\\"发布,包含的特性有:一个新的 VerticleBase 类,它推进了基于future的模型,取代了Vert.x早期版本中使用的回调异步模型。5.0版将支持带有显式模块的Java平台模块系统(Java Platform Module System,JPMS)。JPMS示例\\"已提供给对其入门感兴趣的开发人员。有关该版本的更多详细信息,请参阅发布说明\\"、弃用和重大更改\\"。Vert.x团队预计在2024年12月GA版本发布之前会有更多的候选版本。
Gradle 8.11.1是第一个维护版本,它解决了以下问题:在Gradle的隔离项目\\"和并行配置中损坏的 BuildEventSListener 注册表接口;升级到Gradle 8.11之后,在生成问题报告时出现的 ArrayIndexOutOfBoundsException ;以及由于字节码拦截而无法在8.10版本中执行Gradle任务。有关该版本的更多详细信息,请参阅发布说明\\"。
原文链接:
https://www.infoq.com/news/2024/11/java-news-roundup-nov18-2024/\\"
","description":"本期Java新闻综述主要包括以下新闻:处于JDK 24 Targeted和Proposed to Target状态的OpenJDK JEPs;Jakarta EE 11核心配置文件处于发布审查中;2024年11月Payara平台发布;Vert.x 5.0的第一个候选版本;以及Log4j 2.24.2和JobRunr 7.3.2的小版本。 OpenJDK\\n\\n以下JEP已经成功地完成了各自的审查,现在已处于JDK 24的Targeted状态。\\n\\n \\n\\nJEP 497,基于模格的抗量子数字签名算法\\" [公告\\"]JEP 496,基于模格的抗量子密钥封装机制\\" [公告\\"]\\n\\n \\n\\n以下…","guid":"https://www.infoq.cn/article/GI9kOZYSLh7OwqyK6eCc","author":"Michael Redlich","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-12-02T02:18:01.798Z","media":null,"categories":["编程语言"],"attachments":null,"extra":null,"language":null},{"title":"Cloudflare 使用 OpenTelemetry 彻底检修日志记录管道","url":"https://www.infoq.cn/article/01Ni9I3tq6Z6eoifANNT","content":"互联网基础设施和安全公司 Cloudflare 记录了它是如何通过从 syslog-ng 迁移到 OpenTelemetry Collector 来显著升级其日志记录管道的。
日志记录管道是 Cloudflare 最大的数据管道之一,也是其关键的基础设施,因为它每秒从其网络中的每台服务器收集和处理数百万个日志事件。该管道以前依赖于广泛使用的开源日志记录解决方案 syslog-ng,而迁移到 OpenTelemetry Collector 是 Cloudflare 处理其大量日志数据方式的重大转变。
工程师 Colin Douch 和 Jayson Cena 在 其公司博客文章中详细介绍了这一迁移过程,他们表示,这一改变有几个动机:
语言兼容性:OpenTelemetry Collector 是用 Go 语言编写的,与 syslog-ng 使用的 C 语言相比,Cloudflare 的工程团队更熟悉 Go 语言。这一改变使 Cloudflare 的更多工程师能够为日志系统做出贡献并对其加以改进。更容易与内部库集成:使用 Cloudflare 的内部后量子(Post-Quantum)加密库构建 syslog-ng 是一个挑战。基于 Go 的 OpenTelemetry Collector 简化了这一过程。增强的度量指标:OpenTelemetry Collector 支持 Prometheus 度量指标,使团队能够收集有关收集器性能的更详细的遥测数据。统一遥测基础设施:Cloudflare 已经将 OpenTelemetry Collector 用于一些跟踪基础设施中。将不同类型的遥测技术整合到一个系统中可以降低工程团队的复杂性。
作为迁移的一部分,工程师开发了几个自定义组件,以维护与现有系统的兼容性并满足特定的需求。这些组件包括 Cloudflare 自己的日志格式的自定义导出器、用于其他输出格式的修改后的文件导出器、将外部源 JSON 数据合并到日志条目中的处理器,以及用于防止单个服务淹没日志管道的速率限制器。
Cloudflare 采用了两种策略来推出这些更改。由于核心数据中心的自定义配置和多样化的工作负载,需要采取谨慎的实践方法,而在其边缘数据中心,由于配置更简单,团队可以在仔细监控的情况下逐步推出。
迁移过程暴露出几个挑战,例如故障转移问题,新导出器最初未能检测到与主日志服务器的连接问题,导致日志积压,并在混乱测试期间影响了一些服务。停止 syslog-ng 和启动 OpenTelemetry Collector 之间的切换也导致日志收集短暂中断,影响了一些以阻塞模式写入日志的服务。
Cloudflare 通过在其自定义导出器中实施了更严格的超时、修改故障转移行为以及调整其部署流程以最大限度地减少切换期间的停机时间来解决这些问题。未来的相关计划包括实施更复杂的日志采样技术,包括尾部采样,并向开源社区贡献一些自定义组件。
Cloudflare 并不是唯一一家转向 OpenTelemetry 的公司,Shopify、Splunk、谷歌和 GitHub 等其他大型公司也采用了这项技术。在谷歌云(Google Cloud)网络研讨会上,其中一些组织详细介绍了他们的 OpenTelemetry 使用情况。
谷歌正在多种产品中使用 OpenTelemetry,例如在谷歌 Kubernetes 引擎(Google Kubernetes Engine)和谷歌计算引擎(Google Compute Engine)中使用收集器,以及在云监控(Cloud Monitoring)和云跟踪(Cloud Trace)中替换 OpenCensus SDK。Splunk 内部正在采用 OpenTelemetry,通过多种形式该项目做出了广泛贡献,例如通过使用收集器进行基础设施监控、迁移到 OpenTelemetry 客户端库以及为收集器和自动仪器开发做出贡献等。Shopify 正在将其跟踪收集基础架构迁移到 OpenTelemetry,并在收集器中实施 PII 编辑、采样和跨度(span)重命名。
同样,GitHub 正在采用 OpenTelemetry 来标准化其遥测实践。在一篇博客文章中,GitHub 工程师详细介绍了该公司如何使用 statsd、syslog 以及 OpenTracing 等工具的,statsd 用于获取度量指标、syslog 用于获取文本日志,OpenTracing 用于获取请求跟踪,但这导致了互操作性的挑战,并为每个新系统重复提供了解决方案。
GitHub 正在通过多种关键的方式来实施 OpenTelemetry,如使用 OTLP(OpenTelemetry 协议)作为遥测信号的标准,与供应商无关的格式。它还利用 Ruby 和 Postgres 的自动检测功能来自动添加分布式跟踪。开放标准还允许 GitHub 使用 OpenTelemetry 跟踪作为根来创建不同信号之间的自动关联。
GitHub 认为,一旦跟踪到位,这种方法将允许它们自动获取额外的信号,例如自动计算指标并将跟踪事件转换为详细的日志。它们还为 OpenTelemetry 项目做出了贡献,以造福更广泛的社区。
Matt Saunders 是 Adaptavist 的首席技术官 DevOps 主管。帮助团队使用 DevOps、平台工程和云原生工具和技术,以快速、高效且最小的压力交付可靠、高质量的软件。他曾与复杂的企业、小型初创企业、中小企业以及介于两者之间的所有企业合作过。还联合组织了伦敦 DevOps 聚会小组,该小组拥有 10000 多名成员,每月举办一次非常受欢迎的行业活动。
查看原文链接:
https://www.infoq.com/news/2024/10/cloudflare-opentelemetry/\\"
","description":"互联网基础设施和安全公司 Cloudflare 记录了它是如何通过从 syslog-ng 迁移到 OpenTelemetry Collector 来显著升级其日志记录管道的。 日志记录管道是 Cloudflare 最大的数据管道之一,也是其关键的基础设施,因为它每秒从其网络中的每台服务器收集和处理数百万个日志事件。该管道以前依赖于广泛使用的开源日志记录解决方案 syslog-ng,而迁移到 OpenTelemetry Collector 是 Cloudflare 处理其大量日志数据方式的重大转变。\\n\\n工程师 Colin Douch 和 Jayson Cena…","guid":"https://www.infoq.cn/article/01Ni9I3tq6Z6eoifANNT","author":"作者:Matt Saunders","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-11-27T00:00:04.085Z","media":[{"url":"https://static001.geekbang.org/wechat/images/0c/0ca7713fe250f77eab1116e82813d883.png","type":"photo","width":1080,"height":961,"blurhash":"L7Ss89~XIU_3.m%3%2xuNF%Mxbof"}],"categories":["后端"],"attachments":null,"extra":null,"language":null},{"title":"C++敲响末日警钟:遭遇美政府和科技巨头联合封杀,编程语言王者走向末路?","url":"https://www.infoq.cn/article/GapgFiqC6wtHq5IVtNP9","content":"关于C++的未来该向何处去,似乎有着很多争论甚至是激烈对抗。无论是Reddit上的小打小闹,还是官方C++标准委员会中的严肃讨论,都免不了要陷入立场之争、派系之争。这已经成为无法回避的客观现实。
就目前来看,C++阵营处于如下状态:C++的演进工作组(EWG)刚刚就采用P3466 R0达成共识——即应当重新确认未来C++演进的设计原则:
这意味着拒绝ABI破坏,保留与C以及此前C++的链接兼容性。这也意味着拒绝“病毒注释”(例如不设全生命周期注释)。这大大强调了对一系列不兼容目标的处置,即拒绝ABI破坏以及零开销原则。无论是好是坏,这都是对当前C++语言演进轨迹的强化。
但与此同时,在C++的发展道路上也面临着一系列阻碍,包括美国政府机构(网络安全与基础设施安全局(CISA)、美国国家安全局(NSA)以及白宫)希望人们停止使用C++,美国政府各个部门均已发布文件、报告和建议,警告技术行业不要使用内存不安全的语言。
各大科技巨头也有弃C++转投入Rust之势。
不久前,在微软工作了 22 年的 ISO C++ 委员会主席 Herb Sutter也离开了微软,成为 Citadel Securities 的技术研究员。有消息称微软明显正在使用Rust重写其核心库。早在2022年,Microsoft Azure 首席技术官 Mark Russinovich就敦促科技行业放弃 C/C++。“说到语言,现在是时候停止用 C/C++ 启动任何新项目,并在需要非语言的场景中使用 Rust,”他说。“为了安全和可靠性,行业应该宣布这些语言已弃用。”
谷歌曾在2021年就发文称正在全力推动Rust。谷歌表示:“Android 平台代码的正确性是每个 Android 版本安全性、稳定性和质量的首要任务。C 和 C++ 中的内存安全错误仍然是最难解决的错误来源。我们投入了大量的精力和资源来检测、修复和缓解此类错误,这些努力有效地防止了大量错误进入 Android 版本。然而,尽管付出了这些努力,内存安全错误仍然是稳定性问题的主要因素,并且始终占Android 高严重性安全漏洞的 70%左右。而 Rust 通过结合使用编译时检查来强制执行对象生存期/所有权,并使用运行时检查来确保内存访问有效,从而提供内存安全保障。在提供与 C 和 C++ 相当的性能的同时,还实现了这种安全性。” 实际上已经开始开发C++/Rust双向互操作工具\\"。
AWS也正在重度使用Rust。AWS在官微上发文称,“Rust 带来了完善的工具、强大的包管理器 (Cargo),也许最重要的是——一个快速增长且充满热情的开发者社区。随着 Rust 越来越受欢迎,越来越多的知名组织,包括 AWS,将其用于性能和安全性是首要关注点的关键应用程序。例如,Amazon S3利用 Rust 尝试以个位数毫秒的延迟返回响应。用 Rust 编写的 AWS 产品组件还包括Amazon CloudFront、Amazon EC2和AWS Lambda等。
此外,臭名昭著的Prague ABI投票已经开始(即「C++23不会破坏ABI,但不清楚未来是否变化」)。据称谷歌大幅降低了其在C++开发流程中的参与度,转而开发自己的C++后继语言。他们甚至专门发布总结,概述了在尝试改进C++时遇到的所有问题。这也为C++风雨飘摇的未来多蒙上一层阴影。
多年以来,人们竭尽全力参与C++标准委员会流程,但却最终被彻底驳回的故事已经广为人知,并在整个社区中流传。(哪怕是已经在C中得到实现的功能也不例外。)模块设计仍未实现,C++什么时候才能拥抱模块化?
基于以上种种,不免让人对C++的未来表示担忧。事实上,很多人对C++委员会对于混乱现状的掌控能力已经失去了信心。
人们似乎正在寻求其他解决方案。
比如谷歌自ABI投票以来,就明显对C++委员会的“流程”失去了信心。这并不是对语言本身失去信心,毕竟谷歌拥有世界上最大的C++代码库之一,而且一直为其提供着非常好的维护服务。所谓失去信心,主要是不看好该语言在面对来自不同角度的压力(包括潜在政府法规、竞争语言的冲击、关键参与者对于更高性能以及更佳安全保障的规划等)时能否保持住不断演进的能力。
那么问题的根源是什么?C++为什么会变得这么……食古不化?
这个问题并不难回答,只消看看Herb Sutter\\"在他关于配置文件的文章\\"就能窥得一二:
“我们必须尽量减少对现有代码的变更需求。对于现有代码中已经存在的应用,数十年的经验一直表明,大多数拥有大型代码库的客户不能、也不会为了满足严苛规则而更改哪怕1%的代码行。除非监管要求强迫他们这样做,否则即使是出于安全原因也无法推动这方面举措。” ——Herb Sutter
这话说得……但神奇的是,人们似乎又对此见怪不怪。
现在让我们跟WG21成员页面上Chandler Carruth的小记做一番对比:
“我执掌了基于Clang构建的C++工具与自动重构系统的设计工作,其现在属于Clang项目的组成部分……在谷歌内部,我领导了将基于Clang的自动重构工具扩展到我们整个代码库(共涉及超过1亿行C++代码)的努力。我们可以在20分钟之内分析并对整个代码库执行重构。”
看到了吗,人家好像愿意做变更。
而遗憾的是,自动化迁移工具也是C++阵营目前唯一拿得出手的应用案例了。
基本上,我们看到了两大截然不同的C++用户派系之间的冲突:
灵活、现代且能力更强的科技企业,清楚意识到自己的代码是一种资产。(请注意,这里指的并不只有大型科技企业,任何理智的C++初创公司也都会站在这一边。)除此之外的所有老牌企业,都仍在为代码缩进之类的细节而争吵。部分年轻工程师甚至需要恳求管理层允许他们设置linter。
相信未来一定会出现一支能够优雅处理迁移,并且立足版本化源代码构建其C++技术栈的团队,但绝不会是目前仍强行使用1998年古老预建库的团队。
当然,这在实践中会是一个渐变的过程。我只能想象,要想将大型技术代码库从可怕的混沌转化成具备一定可管理性、可构建性、经过lint分析、拥有正确版本控制的改良形态,必然要付出无数汗水、泪水、成本甚至是牺牲。
事后看来,我们当然可以轻飘飘地认为这一切都是历史大势的必然:谷歌等巨头的需求(即使用高度现代化的C++代码、建立自动化工具与测试以及现代化基础设施)明显与其(非常强烈的)向下兼容意愿之间存在脱节。
我们甚至可以大胆地讲,统一无方言的C++概念似乎在多年之前就已经消亡。目前我们至少面对着两条主要C++发展路线:
任何稍微现代的C++,可能至少是从C++17开始。它们支持uniqe_ptr, constexpr, lambdas还有 optional。一切都可以从版本化的源代码构建,使用某种专用、干净且统一的构建流程,该流程至少要比原始CMake稍微复杂一些,而且只要认真观察应该就能顺利起效。其还具备某种静态分析器、格式化程序、linter等。总之,要支持一切有助于保持代码库干净和现代的协议。不符合以上特征的其他产物。比如那些长期运行在中等规模银行里那古老、布满灰尘的服务器当中的C++项目。这些C++往往依赖于某些极其陈旧的编译代码块,而且对应的源代码已经丢失,且无法联系到其原始作者。还包括一切部署在微型服务器上的C++,要在其他环境下正常启动,工程师们往往需要一个月时间才能厘清其中的所有隐式依赖项、配置和环境变量。这些就是被广泛归类为成本中心的遗留代码库。
大家会注意到,两派最大的分歧并不在于C++本身,而在于依托工具或者其他手段以干净且定义明确的方式,立足版本化源代码进行构建的能力。理想情况下,我们甚至并不需要记住前一个人设置的标记或者环境变更,即可顺畅部署而不致引发崩溃。
很多人会强调,这类生态工具并不在C++标准委员会的职责范围之内。这话也没错,但工具之所以不在他们的职责范围内,是因为C++标准委员会放弃了这份责任(他们只专注于C++语言的规范,而非具体实现)。当然,这跟C++语言本身的设计有关,属于遗留问题,我们也不能过多责怪。总之如今的C++已经成为一套用于统一不同实现的囊括性标准。
但相比之下,如果要说Go有哪件事做得最为正确,那就是它证明了工具非常重要。相比之下,C++就像是来自史前时代、来自linter被发明出来之前。C++没有统一的构建系统,甚至没有勉强能算统一的包管理系统,因此解析和分析起来都极其困难(这对配套工具来说很糟糕),每一次更改都会带来一场艰苦卓绝的折磨和对抗。
这两个派系之间还存在着巨大且仍在不断恶化的裂痕。老实说,我认为这种裂痕不可能很快消失。C++委员会似乎致力于(当然,这已经是很高情商的说法了)保持向下兼容性,甚至愿意为此不计成本。
于是配置文件机制就成了现在这个样子:安全配置文件的意义并不在于帮助已经迈向现代、精通开发技术的C++企业解决问题,它们的目标是在实现改进的同时,保证无需对旧有代码做出任何更改。
模块机制也是如此,开发者应该可以“仅”将header文件作为模块导入,且不致因此引发任何类型的向下兼容性问题。
当然,人人都希望那种可以直接插入即生效,且无需对旧有代码做出任何更改的功能。但很明显,这些功能的设计(也是最重要的特征)是以“遗留C++代码”为目标的。而任何需要对遗留C++进行功能迁移的演进在C++委员会都完全行不通,毕竟正如Herb Sutter所说,绝对不能指望人们愿意承担这份迁移负担。
这就是我在查阅C++讨论资料时最鲜明的印象:阵营中分为两大派系,一派是现代C++,另一派则是遗留C++。两大派系之间存在着激烈分歧,而许多文章都只针对其中某一特定群体的需求撰写而成。
C++委员会正试图防止这种分歧进一步扩大。可能也正因为如此,Sean Baxter在Safe C++方向上做出的任何尝试都注定徒劳无功。这将是一波颠覆性的变革,可能会创造一种全新的C++编写方式,可惜变不得。
当然,这里还有另外一个问题,就是可能某位C++标准委员会成员特别特别固执,不接受任何贡献者在发展取向上的异见。
我绝不是要指责任何人,但我曾经多次听说C++委员会搞双重标准,比如“如果您希望该提案获得批准,希望您能在几款工作编译器上进行全面、有效的实现,但我们仍乐于支持某些未经有效概念验证的大型项目(例如模块和配置文件机制)。”
如果情况继续发展下去,那么我严重怀疑C++阵营的彻底分裂恐怕就在眼前。
而这一切,甚至还没算上破坏ABI兼容性所导致的诸多麻烦和问题。
如果大家对此持怀疑态度,也可以将其理解为对于Rust“全生命周期注释”和Sean Baxter“Safe C++”提案的明确否定。哪怕更乐观地看,这也至少代表着该委员会根本不关心对现有代码的重构需求。 ︎\\"“你不会为自己不用的东西付费。”本质上,现有C++功能只在我们积极使用时才会影响到运行时性能。而这显然跟稳定的ABI有所抵触,毕竟稳定ABI(大家可以将其理解为C++中的一项特性)会排除某些性能改进措施。 我认为Carbon比大多数人印象中要有趣得多。后续我可能会撰写一篇专门的讨论文章。 那么C++阵营真的在分崩离析吗?这要看从哪个角度理解。如果从C++代码存续的角度看,那么并不会,至少原有的C++成果还将长期存在。 请注意,我说的是C++阵营本身,与之对应的各种不同编译器以及编译扩展完全是另一个概念。
该帖子在Reddit社区中引发了诸多讨论。ID名为ravixp的Reddit用户对上述观点表示认同。
“这段话引发了我的强烈共鸣,原因是我曾亲眼见证了一个庞大的 C++ 代码库,在历经数十年的开发过程中,如何从“传统”逐步过渡到“现代”C++。这一转型并非一蹴而就,而是由不同团队在不同时间和以不同速度独立决定的,至今仍在持续进行中。任何新的代码现代化计划都不得不面对这样一个现实:代码库中的各个部分起始的现代化水平参差不齐。 (试想,在一个同时充斥着 std::string、C 风格字符串以及源自 20 年前、因当时 STL 尚不完善而自创的字符串类型的代码库中,引入静态分析将是一项多么艰巨的任务!) 然而,现代化的代价高昂。这里所指的现代 C++,并不仅仅是编写方式上的差异,它还意味着可能需要重建整个工具链上层结构,以使代码符合现代标准,并拥有一支能够紧跟 C++ 发展步伐的工程团队。 重要的是要认识到,这里的冲突并非源于对传统 C++ 与现代 C++ 的个人偏好之争,而是关乎能否承担得起现代 C++ 转型的成本。C++ 确实需要变革,但真正的挑战在于我们共同能够承受多大的变革,以及如何在有限的投入中获得最大的价值回报。”
ID名为KittensInc 的Reddit用户解释了美国禁止C++的合理性,因为美国政府认为C++代码库正成为负担,他们倡导避免重蹈覆辙以减少错误。缓冲区溢出等问题的预防变得重要,导致企业要求第三方审计以确保代码质量。企业面临现代化改造的抉择,否则可能面临倒闭风险,而采用现代开发实践的企业能更轻松应对。
“我并不惊讶于未来几年这种动态可能会发生变化。遗留的 C++ 代码库正迅速成为一项沉重的负担。美国政府已经认识到,通过采取不同的设计决策可以有效避免一类错误的发生,并正在积极倡导避免重蹈覆辙。我认为,相关责任人只是时间问题,他们终将跟上这一变革的步伐。 如果我们认为缓冲区溢出等问题是完全可以预防的,那么当这类问题成为安全事件的根源时,黑客攻击、勒索软件、数据泄露的保险拒赔也将变得合乎逻辑。在这种背景下,企业会愈发要求软件供应商提供第三方代码库的 linting 审计,以确保代码质量。 我们已经到了一个十字路口,不进行现代化改造的代价将变得无法承受。对于代码库而言,要么进行现代化改造以适应新时代的需求,要么面临公司倒闭的风险。那些采用现代开发实践的企业,只需借助一些简单的分析工具并完成必要的文档填写,就能轻松应对;而那些缺乏有效工具、且技术债务在代码库中不断累积的企业,将面临严重的困境。”
但也有人认为,C++代码库的安全性不取决于其现代或遗留属性。90年代C++库注重安全性并多用运行时检查,而现代C++则减少运行时检查,将更多内容纳入类型系统,未定义行为用于优化。
“安全性的实现与 C++ 代码库是现代还是“遗留”并无直接关联。事实上,在 90 年代,流行的 C++ 库在开发时普遍注重安全性,并广泛采用了运行时检查来确保代码的正确执行。在当时,未定义行为并非被视为编译器可以对代码做出严格假设并执行激进优化的手段,而是被视为一种在不同平台和实现之间实现灵活性的合理方式。 然而,进入 21 世纪初期,“现代”C++ 的发展方向发生了转变,决定减少运行时检查,并尝试将所有内容纳入类型系统中。对于那些无法通过静态验证的内容,它们被归类为未定义行为,编译器则可以根据优化需求进行自由处理。”
原文链接:
https://herecomesthemoon.net/2024/11/two-factions-of-cpp/\\"
","description":"关于C++的未来该向何处去,似乎有着很多争论甚至是激烈对抗。无论是Reddit上的小打小闹,还是官方C++标准委员会中的严肃讨论,都免不了要陷入立场之争、派系之争。这已经成为无法回避的客观现实。 C++的当前处境\\n\\n就目前来看,C++阵营处于如下状态:C++的演进工作组(EWG)刚刚就采用P3466 R0达成共识——即应当重新确认未来C++演进的设计原则:\\n\\n \\n\\n这意味着拒绝ABI破坏,保留与C以及此前C++的链接兼容性。这也意味着拒绝“病毒注释”(例如不设全生命周期注释)。这大大强调了对一系列不兼容目标的处置,即拒绝ABI破坏以及零开销原则。无论是好是坏…","guid":"https://www.infoq.cn/article/GapgFiqC6wtHq5IVtNP9","author":"Mond","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-11-26T02:14:31.852Z","media":[{"url":"https://static001.geekbang.org/infoq/14/147806e4178c1c2e68b776c75d496c5e.png","type":"photo","width":553,"height":1,"blurhash":"L00000fQfQfQfQfQfQfQfQfQfQfQ"}],"categories":["编程语言"],"attachments":null,"extra":null,"language":null},{"title":"ISO C++主席Herb Sutter离开微软,并宣布即将发布的C++ 26是自C++11以来最具影响力的版本","url":"https://www.infoq.cn/article/UANAqN0h8MCfwHJiyVUC","content":"本文最初发布于DEVCLASS。
国际标准化组织C++委员会主席Herb Sutter离开工作了22年的微软,前往Citadel Securities担任技术研究员,负责技术战略和培训工作。他将继续担任ISO委员会主席。他说,2024年是该语言的 “关键之年”。
在9月份举行的CppCon大会上\\",Sutter说:“C++ 26标准......很可能会改变我们开发软件的方式”,这是自C++ 11以来该语言的最大变革。顾名思义,C++ 26规范将于2026年年中完成。不过,在Clang和GCC等编译器中实现的特性会逐步推出;有一些已经提供了。
Sutter确认了C++ 26中的4个主要特性。他说,这些特性 “看上去正在按计划进行”。
ISO C++主席Herb Sutter在Cppcon大会上演讲
这4个特性是:
改进std:execution(异步操作标准库),提高并发性和并行性改进类型和内存安全性,目的是与其他更安全的现代语言看齐反射和代码生成,被Sutter称为 “编译时编程这一重大变革的一部分”,\\"可以说是有史以来最具影响力的新增特性契约(Contract),用于对接口做详细说明,以便进行一致性检查,包括前置条件、后置条件和有效状态断言
安全是C++社区的一个大问题。许多安全专家都建议开发人员改用Rust等语言,从而避免出现与内存使用越界和未定义行为等相关的Bug和问题。Sutter在CppCon大会上表示,安全对等并不意味着完美,但 “容易处理的优先目标 ”将得到解决,包括在标准中加入更多安全库、删除与安全相关的未定义行为、新的编译时静态安全规则和动态安全检查。
在2024年11月11日发表的一篇博文\\"中,Sutter写道,上一个里程碑版本C++ 11引入了现代 C++的概念,提供了auto、lambdas和安全智能指针等特性。C++ 26的主要特点是: 默认情况下的安全性,以及对基于反射的生成式编译时库的一等支持。
Sutter对这门语言的热情极富感染力。“有了反射/生成,一切皆有可能!我迫不及待地想看到完整的标准化和编译器实现了!\\"一位开发人员这样评价道。
但也有人对此持谨慎态度,他们担心这门语言会变得更加复杂。一位开发者说,“整个语言变得如此复杂。Cppfront这样的工作是有用,但我们需要一种受C++启发的新编程语言,完全摆脱了C++的困境。”他还补充说,“不,不是Rust。“Cppfront\\"是Sutter为验证新概念而创建的一个实验性编译器。
由于需要与遗留代码兼容,增加语言特性总是比删除语言特性更容易。
Sutter曾在微软公司从事Visual C++的开发工作。在微软内部,该工具被广泛用于Windows和Office等关键应用程序的开发。考虑到Sutter在ISO委员会中的角色,让人颇为奇怪的是,Visual C++在实现C++新特性方面往往比Clang和GCC慢。
近年来,出于安全性和可靠性的考虑,微软内部的一些知名人士主张转向 Rust,其中包括Azure首席技术官Mark Russinovich\\"。
声明:本文为InfoQ翻译,未经许可禁止转载。
","description":"本文最初发布于DEVCLASS。 国际标准化组织C++委员会主席Herb Sutter离开工作了22年的微软,前往Citadel Securities担任技术研究员,负责技术战略和培训工作。他将继续担任ISO委员会主席。他说,2024年是该语言的 “关键之年”。\\n\\n \\n\\n在9月份举行的CppCon大会上\\",Sutter说:“C++ 26标准......很可能会改变我们开发软件的方式”,这是自C++ 11以来该语言的最大变革。顾名思义,C++ 26规范将于2026年年中完成。不过,在Clang和GCC等编译器中实现的特性会逐步推出;有一些已经提供了。\\n\\n \\n\\nSutter确…","guid":"https://www.infoq.cn/article/UANAqN0h8MCfwHJiyVUC","author":"Tim Anderson","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-11-25T07:27:21.340Z","media":[{"url":"https://static001.geekbang.org/infoq/bf/bf72cd8c7b4943475e87c1a879b2c45a.png","type":"photo","width":768,"height":384,"blurhash":"LoDd6MWAIUog.AWAM{j[x_bGWBay"},{"url":"https://static001.geekbang.org/infoq/6b/6b918050ee8366c013d5c4c73730d2c1.jpeg","type":"photo","width":953,"height":1024,"blurhash":"L%FrueWC-@j^tAayR+ayWGa_Rjj?"}],"categories":["编程语言"],"attachments":null,"extra":null,"language":null},{"title":"openEuler Summit 2024:融合产业智慧,共创开源生态新格局","url":"https://www.infoq.cn/article/ZCfH1UEz8rCckcDjiz3A","content":"
近日,openEuler Summit 2024在北京中关村国际创新中心圆满落幕。本次大会由开放原子开源基金会(以下简称“基金会”)孵化及运营的 openEuler社区协同产业伙伴共同主办,以“以智能,致世界”为主题,旨在汇聚全球产业界力量,推动基础软件根技术持续创新,共建全球开源新生态。
openEuler委员会主席江大勇在致辞中表示,开源5年openEuler系操作系统累计装机量超过1000万套,树立了操作系统产业新的里程碑。openEuler商业发展的成功,离不开以社区为主导的健康运作模式。第一,坚持技术创新是openEuler立足的根本,openEuler 持续专注内核创新,累计发布了 588 个软件仓库,覆盖服务器、云计算、边缘计算和嵌入式场景;第二,坚持共建、共治、共享,充分发挥开源社区优势,2024年openEuler 新增9个捐赠人,现有捐赠单位22家,未来将在技术创新、代码贡献、产品开发、国际合作等方面深入贡献;第三,openEuler致力于构建国际化的开源协作平台,联合伙伴发展全球生态,开扩更广泛的产业空间。
openEuler委员会主席江大勇
开放原子开源基金会TOC副主席、openEuler委员会执行总监熊伟表示,开源5年以来,openEuler社区已吸引2万多名社区贡献者,1800多家单位成员加入社区,贡献社区,全球下载量突破360万。openEuler共推出3个LTS版本和7个创新版本,完成194600多次代码合入请求,累计产生20亿行代码,450万次Review。在全球化方面,openEuler社区已与10多个海外头部开源基金会开展技术合作,共建全球开源安全、可信规范标准,为150多个国家和地区提供服务。面向未来,openEuler将沿着智能化、可持续和全球化三个方向持续努力,共建数智基础设施首选开源操作系统。
开放原子开源基金会TOC副主席、openEuler委员会执行总监熊伟
智能化时代,需要更智能、更友好、更持续的操作系统。openEuler将沿着内核关键技术突破,南向使能通用算力、智能算力、异构算力的融合,提升多样算力使用效率,北向提升基于负载感知的加速能力,助力更稳定的模型训练和更高的推理应用性能。
会上,openEuler 技术委员会主席胡欣蔚预告,继2024年发布基于6.6内核的24.03LTS版本和24.09的创新版本之后,预计2025年3月份openEuler还将发布25.03创新版本,全面增强AI能力,持续使能全场景应用。在服务器场景,通过编译系统优化和自适应NUMA亲和技术进一步提升了性能。在云计算场景,提升云基础设施的资源利用率、增强抗干扰和安全能力。对于嵌入式场景,推出预装openEuler操作系统的鸿欧派开发板,为开发者提供低成本、全功能的解决方案。在AI领域,通过CPU+GPU协同推理和框架调度优化,提升了AI推理速度。
开发者基于openEuler打造AI编程工具、大会海报生成应用的故事,展示了为匹配AI时代快速发展,openEuler基础设施通过上游软件实时监测、软件包自动化升级、智能Review等能力,提升社区开发者协作及软件包维护效率。现场用真实、生动的场景展示了openEuler智能计算领域软件包的丰富应用,支持CPU、GPU、NPU等多种算力及AI加速库,可高效支撑AI开发者完成全场景应用开发,也意味着openEuler具备了OS for AI的软硬件生态和易用性。
openEuler社区始终坚持共建、共治、共享的原则,充分发挥开源社区这种创新模式的优势,汇聚产业创新力量,促进生态繁荣发展。openEuler社区的运营与发展离不开社区伙伴、用户的协作与创新,在伙伴们的持续努力下,已经持续迭代发布多个商业版本。
8家伙伴基于openEuler 24.03 LTS发布商业发行版
2024年6月6日,openEuler 24.03 LTS版本全球发布,该版凝聚国内外10多家芯片厂商,20多家操作系统厂商,100多家行业头部软件供应商和5136名社区贡献者,是社区里程碑式版本。本次会上,麒麟软件、麒麟信安、统信软件、超聚变、润和软件、软通动力、凝思软件、中科方德领先发布基于openEuler 24.03 LTS的商业发行版。openEuler24.03 LTS版本汇聚了产业链上下游软硬件厂商技术共识,集合众多开发者的智慧,将成为未来几年中国IT基础设施的坚实基础。
9家单位参与openEuler项目群创新项目贡献签约仪式
自2022年openEuler成立项目群后,各行业领域头部企业、高校、科研院所等的创新项目开始不断加入,openEuler项目群的子项目数量持续赠加,社区涵盖的行业也日趋多样化。会上,天翼云、联通数科、华为、麒麟信安、金蝶天燕、中科院软件所、北京大学与北京大学长沙计算与数字经济研究院、同济大学、厦门大学的9家单位的12个项目与openEuler项目群签订贡献意向。来自不同行业和领域的项目为openEuler注入产业各界的创新力量,进一步增强社区技术创新能力,促进社区生态繁荣。
openEuler致力于打造国际化开源协助平台,与国际主流基金会深度合作,已支持全球98%的主流开源软件。当前openEuler已打通与Linux、OpenInfra、Apache、CNCF、Intel、openHPC 等的技术合作支持 ,覆盖主流应用场景;openEuler社区与OpenChain、OpenSSF、SPDX 等三家达成深度合作,共筑开源软件供应链安全;同时,在开放原子开源基金会的支持下,携手OpenChain、CHAOSS 共建全球可信开源社区规范。目前,openEuler与英特尔持续加强合作,共同加速AI创新与应用进程,推动操作系统生态繁荣发展。同时,openEuler与国际主流软件供应链安全组织共建开源安全标准,和源译识翻译社区联合翻译并发布SPDX3.0中文版,与中金金融认证中心(CFCA)联合发布安全启动代码签名服务平台。
10家组织和单位共同发起全球可持续发展倡议
可持续是openEuler发展的关键。openEuler作为操作系统领域基础软件支撑着关键基础设施的安全稳定运行,如何保障系统自身及运行于系统上数据全生命周期的安全至关重要,需要标准组织、安全评估机构、合作伙伴和客户共同助力社区可持续化发展。会上,openEuler社区与DEKRA、Bureau Veritas 、移动云、天翼云、联通云、中金金融认证中心有限公司(CFCA)、SPDX、全球计算联盟(GCC)、电信终端产业协会(TAF)共同发起《openEuler全球可持续化发展倡议》,倡议表示“持续增强社区安全治理,通过安全技术创新,保障数据/模型安全,融入上游社区漏洞处理生态,运维更可靠”。
社区的繁荣离不开伙伴的持续创新与发展,openEuler自开源以来已经在千行百业积累了众多商业成果及经验。会上,光大银行携手麒麟软件带来在金融行业的实践成果,南京南瑞继保工程技术有限公司携手麒麟信安带来在电力系统中的创新实践,辽宁移动联合超聚变带来在运营商行业的实践分享、统信软件分享了亲身实践的行业应用案例。
子项目是openEuler社区发展的推动力,开发者是社区可持续发展的发动机。会上,openEuler社区评选出20个“openEuler 2024年度社区项目之星”和28名openEuler 2024年度贡献之星。
未来,openEuler社区将继续秉持“共建、共治、共享”的理念,通过与伙伴和全球开发者共同努力,推动基础软件技术的持续创新和应用,构建一个更加开放、多元的全球开源社区。
","description":"近日,openEuler Summit 2024在北京中关村国际创新中心圆满落幕。本次大会由开放原子开源基金会(以下简称“基金会”)孵化及运营的 openEuler社区协同产业伙伴共同主办,以“以智能,致世界”为主题,旨在汇聚全球产业界力量,推动基础软件根技术持续创新,共建全球开源新生态。 openEuler委员会主席江大勇在致辞中表示,开源5年openEuler系操作系统累计装机量超过1000万套,树立了操作系统产业新的里程碑。openEuler商业发展的成功,离不开以社区为主导的健康运作模式。第一,坚持技术创新是openEuler立足的根本…","guid":"https://www.infoq.cn/article/ZCfH1UEz8rCckcDjiz3A","author":"李冬梅","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-11-25T07:03:28.895Z","media":[{"url":"https://static001.geekbang.org/infoq/df/dff3b6e4bd4dc8d7a72fb68738b799f2.png","type":"photo","width":1080,"height":720,"blurhash":"LYDJcBRo03t74Vt5?tM}%2a$M_oe"},{"url":"https://static001.geekbang.org/infoq/81/81a5be40911d61121b58577bbc300c1f.png","type":"photo","width":1080,"height":720,"blurhash":"LfEM9eNHW;t9-@aebFoeNZofoLbE"},{"url":"https://static001.geekbang.org/infoq/c6/c64951f7cfc1026fff263cad734769e8.png","type":"photo","width":1080,"height":720,"blurhash":"LU9HMgR?MuoMIUoft1WBM@j:tAWU"},{"url":"https://static001.geekbang.org/infoq/c2/c26514bba679dd872ef106bdc1743179.png","type":"photo","width":1080,"height":720,"blurhash":"LU9j~tRhRiaitWW9WAj^Dit6oboh"},{"url":"https://static001.geekbang.org/infoq/39/3912c2afbfb0a512b15a5d6c9bed9264.png","type":"photo","width":1080,"height":720,"blurhash":"LNCG]WxxRht94YR;oaWCoXk9j^aw"},{"url":"https://static001.geekbang.org/infoq/35/35a96eebdbb61ea0e70f091c6d92e1ea.png","type":"photo","width":1080,"height":720,"blurhash":"LNEe.DjZNHt6MHofWqf5-Uofogjb"},{"url":"https://static001.geekbang.org/infoq/70/70c261f51115d83c8d74718e0902e17d.png","type":"photo","width":1080,"height":720,"blurhash":"L9CF@lS5Ipt7QkW=R+WBL}NGt7Rj"}],"categories":["操作系统"],"attachments":null,"extra":null,"language":null},{"title":"Greenplum原班人马的“换皮”数据库加入Apache孵化器","url":"https://www.infoq.cn/article/VkG20Wywf2HV3yDIQZgV","content":"11月20日,Apache Cloudberry 正式发布公告宣布已进入 Apache 软件基金会孵化器项目。
2024年10月12日,Cloudberry 数据库项目经社区投票通过,加入了 Apache 软件基金会的孵化器。随后,项目的代码库于2024年11月5日成功迁移至 Apache。至此,Cloudberry 正式成为 Apache 的一员,并在 Apache 的支持下开始开发,该开源项目遵循 Apache License 2.0 协议。
Apache Cloudberry是由Greenplum数据库初始开发团队打造的一套开源大规模并行处理(MPP)数据库。它源自 Pivotal Greenplum 数据库的开源版本,但采用了更新的 PostgreSQL 内核,并提供更多高级企业功能。同时,Cloudberry 也被定位为“用于分析和 AI/ML 工作负载的高级开源 MPP 数据库”。
Greenplum数据库一直广受各行各业、不同规模团队的广泛采用和普遍好评。根据DB-Engines网站,其被列为Top50热门数据库之一。然而,随着开源Greenplum数据库的归档及其社区的彻底关闭,原始开源Greenplum用户已无法免费获取任何安全或者功能更新,这无疑对其业务带来了潜在挑战。
因此,该开发团队宣称他们希望让Cloudberry成为原始Greenplum开源版本的首选开源替代方案,也希望全体开源开发者和Greenplum用户都能迁移至Cloudberry中来。
今年5月,在没有任何公告的情况下,知名开源大规模并行处理(MPP)数据库 Greenplum 突然“404”无法访问。Greenplum 的源码仓库(https://github.com/greenplum-db/gpdb\\")也被修改为“只读”状态,且原有的分支(branch)、标签(tag)、拉取请求(PR)以及问题(issue)等信息均已被清空。
回顾Greenplum的发展,这个数据库的所有权可谓一波三折,在开源与闭源之间反复转换,最终在2024年5月定格为闭源状态。
Greenplum数据库的历史可以追溯到2003年,它最初是由Greenplum公司基于大规模并行处理(MPP)架构和PostgreSQL技术开发而成。
2010年,Greenplum公司被EMC集团收购。
2012年,EMC和VMware(EMC旗下子公司)将双方多项软件资产(包括Greenplum数据库)合并至一家名为Pivotal Software的新公司。
2015年,Pivotal开源了Greenplum核心引擎,并将其更名为Pivotal Greenplum数据库,成为首款开源MPP数据仓库。Pivotal Greenplum数据库的开源核心被用于支撑Apache HAWQ和Apache MADlib等项目,而Greenplum本体则仍属于单一供应商拥有的开源项目。
2019年,VMware收购了Pivotal Software。此番收购也让Pivotal Greenplum数据库归VMware所有。VMware继续支持Greenplum数据库的后续开发及其开源社区,并在随后几年中发布了商业产品VMware Tanzu Greenplum。
2023年11月,博通完成了对VMware的收购,Greenplum由此归博通公司所有。
2024年5月,几乎所有Greenplum的GitHub代码仓库均被归档且转为只读,Slack工作区被删除(https://greenplum.slack.com\\"),user和dev社区的电子邮件列表也陷入沉寂。所有这一切,均由博通公司在未作任何公告的情况下完成。
Greenplum 回归闭源\\"引起了社区用户、开发人员以及生态系统合作伙伴的担忧。
首先对于现有的 Greenplum 社区用户来说,无法继续获得更新、升级和安全支持成为主要问题。用户需要自行解决技术难题,或支付高额费用购买博通的商业服务。这不仅增加了技术团队的压力,也大幅提高了运维成本。
其次可能改变当前国内数据仓库市场的竞争格局。许多基于 Greenplum 的衍生版本或云服务提供商,如果团队自身没有良好的技术储备,较大依赖上游,将在后续竞争中逐渐退出,具备真正技术实力的团队会获得更多机会并加强地位。
同时,Greenplum 拥有许多重量级的头部用户,以及较高的市场渗透率,其上下游生态系统也难以避免波动。一些开发者可能会转向其他数据仓库项目,相关服务商也会寻找新的合作伙伴。大多数 Greenplum 衍生产品都跟随 Greenplum 上游代码的变化,归档意味着引用 Greenplum 代码不那么容易了。
由于项目归单一供应商控制,Greenplum始终缺乏允许社区参与决策流程的开放治理模式。Cloudberry认为,Greenplum数据库在漫长的演进过程中已经失去了创新和对主要功能加以更新的能力。必须承认,与新一代开源数据仓库和分析项目相比,Greenplum的竞争力已经愈发有限。
Cloudberry由初始Greenplum开发团队于2022年推出,其源代码于2023年开放。随着Greenplum突然转向闭源模式,Cloudberry重新拉拢了最初的开源Greenplum开发人员和用户,以开源社区的形式塑造该项目。
众所周知,Greenplum 在 OLAP 和分析工作负载方面的可扩展性远超普通的 PostgreSQL。而随着 Postgres Kernel 14.4 的引入,Cloudberry 实现了重要升级,成功从 Greenplum 的 Postgres 12 内核迁移过来。
不同之处在于,Greenplum,这一几乎被每家《财富》500 强企业广泛使用的数据库,如今已被fork了。这一分支为延续并进一步提升 Greenplum 二十多年的创新成果提供了新途径。理论上,由于该项目将成为 Apache 社区的一部分,它将摆脱单一实体的控制,真正发展为一个开放的开源项目。
但Cloudberry 将坚持使用 MPP(大规模并行处理)架构,这对于大多数中小企业来说已足够。该架构通过在多个服务器或主机上分配数据和计算工作负载,来高效存储和处理大量数据。
从用户角度看,Cloudberry Database 是一个完整的关系型数据库管理系统(RDBMS),物理上包含多个 PostgreSQL 实例,为了使这些独立的 PostgreSQL 实例协同工作,Cloudberry Database 在数据存储、计算、通信和管理等各个层面进行分布式集群处理。同时也隐藏了分布式系统的复杂细节,只提供单一的逻辑数据库视图。
Cloudberry声称该数据库不仅仅是Greenplum的换皮产物,还具有一系列高级功能和新增亮点,增强的安全性、端到端性能优化、支持AI/机器学习工作负载和流式传输、Lakehouse智能湖仓集成等。
参考链接:
https://cloudberry.apache.org/blog/cloudberry-database-enters-the-apache-incubator/\\"
https://cloudberry.apache.org/docs/cbdb-vs-gp-features\\"
https://mp.weixin.qq.com/s/2KTPPv0-D3Mtd77v-lY0iw\\"
https://www.reddit.com/r/PostgreSQL/comments/1gqis0b/announcing_apache_cloudberry_sql_at_scale/\\"
","description":"11月20日,Apache Cloudberry 正式发布公告宣布已进入 Apache 软件基金会孵化器项目。 \\n\\n2024年10月12日,Cloudberry 数据库项目经社区投票通过,加入了 Apache 软件基金会的孵化器。随后,项目的代码库于2024年11月5日成功迁移至 Apache。至此,Cloudberry 正式成为 Apache 的一员,并在 Apache 的支持下开始开发,该开源项目遵循 Apache License 2.0 协议。\\n\\n \\n\\nApache Cloudberry是由Greenplum数据库初始开发团队打造的一套开源大规模并行处理…","guid":"https://www.infoq.cn/article/VkG20Wywf2HV3yDIQZgV","author":"Tina","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-11-25T06:28:45.057Z","media":[{"url":"https://static001.geekbang.org/infoq/b1/b1622c37927574be2039e28a98f636ba.jpeg","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/0e/0e6df165b1207343a147e412ff0907e8.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/2c/2c14088aa36bca4e52cd70f828e9f93b.jpeg","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/a5/a5fd5ac993c4b73aa5156dc8e73d8a6b.jpeg","type":"photo","width":0,"height":0,"blurhash":""}],"categories":["数据库"],"attachments":null,"extra":null,"language":null},{"title":"OpenJDK近期新闻:实例主方法、灵活的构造函数体、模块导入声明","url":"https://www.infoq.cn/article/85uvfSS8YssNx6MVeDpj","content":"
2024 年 11 月 4 日这一周 OpenJDK 生态系统的活动重点如下:五个 JEP 成功完成各自的评审流程,已确定在 JDK 24 中发布;五个新的 JEP 进入 Proposed to Target 状态,目标版本为 JDK 24,并在 2024 年 11 月 11 日这一周接受评审;另外,还有两个 JEP 草案已进入 Candidate 状态。
JEP 493(不使用 JMOD 链接运行时镜像\\")已从 “Proposed to Target” 进入\\"到“Targeted” 状态,目标版本为 JDK 24。这一 JEP 提议允许 工具在不使用 JDK 的 JMOD\\" 文件的情况下创建自定义运行时镜像,从而将 JDK 大小减少约 25%。这个特性在构建 JDK 时需要显式启用。开发者现在可以从本地模块链接运行时镜像,不受模块位置的限制。
JEP 491(同步虚拟线程而不固定\\")已从 “Proposed to Target” 进入\\"到 “Targeted” 状态,目标版本为 JDK 24。该 JEP 提议允许在同步方法和语句中阻塞的虚拟线程释放其占用的底层平台线程,以便其他虚拟线程能够使用这些线程,从而提高 Java 代码的可扩展性。其目的是解决“几乎所有虚拟线程都绑定在特定平台线程上的问题,这一限制严重影响了虚拟线程处理应用工作负载的能力。”
JEP 488(模式、instanceof 和 switch 中的原始类型(第二次预览)\\",已从 “Proposed to Target” 进入\\"到 “Targeted” 状态,目标版本为 JDK 24。该 JEP 来自 Amber Project\\",在经过第一次预览(JEP 455(模式、instanceof 和 switch 中的原始类型(预览)\\")后,再次进行预览以获得更多反馈。该特性增强了模式匹配,允许在所有模式上下文中使用原始类型模式,并扩展了 instanceof 和 switch ,可以支持所有原始类型。更多细节可在 Aggelos Biboudis\\" 的规范草案\\"中找到。
JEP 486(永久禁用安全管理器\\")已从 “Proposed to Target” 进入\\"到 “Targeted” 状态,目标版本为 JDK 24。该 JEP 提议永久禁用 SecurityManager\\" 类,因其已在 JEP 411(弃用安全管理器\\")中被弃用(JDK 17 )。尽管开发者在弃用后仍可启用 SecurityManager,但该特性将在未来被彻底移除。
JEP 450(紧凑对象头(实验)\\")已从 “Proposed to Target” 进入\\"到 “Targeted” 状态,目标版本为 JDK 24。该 JEP 受 Lilliput Project\\" 的启发,提议在 64 位架构上将 HotSpot JVM 中的对象头大小从 96 位至128 位缩减到 64 位。由于该特性是实验性质的,因此默认情况下是禁用的,启用后可能会引发意外后果。
JEP 495(简化的源文件和实例主方法(第四次预览)\\")已从 “Candidate” 进入\\"到 “Proposed to Target” 状态,目标版本为 JDK 24。这一 JEP 提议在之前三轮预览之后进行第四次预览(除了再次更名外未做变更),前三轮预览分别为 JEP 477(隐式声明类和实例主方法(第三次预览)\\")、JEP 463(隐式声明类和实例主方法(第二次预览)\\")和 JEP 445(未命名类和实例主方法(预览)\\")。该特性旨在“让学生可以在不需要理解为大型程序设计的语言特性的情况下编写第一个程序”。更多详情请参阅 Java 语言架构师 Brian Goetz\\" 的博文 Paving the on-ramp\\"。Java 社区成员 Gavin Bierman\\" 已发布\\"首份规范草案\\"供社区评审。评审预计将在 2024 年 11 月 13 日结束。
JEP 494(模块导入声明(第二次预览)\\")已从 “Candidate” 进入\\"到 “Proposed to Target” 状态,目标版本为 JDK 24。这一 JEP 提议在第一次预览之后进行第二次预览,即 JEP 476(模块导入声明(预览)\\")。这个特性将增强Java编程语言的能力,能够简洁地导入一个模块导出的所有包,目标是简化模块库的重用,无需将代码直接导入到模块本身。与第一次预览相比的变化包括:取消了模块不允许声明对java.base模块传递依赖的限制;更新java.se模块的声明,使其传递性地依赖java.base模块;允许按需声明的类型导入覆盖模块导入声明。这些变化意味着导入java.se模块将能够按需导入整个Java SE API。预计评审将在 2024 年 11 月 13 日结束。
JEP 492(灵活的构造方法体(第三次预览)\\")已从 “Candidate” 进入\\"到 “Proposed to Target” 状态,目标版本为 JDK 24。该 JEP 提议进行第三轮预览,仅有少量变更,以便从前两轮的预览中获得更多反馈,具体包括:在 JDK 23 中发布的 JEP 482(灵活的构造方法体(第二次预览)\\")和在 JDK 22 中发布的 JEP 447(super() 的前置语句(预览)\\")。该特性允许在构造方法中调用 或 之前插入不引用正在被创建的对象实例的语句,同时保持现有构造方法安全性和初始化保证。该 JEP 的变更包括:处理局部类,并放宽“字段在显式构造方法调用之前不可访问”的限制,调整为“字段在显式构造方法调用之前不可读取”。Oracle 技术顾问 Gavin Bierman 已提供了初始规范\\",供 Java 社区评审和反馈。该审查预计将于 2024 年 11 月 14 日结束。
JEP 483(预加载和链接类\\")已从 “Candidate” 进入\\"到 “Proposed to Target” 状态,目标版本为 JDK 24。该 JEP 提议在 HotSpot Java 虚拟机启动时立即提供应用程序所需的已加载和已链接类来“提高启动速度”。实现这一目标的方法是在应用程序运行期间监控类加载和链接,并将这些信息存储在缓存中,以便后续运行时使用。该特性将为未来改进启动和预热速度打好基础。评审预计将于 2024 年 11 月 14 日结束。
JEP 479(移除对 Windows 32 位 x86 架构的支持\\")已从 “Candidate” 进入\\"到 “Proposed to Target” 状态,目标版本为 JDK 24。该 JEP 提议在 JEP 449(放弃支持 Windows 32 位 x86 架构\\")(JDK 21)之后,完全移除对 Windows 32 位 x86 架构的支持。其目标是:移除所有仅支持 Windows 32 位平台的代码路径;停止所有针对 Windows 32 位平台的测试和开发工作;并简化 OpenJDK 的构建和测试基础设施,与现代计算标准保持一致。评审预计将于 2024 年 11 月 12 日结束。
JEP 497(基于模格的抗量子数字签名算法\\")已从 JEP Draft 8339010 进入\\"到 “Candidate” 状态。该 JEP 提议“通过提供基于模格的抗量子数字签名算法\\"(ML-DSA)实现”来增强 Java 应用程序的安全性。该算法已由 FIPS 204\\" 标准化。这将通过实现 Java 的 KeyPairGenerator\\"、Signature\\" 和 KeyFactory\\" 类来实现。
JEP 496(基于模格的抗量子密钥封装机制\\",已从 JEP Draft 8339009 进入\\"到 “Candidate” 状态。该 JEP 提议“通过提供基于模格的抗量子密钥封装机制\\"(ML-KEM)实现”来增强 Java 应用程序的安全性。该机制已由 FIPS 203\\" 标准化。这将通过实现 Java 的 KeyPairGenerator\\"、KEM\\" 和 KeyFactory\\" 类来实现。
Oracle Java 平台首席架构师 Mark Reinhold 批准的\\" JDK 24 发布计划如下:
Rampdown Phase One(从主线分叉):2024 年 12 月 5 日Rampdown Phase Two:2025 年 1 月 16 日初始发布候选版本:2025 年 2 月 6 日最终发布候选版本:2025 年 2 月 20 日正式发布:2025 年 3 月 18 日
在距离 JDK 24 Rampdown Phase One(特性集将被冻结)还有一个多月的时间里,目前已纳入特性集的 JEP 共计 19 个(包括 Proposed to Target):
JEP 404: 分代 Shenandoah (实验)\\"JEP 450: 紧凑对象头 (实验)\\"JEP 472: 准备限制 JNI 的使用\\"JEP 475: G1 延迟屏障扩展\\"JEP 478: 密钥派生函数 API (预览)\\"JEP 479: 移除对 Windows 32 位 x86架构的支持\\"JEP 483: 预加载和链接类\\"JEP 484: 类文件 API\\"JEP 485: 流式收集器\\"JEP 486: 永久禁用安全管理器\\"JEP 487: 作用域值 (第四次预览)\\"JEP 488: 模式、instanceof 和 switch 中的原始类型 (第二次预览)\\"JEP 489: 向量 API (第九次孵化)\\"JEP 490: ZGC: 移除非分代模式\\"JEP 491: 同步虚拟线程而不固定\\"JEP 492: 灵活的构造函数体 (第三次预览)\\"JEP 493: 不使用 JMOD 链接运行时镜像\\"JEP 494: 模块导入声明 (第二次预览)\\"JEP 495: 简单源文件和实例主方法 (第四次预览)\\"
JDK 24 的新特性数量已经超过 JDK 16 和 JDK 11 中各自交付的 17 项特性。对于 JDK 24\\",开发者可以通过 Java Bug Database\\" 报告错误。
原文链接:
https://www.infoq.com/news/2024/11/jdk-news-roundup-nov04-2024/\\"
","description":"2024 年 11 月 4 日这一周 OpenJDK 生态系统的活动重点如下:五个 JEP 成功完成各自的评审流程,已确定在 JDK 24 中发布;五个新的 JEP 进入 Proposed to Target 状态,目标版本为 JDK 24,并在 2024 年 11 月 11 日这一周接受评审;另外,还有两个 JEP 草案已进入 Candidate 状态。 Targeted 状态的 JEP\\n\\nJEP 493(不使用 JMOD 链接运行时镜像\\")已从 “Proposed to Target” 进入\\"到“Targeted” 状态,目标版本为 JDK 24。这一…","guid":"https://www.infoq.cn/article/85uvfSS8YssNx6MVeDpj","author":"Michael Redlich","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-11-25T01:30:52.575Z","media":null,"categories":["编程语言"],"attachments":null,"extra":null,"language":null},{"title":"Kotlin HTTP Toolkit Ktor 3.0改进性能,并支持服务器发送事件","url":"https://www.infoq.cn/article/BjvzlJZLb3EE2ZLGKPzv","content":"Ktor 是一个原生的 Kotlin 框架,可用于创建异步 HTTP 服务器和客户端应用程序。Ktor 3.0 已发布。该版本采用了 kotlinx-io,虽然带来了一些破坏性更改,但性能却有所提升,并且增加了服务器发送事件、CSFR、从 ZIP 文件提供静态资源等特性。
kotlinx-io 是围绕Buffer这个抽象概念构建的底层 I/O 库。Buffer是一个可变的字节序列,它的工作方式和队列类似。也就是说,你可以向其尾部写入数据,并从其头部读取数据。Ktor 3 的破坏性变化主要影响了底层 IO API,涉及Input、Output、ByteReadChannel和ByteWriteChannel等类型。直接使用它们的开发人员需要修改他们的应用程序,迁移到新的 API。
kotlinx-io 的主要好处是提升了性能:
我们减少了 ByteReadChannel、ByteWriteChannel 与网络接口之间不必要的字节复制。这样可以提高字节转换和解析的效率,为未来的性能提升留出空间。
JetBrains 表示,根据他们自己的基准测试,Ktor 的这个新版本显著缩短了文件和套接字操作所需的时间,在某些情况下可缩短 90%。
除了性能提升之外,Ktor 3.0 最重要的变化是支持服务器发送事件。这是一种服务器推送技术,可以创建服务器到客户端的通信通道。在数据以单向流动为主的情况下,尤其是需要规避防火墙阻塞或处理连接中断时,服务器发送事件比 WebSockets 更为可取。另一方面,WebSockets 效率更高,延迟更低。
Ktor 3.0 还提供了其他一些有用的特性,包括支持跨站点请求伪造(CSRF)(可以针对任何给定的路由指定)以及直接从 ZIP 文件提供静态资源的能力。ZIP 文件从基本路径提供,可能会包括子目录,这会反映在 URL 结构中。
关于 Ktor 3,最后一点需要注意的是,Ktor 客户端现在支持将 Wasm 作为构建目标。不过,Kotlin/Wasm 仍处于 Alpha 测试阶段,因此,Ktor 3 中的 Wasm 支持尚未到达生产就绪状态。
要使用 Ktor 启动一个新项目,请访问 Ktor 网站并选择最符合你需求的插件,涉及身份验证、路由、监控、序列化等。如果你想将现有的 Ktor 2 项目改为使用 Ktor 3,请务必阅读 JetBrains 提供的迁移指南。
查看原文链接:
https://www.infoq.com/news/2024/10/ktor-3-kotlin-http-server/\\"
","description":"Ktor 是一个原生的 Kotlin 框架,可用于创建异步 HTTP 服务器和客户端应用程序。Ktor 3.0 已发布。该版本采用了 kotlinx-io,虽然带来了一些破坏性更改,但性能却有所提升,并且增加了服务器发送事件、CSFR、从 ZIP 文件提供静态资源等特性。 kotlinx-io 是围绕Buffer这个抽象概念构建的底层 I/O 库。Buffer是一个可变的字节序列,它的工作方式和队列类似。也就是说,你可以向其尾部写入数据,并从其头部读取数据。Ktor 3 的破坏性变化主要影响了底层 IO API,涉及Input、Output…","guid":"https://www.infoq.cn/article/BjvzlJZLb3EE2ZLGKPzv","author":"作者:Sergio De Simone","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-11-21T00:00:06.634Z","media":null,"categories":["编程语言"],"attachments":null,"extra":null,"language":null},{"title":"Java近期新闻:Jakarta EE 11、JReleaser 1.15、JHipster 8.7.3、Quarkus3.16","url":"https://www.infoq.cn/article/KBcT4YaI5jKCCL9RFlN1","content":"OpenJDK
对于 OpenJDK 生态系统,这是繁忙的一周:有 4 个 JEP 成功完成审查,现已进入 JDK 24 的 Targeted 状态;有 5 个新的 JEP 进入 Proposed to Target 状态,并将在 2024 年 11 月 4 日这一周接受审查。要了解更多细节,请查看 InfoQ 的新闻报道。
JDK 24
JDK 24 的早期访问构建Build 22 发布,它是 Build 21 的升级,修复了各种问题。要了解关于这个构建的更多细节,请查看发布说明。
对于 JDK 24,我们鼓励开发者通过 Java Bug 数据库报告缺陷。
Jakarta EE 11
在 Hashtag Jakarta EE 每周博客中,Eclipse 基金会 Jakarta EE 开发大使 Ivar Grimstad 介绍了 Jakarta EE 11 的 最新情况:
Jakarta EE 11 Core Profile API 已准备就绪,并且已经进入 Jakarta EE 准正式库 中。规范文档已经准备就绪,并且有两个兼容的实现已经提交了 CCR(兼容认证申请)。也就是说,在仔细完成上述工作后,Jakarta EE 11 Core Profile 就将开始发布审核。按照计划,Jakarta EE 11 Platform 和 Jakarta EE 11 Web Profile 规范将在 12 月 3 日 JakartaOne Livestream 前后发布。在通往 Jakarta EE 11 的道路上,有 4 个里程碑版本需要发布,而在 2024 年第 4 季度发布 GA 版本之前,还可能根据需要发布候选版本。
GlassFish
GlassFish 8.0.0-M8 是第 8 个里程碑版本,它带来了一些显著的变化,例如:解决了 CVE-2024-9329, 这是 Glassfish 7.0.17 之前的版本中存在的一个漏洞,攻击者如果能够将/management/domain端点的值修改为恶意网站,就可以成功发起网络钓鱼欺诈并窃取用户凭据;删除使用了过时类SecurityManager的安全测试。该版本几乎包含了所有最终的 Jakarta EE 11-M4 API(Jakarta Data 除外),并与 GlassFish 7 发布序列同步。要了解有关该版本的更多细节,请查看发布说明
Spring Framework
Spring 团队披露了一个漏洞 CVE-2024-38821:WebFlux 应用程序中静态资源的授权绕过。这是 Spring Security 5.7 至 6.3 版本序列中的一个漏洞,攻击者可能会在以下情况下绕过静态资源的授权规则:应用程序必须是 WebFlux;必须使用了 Spring 静态资源支持;必须支持应用于静态资源的non-permitAll授权规则。我们鼓励开发人员升级到 Spring Security 的 6.3.4、6.2.7、6.1.11、6.0.13、5.8.15 和 5.7.13 版本。
Quarkus
红帽公司 发布了Quarkus 3.16.0 (随后发布的 3.16.1 版本包含了一个紧急修复),带来了以下特性:支持 OpenTelemetry 日志;改进 Grafana LGTM 面板;新增@AuthorizationPolicy注解,可将HttpSecurityPolicy接口的命名实例绑定到 Jakarta RESTful Web Service 规范中的端点,以替代路径匹配规则。要了解有关这些版本的更多信息,请查看 3.16.1 和 3.16.0 版本的发布说明。
Apache 软件基金会
Apache Kafka 3.8.1 发布,带来了一些 Bug 修复和一项改进,解决了在使用 Kafka Raft(KRaft)模式时委托令牌在创建后立即过期的问题。要了解有关该版本的更多信息,请查看发布说明。
为了与 Quarkus 保持一致,Camel Quarkus 3.16.0(由 Camel 4.8.1 和 Quarkus 3.16.0 组成)版本解决了一些值得注意的问题,例如:由于 Apache Camel 注解参数不能用作LangChain4jProcessor类中的模板变量而导致的TemplateException;更改@BindToRegistry注解,使其在RouteBuilder类实例之外工作,从而可以在任何地方使用它,并将生成的 bean 绑定到注册表。要了解有关该版本的更多信息,请查看发布说明。
JReleaser
JReleaser 1.15.0 版本发布(一款可简化项目发布创建过程的 Java 工具),提供了 Bug 修复、文档改进、依赖项升级以及多项新特性,例如:可配置 PomChecker strict模式,以验证pom文件中的和部分;部署器现在会在上传目标工件之前检查它们是否已被部署。要了解有关该版本的更多信息,请查看发布说明。
JHipster
JHipster 8.7.3 和 8.7.2 发布,提供的特性包括:支持 JDK 23 和 Node 22;依赖项升级到 Spring Boot 3.3.5、Angular 18.2.9 和 Vue 3.5.12;升级与该版本兼容的 8 个 JHipster blueprints;改进 Docker 支持,即在没有容器启动时禁用 Docker Compose 集成。要了解有关这些版本的更多信息,请查看 8.7.3 和 8.7.2 版本的发布说明。
MicroStream
MicroStream 宣布,他们的企业版(EclipseStore 的扩展)将以 “Open-Beta ”的形式推出。也就是说,开发人员可以暂时免费使用企业版,直到最终版本发布。在 EclipseStore 应用程序中使用企业版的好处包括:堆外位图索引(一种使用位图表示集合中是否存在特定值的技术)和 GigaMap(一种专为处理海量数据而设计的索引集合)。
OpenXava
OpenXava 7.4.2 发布,带来了许多 Bug 修复和改进,例如:在Strings类中定义了一个新的changeLast()方法,用于更改一个字符串在另外一个字符串中的最后一次出现;在ReturnPreviousModuleAction类中添加了一个新的布尔属性reinit,用于自定义返回时模块的初始化。要了解有关该版本的更多信息,请查看发布说明。
JDKUpdater
JDKUpdater 14.0.61+81 版本已于上周发布。该工具可以帮助开发人员跟踪与 OpenJDK 和 GraalVM 构建相关的更新。该工具由 Azul 首席工程师 Gerrit Grunwald 于 2024 年 3 月中旬推出,现在支持 Azul Zulu 的 CRaC 构建。要了解有关该版本的更多信息,请查看发布说明。
JDKMon
JDKMon 21.0.7 版本(一款用于监控和更新已安装的 JDK 的工具)也已于上周发布。这个新版本也是由 Grunwald 开发的,其特点是:检测支持检查点协调恢复(CRaC)的 JDK,如 Azul 和 BellSoft;升级到 Gradle 8.10.1。要了解有关该版本的更多信息,请查看发布说明。
Keycloak
Keycloak 26.0.5 发布,提供了 Bug 修复和一项新功能,即使用 Microsoft Active Directory 管理界面时会创建管理员用户并默认启用,从而避免为用户设置密码后更新用户状态。要了解有关该版本的更多信息,请查看发布说明。
Gradle
Gradle 8.11.0 的第 2 个候选版本持续更新了新特性,例如:通过选择并行加载和存储缓存条目来提高配置缓存的性能;C++ 和 Swift 插件现已兼容配置缓存;改进了错误和预警报告,其中 Java 编译错误现在会显示在构建输出的末尾。要了解有关该版本的更多信息,请查看发布说明。
原文链接:
https://www.infoq.com/news/2024/11/java-news-roundup-oct28-2024/\\"
","description":"OpenJDK 对于 OpenJDK 生态系统,这是繁忙的一周:有 4 个 JEP 成功完成审查,现已进入 JDK 24 的 Targeted 状态;有 5 个新的 JEP 进入 Proposed to Target 状态,并将在 2024 年 11 月 4 日这一周接受审查。要了解更多细节,请查看 InfoQ 的新闻报道。\\n\\nJDK 24\\n\\nJDK 24 的早期访问构建Build 22 发布,它是 Build 21 的升级,修复了各种问题。要了解关于这个构建的更多细节,请查看发布说明。\\n\\n对于 JDK 24,我们鼓励开发者通过 Java Bug 数据库报告缺陷。\\n\\nJa…","guid":"https://www.infoq.cn/article/KBcT4YaI5jKCCL9RFlN1","author":"Michael Redlich","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-11-19T03:00:56.001Z","media":null,"categories":["编程语言"],"attachments":null,"extra":null,"language":null},{"title":"PyTorch 2.5发布,支持英特尔GPU","url":"https://www.infoq.cn/article/0mI396HI4cTe19iWvWfN","content":"最近,PyTorch 基金会\\"发布了PyTorch 2.5版本\\",其中包含对英特尔GPU的支持。该版本还包含多项性能增强,如FlexAttention\\"API、TorchInductor CPU后端优化,以及可缩短编译时间的区域编译功能\\"。总体而言,该版本包含了自PyTorch 2.4以来的4095次提交。
最近举行的PyTorch大会\\"演示了PyTorch对英特尔GPU的支持。英特尔工程师Eikan Wang和Min Jean Cho介绍了PyTorch为支持该硬件而做出的改变\\",包括泛化PyTorch运行时和设备层,使其更容易与新的硬件后端集成。此外,对于torch.compile和torch.distributed,该版本实现了特定于英特尔GPU的后端。英特尔人工智能框架工程副总裁Kismat Singh表示\\":
我们在PyTorch 2.5中添加了对英特尔客户端GPU的支持。基本上,这意味着你可以在使用最新英特尔处理器的英特尔笔记本电脑和台式机上运行PyTorch。我们认为,这将在今年为 PyTorch用户解锁4000万台笔记本电脑和台式机,预计到明年年底这一数值将达到1亿左右。
该版本新增了FlexAttention API,它使PyTorch用户更容易在其模型中尝试不同的注意力机制。通常情况下,想要尝试新的注意力机制变体,研究人员需要直接在PyTorch算子中手动编码。然而,这可能会导致 “运行时缓慢和CUDA OOM”。有了该API,用户只需要编写 “几行惯用的PyTorch代码”就可以完成这项工作。然后,编译器会将这些代码转换为最优内核,“不会产生任何额外的内存开销,而性能可与手写内核相媲美”。
有多项性能改进尚处于Beta测试阶段。新增的后端Fused Flash Attention在英伟达H100 GPU上 “比FlashAttentionV2快75%”。torch.compile的区域编译功能不再需要编译完整的模型;取而代之的是编译重复模块nn.Modules,如Transformer层。这可以减少编译延迟,同时只会造成百分之个位数的性能损失。TorchInductor CPU后端也进行了多项优化。
Flight Recorder\\"是一个新的调试工具,用于解决作业卡住的问题。分布式训练过程中可能会出现作业卡住的情况,其根本原因可能有很多,包括数据饥饿、网络问题或软件Bug。Flight Recorder使用内存循环缓冲区来捕获诊断信息。当检测到作业卡住时,它会将诊断信息转储到文件中;然后,可以使用启发式脚本对数据进行分析,找出根本原因。
在Reddit上关于该版本的讨论中,许多用户很高兴看到PyTorch对英特尔GPU的支持\\",称其为 “游戏规则的改变者”。另一位用户写道\\":
很高兴看到torch.compile有了改进,尤其是重用重复模块以加快编译速度的功能。对于拥有大量类似组件的大型模型来说,这可能会改变游戏的规则。FlexAttention API看起来也很有前景——只需几行代码就能实现各种注意力机制,并获得几乎可以媲美手写代码的性能,这实在是太棒了。感谢PyTorch团队和贡献者们又发布了一个出色的版本!
感兴趣的读者可以从GitHub上获取PyTorch 2.5的代码和发布说明\\"。
原文链接:
https://www.infoq.com/news/2024/10/pytorch-25-release/\\"
","description":"最近,PyTorch 基金会\\"发布了PyTorch 2.5版本\\",其中包含对英特尔GPU的支持。该版本还包含多项性能增强,如FlexAttention\\"API、TorchInductor CPU后端优化,以及可缩短编译时间的区域编译功能\\"。总体而言,该版本包含了自PyTorch 2.4以来的4095次提交。 \\n\\n最近举行的PyTorch大会\\"演示了PyTorch对英特尔GPU的支持。英特尔工程师Eikan Wang和Min Jean Cho介绍了PyTorch为支持该硬件而做出的改变\\",包括泛化PyTorch运行时和设备层,使其更容易与新的硬件后端集成。此外…","guid":"https://www.infoq.cn/article/0mI396HI4cTe19iWvWfN","author":"Anthony Alford","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-11-19T02:33:27.061Z","media":null,"categories":["编程语言"],"attachments":null,"extra":null,"language":null},{"title":"从 C 迁移到 Rust 的挑战与经验教训","url":"https://www.infoq.cn/article/fFE1HMoLJ0dRNkXKIpFd","content":"在一个系列文章中,Immunant 软件工程师 Stephen Crane 和 Khyber Sen 讲述了他们如何将互联网安全研究小组 (ISRG) 的 VideoLAN 和 FFmpeg AV1 解码器从 C 语言移植到 Rust 语言。该系列文章详细介绍了他们如何确保不出错并优化性能。
VideoLan VLC 和 FFMpeg 中使用的 AV1 解码器dav1d 已经开发了六年多,包含大约 5 万行 C 代码和 25 万行汇编程序。正如 Crane 所说的那样,它成熟、速度快且应用广泛。因为代码高度优化,所以它的体积小、可移植性好、速度快。因此,他们坚持要移植,而不是使用 Rust 从头开始重写。
Immunant 的工程师们首先要做的选择是,是一步一步地进行移植,还是使用 c2rust 移植整个代码库,获得一个不安全但可运行的 Rust 实现,然后再以此为基础进行重构和重写,使其变得安全而又符合 Rust 的语言习惯。最终,他们决定采用 c2rust,因为它有两大优势:一是可以在重构的同时测试移植的代码,二是降低了对专家领域知识的要求。
我们发现,在重写和改进 Rust 代码的过程中,从一开始就进行全面的 CI 测试是非常有益的。我们可以对代码库进行横向修改,并在每次提交时运行已有的 dav1d 测试。[…] 该项目的大部分团队成员都是系统编程和 Rust 方面的专家,但之前并没有 AV 编解码器方面的经验。我们的编解码器专家 Frank Bossen 为项目提供了宝贵的指导,但大部分的工作他并不需直接要参。
将移植生成的 Rust 代码重构为安全、符合语言习惯的 Rust 代码面临着许多挑战,其中一些挑战与 C 和 Rust 之间的不匹配有关,例如生命周期管理(借用)、内存所有权、缓冲指针和联合体;另一些挑战则源于 dav1d 的设计,它非常依赖于对跨线程共享可变数据的访问。
通过使用Mutex和RwLock加锁,并在运行时使用Mutex::try_lock()和RwLock::try_read()/RwLock:: try_write()进行验证,他们确保了线程可以访问数据而且又不会引入延迟,从而解决了与共享状态相关的线程安全问题。
这种方法可以很好地处理只有一个线程需要修改跨线程共享值的情况。然而,dav1d 还依赖于多个线程对单个缓冲区的并发访问,其中每个线程访问缓冲区的特定子区域。对此,Immunant 工程师并没有使用更符合 Rust 语言习惯的方法,即使用专门分配给不同线程的不相连的区域,而是创建了一个缓冲区封装类型DisjointMut,负责处理可变借用,并确保每一个都能独占访问。
另外两个颇具挑战性的领域是自引用结构(主要用于跟踪缓冲区位置的游标以及上下文结构之间的链接)和无标签联合体。由于 Rust 不允许使用自引用结构,所以游标指针被整数索引取代,而上下文结构之间的链接被取消,并通过函数参数进行引用。在适当的时候,无标签联合体会被转换为带标签的 Rust 联合体,而在其他情况下,zerocopy crate 会在运行时将相同的字节重新解释为两种不同的类型,以避免改变联合体的表示和大小。
移植的一个主要目标是保持性能不变。因此,Immunant 的工程师在每次提交的重构阶段都会仔细监控性能回归情况。在向安全代码转换的过程中,他们意识到,性能主要是受到一些微妙因素的影响,如动态分派汇编代码、边界检查和结构初始化的成本。最后,他们进行了与分支、内联和堆栈使用相关的更细致的优化。
性能优化工作显著降低了移植带来的开销,从 11% 降至 6%。按照 Crane 的说法,总体上,将 dav1d 移植到 rav1d 花费了三个开发人员 20 多个月的时间,所耗费的人工比最初预计的要多。但这也表明,将现有的 C 代码重写为安全、高性能的 Rust 代码并解决所有线程和借用难题是可能的。
对特别注重安全性的应用程序,rav1d 提供了一个内存安全的实现,而且不会因为沙箱等风险缓解措施而额外增加开支。我们相信,通过不断地优化和改进,在任何情况下,Rust 实现都可以与 C 语言实现相媲美,同时还能提供内存安全性。
他们从rav1d的诞生过程中学到的东西远不止这些,如果想了解更多信息,请阅读原文。
查看原文链接:
https://www.infoq.com/news/2024/10/porting-av1-decoder-rust/\\"
","description":"在一个系列文章中,Immunant 软件工程师 Stephen Crane 和 Khyber Sen 讲述了他们如何将互联网安全研究小组 (ISRG) 的 VideoLAN 和 FFmpeg AV1 解码器从 C 语言移植到 Rust 语言。该系列文章详细介绍了他们如何确保不出错并优化性能。 VideoLan VLC 和 FFMpeg 中使用的 AV1 解码器dav1d 已经开发了六年多,包含大约 5 万行 C 代码和 25 万行汇编程序。正如 Crane 所说的那样,它成熟、速度快且应用广泛。因为代码高度优化,所以它的体积小、可移植性好、速度快。因此…","guid":"https://www.infoq.cn/article/fFE1HMoLJ0dRNkXKIpFd","author":"作者:Sergio De Simone","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-11-18T00:10:00.600Z","media":null,"categories":["编程语言"],"attachments":null,"extra":null,"language":null},{"title":"对话Steve Klabnik和Herb Sutter:Rust和C++","url":"https://www.infoq.cn/article/ZHZiDQTXJbwsgXjOiBo8","content":"在 Kevin Ball 主持的《软件工程日报》(Software Engineering Daily )播客中,Steve Klabnik 和 Herb Sutter 讨论了几个与 Rust 和 C++ 相关的话题,其中包括这两种语言的共同点和独特之处、它们的不同之处、以及它们是如何演进的等等。
对于 Klabnik 来说,除了关于 Rust 是一种内存安全的语言的普遍观点之外,真正使其与众不同的是,它汲取了在最近的编程语言中虽并不流行但在编程语言领域广为人知的思想。
另一方面,Sutter 强调零负担抽象(Zero-Overhead Abstraction)的概念,即我们可以用更高层次的方式表达事物,而无需为抽象付出过高的成本。在这里,Klabnik 呼应了 Sutter 的观点,认为 Rust 实现“零成本”抽象的主要机制是通过类型:
[Klabnik] 基本上,在类型系统中可以表达的越多,在运行时需要检查的就越少。
但并非所有抽象都是零负担的,Sutter 表示,他举了两个 C++ 特性的例子,编译器总是提供禁用这两个特性的选项:异常处理和运行时类型。
[Sutter] 如果你仔细查看原因,那是因为这两个特性可以更好地手工编写。或者,即使你不使用它们,你也要为它们付费。
因此,这就引出了这样一种观点,即语言设计同样是一门艺术或一种工艺,深受品味和语言应该是什么的哲学的影响,所以我们还没有达到一种语言可以成为完美语言的地步。
谈到语言的使用方式,Sutter 说,它们有一个非常相似的目标,生态系统成熟度和线程安全保证可能会导致选择一种而不是另一种。Klabnik 强调,Rust 经常被用来创建网络服务,即使是在大型公司也是如此:
[Klabnik] 例如,Cloudflare 正在使用 Rust 代码作为后端。它们为 10% 的互联网流量提供支持。其他公司 […] 用 Python 编写的一些东西,然后用 Rust 重写它们。最后他们就能够从云账单中省去数千台服务器的费用。
Sutter 强调了 C++ 可以让我们控制时间和空间的能力,以及围绕 C++ 构建了 30 多年的工具生态系统的丰富性,而 Rust 相对来说仍然是一门年轻的语言。
[Sutter] 现在,在某些情况下,除非通过这类工具,否则我无法将代码发布出去。它理解 C++,但不理解 Rust。我无法发布该代码。如果我用 Rust 编写,则不允许在没有 VP 异常的情况下发布它。
当谈到语言演进时,关键点在于什么时候值得为一个新特性增加语言的复杂性,这并不总是一个容易做的决定。在这方面,Klabnik 称赞 C++ 的一点是它致力于“在合理范围内”实现向后兼容。
[Klabnik] 我并不是说 Rust 团队在总体上没有类似的观点。但最近有一些关于某些事情的提议增加了一定程度的复杂性,我个人对此并不满意。
Sutter 提到 C# 团队在某种程度上决定在语言中添加可空性,尽管这肯定是一件好事,但它也带来了隐性的成本:
[Sutter] 因为现在用户和语言都很复杂,甚至未来 20 年也会如此。因为我们会永远支持这件事,对吧?它将永远限制演进。[…] 事实证明,一旦你添加了可空性 […],整个语言需要我们更多地理解它,会比我们最初想象的要多得多。
为了进一步强调做出此类决定有多困难,Klabnik 回忆了一个案例,他对 Rust 的 wait 的后缀语法进行的抗争,这与大多数其他语言的前缀语法不同:
[Klabnik] 现在我用 async 和 wait 编写了很多代码,天哪,我很高兴他们选择了后缀 wait。因为它在很多方面都非常好。
Rust Core 团队管理变更的一种方法是定义语言版本,以便在添加新功能时保持源代码的兼容性。
Sutter 表示自己有兴趣了解这种机制是否可以引入到 C++ 中以支持 async/await ,而无需采用 co_async 和 co_await 关键字来防止与现有代码库发生冲突。Klabnik 解释说,版本是一种添加新语法的强大机制,但它们也有局限性:
[Klabnik] 将 mute 更改为 unique 作为纯粹的语法变更是绝对可行的。因为最终发生的事情是,当它为 2015 编译一个包,为 2024 编译另一个包,并且在 2024 中添加了 unique 或其他什么时,它会脱糖到相同的内部 [表示… 但] 你不能在版本中添加 GC,因为这会在更深层次上真正改变事情的运作方式。
类似地,Rust 标准库是一个唯一的二进制文件,因此我们必须确保它包含了所有版本中使用的所有函数。
Klabnik 和 Sutter 在播客中谈论的内容和细节比我们在此总结的要多得多。其中还包括 C++ 标准化过程对 C++ 的重要性;Rust 社区是否会对 ISO 标准语言感兴趣;Rust 拥有多个编译器而不是只有一个编译器的原因和影响;如何处理合规问题;以及在大学里教授 C++ 或 Rust 等语言的价值。如果你有兴趣了解更多信息,请不要错过完整的播客内容。
Sergio De Simone 是一名拥有超过 25 年工作经验的软件工程师。他曾在包括西门子、惠普和小型初创公司等不同的工作环境工作过。在过去的十多年里,他一直专注于移动平台和相关技术的开发。他目前在 BigML, Inc. 工作,负责 iOS 和 macOS 的开发。
查看原文链接:
https://www.infoq.com/news/2024/10/klabnik-sutter-on-cpp-rust/\\"
","description":"在 Kevin Ball 主持的《软件工程日报》(Software Engineering Daily )播客中,Steve Klabnik 和 Herb Sutter 讨论了几个与 Rust 和 C++ 相关的话题,其中包括这两种语言的共同点和独特之处、它们的不同之处、以及它们是如何演进的等等。 完美的语言并不存在\\n\\n对于 Klabnik 来说,除了关于 Rust 是一种内存安全的语言的普遍观点之外,真正使其与众不同的是,它汲取了在最近的编程语言中虽并不流行但在编程语言领域广为人知的思想。\\n\\n另一方面,Sutter 强调零负担抽象(Zero-Overhead…","guid":"https://www.infoq.cn/article/ZHZiDQTXJbwsgXjOiBo8","author":"作者:Sergio De Simone","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-11-15T00:03:00.909Z","media":null,"categories":["编程语言"],"attachments":null,"extra":null,"language":null},{"title":"Firebase Vertex AI SDK简化基于Gemini的移动应用开发","url":"https://www.infoq.cn/article/9AOLdPagedh8OjDw4BlA","content":"目前处于测试阶段的 Firebase Vertex AI SDK 可以让用户开发出超越简单聊天模型和文本提示词的应用程序。谷歌最近提供了一个 colab 来帮助开发者完成将 SDK 集成到应用程序所需的步骤。
新推出的 colab 涵盖了多个核心主题,包括如何设计有效的提示词、设置集成了 Vertex AI 的 Firebase 项目、配置 Android Studio 项目环境,以及如何利用 Kotlin 将这些功能整合到你的代码中。
谷歌工程师 Thomas Ezan 解释说,开发者可以使用 Vertex AI Studio 来打造高效的提示词,这是一个云端的工具,专为快速构建和测试与 Gemini 模型提示词而设计。
Vertex AI 的一项特性旨在简化开发者的工作流,让他们能够更加轻松地定制应用程序的行为,这一特性就是系统指令。
系统指令相当于用户提示词之前的“序言”,确保模型的行为能够与具体的需求和应用场景保持一致。
通过使用系统指令,开发者能够一次性设定所需的输出风格或语调、角色或身份(比如“解释给五岁的孩子听”)、任务目标或规则(例如“直接返回代码片段,无需额外解释”),以及任何与应用程序用户相关的附加上下文。
系统指令在初始化时进行设置,如下面的代码示例:
val generativeModel = Firebase.vertexAI.generativeModel(\\n modelName = \\"gemini-1.5-flash\\",\\n ...\\n systemInstruction = \\n content { text(\\"You are a knowledgeable tutor. Answer the questions using the socratic tutoring method.\\") }\\n)
SDK 还允许开发者指定生成输出的 responseMimeType。比如,在生成 JSON 格式的输出时,这一功能有助于排除所有非 JSON 格式的内容,这非常实用。
Ezan 指出,将 Gemini API 集成到移动应用程序中,并不仅限于提供对话界面,这要归功于 Gemini 的多模态能力。实际上,Gemini 能够处理文本以外的多种输入类型,包括图像、音频和视频。这意味着,例如,你可以为图片生成标题、为音频文件创建摘要、描述视频场景等。
Ezan 着重介绍了另一个强大的功能:创建函数来增强模型的能力。比如,可以设计一个函数从 SQL 数据库读取数据,并将其融入到提示词的上下文中。另外,你还可以定义一组工具,让模型利用这些工具来生成输出,如下图表所示。
在这里,模型通过两次调用你的数据,获取日期和订单列表,来回答用户提出的问题。
Firebase Vertex AI 为这些特性提供了良好的支持,开发者可以自由选择他们最熟悉的编程语言,如 Swift、Kotlin、Flutter 和 JavaScript,来使用这些特性。
Firebase Vertex AI SDK 为 Android 和 iOS 开发者提供直接访问 Gemini API 的能力,不再需要使用 Python、Java 或 Go 编写的中间后端服务层。
查看原文链接:
https://www.infoq.com/news/2024/10/vertex-ai-firebase-gemini/\\"
","description":"目前处于测试阶段的 Firebase Vertex AI SDK 可以让用户开发出超越简单聊天模型和文本提示词的应用程序。谷歌最近提供了一个 colab 来帮助开发者完成将 SDK 集成到应用程序所需的步骤。 新推出的 colab 涵盖了多个核心主题,包括如何设计有效的提示词、设置集成了 Vertex AI 的 Firebase 项目、配置 Android Studio 项目环境,以及如何利用 Kotlin 将这些功能整合到你的代码中。\\n\\n谷歌工程师 Thomas Ezan 解释说,开发者可以使用 Vertex AI Studio 来打造高效的提示词…","guid":"https://www.infoq.cn/article/9AOLdPagedh8OjDw4BlA","author":"作者:Sergio De Simone","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-11-14T00:05:00.749Z","media":[{"url":"https://static001.geekbang.org/wechat/images/e0/e0c3382b1754de0a6372de8a3e2f7626.png","type":"photo","width":1080,"height":475,"blurhash":"LgQJ}n%6%E^nXMjKoxs;^nk7M|NX"}],"categories":["编程语言"],"attachments":null,"extra":null,"language":null},{"title":"Safe C++提案能复制Rust的内存安全性吗?","url":"https://www.infoq.cn/article/2RFSDCaIIRq47h0qwIkJ","content":"本文最初发布于博客THENEWSTACK。
图片来自Unsplash
为了避免与内存相关的Bug,C++开发人员经常被迫\\"改用Rust\\"。但他们是否还有其他的选择呢?
在九月份的邮件\\"中,第21工作组\\"(成立于1990年,由 “对C++工作感兴趣的、公认的专家 ”组成)发布了\\"一项提案。此后,这项名为“Safe C++扩展“的提案在网上\\"引发了广泛的\\"讨论\\"。
一切都表明,C++社区正在开展一场声势更为浩大的运动,为这门已经有39年历史的编程语言探索新的解决方案,以应对人们对内存安全的持续关注。Safe C++提案只是其持续努力的一部分,人们还在不断地\\"提出其他的想法和方法,有些已在讨论\\"中。
这次对话的背景是,编程社区对提升安全代码性的需求日益迫切。因此,新提案Safe C++首先承认,对C++的持续批评 “削弱了该语言对新手的吸引力”,但同时也指出,Rust堪称典范的安全模型\\"可以 “成为加强C++的契机”,并补充说,Rust长达十年之久的内存安全保证工作为我们指明了方向,并为Safe C++的设计提供了大量参考信息。
“采用安全专家证明过的安全模式所有权和借用,是一个能够让下一代C++保持活力的既合理又合时的方法\\"。
根据提案,Safe C++的当前版本花了18个月的时间来设计和实现。该提案由下面这两位非常敬业的开发人员所撰写:
来自纽约的Sean Baxter是一名开发人员,他的职业生涯包括在美国国家航空航天局喷气推进实验室担任了三年半的软件工程师,之后又在英伟达公司(NVIDIA)担任了两年多的研究科学家(参见他在LinkedIn上的个人简介\\"),并创建了一个C++编译器的替代实现Circle\\"。来自萨克拉门托的Christian Mazakas\\"是C++联盟\\"的高级工程师。该联盟\\"是一家成立于2017年的501(c)(3) 慈善机构,旨在通过鼓励提交新代码库和语言提案以及赞助教育活动来支持C++社区。
C++联盟于9月份宣布\\"与Baxter建立合作伙伴关系,并将其称作是“增加C++语言内存安全特性的革命性提案”。C++联盟总裁兼执行董事Vinnie Falco称,这是 “C++生态系统中的一个重要里程碑,因为对安全代码的需求从未像现在这样迫切”。
那么,他们是如何实现的呢?该提案的一个 “关键部分 ”是用所谓的安全标准库来增强C++标准库: “通过将这些组件集成到C++标准库中,确保从一开始编写新代码时就考虑到安全性。“
正如他们的文档所言:”首先是大棒......Safe C++的开发人员被禁止编写可能在生命周期安全、类型安全或线程安全方面导致未定义行为的操作。有时,这些操作会被编译器前段禁止,例如指针运算。有时,这些操作会被编译器中段的静态分析所禁止,防止使用未初始化变量或使用已释放变量的错误,这也是安全模型所有权和借用的使能技术。其余问题,如数组下标越界,则是通过运行时panic和终止来解决。“
而“胡萝卜则是一整套的新功能,它们改进了不安全的特性”,包括新的模式匹配和复杂的借用检查(跟踪引用以避免出现 “释放后使用 ”漏洞的可能性)。
对Baxter来说,他一直对这个很感兴趣。早在2019年,他就创建了Circle\\",那是一个新的C++编译器。他说,只需简单地改进下工具链,它就能提供一种成熟的后继者语言所能提供的所有好处。顾名思义,这种方法与现有的C++代码完全兼容。正是通过Circle,Baxter首次为C++实现了类似Rust的借用检查器,即便在那时,Baxter就已经对C++代码的长远命运表现出了比较大的兴趣。
2022年,在宣布推出新版的Circle时,Baxter对那些C++的诋毁者提出了质疑,称这种语言本身有缺陷/不安全/编译速度慢。“但软件做软件的事,你做你的事,只要努力,就能做出新东西。这里介绍的技术可以扩展C++工具链,修复语言缺陷,使语言更加安全高效,同时与现有代码资产保持100%兼容。“
”C++将不仅仅是一种语言,它还将是一个起点,从此编程将向着更安全、更简单、更高效,同时又与现有C++资产保持互操作的方向发展。“
那么,为什么不干脆让所有人都改用Rust呢?新的Safe C++提案陈述了自己的理由。“对于职业 C++开发人员来说,Rust是陌生的,再加上互操作工具的限制,要通过在Rust中重写关键部分来加固C++应用程序很难。对于内存安全,为什么不用语言内的解决方案?为什么不能是Safe C++ ?“
最近,Register杂志发表的一篇文章\\"回顾了历史,从研究人员\\"到微软Azure首席技术官Mark Russinovich\\",最后甚至是美国国家安全局\\"和白宫\\"都曾发出过警告。Baxter承认:\\"政府最近发出的有关内存安全的警告使整个科技界都在关注这个问题。“
“我做了理论研究,发现有机会利用新工具帮助C++工程师编写更正确的程序,并消除与安全漏洞关系最大的一类软件缺陷\\"。
关于改进C++,这并不是唯一的想法。13个月前,在CppCon大会上,C++的创建者Bjarne Stroustrup就对与会者说,C++语言的现状是“一个机会\\"”。他还补充说,从C++语言诞生之初,类型和资源安全就一直是这门语言的目标。Stroustrup建议用profiles(可由编译器进行检查的安全保证规则)来改进该语言。
对于标准C++基金会(由微软、谷歌和英特尔支持的非营利组织)GitHub存储库中的profiles,人们已经有了一些想法。该库有一个由Bjarne Stroustrup和ISO C++标准委员会主席Herb Sutter\\"共同编写的C++核心指南页面。现在,该页面已经包含了对 “相关规则组”(名为profiles\\")的引用,其中描述了实现类型安全和边界安全等预期结果的指导原则。
“profiles主要是供工具使用,但也可供人类参考。我们的观点并不局限于‘Enforcement’一节,那些我们知道如何强制执行的内容;有些观点仅仅是一些愿望,或许可以为某些工具构建者带去一些启发\\"。
但上周四(10 月 24 日),Baxter新发表了一篇题为 “为什么Safety Profiles失败了\\"”的论文。
“Safety Profiles\\"于2015年推出,承诺检测现有C++代码中所有的生命周期安全缺陷。这是一个大胆的承诺。但经过十年的努力,Profiles未能产生规范、可靠的实现,也未能为C++安全带来任何实实在在的好处。失败的原因在于其核心设计中有一些错误的前提\\"。
这里有我论文的草稿:https://t.co/cfY2Vokfbr。我试图从以下几个方面来分析生命周期安全问题:1. 别名2. 生命周期3. 安全性C++没有提供任何这些方面的信息。其强化安全性的尝试注定会失败。 — Sean Baxter (@seanbax) 20244年10月24\\"
该论文继续写道,C++源代码 “没有足够的信息来实现内存安全......”,并建议 “将Rust的安全模型引入C++”(也将改善Rust和C++之间的互操作性)。“通过在C++中扩展所有可以出现在函数声明中的Rust结构的表示(如Rust枚举、借用和生命周期、ZST、trait等),公共词汇表类型的数量大大增加。
“C++可以实现内存安全,但不是通过摒弃一切有效的东西,而这正是Safety Profiles的作者所做的\\"。该论文认为,C++必须 “更加明确地表达别名、生命周期和安全属性等”。
有些讨论已经在进行,而且可能会有更多的讨论。除了宣布提案外,Baxter和C++联盟还宣布,他们正在 “寻求开发人员、研究人员和其他利益相关者的反馈”,相信合作过程 “将有助于完善项目的范围,并确保它能满足C++生态系统最迫切的需求”。
他们的提案指出:“有了业界的参与,我们就能解决剩余的设计问题。再过18个月,我们就能开发出足够强大的语言和标准库,用于主流评估。虽然Safe C++是对这门语言的一个巨大的扩展,但构建新工具的成本并不高......我们正一起设计Safe C++标准库和语言扩展。感兴趣的读者可以访问我们的GitHub库,了解我们的工作。“
域名“SafeCPP.org\\"”于今年6月创建。现在,它会自动将所有访问者重定向到Safe C++提案的 draft.html页。
声明:本文为InfoQ翻译,未经许可禁止转载。
原文链接:https://thenewstack.io/can-the-safe-c-proposal-copy-rusts-memory-safety/\\"
","description":"本文最初发布于博客THENEWSTACK。 图片来自Unsplash\\n\\n \\n\\n为了避免与内存相关的Bug,C++开发人员经常被迫\\"改用Rust\\"。但他们是否还有其他的选择呢?\\n\\n \\n\\n在九月份的邮件\\"中,第21工作组\\"(成立于1990年,由 “对C++工作感兴趣的、公认的专家 ”组成)发布了\\"一项提案。此后,这项名为“Safe C++扩展“的提案在网上\\"引发了广泛的\\"讨论\\"。\\n\\n \\n\\n一切都表明,C++社区正在开展一场声势更为浩大的运动,为这门已经有39年历史的编程语言探索新的解决方案,以应对人们对内存安全的持续关注。Safe C++提案只是其持续努力的一部分,人们还在不断地\\"提…","guid":"https://www.infoq.cn/article/2RFSDCaIIRq47h0qwIkJ","author":"David Cassel","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-11-14T00:00:00.459Z","media":[{"url":"https://static001.geekbang.org/infoq/e2/e226e7801674bfc827ceb598ae03d3dd.png","type":"photo","width":1024,"height":683,"blurhash":"LXHnc$T0F5of~UoMIvofKksoi{t5"},{"url":"https://static001.geekbang.org/infoq/8c/8c3bdfebcfa0bb02694ae10d330ca69c.png","type":"photo","width":567,"height":179,"blurhash":"LFRW0b%Lt6_3~q%Mt7fk9FjuWBay"}],"categories":["编程语言"],"attachments":null,"extra":null,"language":null},{"title":"SQLite 将从 GNU Autotools 迁移到 Autosetup,团队警告:可能出现“某些构建级别的中断”","url":"https://www.infoq.cn/article/ANlCI02XBKj2pdRPZPhb","content":"SQLite 团队正在将下一个版本 从 GNU Autotools 迁移到 Autosetup,并警告说,虽然这一变化对于大多数用户来说没什么影响,但“某些构建级别的中断是不可避免的”。因为这两种工具之间存在差异,并且自动构建过程使用的配置有很多种类。
这类工具的设计目标是根据开发人员的要求,通过编译时选项为本地环境正确配置并自定义构建(build)。工具的输出包括一个 makefile,其中包含了使用 make 实用程序构建项目时要执行的任务。
许多开源项目都在使用 GNU Autotools,但 SQLite 开发人员发现使用 Autosetup(由嵌入式 Linux 顾问 Steve Bennett 创建)有几个优势。Autosetup 由高级解释语言 TCL 驱动,而 GNU Autoconf 使用 GNU M4(一个宏处理器)生成 shell 脚本。由于“TCL 相对用户较为友好”,使 Autosetup 构建文件更易维护。
Autosetup 的另一个优点是,它的所有文件都保存在 SQLite 源代码树中,而 GNT Autotools 是外部依赖项。Fossil SCM 已经使用了 Autosetup,Fossil SCM 是由 D Richard Hipp 博士创建的软件配置管理器,他也是 SQLite 的开发人员。
Fossil 贡献者 Stephan Beal 在关于工具迁移的官方文章中提到,“对于那些只运行‘./configure && make’的人们来说,就算有变化也是很小的。” 话虽如此,Autotools 与 Autoconf 并不完全兼容。例如,SQLite 的 –enable-tempstore 选项在 Autosetup 中必须变为 –with-tempstore,其中 –enable 具有特殊含义。
最大的问题不是出在开发人员将 SQLite 构建为独立工具的场景中,而是将 SQLite 嵌入另一个项目的自动构建流程的情况。在某些情况下这可能需要重新配置。
另一个问题是 Autosetup 无法像 Autoconf 那样支持那么多平台,这将影响“更边缘的目标平台”,包括 BlackBerrry QNX。该团队建议“一个后备选项是为此类平台提供静态 makefile,类似于目前为 Windows 平台所做的那样。”
这次迁移表明 Hipp 的 SQLite 团队不愿意随波逐流。Hipp 是 Git 怀疑论者,很高兴使用 Fossil 进行源代码管理。Beal 表示,“Richard 的理念之一是‘自由意味着能够照顾好自己’,这一理念贯穿于他的所有软件项目,这些项目都避免了外部依赖,因为每个依赖都会降低项目的自由度……有时甚至会重新发明轮子(比如实现自己的 SCM)。”
放弃 Autoconf,转而使用一个不太知名但在他看来更优秀的工具,体现了他的性格特征。
","description":"SQLite 团队正在将下一个版本 从 GNU Autotools 迁移到 Autosetup,并警告说,虽然这一变化对于大多数用户来说没什么影响,但“某些构建级别的中断是不可避免的”。因为这两种工具之间存在差异,并且自动构建过程使用的配置有很多种类。 \\n\\n这类工具的设计目标是根据开发人员的要求,通过编译时选项为本地环境正确配置并自定义构建(build)。工具的输出包括一个 makefile,其中包含了使用 make 实用程序构建项目时要执行的任务。\\n\\n \\n\\n许多开源项目都在使用 GNU Autotools,但 SQLite 开发人员发现使用 Autosetup…","guid":"https://www.infoq.cn/article/ANlCI02XBKj2pdRPZPhb","author":"Tim Anderson","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-11-12T10:15:44.169Z","media":null,"categories":["数据库"],"attachments":null,"extra":null,"language":null},{"title":"JavaScript 应该分成两种语言吗?谷歌新提案引发了意见分歧","url":"https://www.infoq.cn/article/isePjDZVPmGkh1pCuZMM","content":"
一名谷歌工程师向官方标准化委员会提交了一份提案,该提案将 JavaScript 分为两种语言,一种是由运行时引擎实现的核心语言,另一种则是更强大的变体语言,依赖将其编译为核心语言的工具。
这份提案是在本月初的 Emca TC39 会议上提出的,TC39 是 Ecma International 的一个委员会,负责制定 JavaScript(正式名称为 ECMAScript)规范。
谷歌的一名软件工程师 Shu-yu Guo 发表了演讲,他专攻 JIT、VM、编译器和标准化,幻灯片由 Guo 与 Mozilla、苹果、Moddable 和索尼的合作者共同撰写。Moddable 是一家提供嵌入式编程开源 SDK 的公司,其中包括 XS JavaScript 引擎。
作者认为,新的语言特性对用户的影响大多是负面的。新特性“几乎总是”会降低安全性,使性能受到“中性到负面影响”,稳定性有时会更差,并且只有开发人员使用新特性时,应用程序功能才会得到改进。
他们说,JavaScript VM(虚拟机)“由于速度压力已经变得非常复杂”,这会损害安全性,并且当新特性未被采用时“感觉特别糟糕”。他们引用了一些例子,一个例子是 JavaScript 的 MDN web 参考,已经报告“引擎实现者正在调查是否删除此特性”,以及用于大数值的 BigInt。关于BigInt,演示指出“用例从未得到实现”。
根据该提案,JavaScript 的基础技术应该很简单,因为安全漏洞和运行时的“复杂性成本”影响了数十亿次用例,而好处只有能真正利用这种复杂性的开发人员和应用程序才能享受到。
尽管涉及多个组织,但该计划似乎在某种程度上是由谷歌推动的,其中一张幻灯片包含免责声明:“这一可能的解决方案是谷歌的首选解决方案,不一定是其他实施者的首选解决方案”
JavaScript 开发人员主要根据新提案使用编译器,但一些开发人员希望摆脱这种模式
提议的解决方案不是回溯现有特性,或者撤回那些处于后期提案阶段的新特性,而是将未来的方法改为大多数新特性在工具中,而不是在 JavaScript 引擎中实现。引擎实现的语言称为“JS0”,而工具实现的语言称为“JSSugar”;这些名称是用于讨论起的,并非最终名称。
工具理念特别适用于 JavaScript,因为许多开发人员实际上是在使用 TypeScript 编写代码,并依赖 Babel、Webpack 或 TypeScript 编译器等编译器来输出 JavaScript。从开发人员的角度来看,JavaScript 是 JSSugar,但运行时引擎只需实现 JS0。这意味着各种工具应该更加符合一致的标准。
如果该提案被采纳,则意味着未来的语法特性将进入 JSSugar,而只有 API 和功能特性将进入 JS0。兼容引擎只需支持 JS0。支持 JSSugar 的负担将转移到工具实现者身上,而副作用是工具实现者需要更多地参与标准流程,并可能组建一个新的技术小组。
该提案已经引起争议。“请不要给当前一批 JavaScript 工具授予官方地位……许多 JavaScript 开发人员,包括我自己,都希望减少对这些工具的依赖,”其中一位开发人员说道。
人们普遍认为,优先考虑安全性、性能和稳定性是一件好事,但让 JavaScript 依赖中间工具的想法并不受欢迎。“RIP Vanilla JS”另一位开发人员说道。
","description":"一名谷歌工程师向官方标准化委员会提交了一份提案,该提案将 JavaScript 分为两种语言,一种是由运行时引擎实现的核心语言,另一种则是更强大的变体语言,依赖将其编译为核心语言的工具。 \\n\\n这份提案是在本月初的 Emca TC39 会议上提出的,TC39 是 Ecma International 的一个委员会,负责制定 JavaScript(正式名称为 ECMAScript)规范。\\n\\n \\n\\n谷歌的一名软件工程师 Shu-yu Guo 发表了演讲,他专攻 JIT、VM、编译器和标准化,幻灯片由 Guo 与 Mozilla、苹果、Moddable…","guid":"https://www.infoq.cn/article/isePjDZVPmGkh1pCuZMM","author":"Tim Anderson","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-11-12T10:08:59.181Z","media":[{"url":"https://static001.geekbang.org/infoq/fd/fdb2eff02cc71bfc23096f24c088c0f3.jpeg","type":"photo","width":1654,"height":888,"blurhash":"LKRDAnxa%3x^%gWCofkB^-Sinms."}],"categories":["编程语言"],"attachments":null,"extra":null,"language":null},{"title":"Mojo作者Chris Lattner谈编程言语的进化","url":"https://www.infoq.cn/article/Re9iENKpsDzhMfSY5vVM","content":"
Mojo,一种新的基于Python的模块化编程语言,于2023年问世,专为GPU和其他加速器而设计。它的官方FAQ中提到,“我们的目标不仅仅是打造一个‘更快的Python’,而是实现一个全新的系统编程层面,提供对加速硬件的直接访问能力”。
或者,正如Chris Lattner在接受采访时所说的,他们的目标是专注于“如何表达”硬件的全部能力。同时,他们也希望“在用户熟悉的环境中”保持Python的风格和体验,因为许多人,尤其是在AI领域,都在广泛使用Python。
一种编程语言的演化其实是一个难得的机会,我们不仅可以深入探索语言设计决策背后的逻辑,还可以探究将这些决策聚合在一起的底层哲学。在2024年,程序员真正关心的是什么?在播客“Software Unscripted”的第100集\\",Lattner分享了他对设计编程语言、编译器以及相关基础设施的见解。
播客主持人Richard Feldman,Roc编程语言作者,开场便提出了一个关键的问题:现如今有这么多编程语言,为什么还要开发一种全新的语言?对此,Lattner不假思索地回答:“这本质上是一种解决问题的方式。”
Lattner给出的答案不仅回答了“为什么”,还回答了“做什么”和“怎么做”——为我们提供了对当前整个编程语言生态系统的全面视角。
Lattner认同Feldman的说法,即Mojo正在利用Python生态系统,同时通过“部分演进”来改进性能。这项工作正在进行中。Lattner表示,“我们今年秋天的目标之一是能够轻松地使用Mojo创建Python包”,将Mojo的卓越性能带给Python开发者。
Mojo将“去除与C语言互操作的复杂性,”Lattner说道,同时提供“与C语言或C++相同或更好的性能。”
Lattner随后说这是一件“自然而然的事情”,因为一个成功的语言社区其规模自然会扩大。“程序员希望将自己的技能向前推进,就会自然而然地将这些技能带入他们想要应用的相关领域。”
当然,Lattner最后也给出了一个更简单的答案:“我们开发Mojo,因为我们关心AI、GPU以及加速器相关领域的东西。”
“Python社区有很多声音是关于‘让原生Python变得更快,可以获得20倍的加速’等等,但Mojo的理念是‘怎样不从Python出发却可以让它变得更好’。我们说的是‘挖掘硬件的极限性能’。我们要释放硬件的全部潜能——这不仅仅是,比如,让int类型变得很快……还包括加速器、SIMD(单指令/多数据并行处理)以及所有这类东西……”
“这取决于具体的工作负载,但我们有一篇博文展示了Mojo的性能可能比Python快65000倍。”
“对此常见的反驳是‘在Python中,你不需要编写涉及大量数学运算的代码’,但这正是Mojo的精髓所在——它让你能够使用一种与Python保持一致且连贯的语言编写同样的代码。因此,你无需切换语言!
为了提供一流的并行处理支持,Mojo的SIMD语法包含了所有不同数字类型的元素。
Lattner在这里对现代编程语言做了一番评论:“顺便说一句,自20世纪90年代末以来,所有处理器都支持SIMD,但为什么没有编程语言去拥抱现代计算机呢?这对我来说一直是个谜。”(随后他再次对“如此多的代码仍然是单线程的”表达了惊讶。)
Mojo还找到了一种提升性能的方法,使其可以超越Python。“Python中的整数是大整数,”Lattner解释说,“你可以创建任意大小的整数,它们是堆分配的,具有引用语义。”Mojo在语法中保留了int这个名称,同时也在标准库中引入了自己的替代类型——Int(大写的I)。这个Int是一个结构体,极大地简化了Mojo编译器的工作。
尽管Mojo仍然兼容Python的原始语法,但如果你选择使用Mojo的Int类型,“你将获得更好的性能和可预测性。它还能在GPU上运行,等等。这不是说一个比另一个更好,而是一种权衡。”
Lattner说,“一些芯片厂商”决定全力支持包含“虚数”(虚数在技术应用中被广泛使用,比如工程和物理公式等)的数学。“因此,一旦有人将这些技术集成到硬件中,并惊叹‘这比单独进行乘法和加法快了10倍’,我们也不得不说‘10倍的性能提升’——因为他们将这些技术嵌入到了硅片中……那么我们该如何让这一优势为人们所用,而不必让他们深入了解背后的复杂性呢?”
Mojo支持使用复数来定义结构体,这些结构体具备基本的行为和“一系列方法——包括乘法”。如果编译器检测到存在复数加速硬件,并且该硬件支持特殊的快速乘法指令,那么美妙的事情就会发生。“所有使用复数的程序都将获得加速,而开发者无需操心额外的细节。”
Mojo保留了Python的运算符重载功能,即自定义操作符默认行为的能力,并保留与Python语法的兼容性。最终,许多额外的复杂性都转移给了库开发者。
Lattner提到,他知道有很多编译器工程师,但他想将“人才生态系统”提升到库开发者所在的上游——那些深刻理解自己领域以及知道如何利用GPU性能增强手段的程序员。他说:“我的Mojo旅程实际上是关于释放这些人的潜力,并赋予他们超能力。”
后来他说,这与过去五到十年该领域的“趋势形成了鲜明对比……‘将复杂性嵌入编译器,将其锁定并扔掉钥匙,然后相信我们——我们这些编译器开发者’……但我看到的是,这实际上并不是真的……编译器很少能带来10倍的性能提升。但在应用领域工作的人,因为他们了解自己的应用程序——完全有可能实现,因为他们可以使用合适的工具来实现。”
最终的结果是,在光数字就有十几种不同类型的领域,“我们能够让人们在库中定义这些类型,减轻语言需要与所有硬件打交道的负担!”
在节目结束时,Lattner呼吁有兴趣的程序员可以看看Mojo的官网及其“丰富的文档资源。Mojo社区非常活跃!我们有一个Discord频道——据我所知,大约有20000人,他们在讨论各种话题,共同构建项目。”
他还补充了一句鼓舞人心的话:“Mojo不仅仅是一种AI语言,社区还用它来构建Web服务器、GUI库以及各种其他项目。我们非常希望人们能参与进来。Mojo目前还处于相对早期的阶段,我们仍在不断添加核心功能和构建库。”
“但我们拥有一个庞大的社区,他们都非常热情,我希望人们能够参与进来。”
【声明:本文由InfoQ翻译,未经许可禁止转载。】
原文链接:https://thenewstack.io/mojos-chris-lattner-on-making-programming-languages-evolve/\\"
","description":"Mojo,一种新的基于Python的模块化编程语言,于2023年问世,专为GPU和其他加速器而设计。它的官方FAQ中提到,“我们的目标不仅仅是打造一个‘更快的Python’,而是实现一个全新的系统编程层面,提供对加速硬件的直接访问能力”。 \\n\\n或者,正如Chris Lattner在接受采访时所说的,他们的目标是专注于“如何表达”硬件的全部能力。同时,他们也希望“在用户熟悉的环境中”保持Python的风格和体验,因为许多人,尤其是在AI领域,都在广泛使用Python。\\n\\n \\n\\n一种编程语言的演化其实是一个难得的机会,我们不仅可以深入探索语言设计决策背后的逻辑…","guid":"https://www.infoq.cn/article/Re9iENKpsDzhMfSY5vVM","author":"David Cassel","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-11-12T09:58:32.997Z","media":[{"url":"https://static001.geekbang.org/infoq/88/880358b3ead45c2a999119ab00f32e74.png","type":"photo","width":706,"height":521,"blurhash":"LCRC_F%Nog-;~qofj[oe-;xtRjt7"}],"categories":["编程语言"],"attachments":null,"extra":null,"language":null},{"title":"OpenJDK近期新闻:流收集器、作用域值、分代Shenandoah、ZGC非分带模式","url":"https://www.infoq.cn/article/wONtmB1DxHdgaRCY3TWi","content":"OpenJDK生态系统近期活动频繁,重点包括:已确定在JDK 24中发布的从“Proposed to Target”进入到“Targeted”的JEP以及已提升为Candidate状态的草案。JEP 485(流收集器)是第五个被确认在JDK 24中发布的JEP。四个JEP状态为“Proposed to Target”,并在2024年10月28日这一周进行评审。
在评审结束后,JEP 485(流收集器\\")已从”Proposed to Target“进入\\"”Targeted“状态,目标版本为JDK 24。这个JEP提议在进行了两轮预览后完成这个特性:在JDK 23中发布的JEP 473(流收集器(第二次预览)\\")和在JDK 22中发布的JEP 461(流收集器(预览)\\")。这个特性旨在增强流式API,支持自定义中间操作,“允许流式管道以一种难以通过现有内置中间操作实现的方式进行数据转换。”更多关于这个JEP的细节可以在其设计文档\\"和InfoQ的新闻报道\\"中找到。
JEP 490(ZGC:移除非分代模式\\")已从”Candidate“进入\\"到”Proposed to Target“状态,目标版本为JDK 24。这个JEP提议移除Z Garbage Collector(ZGC)的非分代模式。JEP 474(ZGC:默认分代模式\\")提议分代模式为默认的回收模式,并已在JDK 23中发布。通过移除ZGC的非分代模式,不仅消除了维护两种模式的负担,还加快了分代模式下新功能的开发速度。评审于2024年10月29日结束。
JEP 487(作用域值(第四次预览)\\")已从“Candidate”进入\\"“Proposed to Target”状态,目标版本为JDK 24。之前这个JEP叫作范围本地变量(孵化器),现提议进行第四次预览,其中包含了一个变化,从之前的一轮孵化和三轮预览中获得额外的反馈:在JDK 23中发布的JEP 481(作用域值(第三次预览)\\";在JDK 22中发布的JEP 464(作用域值(第二次预览)\\");在JDK 21中发布的JEP 446(作用域值(预览)\\");以及在JDK 20中发布的JEP 429(作用域值(孵化器)\\")。这个特性支持在单个线程内部以及跨线程共享不可变数据。这比线程局部变量更受青睐,特别是当使用大量虚拟线程时。与之前的预览相比,唯一的变化是移除了ScopedValue\\"类的callWhere()和runWhere()方法,简化了API。通过在ScopedValue.Carrier\\"类中定义的call()和run()方法,可以使用一个或多个绑定的作用域值。评审于2024年10月30日结束。
JEP 478(密钥派生函数API(预览))已从“Candidate”进入\\"到“Proposed to Target”状态,目标版本为JDK 24。这个JEP提议为密钥派生函数\\"(KDF,从密钥和其他数据中派生额外密钥的密码算法)引入API,目标是:允许安全供应商在Java或本地代码中实现KDF算法,并可以在JEP 452(密钥封装机制\\")的实现中使用KDF。评审于2024年10月31日结束。
JEP 404(分代Shenandoah(实验)\\")已从Candidate“进入\\"到”Proposed to Target“状态,目标版本为JDK 24。最初的目标版本为JDK 21,但因“在评审过程中识别出的风险以及缺少进行大规模代码贡献所需的评审时间”而被移出\\"最终特性集。Shenandoah团队决定“提供他们能够提供的最好的分代Shenandoah”,并在未来的JDK版本中发布。评审于2024年10月30日结束。
JEP 495(简单的源文件和实例主方法(第四次预览)\\")已从“JEP Draft 8335984”进入\\"到“Candidate”状态。这个JEP提议在经过之前的三轮预览后进行第四次预览,不包含变更(除了第二次预览进行了名称变更):在JDK 23中发布的JEP 477(隐式声明类和实例主方法(第三次预览)\\");在JDK 22中发布的JEP 463(隐式声明类和实例主方法(第二次预览)\\");以及在JDK 21中发布的JEP 445(未命名类和实例主方法(预览)\\")。这个特性旨在“让学生可以在不需要理解为大型程序设计的语言特性的情况下编写他们的第一程序。”这个JEP将Oracle Java语言架构师Brian Goetz\\"在2022年9月发表的博文Paving the on-ramp\\"推进了一步。Oracle技术顾问Gavin Bierman\\"已经发布\\"了规范文档\\"的第一稿,供Java社区评审。关于JEP 445的更多细节可以在InfoQ的新闻报道\\"中找到。
JEP 494(模块导入声明(第二次预览)\\")已从“JEP Draft 8335987”进入\\"到“Candidate”状态。这个JEP在经过第一轮预览后提议进行第二次预览:在JDK 23中发布的JEP 476(模块导入声明(预览)\\")。这个特性将增强Java编程语言的能力,能够简洁地导入一个模块导出的所有包,目标是简化模块库的重用,无需将代码直接导入到模块本身。与第一次预览相比的变化包括:取消了模块不允许声明对java.base模块传递依赖的限制;更新java.se模块的声明,使其传递性地依赖java.base模块;允许按需声明的类型导入覆盖模块导入声明。这些变化意味着导入java.se模块将能够按需导入整个Java SE API。
JEP 493(不使用JMOD链接运行时镜像\\")已从“JEP Draft 8333799”进入\\"到“Candidate”状态。这个JEP提议“能够通过使jlink工具创建不依赖JMOD\\"文件的自定义运行时镜像,将JDK的体积减少约25%。”这个功能必须在构建JDK时显式启用。开发者可以从他们的本地模块链接运行时镜像,无论这些模块存放在何处。
Oracle Java平台组首席架构师Mark Reinhold\\"批准\\"的JDK 24的发布计划如下:
Rampdown Phase One(从主线分叉):2024年12月5日Rampdown Phase Two:2025年1月16日Initial Release Candidate:2025年2月6日Final Release Candidate:2025年2月20日General Availability:2025年3月18日
对于JDK 24\\",开发者可以通过Java错误数据库\\"报告错误。
原文链接:
https://www.infoq.com/news/2024/10/jdk-news-roundup-oct21-2024/\\"
","description":"OpenJDK生态系统近期活动频繁,重点包括:已确定在JDK 24中发布的从“Proposed to Target”进入到“Targeted”的JEP以及已提升为Candidate状态的草案。JEP 485(流收集器)是第五个被确认在JDK 24中发布的JEP。四个JEP状态为“Proposed to Target”,并在2024年10月28日这一周进行评审。 Targeted的JEP\\n\\n在评审结束后,JEP 485(流收集器\\")已从”Proposed to Target“进入\\"”Targeted“状态,目标版本为JDK 24…","guid":"https://www.infoq.cn/article/wONtmB1DxHdgaRCY3TWi","author":"Michael Redlich","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-11-11T02:46:20.949Z","media":null,"categories":["编程语言"],"attachments":null,"extra":null,"language":null},{"title":"Java近期新闻:Apache Pulsar 4.0、Jakarta EE 11、Open Liberty、Helidon、JHipster和Apache Camel","url":"https://www.infoq.cn/article/vgR3vJv48YbS7zjdezJV","content":"本期的Java新闻汇总主要包括如下内容:Apache Pulsar 4.0发布;Open Liberty 24.0.0.11-beta成为Jakarta EE 11 Core Profile的首个兼容实现;Helidon 4.1.3、JHipster 1.21.0以及Apache Camel 4.8.1和4.4.4的小版本发布。
最近OpenJDK生态系统比较忙碌,多个面向JDK 24的JEP被列为Targeted和Proposed to Target状态,同时也有草案提升为Candidate状态。JEP 485,流收集器(Stream Gatherers)\\"成为JDK 24确定的第五个JEP。已有四个JEP列为Proposed to Target状态。更多详情,请参阅InfoQ的新闻报道\\"。
JDK 24早期访问构建版本\\"的Build 21\\"发布,该版本是对Build 20的更新\\",其中包括对各种问题\\"的修复。关于这个版本的更多细节可以在发布说明\\"中找到。
对于JDK 24\\",鼓励开发人员通过Java缺陷数据库\\"报告缺陷。
Loom项目的早期访问构建版本\\"的Build 24-loom+9-96已经提供给Java社区,该构建版本基于JDK 24早期访问构建版本的Build 20\\"。该版本增强了Java监视器(同步方法)的实现,以增强与虚拟线程的互操作性。
在每周的Hashtag Jakarta EE\\"博客中,Eclipse基金会的Jakarta EE开发人员倡导者Ivar Grimstad\\"介绍了Jakarta EE 11的最新情况\\":
有些好消息!我很高兴地宣布,IBM提交了Jakarta EE 11 Core Profile与Open Liberty 24.0.0.11-beta\\"的兼容性认证申请(CCR,Compatibility Certification Request)。这意味着我们已经有一个产品实现了该规范并通过了TCK,因此我们将能够发布Core Profile\\"。Red Hat也即将发布通过Core Profile TCK的WildFly。
通往Jakarta EE 11的过程中包括了四个里程碑版本,在2024年第4季度发布正式版之前,还可能根据需要发布候选版本。
最近,Spring也比较忙碌,各个团队发布了大量的候选版本和小版本,包括Spring Boot\\"、Spring Security\\"、Spring Authorization Server\\"、Spring Session\\"、Spring Integration\\"、Spring Modulith, Spring Batch、Spring AMQP、Spring for Apache Kafka\\"和Spring for Apache Pulsar\\"。更多详情,请参阅InfoQ的新闻报道\\"。
IBM发布\\"了Open Liberty\\"的24.0.0.11-beta版本,该版本具有以下特性:为InstantOn\\"提供新的消息和授权支持,用户空间检查点/恢复(Checkpoint/Restore in Userspace,CRIU)\\"的Open Liberty实现,以及新的webModuleClassPathLoader配置属性,用于改进企业级应用程序的类加载器控制,该控制由Web模块的Class-Path属性引用。兼容性认证申请正在等待审批,该版本将成为Jakarta EE 11 Core Profile\\"的首个兼容实现版本。
Helidon\\"的4.1.3\\"版本带来了一些值得关注的变化,例如,在Helidon Tracing组件中为Zipkin添加了上下文传播器实现,以便在Helidon服务器中跨线程传播跟踪信息;在Helidon Metrics组件中为内置指标名称配置驼峰或蛇形大小写的功能;修复了DataReader类中定义的findNewLine()方法,当同一缓冲区中存在多个单独的回车字符行时,该方法返回的是最大值而不是新行的索引。有关此版本的更多详情,请参阅变更日志\\"。
Apache Pulsar\\"4.0.0发布\\",该版本提供了一些值得关注的变化,例如,新的负载平衡算法AvgShredder\\",旨在卸载bundle,以将代理资源的范围保持在配置的阈值内;增强的代理级指标\\",可监控和分析Pulsar服务的行为。关于该版本的更多详情,请参阅发布说明\\"。
Apache Camel\\"的4.8.1\\"和4.4.4\\"均为LTS版本,包含了缺陷修复、依赖性升级和新功能,比如,新的ThreadPoolFactory接口,用于传播OpenTelemetry上下文\\";新的starter,用于轻松发布Jolokia\\"端点,以监控Spring Boot应用程序中的Camel。关于这些版本的更多详情,请参阅4.4.4\\"和4.8.1\\"的发布说明。
JHipster Lite\\" 1.21.0发布\\",提供了缺陷修复、依赖性升级和功能增强,例如,使用Spring Boot LiquibaseProperties类中的changelog路径,而不再使用Spring Framework @Value注解进行注入;使用Prettier\\"(一种代码格式化工具)重新格式化Vue.js、React.js和Angular.js文件。有关该版本的更多详细信息,请参阅发布说明\\"。
原文链接:
Java News Roundup: Apache Pulsar 4.0, Jakarta EE 11, Open Liberty, Helidon, JHipster, Apache Camel\\"
","description":"本期的Java新闻汇总主要包括如下内容:Apache Pulsar 4.0发布;Open Liberty 24.0.0.11-beta成为Jakarta EE 11 Core Profile的首个兼容实现;Helidon 4.1.3、JHipster 1.21.0以及Apache Camel 4.8.1和4.4.4的小版本发布。 \\n\\nOpenJDK\\n\\n最近OpenJDK生态系统比较忙碌,多个面向JDK 24的JEP被列为Targeted和Proposed to Target状态,同时也有草案提升为Candidate状态。JEP 485,流收集器(Stream…","guid":"https://www.infoq.cn/article/vgR3vJv48YbS7zjdezJV","author":"Michael Redlich","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-11-11T02:39:08.450Z","media":null,"categories":["编程语言"],"attachments":null,"extra":null,"language":null},{"title":"Spring近期新闻:Spring Boot、Security、Auth Server和Modulith提供发布候选版本","url":"https://www.infoq.cn/article/cI1GlrDNQ64xrzBP2kUp","content":"最近,Spring生态系统的活动较为频繁,重点发布了如下项目的候选版本:Spring Boot、Spring Security、Spring Authorization Server、Spring Integration、Spring Modulith、Spring Batch、Spring AMQP、Spring for Apache Kafka和Spring for Apache Pulsar。
Spring Boot\\" 3.4.0的第一个发布候选版本\\"提供了缺陷修复、文档改进、依赖性升级和许多新特性,比如,通过新的构建器和额外的定制功能改进了对Spring Framework ClientHttpRequestFactory接口的支持;Paketo Buildpack for Spring Boot\\"支持了ARM和x86架构。关于该版本的更多详细信息,请参阅发布说明\\"。
同样,Spring Boot 3.3.5\\"和3.2.11\\"发布,提供了文档改进、依赖性升级并修正了一些值得关注的缺陷,比如,删除了DataSourceProperties类中定义的driverClassIsLoadable()方法在出现异常时向错误流中打印堆栈跟踪信息的功能,因为这已被确认是没有必要的;解决了ArtemisConnectionFactoryFactory类的实例在构建原生镜像时失败的问题。关于这两个版本的更多详细信息,请参阅3.3.5版本\\"和3.2.11版本\\"的发布说明。
在Spring Boot 3.4.0-RC1发布的同时,Spring Framework 6.2.0的第三个发布候选版本\\"也提供了缺陷修复、文档改进和新功能,例如,删除了新@MockitoSpyBean注解中的proxyTargetAware属性,因为它被认为是不必要的;重构了RestClient接口中定义的retrieve()方法,以便执行请求并在必要时提取响应,从而消除了在此工作流中调用两个方法的必要性。有关该版本的更多详细信息,请参阅发布说明\\"。
Spring Security\\" 6.4.0的第一个发布候选版本\\"提供了缺陷修复、依赖性升级和新特性,比如,支持Passkeys\\";新的authorize()方法替换了AuthorizationManager接口中定义的现已废弃的authorize()方法,该方法会返回AuthorizationResult接口的实例;重构了AuthorizationEventPublisher接口中定义的publishAuthorizationEvent(Supplier, T, AuthorizationDecision)方法,该方法现在接受的是AuthorizationResult接口的实例,替换了参数列表中的AuthorizationDecision类。关于该版本的更多详细信息,请参阅 发布说明\\"和新特性\\"页面。
同样,Spring Security的6.3.4、6.2.7和5.8.1版本发布\\",其中包括缺陷修复、依赖性升级并修正了一些值得关注的缺陷,比如,虽然eraseCredentialsAfterAuthentication字段设置为false,但AuthenticationManager接口的自定义实例中的凭据信息依然会被擦除;@PostFilter注解标注的方法会被PostFilterAuthorizationMethodInterceptor类处理两次。关于这些版本的更多详细信息,请分别参阅6.3.4版本\\"、6.2.7版本\\"和5.8.15版本\\"的发布说明。
Spring Authorization Server\\" 1.4.0的第一个发布候选版本\\"提供了依赖性升级和新特性,比如,用Spring Security中定义的类似的DelegatingAuthenticationConverter类替换了认证服务器中同名的DelegatingAuthenticationConverter类;使用Spring Security HttpSecurity类中定义的with()方法简化了专用授权服务器的配置。关于该版本的更多详细信息,请参阅发布说明\\"。
同样,Spring Authorization Server的1.3.3和1.2.7版本发布\\",其中包括依赖性升级和一项修复,以便于更高效地利用JdbcOAuth2AuthorizationService类定义的子类注册AOT contribution。关于这两个版本的更多详细信息,请参阅1.3.3版本\\"和1.2.7版本\\"的发布说明。
Spring for GraphQL\\"的1.3.3和1.2.9版本发布\\",包括了缺陷修复、依赖性升级和新特性,比如,能够为服务器端事件设置超时值;用@BatchMapping注解标注的方法应该从BatchLoaderEnvironment类的实例传递localContext字段(定义在GraphQL for Java DataFetcherResult类中)。关于这些版本的更多详细信息,请参阅1.3.3版本\\"和1.2.9版本\\"的发布说明。
Spring Integration\\"的第一个发布候选版本\\"提供了缺陷修复、文档改进、依赖性升级和新特性,比如,现在可以通过Spring Framework TaskScheduler接口的实例来配置RedisLockRegistry类,以更新存储中的自动锁;迁移Python脚本以支持Python 3和GraalPy\\"。有关该版本的更多详细信息,请参见发布说明\\"和新特性\\"页面。
同样,Spring Integration的6.3.5和6.2.10版本发布,其中包括错误修复、依赖性升级和新特性,比如,在上述RedisLockRegistry类中添加了一个新属性idleBetweenTries,用于指定锁尝试之间的休眠时间;在使用@SpringIntegrationTest注解时改进了对JUnit @Nested注解的支持。有关这两个版本的更多详细信息,请参与6.3.5版本\\"和6.2.10版本\\"的发布说明。
Spring Modulith\\" 1.3.0的第一个发布候选版本提供了缺陷修复、文档改进、依赖性升级和新特性,比如,在JDBC事件发布注册中心中支持Oracle数据库类型;支持MariaDB数据库驱动程序。关于该版本的更多详情,请参阅发布说明\\"。
同样,Spring Modulith的 1.2.5和 1.1.10版本也已发布,其中包括缺陷修复、依赖性升级和参考文档的各种改进。关于这些版本的更多详细信息,请参阅1.2.5版本\\"和1.1.10版本\\"的发布说明。
Spring Batch\\" 5.2.0的第一个发布候选版本提供了缺陷修复、文档改进、依赖性升级和一项新特性,即允许对CompositeItemReader类进行子类化,从而降低了泛型的严格程度。关于此版本的更多详情,请参阅发布说明\\"。
Spring AMQP\\" 3.2.0的第一个发布候选版本\\"提供了文档改进、依赖性升级和新特性,例如,通过 RabbitTemplate类的实例和@RabbitListener注解暴露额外的Open Telemetry语义标记;RabbitTemplate类中的新方法getBeforePublishPostProcessors(),它是现有addBeforePublishPostProcessors()方法的补充,允许开发人员动态访问和修改这些处理器。关于此版本的更多详细信息,请参阅发布说明\\"。
Spring for Apache Kafka\\" 3.3.0的第一个发布候选版本\\"提供了缺陷修复、文档改进、依赖性升级和新特性,比如,新的KafkaMetricsSupport类,用于改进对度量指标的支持;在KafkaAdmin类中定义的createAdmin()方法上使用Java @Override注解的特性,以使用其他实现了Apache Kafka Admin接口的类。该版本还提供了与Spring Boot 3.4.0-RC1的完全集成。有关该版本的更多详细信息,请参阅发布说明\\"。
Spring for Apache Pulsar\\" 1.2.0的第一个发布候选版本\\"提供了依赖性升级和功能改进,例如,确保对Java String类中定义的toLowerCase()和toUpperCase()方法的所有调用均指定一个Java Locale类的实例,默认为Locale.ROOT;当使用lambda生产者定制器(lambda producer customizer)时,提供新日志以警告开发人员,从而提高他们的意识。有关此版本的更多详细信息,请参阅发布说明\\"。
同样,Spring for Apache Pulsar的1.1.5和1.0.11版本也已发布\\",其中包括依赖性升级以及前面提到的对toLowerCase()和toUpperCase()方法的使用。关于这些版本的更多详细信息,请参阅1.1.5版本\\"和1.0.11\\"版本的发布说明。
原文链接:
Spring News Roundup: Release Candidates for Spring Boot, Security, Auth Server, Modulith\\"
","description":"最近,Spring生态系统的活动较为频繁,重点发布了如下项目的候选版本:Spring Boot、Spring Security、Spring Authorization Server、Spring Integration、Spring Modulith、Spring Batch、Spring AMQP、Spring for Apache Kafka和Spring for Apache Pulsar。 Spring Boot\\n\\nSpring Boot\\" 3.4.0的第一个发布候选版本\\"提供了缺陷修复、文档改进、依赖性升级和许多新特性,比如…","guid":"https://www.infoq.cn/article/cI1GlrDNQ64xrzBP2kUp","author":"Michael Redlich","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-11-11T02:36:05.708Z","media":null,"categories":["编程语言"],"attachments":null,"extra":null,"language":null},{"title":"全球超万亿使用量的热门数据库,首次被大模型揪出了严重漏洞","url":"https://www.infoq.cn/article/Y9KuZsVlQ5YcowyYijcg","content":"谷歌的研究人员日前声称,他们首次利用大语言模型发现了一个重要漏洞。
在一篇博客文章中,谷歌表示,他们相信这是 AI agent在广泛使用的现实软件中发现此前未知的、可利用的内存安全问题的首个公开案例。具体来说,它在 SQLite 中发现了一个可被利用的堆栈缓冲区下溢漏洞。
这个漏洞在 10 月就被谷歌报告给 SQLite 开发团队,后者在同一天已经修复了它。由于漏洞在官方发布之前就被消除了,因此并没有影响到 SQLite 的用户。
这款基于大语言模型的漏洞挖掘 AI agent 名为“Big Sleep”,是谷歌的 Project Zero 和 DeepMind 合作的成果。据称,它是今年 6 月宣布的早期项目“Project Naptime”的延伸。
谷歌指出,在 8 月份的 DEFCON 安全会议上,负责创建 AI 辅助漏洞研究工具的网络安全研究人员在 SQLite 中发现了另一个问题,这激发了他们的团队去尝试看能否找到更严重的漏洞。
SQLite是一款开源的数据库引擎,\\"堆栈缓冲区下溢漏洞可能允许攻击者导致程序崩溃,甚至执行任意代码。进一步地说,崩溃或代码执行会发生在 SQLite 可执行文件(而非库)中,原因是在代码的某个地方,特殊值 -1 被意外地用作数组索引。
7476: struct sqlite3_index_constraint {\\n7477: int iColumn; /* Column constrained. -1 for ROWID */\\n7478: unsigned char op; /* Constraint operator */\\n7479: unsigned char usable; /* True if this constraint is usable */\\n7480: int iTermOffset; /* Used internally - xBestIndex should ignore */\\n7481: } *aConstraint; /* Table of WHERE clause constraints */
这种模式会产生一个潜在的边缘情况。但函数 seriesBestIndex 未能正确处理这个边缘情况,导致在处理对 rowid 列有约束的查询时,将负索引写入栈缓冲区。在团队提供给 agent 的构建中,启用了调试断言,这个条件在第 706 行的断言中得到了检查:
619 static int seriesBestIndex(\\n620 sqlite3_vtab *pVTab,\\n621 sqlite3_index_info *pIdxInfo\\n622 ){\\n...\\n630 int aIdx[7]; /* Constraints on start, stop, step, LIMIT, OFFSET,\\n631 ** and value. aIdx[5] covers value=, value>=, and\\n632 ** value>, aIdx[6] covers value<= and value< */\\n633 const struct sqlite3_index_constraint *pConstraint;\\n...\\n642 for(i=0; inConstraint; i++, pConstraint++){\\n643 int iCol; /* 0 for start, 1 for stop, 2 for step */\\n644 int iMask; /* bitmask for those column */\\n645 int op = pConstraint->op;\\n...\\n705 iCol = pConstraint->iColumn - SERIES_COLUMN_START;\\n706 assert( iCol>=0 && iCol<=2 );\\n707 iMask = 1 << iCol;\\n...\\n713 if( pConstraint->usable==0 ){\\n714 unusableMask |= iMask;\\n715 continue;\\n716 }else if( op==SQLITE_INDEX_CONSTRAINT_EQ ){\\n717 idxNum |= iMask;\\n718 aIdx[iCol] = i;\\n719 }\\n720 }
然而,在发布版本中,这个断言不存在。因此,在谷歌的测试中(这会因编译器和优化级别而异),在第 718 行的后续写入操作会破坏指向 pConstraint 的指针的最低有效 32 位,这将在下一次循环迭代中导致取消引用。这种漏洞可能会被利用。
不过,谷歌的研究人员也承认,这个漏洞的利用难度不小。
“Big Sleep”目前仍处于研究阶段,到目前为止,它使用带有已知漏洞的小型程序来评估其查找漏洞的能力。这是它的在真实世界环境中的首次实验。
在测试中,团队收集了 SQLite 代码库最近的几次提交。“在手动删除了琐碎的和仅用于文档的修改后,我们调整了 prompt,向 agent 提供了提交消息和更改的差异,并要求 agent 审查当前的代码库(在 HEAD)中是否存在可能未被修复的相关问题,”谷歌在博文中写道。
基于 Gemini 1.5 Pro 的大模型最终发现了这个漏洞。在博文中,“Big Sleep”团队还详细介绍了代理评估代码、发现漏洞、导致系统崩溃以及生成根本原因分析的步骤要点。详情可查看:https://googleprojectzero.blogspot.com/2024/06/project-naptime.html
像谷歌这样的许多公司使用一种称为“模糊测试”(Fuzzing)的过程,通过向软件提供随机或无效的数据来测试软件,以识别漏洞、触发错误或使程序崩溃。
但谷歌表示,模糊测试在“帮助防御者找到那些难以(或不可能)通过模糊测试发现的漏洞”方面做得还不够,并补充说,他们“希望 AI 能缩小这一差距”。
“我们认为这项工作具有巨大的防御潜力,”“Big Sleep”团队博客文章中宣称。“这个漏洞本身非常有趣,而且现有的 SQLite 测试基础设施(通过 OSS-Fuzz 和项目自己的基础设施)都没有发现这个问题,因此我们做了一些进一步的调查。”
值得注意的是,在 10 月,总部位于西雅图的 Protect AI 公司宣布了一款免费、开源的工具,声称可以在 Anthropic 的 Claude AI 模型的帮助下,在 Python 代码库中发现零日漏洞。这个工具名为 VulnHunter,根据其开发人员的说法,它已经在大型开源 Python 项目中发现了十多个零日漏洞。
根据谷歌的说法,这两个工具的目的不同。谷歌的一位发言人在接受《The Register》采访时强调,“我们在博客文章中的声明是,‘Big Sleep’在广泛使用的真实软件中发现了首个未知的、可被利用的内存安全问题。”“Python 的 LLM 发现的不是与内存安全相关的漏洞,而是不同类型的缺陷。”
“然而,我们想重申,这些都是高度实验性的结果,”谷歌团队写道。“‘Big Sleep’团队的立场是,Big Sleep Agent 目前针对特定目标的模糊测试工具在(发现漏洞)方面至少同样有效。”
参考链接:
https://www.theregister.com/2024/11/05/google_ai_vulnerability_hunting/
https://googleprojectzero.blogspot.com/2024/06/project-naptime.html
https://www.forbes.com/sites/daveywinder/2024/11/05/google-claims-world-first-as-ai-finds-0-day-security-vulnerability/
","description":"谷歌的研究人员日前声称,他们首次利用大语言模型发现了一个重要漏洞。 在一篇博客文章中,谷歌表示,他们相信这是 AI agent在广泛使用的现实软件中发现此前未知的、可利用的内存安全问题的首个公开案例。具体来说,它在 SQLite 中发现了一个可被利用的堆栈缓冲区下溢漏洞。\\n\\n这个漏洞在 10 月就被谷歌报告给 SQLite 开发团队,后者在同一天已经修复了它。由于漏洞在官方发布之前就被消除了,因此并没有影响到 SQLite 的用户。\\n\\n利用大模型发现漏洞:或致程序崩溃甚至执行任意代码\\n\\n这款基于大语言模型的漏洞挖掘 AI agent 名为“Big Sleep…","guid":"https://www.infoq.cn/article/Y9KuZsVlQ5YcowyYijcg","author":"罗燕珊","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-11-07T09:01:31.485Z","media":null,"categories":["数据库","开源"],"attachments":null,"extra":null,"language":null},{"title":"覆盖80%业务场景,原生鸿蒙出行、教育行业样板间专区上线","url":"https://www.infoq.cn/article/weoiQpwETixREpUJeYSZ","content":"华为原生鸿蒙之夜获得广泛关注,华为官宣鸿蒙生态设备数量已超过10亿台,鸿蒙原生应用和元服务数量已超过15000个,鸿蒙生态已进入飞速发展阶段。为更好地助力各行业开发者降本提效开发鸿蒙原生应用和元服务,华为开发者联盟生态市场(简称生态市场)近日上线了原生鸿蒙出行行业、教育行业“样板间”专区。
与此前已上线的金融-银行行业、新闻资讯行业、政务行业和文旅行业样板间专区一致,鸿蒙原生行业应用“样板间”整合了鸿蒙生态ISV伙伴提供的行业解决方案、官方提供的原生鸿蒙创新解决方案、HarmonyOS开放能力和HarmonyOS开发模板&组件等内容,以行业常见痛点场景为切入一站式解决行业客户通用开发问题。
本次全新上线的出行行业样板间\\"总体围绕“近站亮码、智慧助手、实况进度”三大关键词打造。针对用户高峰出行拥堵排队的问题,依托HarmonyOS桌面卡片、近场等创新能力,可在用户到达公交地铁站附近时,通过小艺建议推荐乘车码服务卡片,高效通行方便快捷;针对用户外地旅游乘坐公共交通线路不熟悉的问题也可通过小艺对话直接获取出行路线建议;针对用户打车、航班火车出行无法及时了解旅途进程的问题,依托实况窗可在熄屏、锁屏、状态栏等多位置展示关键事件的进展和变化信息如打车车辆信息、行程剩余距离、航班登机信息等,让用户一眼可见实时动态。
在教育行业样板间专区\\",基于原生鸿蒙操作系统的智能化特性,围绕“智慧助手、实况进度”的关键词打造,已完成80%高校日常业务场景覆盖,可助力开发者轻松打造智慧校园,让校园用户简化2倍的繁琐操作步骤。具体场景包括用户在使用校园服务时,常面临需求功能入口较深查找复杂的问题,此时用户可直接通过小艺对话预约校园服务、获取校园信息,一语即达服务功能;还有依托日历服务、实况窗等能力,帮助用户及时收到重要日程通知并便捷处理校园服务办理进度、维修服务进程等相关信息,提升信息露出率和服务处理效率。
在创新场景之外,本次上线的出行、教育行业样板间专区内还集成了丰富的行业开发模板,如公交地铁类、教育类行业模板等,相信将为开发者提供更加个性化的开发建议和资源匹配,进一步降低开发难度和开发成本,此前已上架的政务行业模板据开发者使用反馈可提升40%以上的开发效率。
感谢创造鸿蒙速度的每一位合作伙伴、开发者和用户。后续,华为开发者联盟生态市场\\"还将持续上线更多行业的“样板间”专区,持续助力千行万业加速鸿蒙化,欢迎开发者搜索进入“华为开发者联盟生态市场行业样板间专区”,共同打造更加繁荣、开放的鸿蒙生态。
","description":"华为原生鸿蒙之夜获得广泛关注,华为官宣鸿蒙生态设备数量已超过10亿台,鸿蒙原生应用和元服务数量已超过15000个,鸿蒙生态已进入飞速发展阶段。为更好地助力各行业开发者降本提效开发鸿蒙原生应用和元服务,华为开发者联盟生态市场(简称生态市场)近日上线了原生鸿蒙出行行业、教育行业“样板间”专区。 与此前已上线的金融-银行行业、新闻资讯行业、政务行业和文旅行业样板间专区一致,鸿蒙原生行业应用“样板间”整合了鸿蒙生态ISV伙伴提供的行业解决方案、官方提供的原生鸿蒙创新解决方案、HarmonyOS开放能力和HarmonyOS开发模板&组件等内容…","guid":"https://www.infoq.cn/article/weoiQpwETixREpUJeYSZ","author":"HarmonyOS","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-11-07T07:59:20.737Z","media":[{"url":"https://static001.geekbang.org/infoq/b8/b8473da9ef6d0242c1193854a6c77e7d.png","type":"photo","width":1045,"height":396,"blurhash":"L9OgpUDhIV-paK%2_4xu-QRONGWA"},{"url":"https://static001.geekbang.org/infoq/d8/d858bbfc326403da41004066d7ea95d3.png","type":"photo","width":927,"height":810,"blurhash":"LCQcuF^*Rl~pxsR.WBRjM|jFE1WC"},{"url":"https://static001.geekbang.org/infoq/02/02eb6ceef4ef2fdeb05e742cbcb69535.png","type":"photo","width":1045,"height":396,"blurhash":"L6OziM0JIU^,$x_4_4D%,mR4NGWm"},{"url":"https://static001.geekbang.org/infoq/f4/f445eb720aa97ce75434e106e1b5ca08.png","type":"photo","width":794,"height":682,"blurhash":"LIQA2A_N%gD*.9NKD+WEIVogNGIU"}],"categories":["华为","操作系统","HarmonyOS"],"attachments":null,"extra":null,"language":null},{"title":"QCon演讲实录丨徐广治:边缘云原生操作系统的设计与思考","url":"https://www.infoq.cn/article/KJKormWxuHxcJkPHyVkI","content":"10月18日,在 QCon 全球软件开发大会 2024(上海站),火山引擎边缘云资深架构师徐广治围绕火山引擎边缘计算产品背后的算力底座 - 边缘云原生操作系统,探讨如何实现算力服务的混合部署和跨区域弹性调度,以及在小型化、集成化、轻量化基础上的技术创新,并展开介绍了边缘云原生操作系统的研发动因、面临挑战、架构设计和未来演进方向。
演讲内容主要包括了五部分:边缘云行业现状和发展历程,边缘场景的技术挑战,边缘云原生操作系统,业务应用实践,演进和未来思考。
以下是演讲实录:
大家好,很高兴有机会和大家分享火山引擎边缘云在边缘计算场景架构设计上的思考和实践,我今天分享的主题是《边缘云原生操作系统设计与思考》。分享分为五个部分:
第一部分,边缘云当前的业务状态以及历史发展路径;第二部分,边缘场景存在的技术挑战和解决思路;第三部分,在技术挑战、业务发展的背景下,火山引擎边缘云的思考与实践,也就是边缘云原生操作系统;第四部分,云原生操作系统之上的应用,即边缘云的产品矩阵和行业应用;最后,回归技术主线,畅想边缘云技术架构的未来。
从 06 年 AWS 推出 EC2 、S3 到今天已经过去了 18 年,云计算早已不是一个新鲜词汇,从当前业务来看,我们能看到云计算从中心到中心+边缘的发展趋势,为什么会有这样的变化呢?在业务角度有三个关键的诱因:
第一,越来越多的本地化应用。最近 Meta 发布了新的 AR 智能眼镜,APPLE 也有 Vision Pro ,这些都是典型的 AR/VR 应用的场景,随着更多工业制造、网络直播、智慧园区、自动驾驶、云游戏等本地化应用的崛起,促使计算资源从中心走到边缘。第二,基础设施的演变。正因为应用就近部署的需求,基础设施正在从中心向边缘靠拢,形成靠近客户的三种边缘基础设施形态:现场边缘、近场边缘和云边缘,这三种基础设施分别提供不同的延时保证和资源,现场边缘的延时是 1-5 ms,近场边缘是 5-20 ms,云边缘是 20-40 ms。第三,算力和网络的结合。有了靠近用户的基础设施、广泛分布的网络和算力,企业因此产生了对最优算力访问链路的需求,期望能找到靠近客户的算力和靠近算力的存储,这就是算力和网络的融合。通过算网融合,可以为企业提供更好的云服务。
这三个业务诱因,驱动云计算向边缘迈进。
除了业务诱因,我们也观察到了业务驱动力之外的技术演进背景。从应用架构的角度来看,当前应用将看到三类资源:
终端资源:提供实时的服务响应,具备友好的硬件形态,可以是用户使用的手机、平板、车机等,能为应用提供最好的呈现,同时还具备通用的辅助算力;中心资源:提供弹性资源池,可以方便地进行数据计算和聚合,支持敏捷的开发流程;边缘资源:提供就近的接入服务,覆盖广域的城市和运营商,具备对整个网络的精确感知能力,可以快速找到就近的算力和资源。
传统的中心部署架构,已经不能充分利用云、边、端这三者的资源,不能充分发挥三者的组合优势,因此我们观察到应用正在从集中部署迈向云边端混合部署的新架构。
同时,云计算也开启了边缘时代。据 IDC 预估,到 2024 年底,全球在边缘计算上的开支将达到 2320 亿美元,另外,据 Gartner 预估,到 2025 年底,全球 75% 的企业生成数据将会在边缘产生和处理。另外,从市场发展上看,IDC 预估到 2026 年中国边缘云的市场增速年复合增长率可达到 40% 。在这样的蓬勃发展背后是越来越多业务和边缘的结合,这些业务的发展可分为三个阶段:萌芽期、爆发期、成熟期。随着时间的推移,像 vCDN、直播这类业务会趋于成熟,而像自动驾驶、AR 等业务将迎来爆发,共同推动边缘云的进一步扩张。
这里也跟大家简单介绍一下边缘云的发展历程。
阿卡迈在 1998 年首次提出了 CDN 的概念,从那之后,内容分发网络成为了 APP 、网站、客户端背后的基础服务,通过就近缓存内容,提升了数据的访问效率。到了 2002 年,微软和 IBM 与阿卡迈合作,将 .Net 和 J2EE 服务部署到了CDN PoP 节点,这形成了最早的边缘计算的概念。到 2009 年,CMU 提出了 Cloudlet 的概念,将 VM 与边缘基础设施结合,这就有了在边缘提供 IaaS 服务的雏形,到 2012 年,我们迎来了万物互联的物联网时代,也因此产生了处理海量数据的需求,于是雾计算、MEC 的概念相继出现,从那时到现在,我们迎来了云计算和边缘的结合。边缘云,在端和中心云之间,提供弹性、轻量、低延时的云服务。
了解了整个边缘云业务状态和发展历程之后,再来聊聊发展背后对技术上的挑战。从整体看,边缘场景有四个挑战,分别是海量节点管控、小型化约束、弱网环境、复合场景。
挑战一:海量节点管控。从宏观角度来看,要提供就近的算力和网络就要从地理位置上接近客户的业务,这意味着我们面对的是广域分布的物理资源。火山引擎边缘云在全球有 2500 多个节点,如何高效管理节点、如何调度节点上的异构资源,是关键挑战之一;挑战二:小型化约束。从节点本身来看,与传统中心云不同,单个边缘节点的资源是有限的,这就对我们管控的资源开销提出了要求,如何做到小型化、轻量化,如何做到最大限度售卖节点资源;挑战三:弱网环境。从网络环境上看,大多数边缘节点之间,以及节点和中心机房的连接,都采用公网通信,这导致了网络环境的问题,可能存在网络中断、连接不稳定的情况,也存在安全上的隐患;挑战四:复合场景。从业务维度来看的,当前面向的边缘业务场景比较复杂,需要技术具备较高灵活性,需要提供多形态算力支撑,包括虚拟机、裸金属、容器等等。还需要考虑不同硬件环境,比如 x86 arm,异构计算需要 GPU ,需要算力的 ASIC 。
首先,我们来看看如何纳管、调度广域分布的算力资源?两个非常关键的因素:抽象、编排。抽象意味着标准化,从资源维度出发,足够好的抽象和标准化才能形成统一的资源池,不同的 CPU 型号也可以通过抽象和统一的指令集来提供。从服务维度出发,基于多数量节点,每个节点部署着不同异构服务,好的服务抽象可以将服务原子化,从而为部署和运维提供便利。基于良好的抽象和编排能力,就能实现资源和服务的标准、统一,以及服务的灵活组合,从而达到为客户提供差异化算力的目的。因此在管控关于分布的算力资源,好的抽象和编排能力很重要。
小型化是边缘场景特有的问题,相较于传统中心云环境,单个边缘节点的资源有限,如何在这个背景下为客户最大化提供可售卖资源就成了一个问题。要解决这个问题,有两个同时要做的事情:
第一点是按需混部。每个节点可以按照业务需求发布算力和对应服务,例如不需要云盘就不用部署云盘,按需混部服务是做到小型化的路径之一。混部又包含两点,第一是算力的混部,虚拟机、容器实例、函数这些算力本身就是混部的,混合部署在同样的资源池上。其次是服务的混部,例如本地盘、云盘这类存储服务,VPC、LB 等网元服务,这些服务按照节点的需求混合部署,共享同个物理资源。算力和服务混部的底层依赖统一资源池和统一调度,也需要关联的资源隔离机制和对应系统实现。第二点是在管控层面实现极致的轻量化。这又有两个要点,第一点相对传统,是做边缘管控组件的轻量化,降低组件数量和组件的资源开销。另一点更重要,就是要做管控分层,把非必要逻辑从边缘抽离出来,形成中心/区域 + 边缘的多级管控形态,边缘仅保留数据缓存和基础能力,通过这种方式来大幅降低边缘开销。
边缘节点之间、边缘节点与中心节点之间大多数采用公网连接。然而,公网链路上存在很多传输的不确定性,有可能存在传输链路抖动、机房故障、区域断网等情况,怎么在弱网环境下保证服务的连续性?依靠边缘的两个核心要点:
第一是边缘自治。边缘自治意味在网络抖动/中断的情况下边缘集群仍能继续维持集群内算力服务运行。;第二是系统化的数据传输保障方案。怎么保证云边服务之间、算力应用之间的网络通信稳定、可靠?这就需要系统化的解决方案 - 云边通道。云边通道在高可用维度提供在机房故障,网络链路故障等场景下的数据传输能力,同时也提供了鉴权和加解密能力保障了公网传输的数据安全。
为了支持边缘泛 CDN、云游戏、车联网、AIGC 等广泛应用场景,边缘侧需要提供虚拟机/裸金属/容器/函数多种算力形态,叠加底层异构算力资源,这也要求技术架构具备足够广的覆盖面和较高的灵活性。
上述技术挑战促使着边缘技术架构的持续演进,大体可以分为三个阶段:
第一个阶段是面向资源的传统虚拟化,主要方式是通过 hypervisor 和上层管控实现资源隔离,这里比较有代表性的是基于 OpenStack 的传统 IaaS 架构;第二个阶段是随着 K8s 兴起的云原生技术,借助云原生可以降低运维复杂度,实现面向应用的统一调度、统一编排,但是依然没法彻底应对上述边缘场景的技术挑战,这也就引出了架构演进的第三个阶段;第三个阶段是面向边缘场景和应用,通过将云原生与边缘特性结合,形成边缘独有的技术方案,也就是边缘原生,在火山引擎的落地实践,就是我们的边缘云原生操作系统。
边缘云原生操作系统,统一纳管了字节跳动边缘计算硬件资源,在小型化、集成化、轻量化的基础上,为业务就近提供虚拟机、裸金属、容器等多形态算力,实现算力服务混合部署、跨区域弹性调度。
边缘云原生操作系统拥有 4 个核心特点:
统一资源纳管&调度:纳管全球边缘云硬件资源,为边缘应用提供统一资源调度支撑算力&服务按需混部:按需混部单节点计算实例和关联服务,降低节点资源开销,提高服务灵活性云边分层轻量化管控:部分上移边缘管控逻辑,在保证自治能力的基础上最大化节点可售卖资源云边&边边协同支持:基于全球云网基础设施和云边、边边数据通道,提供可靠数据传输支持
从架构上来看,边缘云原生操作系统有八个组成部分:
编排中心:面向应用、服务编排需求,编排中心提供集群编排、多应用编排、中间件编排、多集群管理等核心能力,基于这些能力,实现服务的按需混部和对客户交付侧的支撑;调度中心:调度中心通过在线、离线调度,实现对异构资源的池化和统一调配,保障资源交付效率及资源交付稳定性,支撑持续资源运营、治理;可观测中心:要掌控边缘离散分布的算力资源和支撑服务状态,系统提供的可观测能力就非常关键,可观测中心支持资源、服务、产品观测,提供一站式观测平台,支撑对外可观测产品和内部系统运维及质量保障;运维中心:基于编排中心、可观测中心能力,运维中心统一支撑云原生操作系统自身组件和上层算力应用日常运维和稳定性保障;云边中间件:提供中间件统一接入平台,具备云边通道等边缘场景核心能力,支撑云边、边边场景编排、运维、服务、数据多维度协同;边缘轻量管控:指算力产品底层依赖的计算、存储、网络管控,为了实现边缘的轻量化,实现了两个层面的工作,一个是分层管控,把业务逻辑、数据处理、数据持久化上移,另一个是精简管控逻辑本身;边缘云原生套件:这部分是定制的云原生组件,包含基础的 K8s、ETCD 等服务,定制化的工作一是保障组件在边缘场景下的安全性和稳定性,二是在资源占用和带宽占用维度对组件做的轻量化;边缘轻量基础环境:标准化的操作系统环境、内核、固件基线,包含在边缘场景下对操作系统层面进行的的轻量化裁剪,也包含支撑算力的高性能虚拟化实现;
在八大能力之下是底层的资源池,包括现场边缘、近场边缘、云边缘的硬件资源,在这之上是对外提供的不同形态的算力产品,包括边缘计算节点(虚拟机/裸金属)、边缘容器、边缘函数及周边服务,这些共同构成了小型化、集成化、轻量化的边缘云原生操作系统。
前述介绍边缘云原生操作系统的一大特点是建立在资源池之上的统一调度。调度面向资源交付场景,为客户和内部服务统一交付计算、存储、网络等资源,同时保障资源交付的效率和稳定性,持续优化碎片率并提供对应运营能力。
在统一资源交付背后,是在线调度和离线调度两大核心能力,在线调度负责实时为业务提供资源,离线调度负责资源运营以及为在线调度提供调度推荐。目前支持的调度域覆盖全局、区域、节点内三个维度,针对客户弹性需求,可以提供跨节点的算力资源交付。在线调度、离线调度之下是为调度提供数据支撑的库存中心系统,这里维护了线上的实时资源情况,支持对应的审计、规划和资源流转,同时为了支撑离线调度,库存中心也维护了离线计算所依赖的数据仓库,包含客户、业务画像及从实时库同步的离线信息。
为应对边缘小型化约束,边缘云原生操作系统通过运维中心和编排中心的配合实现算力和服务的按需混部,其有两个关键实现:
一是算力实例和依赖服务共享同个资源池,虚拟机、容器实例可以和存储、网络、管控等服务分布到同个物理资源上;二是服务的按需部署,运维中心结合编排中心的能力,实现集群功能的定制化,每个集群有自己的集群模板,集群模板动态可同时关联多应用编排,实现根据集群业务需求部署必要服务,从而减少非必要服务的资源开销。
为实现轻边缘,边缘云原生操作系统在各个细分管控均引入了分层设计。通过将管控拆分为中心控制、区域、边缘管控,边缘仅保留最必要的处理逻辑,其他数据处理、持久化和业务逻辑上移至中心或区域管控,以此实现了边缘的极致轻量化。图里举了一个例子,在 IaaS 管控这一侧,拆分出中心控制器和边缘管控,裸金属的持久化数据放在中心管控维护,边缘维护的仅仅是缓存的元数据信息。
这里针对 IaaS 管控再进行一下延展。我们自研了一套 IaaS 的云原生管控,针对虚拟机,结合了云原生运维上的便利性和调度能力,以及传统虚拟化的实现,实现了数据面在容器之外,虚拟机生命周期与容器解耦,通过自研 Resource Manager 来管理单机资源,并实现和统一调度对接;针对裸金属,我们把数据持久化和处理尽量上移至中心管控,实现了边缘裸金属管控的轻量化。结合了分层管控和自研管控,真正在管控这一侧做到了轻边缘。
为了应对弱网环境带来的挑战,边缘云原生操作系统在中间件维度建设了云边通道方案,通过云边通道,在高可用维度,提供了机房容灾,网络容灾的能力;在安全性维度,提供了必要的鉴权和隔离支持。云边通道覆盖了边缘不同的协同场景,包含编排的协同、服务间的协同、运维协同和数据协同。通过云边通道的整体解决方案,我们实现了在边缘网络环境下对客户及内部业务间通信的有效保障。
在边缘云原生操作系统内,我们提供了资源、服务、产品的全面一站式观测,通过数据采集、治理、到标准化观测,到业务能力打通,可观测这一侧支撑了边缘云操作系统的自身运维、稳定性建设,也支撑了上层服务的质量保障。
最后是支撑边缘云操作系统系统运行的关键子系统 - 运维中心,运维中心覆盖场景包括服务和资源交付、运营分析、稳定性保障等。运维能力的建设搭建在其他基础能力之上,比如基于编排中心,实现了集群编排和多集群管理。运维中心的原子能力还包括 CMDB 、软件包管理、配置单元、作业管理等,通过原子能力、服务能力打造出来的整体运维能力,支撑了边缘云操作系统和其上应用/服务的稳定运行和日常发布。
有了对边缘云原生操作系统特性、架构和子系统的了解,下面来看看边缘云原生操作系统实际落地的业务场景 - 火山引擎边缘云。
首先来总体了解一下火山引擎边缘云。火山引擎边缘云,融合异构算力和边缘网络,构建在大规模边缘基础设施之上的云计算服务,覆盖了现场边缘到云边缘,形成了以边缘位置的计算、分发、网络、存储、安全、智能为核心能力的新一代分布式云计算平台,这个平台的底座就是边缘云原生操作系统,目前,火山引擎边缘云在全球覆盖了 2500+ 节点,拥有 150T+ 的储备带宽。
火山引擎边缘云基于覆盖现场边缘、近场边缘、云边缘的基础设施,在核心底座边缘云原生操作系统之上,提供计算服务和网络服务。计算服务分为通用化计算服务和场景化计算服务,通用化计算服务又包括边缘计算节点,虚拟机、裸金属、x86 各种各样的 IaaS 算力、包括安全容器和普通容器在内的边缘容器实例,以及边缘函数;场景化计算服务则包括支持面向 AI 场景的边缘智能。在网络服务这一侧,我们也支持两类服务,一类是全球一体化内容分发与加速服务,包括火山引擎 CDN 、 BytePlus CDN 和多云 CDN,第二类是基于边缘网络原生的全域联网加速解决方案类,包括全站加速DCDN、全球加速GA、边缘联网ECW。在计算服务和网络服务之上,构建了我们的行业解决方案,涵盖音视频、应用分发、云游戏、智慧城市等等。
目前,火山引擎边缘云已在多个行业领域实现应用落地,包括但不限于:泛互联网领域的视频直播、实时音视频、影视娱乐、移动终端、在线教育、电商零售和媒资信息处理;汽车行业的辅助驾驶和车联网技术;媒体行业的数字人和影视渲染;游戏行业的游戏加速、AR/VR体验;以及金融行业的税票政务本地化和分布式计算等。
面向未来,我们将从以下三个维度持续提升产品与服务能力:
在地域覆盖方面,随着边缘云服务内外部客户业务的增长,边缘云覆盖的节点范围也将持续扩大。火山引擎边缘云将从节点管理规模和合规性两个技术维度,满足业务发展诉求。在技术链路方面,随着部分业务场景的成熟,在成本、性能等核心技术点的建设将成为边缘云的强技术竞争力和业务探索的基础。火山引擎边缘云将持续建设该部分能力,帮助业务实现单位性能的大幅提升。在前沿技术领域,随着人工智能的发展,大量的 AIGC(AI生成内容)将推动 AI 计算能力向边缘端延伸,以降低带宽需求和减少延迟。火山引擎边缘云也将持续探索边缘计算与 AI 技术的融合,致力于让 AI 触手可及,从而为用户带来更加卓越的体验。
同时,边缘云原生操作系统针对追求极致轻量化、提供高性价比边缘算力的目标,未来将在持续优化基础设施成本的基础上,构建更轻量基础环境,叠加细粒度资源管理、轻量化管控、按需混合部署的持续建设,结合资源调度优化,实现物理资源的最大化利用及客户业务资源的最优配比。
","description":"10月18日,在 QCon 全球软件开发大会 2024(上海站),火山引擎边缘云资深架构师徐广治围绕火山引擎边缘计算产品背后的算力底座 - 边缘云原生操作系统,探讨如何实现算力服务的混合部署和跨区域弹性调度,以及在小型化、集成化、轻量化基础上的技术创新,并展开介绍了边缘云原生操作系统的研发动因、面临挑战、架构设计和未来演进方向。 演讲内容主要包括了五部分:边缘云行业现状和发展历程,边缘场景的技术挑战,边缘云原生操作系统,业务应用实践,演进和未来思考。\\n\\n以下是演讲实录:\\n\\n大家好,很高兴有机会和大家分享火山引擎边缘云在边缘计算场景架构设计上的思考和实践…","guid":"https://www.infoq.cn/article/KJKormWxuHxcJkPHyVkI","author":"火山引擎","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-11-07T06:26:33.436Z","media":[{"url":"https://static001.geekbang.org/infoq/21/21aedd74ff1ca0eced1a77352f1bd89e.webp","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/56/5626d9bc560882b1e563872e8e118051.webp","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/d5/d59b17f503a161705b76383599d199f7.webp","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/1e/1e7f9ba90c290feb8ee8446d21d72286.webp","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/dd/ddb8e07705e1e87ff2d70e233e500618.webp","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/4c/4cf72979d4a339a3ce74a28e22758e22.webp","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/18/180d77c551b27fe6f79a2f95d6f03ae2.webp","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/7f/7fac7f34dc6756b96e59640097db8acd.webp","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/e1/e136dc70ddf1795f3299e820d75fb591.webp","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/c9/c9ebbcf87b686dcf9b12776e00aff300.webp","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/75/753c683e974f58ebd8f2c7332b62e2dc.webp","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/38/383c685f8881e7ab02b88604ec06e598.webp","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/5c/5c376d1bb8d90e67f3b62a2c4c4ba72c.webp","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/c6/c6af079af3080ef4373c4aecc77c479c.webp","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/c6/c62ba8eb364abb19b1b786ac72f54106.webp","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/77/779e1a20937afa0c2a91e70d1951b7d1.webp","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/33/336ae9caf6e2ba099c4342226e4a4bf8.webp","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/6b/6be2413613f34e318b59b010720fa99b.webp","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/af/af1fc8bb4f827b401996b2ec9a580ca1.webp","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/90/903750423aa93549204c65e45486993d.webp","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/7e/7e5eb9ea93a715cfe3de65a4c37e411b.webp","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/4c/4c43e360f780b7888d3a52f6b5131099.webp","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/e4/e410045de99455a388fc51a2b6d48109.webp","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/e8/e804cac2a4f34d2f6d89173c12bbb0a2.webp","type":"photo","width":0,"height":0,"blurhash":""}],"categories":["字节跳动","云计算","操作系统"],"attachments":null,"extra":null,"language":null},{"title":"解析Go切片:为何按值传递时会发生改变?|得物技术","url":"https://www.infoq.cn/article/e7d65de175b0e4b6c4f166f6c","content":"在Go语言中,切片是一个非常常用的数据结构,很多开发者在编写代码时都会频繁使用它。尽管切片很方便,但有一个问题常常让人感到困惑:当我们把切片作为参数传递给函数时,为什么有时候切片的内容会发生变化?这让很多人一头雾水,甚至在调试时浪费了不少时间。
这篇文章简单明了地探讨这个问题,揭示切片按值传递时发生变化的原因。我们通过一些简单的示例,帮助大家理解这一现象是如何发生的,以及如何在实际开发中避免相关的坑。希望这篇文章能让你对Go切片有更清晰的认识,少走一些弯路!
在开始之前我们先来看几则单测,思考一下切片调用reverse之后会发生什么样的变化?为什么会有这样的变化?
func TestReverse(t *testing.T) {\\n var s []int\\n for i := 1; i <= 3; i++ {\\n s = append(s, i)\\n }\\n reverse(s)\\n}\\n\\n\\nfunc reverse(s []int) {\\n for i, j := 0, len(s)-1; i < j; i++ {\\n j = len(s) - (i + 1)\\n s[i], s[j] = s[j], s[i]\\n }\\n}\\n
func TestReverse2(t *testing.T) {\\n var s []int\\n for i := 1; i <= 3; i++ {\\n s = append(s, i)\\n }\\n reverse2(s)\\n}\\n\\n\\nfunc reverse2(s []int) {\\n s = append(s, 4)\\n for i, j := 0, len(s)-1; i < j; i++ {\\n j = len(s) - (i + 1)\\n s[i], s[j] = s[j], s[i]\\n }\\n}\\n
func TestReverse3(t *testing.T) {\\n var s []int\\n for i := 1; i <= 3; i++ {\\n s = append(s, i)\\n }\\n reverse3(s)\\n}\\n\\n\\nfunc reverse3(s []int) {\\n s = append(s, 4, 5)\\n for i, j := 0, len(s)-1; i < j; i++ {\\n j = len(s) - (i + 1)\\n s[i], s[j] = s[j], s[i]\\n }\\n}\\n
带着上面的疑问,接下来我们回顾一下切片的基础知识点。
type slice struct {\\n array unsafe.Pointer\\n len int\\n cap int\\n}\\n
Go切片的底层结构由以下三个部分组成:
指针(unsafe.Pointer):指向底层数组的第一个元素。如果切片的长度为 0,那么指针可以是nil。这个指针允许切片访问底层数组中的元素。长度(len):切片中实际包含的元素个数。通过len(slice)可以获取切片的长度。长度决定了切片在进行迭代或访问元素时的范围。容量(cap):切片底层数组的大小,表示切片可以增长的最大长度。可以通过cap(slice)获取容量。当切片的长度达到容量时,使用append函数添加更多元素时,Go会新分配一个更大的数组并复制现有元素。
一个切片的示意图如下:
func TestCreate(t *testing.T) {\\n slice := []int{1, 2, 3}\\n fmt.Printf(\\"len=%d, cap=%d, slicePointer=%p, sliceArrayPointer=%p\\\\n\\",\\n len(slice), cap(slice), &slice, slice)\\n}\\n
上述示例代码运行输出如下:
len=3, cap=3, slicePointer=0xc0000980d8, sliceArrayPointer=0xc0000b2048\\n
此时创建出来的切片对应图示如下:
直接创建切片时,会为切片的底层数组开辟内存空间并使用指定的元素对数组完成初始化,且创建出来的切片的len等于cap等于初始化元素的个数。
func TestCreate(t *testing.T) {\\n originArray := [3]int{1, 2, 3}\\n slice := originArray[:]\\n fmt.Printf(\\"originArrayPointer=%p\\\\n\\", &originArray)\\n fmt.Printf(\\"len=%d, cap=%d, slicePointer=%p, sliceArrayPointer=%p\\\\n\\",\\n len(slice), cap(slice), &slice, slice)\\n}\\n
上述示例代码运行打印如下:
originArrayPointer=0xc000010198\\nlen=3, cap=3, slicePointer=0xc0000080f0, sliceArrayPointer=0xc000010198\\n
此时创建出来的切片对应图示如下:
从整个数组切,实际就是切片直接使用了这个数组作为底层的数组。
func TestCreate(t *testing.T) {\\n originArray := [6]int{1, 2, 3, 4, 5, 6}\\n slice := originArray[:3]\\n fmt.Printf(\\"originArrayPointer=%p\\\\n\\", &originArray)\\n fmt.Printf(\\"len=%d, cap=%d, slicePointer=%p, sliceArrayPointer=%p\\\\n\\",\\n len(slice), cap(slice), &slice, slice)\\n}\\n
上述在切数组时,没有指定数组的开始索引,表示从索引0开始切(inclusive),指定了数组的结束索引,表示切到结束索引的位置(exclusive),运行代码输出如下:
originArrayPointer=0xc0000144c0\\nlen=3, cap=6, slicePointer=0xc0000080f0, sliceArrayPointer=0xc0000144c0\\n
此时创建出来的切片对应图示如下:
从前到后切数组得到的切片,len等于切的范围的长度,对应示例中索引0(inclusive)到索引2(exclusive)的长度3,而cap等于切的开始位置(inclusive)到数组末尾(inclusive)的长度6。
func TestCreate(t *testing.T) {\\n originArray := [6]int{1, 2, 3, 4, 5, 6}\\n slice := originArray[3:]\\n fmt.Printf(\\"originArrayPointer=%p\\\\n\\", &originArray)\\n fmt.Printf(\\"len=%d, cap=%d, slicePointer=%p, sliceArrayPointer=%p\\\\n\\",\\n len(slice), cap(slice), &slice, slice)\\n}\\n
上述在切数组时,指定了数组的开始索引,表示从索引3(inclusive)开始切,没有指定数组的结束索引,表示切到数组的末尾(inclusive),运行代码输出如下:
originArrayPointer=0xc0000bc060\\nlen=3, cap=3, slicePointer=0xc0000980d8, sliceArrayPointer=0xc0000bc078\\n
此时创建出来的切片对应图示如下:
从数组中间切到最后得到的切片,len等于cap等于切的范围的长度,对应示例中索引3(inclusive)到数组末尾(inclusive)的长度3。并且由上述图示可以看出,切片使用的底层数组其实还是被切的数组,只不过使用的是被切数组的一部分。
func TestCreate(t *testing.T) {\\n originArray := [6]int{1, 2, 3, 4, 5, 6}\\n slice := originArray[2:5]\\n fmt.Printf(\\"originArrayPointer=%p\\\\n\\", &originArray)\\n fmt.Printf(\\"len=%d, cap=%d, slicePointer=%p, sliceArrayPointer=%p\\\\n\\",\\n len(slice), cap(slice), &slice, slice)\\n}\\n
上述在切数组时,指定了数组的开始索引,表示从索引2(inclusive)开始切,也指定了数组的结束索引,表示切到数组的索引5的位置(exclusive),运行代码输出如下:
originArrayPointer=0xc0000bc060\\nlen=3, cap=4, slicePointer=0xc0000980d8, sliceArrayPointer=0xc0000bc070\\n
此时创建出来的切片对应图示如下:
从数组切一段得到的切片,len等于切的范围的长度,对应示例中索引2(inclusive)到索引5(exclusive)的长度3,cap等于切的开始位置(inclusive)到数组末尾(inclusive)的长度4。切片使用的底层数组还是被切数组的一部分。
func TestCreate(t *testing.T) {\\n originArray := [6]int{1, 2, 3, 4, 5, 6}\\n originSlice := originArray[:]\\n derivedSlice := originSlice[2:4]\\n fmt.Printf(\\"originArrayPointer=%p\\\\n\\", &originArray)\\n fmt.Printf(\\"originSlice: len=%d, cap=%d, slicePointer=%p, sliceArrayPointer=%p\\\\n\\",\\n len(originSlice), cap(originSlice), &originSlice, originSlice)\\n fmt.Printf(\\"derivedSlice: len=%d, cap=%d, slicePointer=%p, sliceArrayPointer=%p\\\\n\\",\\n len(derivedSlice), cap(derivedSlice), &derivedSlice, derivedSlice)\\n}\\n
上述示例代码中,originSlice是切数组originArray得到的切片,derivedSlice是切切片originSlice得到的切片,运行代码输出如下:
func TestCreate(t *testing.T) {\\n slice := make([]int, 3, 5)\\n fmt.Printf(\\"slice: len=%d, cap=%d, slicePointer=%p, sliceArrayPointer=%p, slice=%v\\\\n\\",\\n len(slice), cap(slice), &slice, slice, slice)\\n}\\n
此时创建出来的切片对应图示如下:
从切片切得到切片后,两个切片会使用同一个底层数组,区别就是可能使用的是底层数组的不同区域,因此如果其中一个切片更改了数据,而这个数据恰好另一个切片可用访问,那么另一个切片访问该数据时就会发现数据发生了更改。但是请注意,虽然两个切片使用同一个底层数组,但是切片的len和cap都是独立的,也就是假如其中一个切片通过类似于append() 函数导致len或者cap发生了更改,此时另一个切片的len或者cap是不会受影响的。
make() 函数专门用于为slice,map和chan这三种引用类型分配内存并完成初始化,make() 函数返回的就是引用类型对应的底层结构体本身,使用make() 函数创建slice的示例代码如下所示:
func TestCreate(t *testing.T) {\\n slice := make([]int, 3, 5)\\n fmt.Printf(\\"slice: len=%d, cap=%d, slicePointer=%p, sliceArrayPointer=%p, slice=%v\\\\n\\",\\n len(slice), cap(slice), &slice, slice, slice)\\n}\\n
上述示例代码中,会使用make() 函数创建一个int类型的切片,并指定len为3(第二个参数指定),cap为5(第三个参数指定),其中可以不指定cap,此时cap会取值为len。运行代码输出如下:
slice: len=3, cap=5, slicePointer=0xc0000980d8, sliceArrayPointer=0xc0000bc060, slice=[0 0 0]\\n
此时访问索引3或索引4的元素,会引发panic:
func TestCreate(t *testing.T) {\\n slice := make([]int, 3, 5)\\n fmt.Printf(\\"slice: len=%d, cap=%d, slicePointer=%p, sliceArrayPointer=%p, slice=%v\\\\n\\",\\n len(slice), cap(slice), &slice, slice, slice)\\n fmt.Printf(\\"%p\\\\n\\", &slice[3])\\n fmt.Printf(\\"%p\\\\n\\", &slice[4])\\n}\\n
panic: runtime error: index out of range [3] with length 3\\n
在Go语言中,当使用append()函数向切片添加元素时,如果切片的当前长度达到了它的容量,Go会自动触发扩容。扩容是指创建一个新的更大的底层数组,并将原有元素复制到新数组中。以下是关于切片触发扩容的详细说明。
当调用append()函数,如果当前长度小于容量,可以直接在底层数组中添加新元素;当切片的长度(len)达到或超过它的容量(cap)时,就会触发扩容。
扩容操作
Go 会分配一个新的底层数组。原有的元素会被复制到新的数组中。切片的指针会更新为指向新的底层数组,长度和容量也会相应更新。
最新的扩容规则在1.18版本中就已经发生改变了,具体可以参考一下这个 commit:runtime: make slice growth formula a bit smoother。
在之前的版本中:对于<1024个元素,增加2倍,对于>=1024个元素,则增加1.25倍。而现在,使用更平滑的增长因子公式。在256个元素后开始降低增长因子,但要缓慢。
它还给了个表格,写明了不同容量下的增长因子:
从这个表格中,我们可以看到,新版本的切片库容,并不是在容量小于1024的时候严格按照2倍扩容,大于1024的时候也不是严格地按照1.25倍来扩容;在slice.go源码中也验证了这一点。
// nextslicecap computes the next appropriate slice length.\\nfunc nextslicecap(newLen, oldCap int) int {\\n newcap := oldCap\\n doublecap := newcap + newcap\\n if newLen > doublecap {\\n return newLen\\n }\\n\\n\\n const threshold = 256\\n if oldCap < threshold {\\n return doublecap\\n }\\n for {\\n // Transition from growing 2x for small slices\\n // to growing 1.25x for large slices. This formula\\n // gives a smooth-ish transition between the two.\\n newcap += (newcap + 3*threshold) >> 2\\n\\n\\n // We need to check `newcap >= newLen` and whether `newcap` overflowed.\\n // newLen is guaranteed to be larger than zero, hence\\n // when newcap overflows then `uint(newcap) > uint(newLen)`.\\n // This allows to check for both with the same comparison.\\n if uint(newcap) >= uint(newLen) {\\n break\\n }\\n }\\n\\n\\n // Set newcap to the requested cap when\\n // the newcap calculation overflowed.\\n if newcap <= 0 {\\n return newLen\\n }\\n return newcap\\n}\\n
上面说到:一旦触发扩容,会创建新容量大小的数组,然后将老数组的数据拷贝到新数组上,再然后将附加元素添加到新数组中,最后切片的array指向新数组。也就是说,切片扩容会导致切片使用的底层数组地址发生变更,我们通过代码来了解这一过程:
func TestSliceGrow(t *testing.T) {\\n // 原始数组\\n originArray := [6]int{1, 2, 3, 4, 5, 6}\\n // 原始切片\\n originSlice := originArray[0:5]\\n // 打印原始切片和原始数组的信息\\n fmt.Printf(\\"len=%d, cap=%d, slicePointer=%p, sliceArrayPointer=%p, originArrayPointer=%p\\\\n\\",\\n len(originSlice), cap(originSlice), &originSlice, originSlice, &originArray)\\n // 第一次append不会触发扩容\\n firstAppendSlice := append(originSlice, 7)\\n // 打印第一次Append后的切片和原始数组的信息\\n fmt.Printf(\\"len=%d, cap=%d, slicePointer=%p, sliceArrayPointer=%p, originArrayPointer=%p\\\\n\\",\\n len(firstAppendSlice), cap(firstAppendSlice), &firstAppendSlice, firstAppendSlice, &originArray)\\n // 第二次append会触发扩容\\n secondAppendSlice := append(firstAppendSlice, 8)\\n // 打印第二次Append后的切片和原始数组的信息\\n fmt.Printf(\\"len=%d, cap=%d, slicePointer=%p, sliceArrayPointer=%p, originArrayPointer=%p\\\\n\\",\\n len(secondAppendSlice), cap(secondAppendSlice), &secondAppendSlice, secondAppendSlice, &originArray)\\n}\\n
运行上面代码输出如下:
len=5, cap=6, slicePointer=0xc0000980d8, sliceArrayPointer=0xc0000bc060, originArrayPointer=0xc0000bc060\\nlen=6, cap=6, slicePointer=0xc000098108, sliceArrayPointer=0xc0000bc060, originArrayPointer=0xc0000bc060\\nlen=7, cap=12, slicePointer=0xc000098138, sliceArrayPointer=0xc0000862a0, originArrayPointer=0xc0000bc060\\n
在示例代码中,切数组originArray得到的切片如下所示:
第一次append元素后,切片如下所示:
第二次append元素时,会触发扩容,扩容后的切片如下所示:
可见,扩容后切片使用了另外一个数组作为了底层数组。对扩容之后的切片任何操作将不再影响原切片;反之:扩容之前,对新切片的新增和修改影响的是底层数组,同时也会影响引用了该数组的任何切片。
现在,让我们回顾一下文章开头提到的三个单元测试,运行它们后得到的结果是否符合你的预期?结合我们对切片创建、初始化和扩容的基础知识,你是否能理解为何切片在传递时是值传递,但原始切片中的元素却可能会发生变化?
这篇文章通过简单明了的示例,深入分析了Go语言中切片作为参数传递时值变化的问题。揭示了切片的运行机制,帮助开发者理解为什么在函数内部对切片的修改会影响到原始切片的内容。这样的分析旨在消除开发中遇到的困惑,为实际开发提供更清晰的指导。
最重要的是,希望这篇文章能够传达一个信息:当你对某个现象的原因尚不完全理解时,花时间去深入探究是非常值得的。这种探究不仅能提升你的编程能力,更能培养解决问题的能力。
*文/徒徒
本文属得物技术原创,更多精彩文章请看:得物技术\\"
未经得物技术许可严禁转载,否则依法追究法律责任
","description":"在Go语言中,切片是一个非常常用的数据结构,很多开发者在编写代码时都会频繁使用它。尽管切片很方便,但有一个问题常常让人感到困惑:当我们把切片作为参数传递给函数时,为什么有时候切片的内容会发生变化?这让很多人一头雾水,甚至在调试时浪费了不少时间。 这篇文章简单明了地探讨这个问题,揭示切片按值传递时发生变化的原因。我们通过一些简单的示例,帮助大家理解这一现象是如何发生的,以及如何在实际开发中避免相关的坑。希望这篇文章能让你对Go切片有更清晰的认识,少走一些弯路!\\n\\n在开始之前我们先来看几则单测,思考一下切片调用reverse之后会发生什么样的变化…","guid":"https://www.infoq.cn/article/e7d65de175b0e4b6c4f166f6c","author":"得物技术","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-11-07T06:08:24.387Z","media":[{"url":"https://static001.geekbang.org/infoq/41/412087456c63f7461b7dc6a67e630c2c.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/e7/e747bbb723f9f6442249bee7bf0a715f.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/52/5288615156907e8242c0ddf9920bbf04.jpeg","type":"photo","width":2156,"height":648,"blurhash":"LRRysRxuof%MV-ofWBWB%Mayj[ay"},{"url":"https://static001.geekbang.org/infoq/8d/8d68779506c8312bd577783da8013858.jpeg","type":"photo","width":3180,"height":780,"blurhash":"LbSPX*%Lj@%Lt0j?j@j?-@j]a#j]"},{"url":"https://static001.geekbang.org/infoq/20/208d8cb6dbe5d888ecc347c7eb1593fe.jpeg","type":"photo","width":3168,"height":824,"blurhash":"LTRW3dxwj]%L?cobV[a$?wt1t6kD"},{"url":"https://static001.geekbang.org/infoq/b7/b7cb3265c4df9a25abfa3b287fc61757.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/b0/b0035f413dda774002f25f405525b79a.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/74/74526c4983ab7d41a4aec30d0c10550e.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/c7/c7d2848d2e4e22acf61418f42faae5f5.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/2d/2d1bb587c5c9577ac1a3cb54cf0d6abc.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/b1/b1081b552aad692c5980b1a117f29ac4.png","type":"photo","width":0,"height":0,"blurhash":""}],"categories":["编程语言","golang","扩容","切片"],"attachments":null,"extra":null,"language":null},{"title":"暂时 ID:Cloudflare 的最新欺诈检测工具","url":"https://www.infoq.cn/article/FxgceKNMZN2JkYeZwrkw","content":"在最近的生日周活动期间,Cloudflare 推出了一项用于欺诈检测的新功能,暂时 ID(Ephemeral IDs)。该工具通过将行为与特定的客户端而不是 IP 地址进行关联来识别欺诈活动,无论该欺诈活动是来自机器人还是人类。
通过 Turnstile 站点验证响应,这项新的识别技术旨在解决攻击者轮换大量 IP 地址以逃避标准 WAF 监控技术的常见问题。由于暂时 ID(Ephemeral IDs)是基于 IP 地址之外的模式生成的,因此恶意行为者会发现他们要完全伪装其请求会更具挑战性。Cloudflare 工程经理 Oliver Payne、Cloudflare 产品经理 Sally Lee 和 Cloudflare 高级软件工程师 Benedikt Wolters 解释道:
暂时 ID(Ephemeral IDs)的一个实际用例是防止欺诈性帐户注册。想象一下,一个坏人,一个使用真实设备的真人,在轮换 IP 地址以避免被检测发现的同时创建了数百个虚假帐户。通过摄取暂时 ID(Ephemeral IDs)并将其与帐户创建日志一起记录,我们可以根据帐户创建阈值实时设置预警或追溯排查可疑活动。
IP 地址(绿色)与暂时 ID(蓝色)。来源:Cloudflare 博客
两年前推出的 Turnstile 是一种验证工具,旨在通过生成各种类型的非侵入式挑战来验证用户是否是人类,从而取代验证码,不再需要访问者解答难题。一旦在部署中启用了暂时 ID(Ephemeral IDs),向 Turnstile 发出的 curl 请求将会演示如何返回临时的暂时 ID(Ephemeral IDs)以标识客户端:
curl \'https://challenges.cloudflare.com/turnstile/v0/siteverify\' --data \'secret=verysecret&response=\'\\n{\\n \\"success\\": true,\\n \\"error-codes\\": [],\\n \\"challenge_ts\\": \\"2024-09-10T17:29:00.463Z\\",\\n \\"hostname\\": \\"example.com\\",\\n \\"metadata\\": {\\n \\"ephemeral_id\\": \\"x:9f78e0ed210960d7693b167e\\"\\n }\\n}
来源:Cloudflare 博客
虽然新选项可以跨时间跟踪不同的请求,但 Cloudflare 强调了现有的隐私和合规性保护:当访问者与不同的 Cloudflare 客户交互时,他们会为每个客户分配不同的暂时 ID(Ephemeral IDs)。此外,由于这些 ID 会经常更改,因此它们不能用于长时间跟踪单个访问者。用户 techcyclev 在 X 上 评论 道:
Cloudflare 对暂时 ID(Ephemeral IDs)采取的创新方式给我留下了深刻的印象。作为一名用户体验(UX)设计师,我很欣赏其在保持有效欺诈检测的同时重视用户隐私的做法。这对于安全在线交互来说是一个改变游戏规则的举措。
Payne、Lee 和 Wolters 补充道:
尽管暂时 ID(Ephemeral IDs)的存在时间很短,并在考察开始时可能已经发生了变化,但它们仍然可以通过汇总分析提供有价值的见解,并为识别欺诈和滥用行为提供额外的维度。
暂时 ID(Ephemeral IDs)并不是 Cloudflare 生日周活动期间唯一的公告,Workers 平台有 18 项更新,还包括每个 Durable Object 中都有零延迟的 SQLite 存储,以及更快的 AI 平台等其他重大更新。
尽管每次 Cloudflare 部署都能受益于向挑战平台(Challenge Platform)添加暂时 ID(Ephemeral IDs),但目前只有 Turnstile 企业和 Bot 管理企业客户才能通过 Turnstile 站点验证响应使用新选项。
Renato Losio 作为云架构师、技术主管和云服务专家拥有丰富的经验。目前,他住在柏林和的里雅斯特之间,作为首席云架构师远程工作。他的主要兴趣领域包括云服务和关系数据库。他是 InfoQ 的编辑,也是公认的 AWS 数据英雄。你可以在领英上与他联系。
查看原文链接:
https://www.infoq.com/news/2024/10/cloudflare-ephemeral-id/\\"
","description":"在最近的生日周活动期间,Cloudflare 推出了一项用于欺诈检测的新功能,暂时 ID(Ephemeral IDs)。该工具通过将行为与特定的客户端而不是 IP 地址进行关联来识别欺诈活动,无论该欺诈活动是来自机器人还是人类。 通过 Turnstile 站点验证响应,这项新的识别技术旨在解决攻击者轮换大量 IP 地址以逃避标准 WAF 监控技术的常见问题。由于暂时 ID(Ephemeral IDs)是基于 IP 地址之外的模式生成的,因此恶意行为者会发现他们要完全伪装其请求会更具挑战性。Cloudflare 工程经理 Oliver Payne…","guid":"https://www.infoq.cn/article/FxgceKNMZN2JkYeZwrkw","author":"作者:Renato Losio","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-11-06T00:00:00.104Z","media":[{"url":"https://static001.geekbang.org/wechat/images/be/be22c40a155b9294af31955783343aac.png","type":"photo","width":0,"height":0,"blurhash":""}],"categories":["芯片&算力","编程语言"],"attachments":null,"extra":null,"language":null},{"title":"直播预约|登顶 TPC-DS!数据库 MPP 架构的极致优化与产业化实践","url":"https://www.infoq.cn/article/gWFQ2UIbRE6p0r07KVje","content":"数据驱动的时代,数据库的性能和成本效率是企业竞争力的关键。近日,腾讯云数据库 TDSQL 在数据库性能基准测试 TPC-DS 中取得了历史性的突破,以 7260 万 QphDs 的卓越性能和 37.52 元 /kQphDs 的超高性价比,成功刷新了世界纪录。这一成就不仅标志着腾讯云在数据库领域的技术领先地位,也为数据库 MPP 架构的优化与产业化实践树立了新的标杆。
TPC-DS 作为业界公认的数据库性能测试标准,模拟了复杂的决策支持系统,对数据库的查询处理能力、数据加载性能和系统稳定性提出了极高的要求。腾讯云 TDSQL 的成功登顶,展示了其在数据库领域的强大实力和技术创新能力。
11 月 7 日,腾讯云 DB-Talk 将举办一场主题为 《登顶 TPC-DS!数据库 MPP 架构的极致优化与产业化实践》的直播。在这场直播中,腾讯云的技术专家将带大家深入探讨 TDSQL PG 的技术创新与产业化实践,分享其如何在复杂任务处理能力上实现突破,成为行业的领先者。
登顶 TPC-DS!数据库 MPP 架构的极致优化与产业化实践
TPC-DS 新纪录:腾讯云 TDSQL 以 7260 万 QphDs 刷新世界纪录,展现顶尖性能。技术创新:探讨 TDSQL PG 的分布式架构和 Runtime Filter 技术,提升查询效率。实战经验:分享 Oracle 数据库替换的最佳实践。专家互动:与腾讯云数据库专家交流互动,获取深度见解。
让我们一起见证腾讯云数据库 TDSQL 如何以技术创新引领行业,扫码下方二维码或点击阅读原文,即刻预约直播 ⬇️
在华为应用市场,很少笔记类的App拥有高达4.8分的综合评分,评论区也是一片赞扬:
这个小众宝藏App就叫“幕布”——一款强大的效率工具,有近5000万用户正在频繁地使用它。现在,鸿蒙原生版的“幕布”上线了。除了一如既往的好用,鸿蒙原生版“幕布”更是结合了多项HarmonyOS NEXT创新特性,让人更加爱不释手。
作为一款大纲笔记与思维导图工具,“幕布”帮助千万学生和知识工作者们,用更高效的方式和清晰的结构来记录笔记、管理任务、制定工作计划、头脑风暴等。同时能一键生成思维导图,让思考更加清晰。
好多人就是因为使用了“幕布”,爱上了用手机做思维导图。这次,鸿蒙原生版“幕布”,将更精致、更智能、更流畅。同时,基于HarmonyOS NEXT原生互联的创新特性,用户在大屏、平板等其他终端上使用幕布App的时候,也能享受极其流畅的体验,比如,原生鸿蒙版“幕布”的大屏适配就充满亮点,针对直板机、折叠屏、平板等不同设备,自动适配显示模式;还支持分屏、悬浮窗等多窗口交互。
自“幕布”App诞生以来,不断根据用户的反馈优化产品体验。此次利用原生鸿蒙的优势,赋能产品创新,超越用户期待,正是“幕布”团队一直追求的。同时,幕布团队的另外两款产品 “flomo浮墨笔记”和“习惯点点”App也正在进行原生鸿蒙适配,并即将上线。在HarmonyOS NEXT应用市场,像这样的宝藏应用还有很多,等待你的发现!
鸿蒙原生应用开发者激励计划现已发布,开发上架鸿蒙原生应用,就有机会获得直接的现金激励和流量扶持,助力更多中小企业创新发展。
美政府要求关键“供应商”必须在2016年前制定迁移路线图,对于要挣钱的软件供应商来说,这份自称“建议性”的文件很快引起广泛关注,这意味着他们必须在接下来的一年里取得实质性进展。而且目前已经有230多家软件供应商自愿加入“安全设计”计划,这些厂商承诺在一年内达成一系列网络安全目标,如“消除特定类别的漏洞”。
美联邦政府正在加强关于危险软件开发实践的警告,日前美国网络安全与基础设施安全局(CISA)和联邦调查局(FBI)陆续发布关于困扰关键基础设施的基本安全问题的明确处置信号。
CISA和FBI在关于产品安全性不良实践的最新报告中,提醒软件开发商应高度关注使用非内存安全编程语言等不良行为,而C和C++更是在其中被列为反面典型。
报告指出,“在支持关键基础设施或国家关键职能(NCF)的新产品线的开发过程中,使用非内存安全语言(例如C或C++)可能引发风险,即显著提高了国家安全、国家经济安全以及国家公共卫生及安全所面临的风险。”
这份报告还将不良实践具体分为三大类别:
产品属性,即描述软件产品中肉眼可见与安全相关的质量属性。安全功能,描述产品所支持的安全功能。组织流程和政策,描述软件开发商在确保安全方法的透明度等方面采取的实际行动。
这份报告主要面向负责为关键基础设施或者国家关键职能等应用场景开发软件产品及服务的各软件开发商(包括本地软件、云服务以及SaaS软件即服务)。
此外,这份报告还鼓励全体软件开发商避免采取这些可能影响产品安全性的不良实践。报告提到,“通过遵循本指南中的建议,开发商将向客户发出信号,表明他们高度关注向客户交付成果的安全因素、牢牢秉持在设计之初就重视安全的基本原则。”
Omdia分析师Brad Shimmin表示,“这项指南是对美国政府此前关于软件安全问题的早期声明的延续,当时的声明可以追溯到2022年,意在提醒技术提供商和企业用户尽量使用或迁移至内存安全语言。”
他解释称,“抛开新增代码不谈,当时的文件和美国政府表达的立场相对比较和缓,没有立即要求从C/C++迁移至Rust。CISA的设计文档中也提到,软件维护者根本不可能在短时间内完成如此规模的代码库迁移。”
当时的指南虽然属于自愿性质,但也代表着CISA在基准安全实践方面的最强立场,包括提醒企业注意到可能被疏忽的不良软件开发实践,特别是其中触及基础设施的部分。
但时间的洪流一刻不停向前奔涌,最新报告已经要求企业必须在2026年1月1日之前建立内存安全发展路线图。
报告指出,“对于以非内存安全语言编写的现有产品,到2026年1月1日前仍缺少明确内存安全迁移路线图的情况,将被视为存在风险,即显著提高了国家安全、国家经济安全以及国家公共卫生及安全所面临的风险。”
CISA战略合作伙伴关系及漏洞项目开发负责人Rina Rakipi表示,CISA已获得超过230家软件厂商的自愿承诺。加入“安全设计”计划,意味着这些厂商承诺在一年内达成一系列网络安全目标,包括减少产品中的默认密码、增加多因素身份验证的使用,以及消除特定类别的漏洞。
Rakipi说:“我们非常高兴有超过230家软件厂商自愿参与这一承诺。展望未来,我们期待在接下来的一年中,看到这230家公司取得的实质性进展。”
截图来源:https://www.cisa.gov/securebydesign/pledge/secure-design-pledge-signers\\"
随着软件供应商不断推进履行这些承诺,美国网络安全与基础设施安全局(CISA)和联邦调查局(FBI)发布了该“不良实践”报告,作为“安全设计”原则的自然延续。该文件旨在于产品投入生产之前消除极其棘手的问题。
此外,报告还要求企业在同一日期之前移除管理员账户中使用的全部默认密码。这一截止日期已经将指南内容从建议升级为预期标准。
报告同时指出,内存安全路线图应要搞开发商在主要代码组件(例如面向网络的代码或者处理加密操作等敏感功能的代码)当中将要采取的首选内存安全漏洞消除方法。
报告指出,“开发商应当证明,其内存安全路线图将如何优先缓解其所开发产品中内存安全性的脆弱性,同时证明他们正做出合理努力以实施并推进其内存安全路线图。”
Shimmin在采访中解释称,“但有两个现实理由会迫使企业继续维护由COBOL和Fortran编写的成规模代码——成本和风险。首先,对数百万行旧代码进行迁移在财务上不具备可行性,而且任何负责任的组织都无法承担由此带来的业务风险。”
此外,根据报告内容,关键基础设施还面临着以下“异常风险”的困扰:
默认密码。直接SQL注入漏洞。缺少基本注入检测机制。缺少多因素身份验证机制。
对于开源软件,该报告称应特别关注开源漏洞。其他建议还包括:
企业必须维护明确的软件物料清单(SBOM)。应当缓存依赖项,而非直接从公共来源处提取。需要以负责任方式为其依赖的开源项目做出贡献。
报告提到,“软件开发商应当以负责任的方式使用并持续为其所依赖的开源软件做出贡献。”
报告还敦促提高软件开发透明度,包括:
企业必须发布漏洞披露政策。应当为所有关键漏洞发布CVE。必须提供关于安全问题的清晰说明文档。预计将安全日志维护并保存六个月。
最后,Shimmin总结称,CISA建议掌握关键软件的企业在2026年初之前制定出明确的安全计划无疑是件好事。因为这能让软件行业有更多时间探索出理想的方法,确保我们的关键软件资产免遭威胁侵扰。
“这些方法能够包括在硬件制造层面消除潜在的攻击面,以及由编程语言维护者提出方案。以Safe C++提案为例\\",其呼吁为C++创建一个超集以解决内存安全问题,借此避免强制进行大规模代码重写。”
这并不是CISA对内存安全语言的首次提倡。
在去年 9 月的一篇博文中,CISA也曾公开敦促开发人员使用内存安全编程语言。网络与基础设施安全局、联邦调查局(FBI)、国家安全局及各盟国机构随后于 12 月发布了题为《内存安全路线图案例》(The Case for Memory Safe Roadmaps)的研究报告,其中就点名 C/C++存在内存安全漏洞,软件开发商应放弃使用,改用 C#、Rust、Go、Java、Python 和 Swift 等内存安全的编程语言 (MSL)。
今年2月底,白宫国家网络主任办公室 (ONCD) 也就此发布了一份报告,呼吁科技界主动减少网络空间的攻击面;通过改用 Rust 等内存安全编程语言、避免使用 C++ 和 C 语言等易受攻击的语言,以减少内存安全漏洞的数量来提高软件安全性。(详情点击:《拜登:“一切非 Rust 项目均为非法”\\"》)
随后,C++的创建者Bjarne Stroustrup针对白宫的这些言论进行了反驳。
Stroustrup 指出了 C++ 的优势,并提到该语言最早于1979年设计。“令我感到惊讶的是,这些政府文件的作者似乎忽略了现代 C++ 的优势以及在提供强大安全保障方面所做的努力,” Stroustrup 表示,“但另一方面,他们似乎认识到编程语言只是工具链的一部分,因此改进工具和开发流程也至关重要。”
Stroustrup 强调,C++ 开发始终将安全性改进作为目标之一。“自第一天起,安全性改进就是 C++ 发展的目标之一,并贯穿了整个演进过程。只要将 K&R 时代的 C 语言与最早的 C++ 比较,再将早期的 C++ 与当代 C++ 比较就可以看出这一点,”他说。“许多高质量的 C++ 代码采用了基于 RAII(资源获取即初始化)、容器和资源管理指针的技术,而不是传统的 C-style pointer messes。”
其实在更早之前,Stroustrup就明确表达过自己的看法\\",他曾在CppCon2023大会上主题演讲上阐述了C++的演变,还花了一些时间回应了批评。批评者说问题出在 C++ 本身,解决方案应该是改用另一种语言。Stroustrup在演讲中向与会者详细说明了C++语言在安全性方面所需的具体措施,并介绍了一项引入全新安全工具的提案,旨在为全球数十亿行C++代码提供更可靠的安全保障。
Stroustrup反对通过更换语言来解决安全问题。他指出安全问题不仅仅是内存安全,还包括资源泄漏、溢出、并发和计时错误等多种复杂的隐患。
他强调,完全转向其他语言不仅成本高昂,还缺乏关注跨语言互操作的需求——“实际上,我们在替换C++时,可能需要用七种不同的语言来完成。而到40年后,可能会有20种语言需要彼此兼容。这是巨大的挑战。”
此外,Stroustrup指出,许多所谓“安全”语言实际上将底层任务外包给C或C++,以便访问操作系统、硬件资源或其他历史代码库,这些代码往往隐藏在库中,甚至使用完全不同的语言开发。
与CISA的“安全设计”计划类似,Stroustrup主张采用逐步改进的方案来提升C++的安全性,而非推倒重来。他援引加尔定律,指出“有效的复杂系统总是从简单系统演变而来”。
在他看来,“一边倒地构建一个无旧系统问题的新系统是幻想,但这种幻想确实颇具吸引力。”
参考链接:
https://thenewstack.io/feds-critical-software-must-drop-c-c-by-2026-or-face-risk/\\"
https://cyberscoop.com/cisa-secure-by-design-software-bad-practices/\\"
https://www.infoq.cn/article/1wy3xq56dj6cmnwlgavi\\"
https://www.infoworld.com/article/2336463/c-plus-plus-creator-rebuts-white-house-warning.html\\"
","description":"美政府要求关键“供应商”必须在2016年前制定迁移路线图,对于要挣钱的软件供应商来说,这份自称“建议性”的文件很快引起广泛关注,这意味着他们必须在接下来的一年里取得实质性进展。而且目前已经有230多家软件供应商自愿加入“安全设计”计划,这些厂商承诺在一年内达成一系列网络安全目标,如“消除特定类别的漏洞”。 \\n\\n美联邦政府正在加强关于危险软件开发实践的警告,日前美国网络安全与基础设施安全局(CISA)和联邦调查局(FBI)陆续发布关于困扰关键基础设施的基本安全问题的明确处置信号。\\n\\n \\n\\nCISA和FBI在关于产品安全性不良实践的最新报告中…","guid":"https://www.infoq.cn/article/fZrHuXKG08q8K9yX4dPu","author":"核子可乐,Tina","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-11-04T05:50:40.737Z","media":[{"url":"https://static001.geekbang.org/infoq/be/be3a56914ec914e01c47e2bbb0d707ed.jpeg","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/d5/d5e7bfa023a5a12ab4e9c2586d9cd15f.jpeg","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/fd/fd21d677f3b6ce0acd28982776442e11.png","type":"photo","width":0,"height":0,"blurhash":""}],"categories":["编程语言"],"attachments":null,"extra":null,"language":null},{"title":"Java近期新闻:WildFly 34、Stream Gatherers、Oracle CPU、Quarkiverse发布流程","url":"https://www.infoq.cn/article/JS6e1PNr5PuBAAr6XVV1","content":"JEP 485(Stream Gatherers\\")已从Candidate进入到Proposed to Target状态,目标版本为JDK 24。这个JEP提议在经过两轮预览之后完成这个特效:在JDK 23中交付的JEP 473(Stream Gatherers (第二轮预览)\\"和, 在JDK 22中交付的JEP 461(Stream Gatherers (预览)\\")。该功能旨在增强Stream API,使其能够支持自定义中间操作,“让流式管道能够以一种不易通过现有内置中间操作实现的方式转换数据。”有关此JEP的更多细节,可在原始设计文档\\"和InfoQ的报道\\"中找到。评审在2024年10月23日结束。
Oracle已发布\\"JDK的23.0.1、21.0.5、17.0.13、11.0.25和8u431版本,作为2024年10月季度关键补丁更新\\"的一部分。有关这些发布的更多细节,可在23.0.1\\"、21.0.5\\"、17.0.13\\"、11.0.25\\"和8u431\\"的发布说明中找到。
JDK回归测试工具jtreg\\"的7.5.0版本已发布\\",并准备集成到JDK中。最重要的变化包括:恢复jtdiff\\"工具;支持在@library标签指定的目录中的LIBRARY.properties文件,这些文件将在jtreg编译该库中的类时读取。JUnit升级到5.11.0版本。有关该版本的更多细节,可在发布说明\\"中找到。
JDK 24早期访问构建\\"版本的Build 20\\"已发布,包含了自Build 19以来的更新\\",修复了各种问题\\"。有关该版本的更多细节,可在发布说明\\"中找到。
对于JDK 24\\",开发者可以通过Java Bug数据库\\"报告错误。
Eclipse基金会的Jakarta EE开发者布道师Ivar Grimstad\\"在每周的Hashtag Jakarta EE\\"博客中分享了有关Jakarta EE 11的最新进展\\",他写道:
GlassFish已通过重构的Jakarta EE 11 TCK 84%的测试,剩余的测试主要与应用客户端容器有关。Jakarta EE平台项目提议在Jakarta EE 12中弃用应用容器。目前正在讨论这些测试对Jakarta EE 11的重要性。 Jakarta EE 11 Core Profile TCK已分阶段进行,Open Liberty和WildFly正在通过(或非常接近通过)测试。因此,我们有望在Jakarta EE 11 Core Profile之前发布Jakarta EE 11 Platform和Jakarta EE 11 Web Profile。
Jakarta EE 11将经理四个里程碑版本,必要时可能会发布候选版本,然后在2024年第四季度发布GA版本。
与Oracle发布的2024年10月关键补丁更新\\"同步,BellSoft也发布\\"了关键补丁更新,分别针对Liberica JDK\\"(OpenJDK下游发行版)的21.0.4.0.1、17.0.12.0.1、11.0.24.0.1、8u431、7u441和6u441版本,解决了这些CVE问题\\"。此外还发布了包含关键布丁更新和非关键修复的Patch Set Update (PSU)版本23.0.1、21.0.5、17.0.13、11.0.25和8u432。
BellSoft表示,他们总共参与了1169个修复和回溯,解决了所有发布版本中的18个问题。
Spring Framework\\" 6.2.0的第二个发布候选版本\\"包含了错误修复、文档改进、依赖项升级和许多新特性,例如:将OverrideMetadata\\"类重命名为BeanOverrideHandler\\",以便与org.springframework.test.context.bean.override\\"包中定义的其他类、接口和注释的命名约定保持一致;向RestClient.Builder\\"接口添加了messageConverters()方法,允许在不初始化默认设置的情况下为RestClient\\"接口设置转换器。这个版本将包含在即将发布的Spring Boot 3.4.0-RC1中。有关该版本的更多细节,可在发布说明\\"中找到。
类似的,Spring Framework 6.1.14也已发布\\",包含了错误修复、文档改进、依赖项升级和新特性,例如:在ResourceHandlerUtils\\"类中移除了对相对路径的支持,消除了潜在的安全问题;确保在遇到格式错误的Origin表头时,CorsUtils\\"类中定义的isCorsRequest()方法能够正确处理异常。这个版本将包含在即将发布的Spring Boot 3.3.5和3.2.11中。有关该版本的更多细节,可在发布说明\\"中找到。
Spring Framework团队还披露\\"了两个常见的CVE:
CVE-2024-38819\\",影响Spring Web MVC和Spring WebFlux的路径遍历漏洞。攻击者可以通过创建恶意HTTP请求来获取对运行Spring应用程序的服务器文件系统的访问权限。这个CVE是CVE-2024-38816(功能性Web框架中的路径遍历漏洞\\"的延续,只是后者使用的是不同的恶意输入。CVE-2024-38820\\":Java String\\"类中定义的toLowerCase()方法对Locale\\"类存在依赖异常,有可能导致字段未能受到预期的保护。这是解决CVE-2022-22968\\"所带来的副作用,该解决方案将DataBinder\\"类中定义的disallowedFields字段的模式变成不区分大小写。
这些CVE影响了Spring Framework的5.3.0 - 5.3.40、6.0.0 - 6.0.24和6.1.0 - 6.1.13版本。
Spring Data\\" 2024.1.0的第一个发布候选版本\\"带来了对Spring Data Value Expressions\\"的扩展支持,属性占位符现在可以在用@Query\\"注解的仓库查询方法中使用。还更新了子项目,如:Spring Data Commons 3.4.0-RC1、Spring Data MongoDB 4.4.0-RC1、Spring Data Elasticsearch 5.4.0-RC1和Spring Data Neo4j 7.4.0-RC1。有关该版本的更多细节,可在发布说明\\"中找到。
同样,Spring Data 2024.0.5和2023.1.11发布\\",包括了错误修复和子项目的依赖项升级,如:Spring Data Commons 3.3.5和3.2.11、Spring Data MongoDB 4.3.5和4.2.11、Spring Data Elasticsearch 5.3.5和5.2.11,以及Spring Data Neo4j 7.3.5和7.2.11。这些版本将包含在即将发布的Spring Boot 3.3.5和3.2.11中。
WildFly\\" 34发布\\",主要关注WildFly Preview\\",即WildFly服务器的技术预览版本。新功能包括:支持Jakarta Data 1.0\\"、MicroProfile Rest Client 4.0\\"和MicroProfile Telemetry 2.0\\";WildFly Preview新的Bill of Materials\\";以及HTTP管理界面\\"配置中的四个新系统属性(backlog、connection-high-water、connection-low-water和no-request-timeout)。有关该版本的更多细节,可在发布说明\\"中找到。InfoQ将跟进更详细的报道。
Quarkus团队披露\\",他们最近发现Quarkiverse和SmallRye的发布过程中可能存在漏洞,但并没有造成任何损害。
Red Hat杰出工程师Clement Escoffier\\"总结了这个问题,写道:
我们发现在Quarkiverse和SmallRye的发布流程中存在一个安全漏洞,该漏洞可能被恶意行为者利用,冒充项目发布者并上传恶意篡改的构件。 我们已经采用一个新的、更安全的发布流程来解决这个问题。如果你是维护者,可能已经收到了一个迁移到新流程的拉取请求。Quarkus本身不受这个问题的影响,问题仅涉及SmallRye和Quarkiverse。
他们采用了更安全的发布流程,并希望与Java社区分享这些细节。InfoQ将跟进更详细的报道。
Micrometer Metrics 1.14.0首个发布候选版本包含了错误修复、文档改进、依赖项升级和一些新功能,例如:通过AssertJ的assertThat()方法在Assertions\\"类中暴露TestObservationRegistry\\"类的实例;增加指标,包含了虚拟线程数据;用排序的唯一标签数组初始化Tags\\"类,提高了性能。有关该版本的更多细节,可在发布说明\\"中找到。
同样,Micrometer Metrics的1.13.6和1.12.11版本也包含了错误修复、文档改进和一项新特性,即通过移除可以从FixedBoundaryHistogram\\"实例访问内部字段来优化StepBucketHistogram\\"的内存使用。有关这些版本的更多细节,可在1.13.6\\"和1.12.11\\"的发布说明中找到。
Micrometer Tracing 1.4.0首个发布候选版本带来了依赖项升级和新功能:在Span\\"和SpanCustomizer\\"接口中支持标签中的列表值;将OtelSpan\\"类从私有改为公共,避免使用底层的OpenTelemetrySpan\\"接口。有关该版本的更多细节,可在发布说明\\"中找到。
Micrometer Tracing 1.3.5和1.2.11仅包含了依赖项升级。有关这些版本的更多细节,可在1.3.5\\"和1.2.11\\"的发布说明中找到。
Project Reactor 2024.0.0首个发布候选版本包含这些依赖项升级:reactor-core 3.7.0-RC1、reactor-netty 1.2.0-RC1、reactor-pool 1.1.0-RC1、reactor-addons 3.6.0-RC1、reactor-kotlin-extensions 1.3.0-RC1和reactor-kafka 1.4.0-RC1。从Spring Calendar\\"来看,预计Project 2024.0.0的GA版本将在2024年11月发布。有关该版本的更多细节,可在更新日志\\"中找到。
Project Reactor 2023.0.11,即第十一个维护版本,包含了reactor-core 3.6.11和reactor-netty 1.1.23依赖项升级,reactor-pool 1.0.8、reactor-addons 3.5.2、reactor-kotlin-extensions 1.2.3和reactor-kafka 1.3.23保持不变。有关该版本的更多细节,可在更新日志\\"中找到。
Piranha 24.10.0发布\\",包含了错误修复和一些显著的变化,例如:确保在必要时安装Eclipse Jersey的InjecteeSkippingAnalyzer\\"实例;在DefaultServletRequestDispatcher\\"类中使用Java的PrintStream\\"类或在DefaultWebApplicationResponse\\"类中定义的isWriterAcquired()方法,作为对顶级异常的响应。有关该版本的更多细节,可在其文档\\"和问题追踪器\\"中找到。
Apache TomEE 10.0.0 第三个里程碑版本\\"包含了错误修复、依赖项升级和一些新功能,例如:改进了数据源和实体管理器的导入,不再必要使用ImportSql\\"类;新的RequestNotActiveException\\"类,替代在没有活动的Servlet请求的线程上调用Jakarta ServletHttpServletRequest\\"实例时抛出的NullPointerException。有关该版本的更多细节,可在发布说明\\"中找到。
JobRunr 7.3.1\\"带来了一些新功能,例如:作为接口而不是实现注入时,JobDetails\\"的实例是可缓存的;增强的JobRunr仪表盘,包含了诊断严重JobRunr异常的提示,提高了通知的清晰度。有关该版本的更多细节,可在发布说明\\"中找到。
Keycloak\\" 26.0.1\\"发布,包含错误修复和一些功能增强:对在同一集群操作符中安装多个Keycloak Operator\\"版本的明确说明;改进事务提交期间的错误日志记录。有关该版本的更多细节,可在发布说明\\"中找到。
JDKUpdater 14.0.59+79\\"发布,这是一个新的实用工具,旨在帮助开发者跟踪与OpenJDK和GraalVM构建相关的更新,由Azul首席工程师Gerrit Grunwald\\"在3月中旬推出,这个版本解决了计算JDK下一个更新和下一个发布日期的问题。有关该版本的更多细节,可在发布说明\\"中找到。
Gradle 8.11.0首个发布候选版本\\"带来了一些新功能,例如:通过在配置缓存中引入选择性并行加载和存储\\"缓存条目来提升性能;C++\\"和Swift\\"插件现在与配置缓存兼容;改进了错误和警告报告,其中Java编译错误\\"显示在构建输出的末尾。有关该版本的更多细节,可在发布说明\\"中找到。
原文链接:
https://www.infoq.com/news/2024/10/java-news-roundup-oct14-2024/\\"
","description":"OpenJDK JEP 485(Stream Gatherers\\")已从Candidate进入到Proposed to Target状态,目标版本为JDK 24。这个JEP提议在经过两轮预览之后完成这个特效:在JDK 23中交付的JEP 473(Stream Gatherers (第二轮预览)\\"和, 在JDK 22中交付的JEP 461(Stream Gatherers (预览)\\")。该功能旨在增强Stream API,使其能够支持自定义中间操作,“让流式管道能够以一种不易通过现有内置中间操作实现的方式转换数据。”有关此JEP的更多细节,可在原始设计文档\\"…","guid":"https://www.infoq.cn/article/JS6e1PNr5PuBAAr6XVV1","author":"Michael Redlich","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-11-04T03:09:52.739Z","media":null,"categories":["编程语言"],"attachments":null,"extra":null,"language":null},{"title":"研究表明 AI 编码助手可提高开发人员的生产力","url":"https://www.infoq.cn/article/PYEYWoovU20rM0CcN5X2","content":"来自微软、麻省理工学院、普林斯顿大学和宾夕法尼亚大学沃顿商学院的研究人员最近发表了一项研究,表明使用 GitHub Copilot 可提高开发人员的生产力。该团队进行了三项独立的随机对照试验(RCT),涉及 4,000 多名开发人员;结果发现使用 Copilot 的开发人员的生产力提高了 26%。
这三项实验是在微软、埃森哲和一家“未透露名称的财富 100 强电子制造公司”进行的。对于参与研究的 4,867 名开发人员,研究人员测量了他们每周执行的拉取请求、提交和代码构建的数量。他们发现,使用 Copilot 的开发人员每周完成的拉取请求数量平均增加了 26.08%。他们还发现,生产力提升情况因开发人员的经验而异,经验较少的开发人员从 Copilot 中获益更多。根据研究团队的说法:
我们的工作通过在实际工作场所环境中使用现场实验来研究生成式人工智能的影响,是对实验室实验文献以及这些观察性研究的补充。迄今为止,业内仍然缺乏在现场环境中研究生成式人工智能影响的实验研究。
实验于 2022 年和 2023 年进行,使用基于 GPT-3.5 的 Copilot 版本。在微软和埃森哲,实验中的开发人员被随机选择使用 Copilot,而在匿名公司,所有开发人员最终都被授予访问权限,但开始日期是随机选择的。除了跟踪开发人员的生产力指标外,研究人员还跟踪了 Copilot 的采用和使用情况。
研究团队分析了所有开发人员的结果,还根据开发人员从业时间和技能水平做了更细致的分析。他们发现,从业时间较短和技能偏初级的开发人员更有可能采用 Copilot,并继续使用超过一个月,并且这些开发人员更有可能接受 Copilot 生成的输出代码。他们还从该工具中获得了最大的生产力提升。
沃顿商学院教授 Ethan Mollick 在 X 的一个帖子中分享了研究结果,他写道:
我们现在有了随机对照试验,表明使用人工智能在实际公司中大幅提升了编码、管理、创业和写作方面的表现
在 Hacker News 上关于这项研究的讨论中,几位用户表示,该论文的结果与他们自己使用 Copilot 的经历相符。一位用户写道:
对我来说,这项研究最有趣的地方在于,当他们按经验水平进行细分时,超过平均从业时间的开发人员的生产力并没有显著提高……Copilot 可以很好地处理一些乏味的事情,让我的大脑可以更多地关注更深层次的问题,但它并不像初级开发人员所描述的那样改变世界。它还经常出现一些新开发人员无法察觉的微妙错误,这就要求我停下来,以一种经验不足的开发人员可能不知道的方式调整它生成的大多数东西。
生成式人工智能对员工生产力(尤其是软件开发人员生产力)的影响是一个开放的研究领域。今年早些时候,InfoQ 报道了 Upwork 研究所的一项调查,其中大多数接受调查的员工实际上表示 GenAI 降低了他们的生产力。InfoQ 还报道了 eBay 的一项研 究,其中 GitHub Copilot 确实提高了开发人员的生产力。
查看原文链接:
https://www.infoq.com/news/2024/09/copilot-developer-productivity/\\"
","description":"来自微软、麻省理工学院、普林斯顿大学和宾夕法尼亚大学沃顿商学院的研究人员最近发表了一项研究,表明使用 GitHub Copilot 可提高开发人员的生产力。该团队进行了三项独立的随机对照试验(RCT),涉及 4,000 多名开发人员;结果发现使用 Copilot 的开发人员的生产力提高了 26%。 这三项实验是在微软、埃森哲和一家“未透露名称的财富 100 强电子制造公司”进行的。对于参与研究的 4,867 名开发人员,研究人员测量了他们每周执行的拉取请求、提交和代码构建的数量。他们发现,使用 Copilot 的开发人员每周完成的拉取请求数量平均增加了…","guid":"https://www.infoq.cn/article/PYEYWoovU20rM0CcN5X2","author":"作者 | Anthony Alford","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-11-01T00:00:00.613Z","media":null,"categories":["AI 工程化","编程语言"],"attachments":null,"extra":null,"language":null},{"title":"原生鸿蒙应用市场升级焕新 全新体验开启沉浸探索","url":"https://www.infoq.cn/article/fYmwUaKb1AShUjRwLOzG","content":"北京时间10月22日晚,华为正式发布了HarmonyOS NEXT商用版本。与此同时,华为应用市场(AppGallery)也完成了全新改版升级,原生鸿蒙应用市场焕新登场,为用户带来全新的杂志化布局、沉浸式探索的应用呈现方式,以及更透明、更彻底的隐私安全保护。
截至目前,鸿蒙已拥有675万注册开发者,鸿蒙生态设备超过10亿,超过15000个鸿蒙原生应用和元服务已上架原生鸿蒙应用市场。星河璀璨,万象更新,而今迈步从头越,作为鸿蒙世界的重要入口,华为应用市场将携手更多开发者及广大用户一起,共同迈入万物智联的鸿蒙新世界。
在探索全新鸿蒙世界的旅途中,原生鸿蒙应用市场在内容层面上对用户体验进行了全面提升——它不仅是通往数字世界的重要入口,更是汇聚人文气息的App精品廊。用户在焕新后的原生鸿蒙应用市场首页即可体验到杂志化的全新交互与故事化内容。
在原生鸿蒙应用市场,超50人的专业编辑团队深度策划、每周超过400小时的亲测试玩后从专业视角出发,为用户精心挑选及推荐高质量的应用和游戏,以匠心独运的策划、引人入胜的应用相关故事和艺术感十足的陈列展示,为走进“画廊”的每位顾客构建一个科技与艺术完美融合的探索乐园。
原生鸿蒙应用市场焕新后的页面布局,让用户视觉焦点全面聚焦于每款精品应用本身,营造出前所未有的简洁与纯粹。这一变革旨在为用户打造一个更加直观、高效的应用搜索与使用环境,让每一次探索都能直抵心之所向,回归最纯粹的体验初衷。
原生鸿蒙应用市场的全新体验还包括对用户的敏感数据实行更透明可视的保护。不满足安全要求的应用无法上架、安装、运行,确保用户在应用下载前可充分了解自己的数据将被如何收集、为何收集以及如何使用。
焕新后的原生鸿蒙应用市场,不仅是Store,更是Gallery。它构建了一个更为纯净和安全的新平台,深度整合了鸿蒙生态,为用户提供沉浸式的创新体验。在此之中,鸿蒙生态的开放性、协同性和智能性得到了充分的体现,确保用户的每一段数字旅程都充满乐趣与收获。
","description":"北京时间10月22日晚,华为正式发布了HarmonyOS NEXT商用版本。与此同时,华为应用市场(AppGallery)也完成了全新改版升级,原生鸿蒙应用市场焕新登场,为用户带来全新的杂志化布局、沉浸式探索的应用呈现方式,以及更透明、更彻底的隐私安全保护。 \\n\\n截至目前,鸿蒙已拥有675万注册开发者,鸿蒙生态设备超过10亿,超过15000个鸿蒙原生应用和元服务已上架原生鸿蒙应用市场。星河璀璨,万象更新,而今迈步从头越,作为鸿蒙世界的重要入口,华为应用市场将携手更多开发者及广大用户一起,共同迈入万物智联的鸿蒙新世界。\\n\\n \\n\\n \\n\\n焕新后的原生鸿蒙应用市场…","guid":"https://www.infoq.cn/article/fYmwUaKb1AShUjRwLOzG","author":"HarmonyOS","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-10-31T08:51:53.516Z","media":[{"url":"https://static001.geekbang.org/infoq/e7/e74697105e1542f8e8fb34b867cc668f.png","type":"photo","width":830,"height":511,"blurhash":"LKDvNZxbjYs:Z{WAxut60gf9ITNG"},{"url":"https://static001.geekbang.org/infoq/39/39be71849bede0f518559cd3f172095f.png","type":"photo","width":825,"height":550,"blurhash":"LULOTh_2%MxuI9fPofWB00IUM{WB"},{"url":"https://static001.geekbang.org/infoq/f8/f86a0fb1016571ddbc9ffdcb7c8e11dc.png","type":"photo","width":827,"height":551,"blurhash":"LrMHu+-:M|t8MxaxkCWV00NGt6ae"}],"categories":["华为","操作系统"],"attachments":null,"extra":null,"language":null},{"title":"Java新闻汇总: JDK 24、Tomcat 11.0、Cassandra 5.0、EclipseStore 2.0、Payara Platform和Ktor 3.0","url":"https://www.infoq.cn/article/h8GKMqGFQMRGNak8N1Ie","content":"本期的Java新闻汇总主要包括如下新闻:JEP 489,向量API(Vector API,第九轮孵化)和JEP 484,类文件API(Class-File API)均计划在JDK 24实现;Apache项目的发布,包括Tomcat 11.0.0和Cassandra 5.0.0;EclipseStore 2.0.0发布;Payara Platform的2024年10月版发布以及Ktor 3.0.0发布。
在审查结束后,JEP 489,向量API(Vector API,第九轮孵化)\\"已经从JDK 24的Proposed to Target状态提升为Targeted状态。这个JEP根据前八轮孵化的反馈进行了增强,也就是JDK 23交付的JEP 469,向量API(第八轮孵化)\\"、JDK 22交付的JEP 460,向量API(第七轮孵化)\\"、JDK 21交付的JEP 448, 向量API(第六轮孵化)\\"、JDK 20交付的JEP 438, 向量API(第五轮孵化)\\"、JDK 19交付的JEP 426, 向量API(第四轮孵化)\\"、JDK 18交付的JEP 417, 向量API(第三轮孵化)\\"、JDK 17交付的JEP 414, 向量API(第二轮孵化)\\"和JDK 16交付的JEP 338, 向量API(孵化)\\"。原本的计划是继续使用原有的孵化器状态,但后来决定进行编号的重新计算。向量API将会继续孵化,直到Valhalla项目\\"的必要特性达到预览可用。到时候,向量API团队将调整向量API及其实现,以使用这些特性,并将向量API从孵化状态提升为预览状态。
在审查结束后,JEP 484,类文件API(Class-File API)\\"已经从JDK 24的Proposed to Target状态提升\\"为Targeted状态。该JEP建议在经过两轮预览后,即JDK 23交付的JEP 466, 类文件API(第二轮预览)\\"和JDK 22交付的JEP 457, 类文件API(预览)\\",在JDK 24中最终确定本特性。该特性提供了一个API来解析、生成和转换Java类文件。它最初作为JDK中ASM\\"的替代品,ASM是一个Java字节码操作和分析框架,并计划将其作为公开API对外开放。甲骨文的Java语言架构师Brian Goetz\\"将ASM描述为“带有大量遗留包袱的旧代码库”,并提供了关于该草案如何发展并最终取代ASM的背景信息\\"。
JEP 490,ZGC:移除非分代模式(ZGC: Remove the Non-Generational Mode)\\",已经从JEP Draft 8335850状态提升\\"到了Candidate状态。该JEP建议移除Z垃圾收集器(ZGC)的非分代模式。根据JDK 23交付的JEP 474, ZGC:默认的分代模式(ZGC: Generational Mode by Default)\\",分代模式现在是默认选项。通过移除ZGC的非分代模式,能够避免维护两种模式,并缩短了分代模式新特性的开发时间。
JDK 24的早期访问构建版本\\"的Build 19\\"发布,该版本是对Build 18的更新\\",其中包括对各种问题\\"的修复。关于这个版本的更多细节可以在发布说明\\"中找到。
距离Rampdown第一阶段\\"还有不到两个月的时间,JDK 24的目标包含了四个JEP:
472:准备限制对JNI的使用(Prepare to Restrict the Use of JNI)\\"475:G1的后期屏障扩展(Late Barrier Expansion for G1)\\"484:类文件API(Class-File API)\\"489:向量API(Vector API,第九轮孵化Ninth Incubator)\\"
对于JDK 24\\",鼓励开发人员通过Java缺陷数据库\\"报告缺陷。
Loom项早期访问构建版本\\"的Build 24-loom+8-78已经提供给Java社区,该构建版本基于JDK 24早期访问构建版本的Build 18\\"。该版本增强了Java监视器(同步方法)的实现,以增强与虚拟线程的互操作性。
在每周的Hashtag Jakarta EE\\"博客中,Eclipse基金会的Jakarta EE开发人员倡导者Ivar Grimstad\\"介绍了即将发布的Jakarta EE 11\\"的最新情况\\":
Jakarta EE TCK的重构工作仍在继续。我们似乎很快就能发布Jakarta EE 11 Core Profile,并将Open Liberty\\"作为正式批准的实现。关于Platform和Web Profile,还需要再等一段时间。现在看来,它们仍有可能在2024年12月3日的JakartaOne Livestream\\"上准时发布。
通往Jakarta EE 11的过程中包括了四个里程碑版本,在2024年第4季度发布正式版之前,还可能根据需要发布候选版本。
Spring Cloud\\" 2024.0.0的第二个里程碑版本\\"代号为 Moorgate,主要包括缺陷修复和对子项目的重要更新,比如,Spring Cloud Kubernetes\\" 3.2.0-M2、Spring Cloud Function\\" 4.2.0-M2、Spring Cloud OpenFeign\\" 4.2.0-M2、Spring Cloud Stream\\" 4.2.0-M2、Spring Cloud Gateway\\" 4.2.0-M2。该版本与Spring Boot 3.4.0-M3兼容。关于该版本的更多详细信息,请参阅发布说明\\"。
Spring AI\\" 1.0.0的第三个里程碑版本\\"提供了新特性,例如,改进了Spring Advisors API\\"、新的ToolContext类取代了用于函数回调的Map、支持更多可观测性模型\\",包括,Azure OpenAI\\"、Google Vertex AI\\"和MiniMax AI\\"。
Spring Batch\\" 5.2.0的第二个里程碑式版本\\"提供了以下新特性:支持MongoDB作为JobRepository接口的实现、新的CompositeItemReader类补充了现有的CompositeItemWriter和CompositeItemProcessor类。关于此版本的更多详细信息,请参阅发布说明\\"。
继Spring Framework 7.0和Spring Boot 4.0最近公布了2025年11月份的发布计划\\"之后,Spring Cloud Data Flow\\"(SCDF)团队也制定了自己的计划\\",即在2025年11月发布3.0版本。其目标是使SCDF项目(如,SCDF服务器组件、Composed Task Runner和SCDF UI)与Spring Framework 7.0和Spring Boot 4.0保持同步。
Payara发布\\"了Payara Platform\\"的2024年10月版,包括社区版6.2024.10、企业版6.19.0和企业版5.68.0。除了缺陷修复和依赖性升级外,这三个版本主要解决了CVE-2024-8215\\"漏洞,该跨站脚本漏洞允许攻击者通过Payara Management REST\\"接口远程执行代码。这些版本还集成了WriteLockManager类的EclipseLink\\"中断增强功能,以提高数据库操作的性能。有关这些版本的更多详细信息,请参见社区版6.2024.10\\"、企业版6.19.0\\"以及企业版5.68.0\\"的发布说明。
IBM发布了Open Liberty 24.0.0.10版本,其特性包括,支持JDK 23;新的versionless特性\\",支持MicroProfile Context Propagation\\"、MicroProfile GraphQL\\"、MicroProfile Reactive Messaging\\"和MicroProfile Reactive Streams Operators\\"规范。
Micronaut基金会发布\\"了Micronaut Framework\\" 4.6.3版本,特性包括Micronaut Core 4.6.6\\"和对如下模块的更新:Micronaut Security\\"、Micronaut Test Resources\\"、Micronaut MQTT\\"、Micronaut Data\\"、Micronaut gRPC\\"、Micronaut Oracle Cloud\\"和Micronaut Security\\"。有关此版本的更多详情,请参阅发布说明\\"。
EclipseStore\\" 2.0.0发布\\",提供了缺陷修复和新特性,例如,新的BinaryHandlerSetFromMap类,用于Java Collections类中定义的内部私有静态类 SetFromMap,以改进数据处理;Storer接口的增强功能包括新的UsageMarkable接口,以防止Lazy接口的引用在有未存储的更改时被清除。有关此版本的更多详情,请参阅发布说明\\"。
在发布了26个里程碑版本之后,Apache Tomcat 11.0.0正式发布,其特性包括,支持虚拟线程;增加了对JEP 454,外部方法与内存API(Foreign Function & Memory API)\\"的兼容性方法,支持OpenSSL\\"、LibreSSL\\"和BoringSSL\\",它们均需要JDK 22作为最低版本;与Let’s Encrypt\\"的轻松集成,以及自动重新加载更新后的TLS密钥和证书,改进了TLS证书的更新流程,实现零停机时间。2024年10月7日是 Sun Microsystems向Apache软件基金会捐赠Tomcat后首次提交Apache Tomcat源代码库的25周年纪念日。关于该版本的更多详细信息,请参阅发布说明\\"。
Apache Tomcat 9.0.96发布\\",其中包括缺陷修复和一些值得关注的变更,例如,通过对WebdavServlet类的小范围重构改进了对WebDAV\\"的支持;在垃圾回收期间销毁SSLContext接口实例时提高了Tomcat Native Library\\"的稳定性。有关此版本的更多详情,请参阅发布说明\\"。
OpenXava\\" 7.4.1发布\\",提供了缺陷修复、文档改进、依赖性升级和新功能,例如,新的Maven archetypes openxava-invoicing-archetype和openxava-invoicing-archetype-spanish,分别对应英语和西班牙语版本;使用flowLayout=true属性的简单视图布局,现在最多可应用15个简单属性,而不再是8个。关于此版本的更多详细信息,请参阅发布说明\\"。
JHipster Lite\\" 1.20.0版本发布\\",包含了缺陷修复、文档改进、依赖性升级和新功能/改进,例如,使用Tikui\\"(一个用于构建静态组件的库)改进了生成的样式;使用Vue.js\\"支持JWT和OAuth2身份验证。有关此版本的更多详细信息,请参阅发布说明\\"。
JetBrains Ktor\\" 3.0.0发布\\",它是用来创建微服务和Web应用程序的异步框架,该版本提供了缺陷修复和改进,例如,迁移到kotlinx-io\\"库,以标准化Kotlin库中I/O功能并提高性能;支持服务器端事件;在Ktor Client中支持WebAssembly。关于该版本的更多详细信息,请参见发布说明\\"。InfoQ将通过更详细的新闻报道进行跟踪报道。
原文链接:
Java News Roundup: JDK 24, Tomcat 11.0, Cassandra 5.0, EclipseStore 2.0, Payara Platform, Ktor 3.0\\"
","description":"本期的Java新闻汇总主要包括如下新闻:JEP 489,向量API(Vector API,第九轮孵化)和JEP 484,类文件API(Class-File API)均计划在JDK 24实现;Apache项目的发布,包括Tomcat 11.0.0和Cassandra 5.0.0;EclipseStore 2.0.0发布;Payara Platform的2024年10月版发布以及Ktor 3.0.0发布。 OpenJDK\\n\\n在审查结束后,JEP 489,向量API(Vector API,第九轮孵化)\\"已经从JDK 24的Proposed to…","guid":"https://www.infoq.cn/article/h8GKMqGFQMRGNak8N1Ie","author":"Michael Redlich","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-10-31T02:58:59.284Z","media":null,"categories":["编程语言"],"attachments":null,"extra":null,"language":null},{"title":"中国存储厂,杀入顶分桌","url":"https://www.infoq.cn/article/wuluG9t62jRi6BZh3Cf9","content":"如果不是 2016 年,AI 在围棋上大放异彩,关于高性能存储的故事本不会这么复杂——它应该是一场玩家数量极其有限的牌局,由英特尔、IBM、DataDirect Networks、WEKA 等寥寥几家头部玩家轮流坐庄。
这个牌局不欢迎生面孔,即使偶有例外,大概也会是像 Nutanix 一般——其 CEO 先后供职于 VMware 、博通、思科,算是“老朋友的新爱好”。
通常情况下,你很难在“存储”这般重要的事情上,获取大客户的信任。相对于其他赛道而言,存储领域对“后起之秀”更加不友好。
但 AI 好似一条巨型“鲶鱼”,搅混了高性能存储的水。
AI 兴起前,高性能存储的目标客户,以“超算中心”为主。时间一过 2016 年,这个市场就变成了由云计算、AI 公司、超算中心等客户构成的复合型市场。等到 2022 年,生成式 AI 兴起后,情况变得更加复杂。
今天,有许多创业公司专攻面向 AI 的文件存储系统,并且获得了挑战“存储巨头”们的机会。
这是为什么 MLCommons 社区和焱融科技这家公司,在近期吸引了如此之多的关注——
前者作为人工智能工程联盟,在 AI 工程相关的基准测试方面,颇有公信力。今年,MLCommons 围绕其核心的 MLPerf Training 基准测试套件,发起了一个面向 AI 存储场景的横向性能测试,叫做 MLPerf® Storage v1.0 ,吸引了众多在国际上“有头有脸”的存储厂商参加。
后者则是这套测试里,唯一一个参加了全部测试项目的国产厂商,且成绩相当不错,足以和“领头羊”DDN(DataDirect Network)掰掰手腕。
看起来,一个诞生于 2016 年前后,性能堪比 DDN 的中国玩家已经上桌了。但是,对于所有关注 AI 存储的企业和开发者来说,这次测试内含哪些信息,该如何解读?焱融科技又做对了什么?
这首先取决于 MLPerf® Storage v1.0 本身,相对于 IO 500 这样的老牌榜单,在专业度和公信力层面表现如何。
至少从 MLCommons 社区的董事会名单来看,MLPerf 的专业度是有保障的——里面既有来自英伟达、英特尔、谷歌的 AI 业务高管,也有来自哈佛的教授,以及来自 Facebook 的 AI 研究员,可谓背景雄厚。
这也给 MLCommons 带来了额外好处:成熟的开源文化和独到的技术能力。以 MLPerf® Storage v1.0 为例,MLPerf 可以通过 CPU 来完美模拟 GPU 活动,你甚至可以选择是针对 A100 进行测试,还是 H100 进行测试。不需要大量的真实物理资源来完成压测,这是 MLPerf® Storage v1.0 能成功推出的关键。
从结果来看,多家存储公司参加了这次测试。既包括老牌企业 DDN、Nutanix,也包括 WEKA、Hammerspace 这类新兴明星企业,以及 simplyblock 这般成立仅两年的初创企业,在国内,则有焱融科技、华为、浪潮、JuiceFS 等多家公司参加。
而具体的测试方法,有着浓厚的、来自生成式 AI 的“时代特色”:根据存储服务场景的不同,MLCommons 在两个不同的测试版本上,分别选用了四款模型:3D U-Net(图像分割、医学类)、ResNet-50(图像分类,仅 v1.0 版本)、 CosmoFlow (宇宙学参数预测,仅 v1.0 版本)和 BERT-large(语言处理,仅 v0.5 版本),用以测试不同场景下的存储性能。
拿 1.0 版本来说,3D U-Net、ResNet-50、CosmoFlow 不但覆盖了常见的 AI 存储场景,也对存储设备的性能提出了不同要求。这三个模型的单个样本大小,分别是 150MB、150K、2MB,基本覆盖了不同标准下的“大文件”、“小文件”,考验的是厂商在不同场景下的性能调校,以及对元数据的处理策略。
更进一步,MLCommons 要求在 3D U-Net、ResNet-50 的测试中,AU(加速器利用率)必须大于 90%;CosmoFlow 测试的 AU 必须大于 70%。若 AU 一旦低于此值,说明存储性能不足以支撑 GPU 高效运行,即被认定为低效存储,花费太多时间在网络等开销上。
在整个测试过程中,MLPerf® Storage v1.0 会不断增加 ACC(虚拟加速器,也就是模拟 GPU)的数量,直到 AU 低于 90% 或 70%,。最终输出三项数据用作最终比对,分别是:被测机器支持的 ACC(虚拟加速器)总数、测试数据集大小、吞吐速率。
所有测试数据都会被公示,参评的厂商互相审校,交叉提问,只有关于测试成绩的提问全部被“Close”掉,才算做最终测试完成,保证了测试的公正合理。
当然,MLPerf® Storage v1.0 也存在一些问题,其核心是对测试场景的覆盖不够完整。比如缺少对大参数量级的模型的测试,从 3D U-Net 到 BERT-large,参数量级都很小;此外,测试只模拟模型对训练数据的访问,没有测试重新加载模型,或者写 CheckPoint 时,表现出来的存储峰值性能。
另外从 MLCommons 官方公布的结果来看,你很难直接得出一个厂商维度的综合成绩和排名。因为官方只公布了各厂商所提供机器的测试结果,而每台机器配置不同,价格不同,所以数据差异也较大。
我们只能结合存储市场的实际选型情况做自主推测:三项测试数据中,“ACC 总数”这项数据更为关键。至于数据集大小,其实可以忽略——测试数据集的大小,会被设定为测试机器内存的五倍,用以防止参与测试的厂商提前缓存训练数据。
综合来看,MLCommons 真正想展示给公众的数据是两个维度的数据:
某厂商的一套存储系统,能支撑的虚拟 GPU 是多少颗,吞吐速度如何;该存储系统里的单个计算节点,能支撑的虚拟 GPU 是多少颗,吞吐速度如何;
但出于某些原因,社区没有将测试结果,细化到这个层面,也导致各家公关口径的成绩大相径庭。
比如 DDN 选择计算单闪存可以支撑的虚拟 GPU 数量。在这种算法下,DDN 排名第一,排名第二的是国产厂商——焱融科技。
但闪存数量通常不是一套存储系统的性能瓶颈,整体的网络开销才是。且各家产品架构不同,闪存数量,并不是存储设备在性能方面的通用单位。通过计算单闪存平均支持的 ACC 数量来做排名,无疑有失偏颇。
相比较之下,焱融科技以计算节点为单位衡量存储性能,泛用性更强。分布式训练集群场景,焱融存储在所有三个模型的测试中,能够支撑的每个计算节点平均 ACC 数量和存储带宽性能排名第一,排名第二的则是来自美国的独角兽 WEKA。
抛开计算方法层面的分歧,排名靠前的厂商大致有哪些,其实已经明确了——当下,虽然不能说,像焱融科技这般的国产存储厂商,已经完成了对老牌国外存储厂商的追赶和反超,但在部分垂直场景的存储技术上,“国货”和“洋货”确实已经可以同台竞技,甚至战而胜之。
当然,对于国内厂商而言,技术实力很关键,但并不是全部。
这种来自国际权威组织的公开测试,与其说是一场“同台竞技”,不如说是一次宝贵的宣传机会。毕竟在硬科技领域,国内企业往往长于技术,短于生态和营销,几乎已经形成某种刻板印象。
好在,AI 技术的爆发,将市场拉回了某种混沌态,客户的需求几乎年年都在变,这是创业公司更为适应的生存环境——相较于传统巨头们,他们更灵活,也更有侵略性。
早期 AI 客户往往扎根于计算机视觉、自然语言理解等领域,对存储的要求与性能强相关,且主要考察“读”能力,对“写”能力要求不高。而到了大语言模型兴起后,对“写”能力的要求大幅提升。同时,为了保证模型训练、微调等环节的业务连续性,大模型要经常写 CheckPoint,这进一步增加了存储设备的“写”压力。
无论是 CV、NLP,还是大语言模型,对于存储设备而言,都是进行大文件读写。等到多模态能力在生成式 AI 中得到普及,图片和视频切片,形成了海量的小文件。对存储厂商而言,技术难度进一步上升。
“国货”的机会,也恰恰是在这些挑战中诞生的。
相比于存储大厂,新兴企业,尤其是国内的新兴企业,通常更加专注,比如焱融科技,只关注 AI 场景下的分布式文件存储。
此外,国产化替代仍然在进行中。生成式 AI 的发展,和新质生产力相关政策的出炉,不断刺激着国内分布式存储行业的发展。
单从市场层面看,“国货”在存储领域对“洋货”形成替代,实际上也是必然的。
首先存储直接影响业务的连续性和稳定性,一旦发生故障,相关技术团队需要立刻到位。这对于外企而言,显然有些困难。
其次,国内厂商对客户的定制化要求,包容度足够高,愿意配合客户进行一些架构上的探索,这更符合国内甲方企业的实际诉求。
最大的优势,还是在产业链层面。据业内人士透露,在闪存选 QLC,网络解决方案选 RoCE 的情况下,国内有不少上游厂商可供存储厂商选择,对比国外企业,大概会有 20% 的成本节省,从而表现的在终端售价上更有竞争力。
这是为什么,成立还不到十年的焱融科技,今时可以在 MLCommons 举办的测评中,和已经成立 26 年的 DDN 打擂台。
与上述判断相符的是,售卖存储设备的外企,在中国,仍处于长达十年的持续衰退中。以至于有研究机构,围绕国内市场做竞争力象限图时,DDN 这样企业的位置,已经从右上角(领导者)跌入左下角(专精者)。
这既给国内企业留出了充足的发展空间,同时也意味着,未来的增长故事不会发生在国内,而是发生在海外。有研究机构预测,到 2031 年,北美地区的软件定义存储市场预计增长到 380 亿美元以上,亚太地区预计增长至 275 亿美元以上,中国地区预计占到其中 33.7% 的份额。
类似 MLPerf® Storage v1.0、IO 500 这样的测试和榜单,对于国内企业而言,今后会变得更加重要。
焱融科技对此认知十分清醒。焱融科技 CTO 张文涛透露,对于六月底开始的 MLPerf® Storage v1.0,焱融科技实际上在 4 月就开始测试了。由于早期不知道同台竞技的企业有哪些,只能尽量逼近自身产品的极限值。
同时,今天的存储厂商每谈成一单生意,要解决的不光是性能问题,也是产品问题和服务支持问题。
大模型超长的训练周期以及其特殊的业务流程,要求存储厂商的产品,不仅性能够强,在产品设计和服务支持方面也要跟得上。
这是为什么焱融科技投入人力开发了 Dataload 智能数据加载功能——多云、混合云架构是过去几年间,国内最主要的云构建策略,而以 Dataload 为核心的解决方案,可以激活历史数据的价值,打通对象存储与文件存储,实现多云间的数据流转,消除性能瓶颈。
这其实是市场对产品提出的新要求。
成立于 2016 年前后的存储企业,即将迈过十周年的门槛,变得不再年轻。而随生成式 AI 的发展而诞生的新兴存储企业,正逐步进入市场主流视野。
曾经的“少壮派”们,如今面临着向上从巨头手中抢市场,向下严守基本盘的空前竞争压力。能否走出舒适区,将成为后续发展的关键一步。
","description":"如果不是 2016 年,AI 在围棋上大放异彩,关于高性能存储的故事本不会这么复杂——它应该是一场玩家数量极其有限的牌局,由英特尔、IBM、DataDirect Networks、WEKA 等寥寥几家头部玩家轮流坐庄。 这个牌局不欢迎生面孔,即使偶有例外,大概也会是像 Nutanix 一般——其 CEO 先后供职于 VMware 、博通、思科,算是“老朋友的新爱好”。\\n\\n通常情况下,你很难在“存储”这般重要的事情上,获取大客户的信任。相对于其他赛道而言,存储领域对“后起之秀”更加不友好。\\n\\n但 AI 好似一条巨型“鲶鱼”,搅混了高性能存储的水。\\n\\nAI 兴起前…","guid":"https://www.infoq.cn/article/wuluG9t62jRi6BZh3Cf9","author":"焱融科技","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-10-31T02:50:48.903Z","media":[{"url":"https://static001.geekbang.org/infoq/85/85e108e98444eaf29fb47fb2edbf7244.webp","type":"photo","width":0,"height":0,"blurhash":""}],"categories":["大数据","数据库"],"attachments":null,"extra":null,"language":null},{"title":"AI 注入新活力,OceanBase 的含金量还在上升","url":"https://www.infoq.cn/article/UYW2sjD6TejVrhBagmEd","content":"2023 年被广泛认为是大语言模型的元年,这一年我们见证了人工智能技术前所未有的飞跃。而步入 2024 年,围绕大语言模型诞生出来的 AI 原生应用如雨后春笋般涌现。越来越多的 AI 应用已经不再局限于纯文本生成和回答,而是逐渐向多模态应用程序演进。
以典型的多模混合查询为例,消费者在 AI 应用中搜索“推荐距离 500 米以内,人均消费 24 元以下,评价 4.5 分以上,不用排队的奶茶店”时,数据库要同时处理 GIS 数据(距离)、关系型数据(价格、评分)、向量数据(不排队)等不同类型的数据。这就意味着,传统的数据处理方式已经很难满足新 AI 应用带来的复杂需求。
意大利 PXR 研究机构数据统计,全球范围内创建、捕获、复制和消费的数据 / 信息量从 2010 年的 2ZB 增长到 2020 年的 64.2ZB。预计到 2025 年,全球数据总量将超过 181ZB。
这些数据中,既包含动态、实时的数据流,也涵盖静态、历史的数据存储;既有结构化的数据库记录,也有非结构化的语音、图像和视频。如此海量、复杂的数据给数据库提出了新要求:
实时性与低延迟:随着实时数据分析和决策的需求增加,数据库必须能够快速处理大量数据,以支持实时应用,如在线推荐和动态定价。这对传统数据库在性能和响应时间上提出了更高的要求。海量数据与多样性:AI 应用生成的数据量大且类型多样(结构化、半结构化和非结构化),数据库需要具备处理和存储不同类型数据的能力,要求支持多模架构,以满足多模态的数据需求。复杂融合查询:AI 应用对复杂数据分析提出更高的需求,数据库需要支持复杂 SQL 查询优化,提升查询性能,以满足深度学习和机器学习模型的训练与预测需求。多源数据融合:不同来源的数据需要进行融合处理,以获取更全面、更准确的信息。例如,将企业内部不同业务、不同工作负载的数据,甚至生态业务数据、行业数据进行融合,分析企业的市场竞争力和发展趋势。
在 AI 技术的推动下,单一、结构化、静态数据架构的时代已经一去不复返,数据库架构的变革正在呼之欲出。那么落实到技术上,到底什么样的数据库才能应对以上种种挑战,能承接住 AI 应用井喷后带来的海量数据处理需求?
刚刚,OceanBase 提出了自己的解法。
在 10 月 23 日举办的 2024 OceanBase 年度发布会上,OceanBase 推出了 OceanBase 4.3.3 版本,增加了全新的向量检索与索引功能,实现了 SQL+AI 一体化。该版本深度融合 AI 与数据库处理能力,支持多模态数据融合查询,帮助企业简化 AI 技术栈,提升 AI 应用构建效率。
也就是说,OceanBase 希望用一个数据库满足客户 80% 的数据库场景需求,将所有的复杂性工作交给数据库,将简单留给客户。
作为首个面向实时分析的 GA 版本,OceanBase 4.3.3 在多个关键能力上取得了显著突破,其重要创新与对 AI 场景的支持主要体现在以下几个方面:
向量融合查询能力:OceanBase 4.3.3 在关系型数据库基础上新增了向量检索能力,支持向量数据类型、向量索引以及基于向量索引的搜索能力。用户可以通过 SQL 和 Python SDK 等方式灵活使用 OceanBase 的向量检索能力。结合 OceanBase 对海量数据的分布式存储能力,以及对多模数据类型和多种索引的支持,OceanBase 4.3.3 提供了更加丰富的融合查询能力,大幅简化 AI 应用的技术栈,加速 RAG、智能推荐和多模态搜索等业务场景的落地。
全新的列存副本形态:为了更好地支持 HTAP 混合负载场景,OceanBase 4.3.3 引入了列存副本的新形态,满足 TP 和 AP 负载资源物理强隔离的需求。在混合场景中,事务处理和分析处理通常会对系统资源产生不同的需求,而这种物理隔离的副本机制确保了系统在处理事务型负载的同时,不会受到分析型负载的干扰。尤其对于实时数据分析和决策,这种隔离机制能够确保系统的高性能和稳定性。
AP 类查询的性能优化:在新的版本中,OceanBase 针对 AP(分析处理)场景进行了大幅度的性能优化。通过对 AP 类 SQL 的执行计划生成和执行策略的优化,显著提升了复杂查询的效率。特别是在海量数据分析和复杂数据融合查询时,新版本提供了更短的响应时间和更高的吞吐能力,帮助企业在实时分析和预测任务中更快获得结果。新增并且优化了对复杂数据类型的支持:OceanBase 4.3.3 进一步扩展了对复杂数据类型的支持,新增了 Array 类型,并优化了 Roaringbitmap 类型的计算性能。这为企业处理多样化数据结构提供了更大的灵活性,同时强化了基于物化视图的改写与刷新机制,使得复杂的分析任务能够更高效地执行。外表功能扩展及性能提升:在数据导入和集成方面,OceanBase 4.3.3 大幅优化了外表(External Table)的功能,并提高了数据导入的性能。这使得外部数据源的整合更加流畅,特别是对于需要频繁导入大规模数据的场景,企业可以更快地完成数据同步,满足业务的实时需求。快速恢复与 QUERY 级资源组支持。OceanBase 4.3.3 引入了一种无需恢复数据到本地即可通过恢复日志提供读写服务的快速恢复能力,这种机制在数据恢复场景中显著提升了系统的可用性。此外,该版本还支持了 QUERY 级别的资源组设定,使得系统能够更灵活地分配和管理资源,进一步提升了在高并发、复杂查询环境下的可靠性。
总的来说,OceanBase 4.3.3 通过对向量支持、实时 AP 及混合负载、复杂查询优化、外部数据集成及系统可靠性的全面提升,为 AI 时代的企业数据处理提供了更高效、灵活和稳定的技术支撑。
发布会上,OceanBase 与蚂蚁集团联合开发的向量库在业内标准的 ANN Benchmarks 基准测试中,针对 GIST-960 数据集表现出色。测试结果显示,该向量库在 ANN Benmarks 测试中性能远超其他算法,排名第一。特别是在 90% 以上的召回率区间,查询性能(QPS)相比此前最优算法 glass 提升 100%,相比基线算法 hnswlib 提升 300%。
CEO 杨冰表示,伴随着互联网 / 移动互联网时代向 AI 时代演进,数据库也正从分向合统一,一体化数据库将成为 AI 时代的数据底座。
那么,该如何理解所谓的一体化数据库?OceanBase 又为何会在这样的时间点上提出一体化数据库的概念?
据杨冰介绍,一体化数据库是一种能够处理多种工作负载、数据类型及场景的数据库系统,旨在通过一个数据库满足企业各种复杂的数据需求,简化技术栈,提升效率并应对日益复杂的数据需求。这种数据库通常具备事务处理(TP)和分析处理(AP)能力,支持多模数据处理(如 JSON、XML、GIS、文档等),并兼容多种主流数据库协议(如 MySQL 和 Oracle),让用户能够在一个数据库上满足多样化的数据处理需求。
OceanBase 的一体化数据库的概念并非一蹴而就,而是伴随着 OceanBase 的整个生命周期,逐步演化、成熟。这种一体化能力并非凭空设计,而是深深植根于客户场景和需求之中,是市场实践的结晶。在这一过程中,OceanBase 经历了两次大的技术迭代。
第一次是 OceanBase 1.0,真正实现了原生分布式架构的可读可写。第二次是 OceanBase 4.0,提出并实现了单机分布式一体化架构,用一个系统满足一个用户从小到大、全生命周期的数据存储与管理需求。
基于分布式和单机分布式的一体化架构,OceanBase 不断丰富数据库功能。包括打造一体化 SQL 引擎,全面兼容 MySQL 和 Oracle;增强对实时 AP 的支持,实现 TP+AP 一体化;打造 SQL+NoSQL 能力,增强对多数据类型的支持。
而随着 AI 技术不断深入应用,OceanBase 进一步实现 SQL+AI 的能力,支持向量检索,并能处理向量与其他数据类型的混合查询,如 GIS、关系型数据、向量数据、文档等。通过向量融合查询能力,帮助企业更轻松地将 AI 能力与数据库系统集成,简化 AI 应用技术栈,为复杂的 AI 应用提供强有力的支持。
想象一下,如果某家公司需要处理各种各样的数据任务,既要管理日常的财务记录,又要进行大数据分析来预测市场趋势,还要存储和查询各种格式的信息,如地图数据、文档报告等。以往,他们可能需要用到几种不同的数据库系统来完成这些任务,每个系统都有自己的一套规矩和工具,这不仅麻烦,而且效率不高。
而类似于一体化数据库这样的产品出现后,它就像一个超级智能助手,它能一口气搞定所有事情。这个助手不仅精通处理日常交易(TP),比如快速准确地记录每一笔收支;还擅长做数据分析(AP),比如帮公司算出哪个产品最畅销,未来市场可能会怎么变化。更重要的是,它在处理结构和非结构化数据上也游刃有余,无论是简单的文字记录、复杂的地图信息,还是各种文档报告,它都能轻松应对。
这样一来,无论是财务部门想要精确记录每一笔账目,还是市场部门想要分析大数据预测未来,或者是研发团队需要存储和查询各种格式的研发文档,都可以在同一个数据库系统上完成,大大简化了工作流程,提高了效率。这就是一体化数据库的魔力所在。
一体化数据库的出现,弥补了传统独立式数据库在处理结构化、半结构化和非结构化数据时存在的诸多局限,比如技术栈的复杂性、数据库系统运维的困难性、数据处理效率和准确性低等问题。
AI 时代,一体化数据库在多工作负载处理、多模数据处理以及向量(SQL+AI)融合等方面展现出了显著的优势。
事实上,不只是 OceanBase 在加快向一体化数据库演进的速度,放眼国际,不少全球头部数据库厂商也在积极推进向一体化数据库的演进。
Snowflake 是作为新生代的云原生数仓的主动者之一,目前已经实现了基于多个公有云架构的云上数仓服务。作为一家从数仓起家的公司,Snowflake 近年来却一直忙于拥抱数据湖,实现数据湖、数据仓库一体化,并且通过并购和与行业巨头合作的方式加速向 AI 靠拢。自 2022 年以来,Snowflake 开始布局“数据 +AI”模式,共先后并购六家相关公司并且已经与微软和英伟达等公司展开合作。
作为 NoSQL 数据库的佼佼者,MongoDB 也一直推进其一体化数据库的进程,而 MongoDB 走的路线是为开发者提供多模数据库平台。MongoDB 的 Atlas 平台不仅支持文档、键值、图和搜索等多种数据模型,还通过自动化的扩展能力和多云部署,极大地简化了企业复杂的数据架构管理。这种灵活性使得 MongoDB 在应对多样化数据需求时游刃有余。同时,MongoDB 在 SQL 与非关系型数据(如 JSON)的融合上持续优化,进一步拓宽了其应用场景。然而,MongoDB 也面临着提升混合负载处理能力的挑战,特别是在事务处理(TP)与分析处理(AP)之间的平衡上,这对其底层架构的创新提出了更高要求。
全球单机数据库领导者 Oracle 也越来越注重 AI、ML 和多模处理能力的融合。Oracle 的 Autonomous Database 不仅支持关系型、文档型、JSON、图形和向量数据等多种数据类型,还通过 HTAP(混合事务与分析处理)技术,实现了在同一平台上高效处理事务型和分析型数据的能力。这使得 Oracle 在应对复杂业务场景时表现出色。然而,随着多租户环境和复杂分析任务的增多,Oracle 也面临着资源隔离和性能优化的难题,如何保持高效的资源利用率和成本控制,成为其需要重点解决的问题。
此外,Amazon Redshift、Google BigQuery 等云数据仓库也在不断优化其一体化数据库的功能和性能,以满足用户对高效、灵活数据处理的需求。
由此可见,SQL+AI 正被越来越多数据库厂商视为重要技术演进方向,但在此过程中他们也面临着共同的挑战和难题。
具体而言,HTAP 性能优化、多模数据处理的深度融合以及 AI 与数据库的深度集成是当前一体化数据库发展面临的主要挑战。如何在混合负载下实现更加高效的资源隔离和优化 AP 与 TP 之间的调度,是提升 HTAP 性能的关键。
同时,随着数据类型的多样化和复杂化,如何进一步优化多模数据的处理性能,特别是在高并发场景下的查询性能,也是当前需要解决的问题之一。而且随着 AI 技术的快速发展,如何在一体化数据库中高效地支持 AI 模型的训练和推理,特别是在 AI 数据预处理和向量检索方面,需要进一步的架构调整与创新。
基于以上,我们有理由相信,一个由“SQL+AI”引领的一体化数据库新时代正在走来。在这个时代里,数据库将不再是简单的数据存储工具,而是成为推动业务创新与发展的重要引擎。
","description":"AI 应用的崛起,推动了数据处理方式的变革 2023 年被广泛认为是大语言模型的元年,这一年我们见证了人工智能技术前所未有的飞跃。而步入 2024 年,围绕大语言模型诞生出来的 AI 原生应用如雨后春笋般涌现。越来越多的 AI 应用已经不再局限于纯文本生成和回答,而是逐渐向多模态应用程序演进。\\n\\n以典型的多模混合查询为例,消费者在 AI 应用中搜索“推荐距离 500 米以内,人均消费 24 元以下,评价 4.5 分以上,不用排队的奶茶店”时,数据库要同时处理 GIS 数据(距离)、关系型数据(价格、评分)、向量数据(不排队)等不同类型的数据。这就意味着…","guid":"https://www.infoq.cn/article/UYW2sjD6TejVrhBagmEd","author":"李冬梅","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-10-28T10:20:29.227Z","media":[{"url":"https://static001.geekbang.org/infoq/55/5562c2142f8af2a016f44aff8b7a9735.webp","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/9b/9b7e31bbd8823bf34917de9f08ec6f05.webp","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/c6/c63f4575fc3563df3149bbde897a6c93.webp","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/3c/3c9efd56092de115db489d37acbb7d08.webp","type":"photo","width":0,"height":0,"blurhash":""}],"categories":["数据库"],"attachments":null,"extra":null,"language":null},{"title":"第十届 RTE 大会开幕,探讨生成式 AI 时代 RTE 的发展与进化","url":"https://www.infoq.cn/article/F7J16KwIg5KasXxp7aUV","content":"10月25日,由声网和 RTE 开发者社区联合主办的 RTE2024 第十届实时互联网大会在北京正式开幕,InfoQ作为本次大会的社区伙伴。本届大会主题为“AI 爱”,覆盖AI、出海、社交泛娱乐、IoT、Voice AI、空间计算等20+行业及技术分论坛。今年是声网成立的十周年,也是 RTE 大会的第十届。十年间,实时互动从“理念”发展成一个“行业”。实时互动技术不仅助力社交泛娱乐、在线教育、IoT、企业服务等几十个行业、数百个场景实现了跨越式成长,也支撑了诸多互联网风口的进化,从过去的电商直播、互联网医疗、秀场直播到如今的大模型,都离不开 RTE 能力的参与和赋能。
在全新的生成式 AI 时代,RTE 与 AI 也将迎来更多可能性。25日上午的 RTE2024 主论坛中,声网创始人兼 CEO 赵斌、Lepton AI 创始人兼 CEO 贾扬清、声网首席科学家、CTO 钟声分别带来主题演讲。赵斌分享了声网十年以来专注实时互动行业的深刻洞察,以及他对 RTE 在生成式 AI 时代下未来发展的趋势判断。贾扬清则站在 AI 基础设施的视角下,分享了他对 AI 应用、云、和 GPU 算力云技术的独到观点。钟声的主题演讲聚焦在对实时 AI 基础设施的探讨上,并分享了 AI 与 RTE 结合的前沿技术实践。
生成式 AI 正在驱动 IT 行业发生大变革,赵斌认为,这一趋势主要体现在四个层面:终端、软件、云和人机界面。在终端上,大模型能力将驱动 PC 和 Phone 往 AI PC 和 AI Phone 的方向进化。在软件上,所有的软件都可以、也将会通过大模型重新实现,并从 Software with AI 发展至 AI Native Software 。在云的层面,所有云都需要具备对大模型训练和推理的能力,AI Native Cloud 将成为主流。此外,人机界面的主流交互方式也将从键盘、鼠标、触屏变成自然语言对话界面(LUI)。
随着生成式 AI 成为下个时代 IT 行业进化的主题,RTE 也成为了多模态应用和基础设施中一个关键的部分。10月初,声网的兄弟公司 Agora 作为语音 API 合作者,出现在了OpenAI 发布的 Realtime API 公开测试版中。
在此次大会中,赵斌表示,声网与 MiniMax 正在打磨中国第一个Realtime API。赵斌也展示了声网基于 MiniMax Realtime API 打造的人工智能体。在演示视频中,人与智能体轻松流畅的进行实时语音对话。当人类打断智能体并提出新的疑问时,智能体也能够非常灵敏的快速反应,实现了与人类自然流畅的对话。
在生成式 AI 的大潮下,RTE 将会提供更为广阔的空间。赵斌也在分享中宣布,声网正式发布了 RTE+AI 能力全景图。在全景图中,声网从实时 AI 基础设施、RTE+AI 生态能力、声网 AI Agent、实时多模态对话式 AI 解决方案、RTE+AI 应用场景五个维度,清晰呈现了当下 RTE 与 AI 相结合的技术能力与应用方案。生成式 AI 与RTE 结合带来的场景创新,将成为下一个十年的主题。
过去十年,声网不仅见证并推动了 RTE 从一个理念变成一个行业的过程,更身体力行的打破了国内实时音视频领域的三无状态。赵斌称,10年前行业内没有行业会议、专业书籍、以及专业媒体和社区。如今,RTE 大会迈入第10年,声网也于今年8月正式出版行业首本系统介绍实时互动的技术型科普图书《读懂实时互动》,同时,RTE开发者社区也持续繁荣,加速推动。
随着 AI 技术的发展,AI 时代的大模型应用开发、AI 云、以及 GPU 等基础设施建设逐渐成为热门话题,也成为了支撑整个行业发展、催生新应用诞生、新商业价值实现的基本底座。Lepton AI 创始人兼 CEO 贾扬清在 RTE2024 主论坛上分别从 AI 应用、云、GPU 算力云技术以及企业大模型自主性等层面带来了他对 AI 基础设施进化的解读。
针对 AI 应用,贾扬清指出,今天是最容易建设 AI 应用的时代,越是简洁的 AI 模型思路越容易产生优秀的效果。AI 能力加持后,应用本身的开发范式也在从数据、模型、应用构建三个维度发生变化,未来的应用开发将从“以流程为中心” 转化为“以模型为中心”。
除了 AI 应用层面,传统的云架构也在大模型、GPU 优化等需求的催化下发生了翻天覆地的变化。贾扬清认为,AI 是云的第三次浪潮,继 Web 云、数据云之后,AI 将成为第三朵云。AI 云有以下三个特征:算力会成为智能的基础、AI 云需要大量计算与大规模的异构集群,以及少量但高质量的通讯。总体而言,云的产品形态,本质是计算和传输的平衡。贾扬清指出,在 AI 云的形态下,实时的交流和智能的结合在用户体验环节非常重要。毫不夸张的说,实时将直接与生产力划上等号。
企业在构建自己的大模型自主性上,到底该如何决策?贾扬清强调,企业应该将开源和闭源大模型都纳入考虑范畴。采用开源模型+定制化的优势不仅仅是具备更强的可定制性,还有更低的成本以及更高的速度,开源+定制化能够达到比闭源模型更好的效果。
在已经到来的 AI 时代,现代化基础设施应该是什么样?声网首席科学家、CTO钟声提到,大量用户设备往往会先接入边缘节点、并在需要的时候再接入云端,数据将在端设备、边缘节点和云之间往返传递。AI 时代的数据中心会包含以大量异构算力组成的超级计算集群(SuperScaler)。但是,停留在仅依赖超级计算集群的系统是远远不够的,万亿参数、多模态引入所造成的高昂计算成本、缺乏机制约束的数据隐私保护、几秒钟的延时都将阻碍大模型的普惠,极大地限制其在很多场景下的应用。
钟声认为,分布式端边云结合的 AI 系统将有效解决这些痛点。这个系统将把计算和传输在各节点做合理地配置,系统会智能地以自适应的方式把任务编排到端与边上执行,非常有效地降低了成本,同时提供了更低延时(低于1秒级的响应速度)、更高网络抖动容忍度、优秀的抗噪声能力,并且完整的用户数据只会保留在端上。
分享过程中,钟声还在大会现场演示了一个由STT、LLM、TTS 、RTC四个模块组成的端边结合实时对话AI智能体,这也是全球首次有厂商在比日常实际场景更具挑战的环境下展示实时AI 对话能力。大会现场观众规模超过千人,面临复杂的噪声、回声、麦克风延迟等困难,但智能体与钟声的互动仍然表现出了优秀的对话能力,在普通5G网络环境下实现了流畅、自然、有趣的双向实时对话,对话模型的极快响应速度、及时打断与被打断的自然程度、对抗噪声能力、遵循语音指令做等待能力都非常突出。
正如钟声在最后分享的,随着端设备的多样化以及能力的提升,AI 基础设施会变得更优化合理,使得 AI 无处不在,AI助理、AI分身帮助我们有效缓解时间稀缺性,改善工作效率和生活体验。
AI 的6000亿美元难题,一直都是整个行业非常关心的话题,在圆桌讨论环节中,Lepton AI 创始人兼 CEO 贾扬清、MiniMax 合伙人魏伟、面壁智能联合创始人&CTO 曾国洋、Hugging Face 工程师王铁震、Agora 联合创始人 Tony Wang 五位嘉宾一起探讨了从 AI 基础设施到 AI 商业化落地的机会与挑战。
针对商用大模型和开源大模型未来的发展趋势,贾扬清分享了两个核心观点:其一,同等质量模型的Size会变得越来越小,计算效率会越来越高,模型架构也会变得更加开放和标准。其二,除了极少数头部公司之外,越来越多的企业会采用开源架构来做下一代模型。因此,开源架构的应用会变的越来越普遍,通过开源架构训练出来的模型也都会有各自不同的风格。
王铁震则表示,我们将在未来看到越来越多 Infra 和 Realtime 的工作,大家不仅需要关注开源模型本身,还需要重视开源模型的基础设施和数据闭环,才能把开源模型跑得更好、更快。Realtime 需要TTS、也需要大模型,如果能够通过一些方式放在一起,放在边缘侧、离用户更近的地方,才能产生非常好的效果。
关于如何看待音视频多模态模型的实际应用潜力,魏伟表示,随着多模态的出现,生成式人工智能的边界一定会被继续拓展,并加速这一产业的变革。从产品和用户服务过程中魏伟发现,文本、语音、音乐、视频这些模型可以很好的帮助艺术、影视、音乐等领域的创作者极大地提高效率,并为他们提供新的思路和方法。
针对大模型技术巨大的成本使用问题,曾国洋分享到,随着技术的前进,算力一定会变得越来越便宜,相同能力的模型规模也会变得越来越小,但算力成本优化会最终转化为训练更强大的模型。真正达到 AGI 水平之前,我们只能感受到模型在变得越来越强,很难感受到成本的变化。他还提到,由于面壁智能是做端侧模型的,所以很关注如何让模型在端上跑得更快,在实际部署过程中,他们会用各种量化压缩甚至是稀疏化方法去优化实际部署的开销。
总结来说,Tony Wang 认为想要推动 AI Infra 到模型、再到商业化落地,技术驱动和成本是最核心的两个点。此外,在产品真正走向市场的过程中,流量和口碑也是关键。
过去十年,声网不仅见证并推动了 RTE 从一个理念变成一个行业的过程,更身体力行的打破了国内实时音视频领域无行业会议、无专业书籍、无专业媒体及社区的三无状态。自此,RTE 大会迈入第10年,行业首本系统介绍实时互动的技术型科普图书《读懂实时互动》于今年8月正式出版,RTE开发者社区也正在秉持着“开放、连接、共创” 的理念加速实时互动和 AI 的共生。
未来,声网将继续和大家一起,站在全新的起点、拥抱繁荣且充满挑战的 AI + RTE 新时代。大家也可以期待即将在12月正式发布、InfoQ和RTE开发者社区联合发布的年度报告。
","description":"10月25日,由声网和 RTE 开发者社区联合主办的 RTE2024 第十届实时互联网大会在北京正式开幕,InfoQ作为本次大会的社区伙伴。本届大会主题为“AI 爱”,覆盖AI、出海、社交泛娱乐、IoT、Voice AI、空间计算等20+行业及技术分论坛。今年是声网成立的十周年,也是 RTE 大会的第十届。十年间,实时互动从“理念”发展成一个“行业”。实时互动技术不仅助力社交泛娱乐、在线教育、IoT、企业服务等几十个行业、数百个场景实现了跨越式成长,也支撑了诸多互联网风口的进化,从过去的电商直播、互联网医疗、秀场直播到如今的大模型,都离不开 RTE…","guid":"https://www.infoq.cn/article/F7J16KwIg5KasXxp7aUV","author":"声网","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-10-26T09:32:28.536Z","media":[{"url":"https://static001.infoq.cn/resource/image/9f/81/9f1e0210e6af0a1225eb2c7f24e7fa81.jpg","type":"photo","width":832,"height":554,"blurhash":"LPGbSZD%D%xa_4V_VrkCk9a%xCRk"},{"url":"https://static001.infoq.cn/resource/image/84/0c/84a19905c686d8f7e1ce7e478280630c.jpg","type":"photo","width":1274,"height":849,"blurhash":"L58p[%IS%2nmtVIoNFRkq?bdsoxu"},{"url":"https://static001.infoq.cn/resource/image/49/e8/4998ddbbe001dea529cyya981b1d57e8.jpg","type":"photo","width":1274,"height":849,"blurhash":"LVF55X-qIWVt}]t7E2aO}@n$M}xH"},{"url":"https://static001.infoq.cn/resource/image/4c/e4/4cac5yyb5ac8610b13065071a650e0e4.png","type":"photo","width":840,"height":1396,"blurhash":"L97VDh.S8^DjMdVYaJX88{Mx.8?u"},{"url":"https://static001.infoq.cn/resource/image/36/a6/3642c76b49e0d5c705de71d307b82fa6.jpg","type":"photo","width":832,"height":554,"blurhash":"L59@0X^P-:NG0yD*ogIm}5sRxwt7"},{"url":"https://static001.infoq.cn/resource/image/2c/32/2c7ea9bfe33c850cbc759b91059c2d32.jpg","type":"photo","width":1274,"height":849,"blurhash":"L+IiOYtQV[t7%gayV@j[8^V@bHWB"},{"url":"https://static001.infoq.cn/resource/image/cd/6c/cd19cf0ae5547057fb9f07b6b66b086c.jpg","type":"photo","width":1274,"height":849,"blurhash":"LOE.ClRhIoM}-EbaRkRR}@%MR+M|"}],"categories":["AI&大模型","音视频(后端)"],"attachments":null,"extra":null,"language":null},{"title":"谷歌建议在 SQL 中增加管道语法","url":"https://www.infoq.cn/article/zuOjSXstvUwLWJP0bYrJ","content":"在最近一篇题为“SQL 有问题,我们可以解决”(SQL Has Problems. We Can Fix Them)的论文中,谷歌的一个研究团队建议在 SQL 中引入新的管道语法。谷歌为解决 SQL 被认为存在的局限性而提出的这一解决方案目前已在 GoogleSQL 和 ZetaSQL 方言中提供,但社区对此的反馈却褒贬不一。
为了解决 SQL 的设计挑战并使其成为一种更灵活的语言,谷歌的研究团队提出通过引入管道数据流语法来扩展 SQL。这种设计遵循了与 MongoDB 查询语言 等新兴数据语言相似的模式。谷歌的软件工程师 Jeff Shute 及其同事写道:
我们不必容忍 SQL 的缺陷。这种语言是可以修复的!本文展示了如何借鉴其他语言和 API 的灵感,将管道结构化数据流添加到 SQL 中,而且只需可接受的开销。由此产生的语言依然是 SQL,但却是更好的 SQL。它更灵活、更可扩展,也更易于使用。
传统 SQL 将操作组合成一个语句,而管道式 SQL 则将其拆分为一系列步骤。例如,以下查询:
SELECT name, price FROM products WHERE price > 10;
现在可以写成:
products | WHERE price > 10 | SELECT name, price;
作者和其他专家认为,采用 SQL 的管道语法可以带来多种实际好处,包括提高代码的可读性和可维护性、更好的工具和 IDE 支持,以及提高工作效率。由于新语法旨在简化 SQL 查询的编写、读取和维护过程,因此可以加快开发周期,使查询结构更直观,更容易理解和修改。
来源:谷歌研究
目前,GoogleSQL 支持管道语法,这是一种 SQL 方言,用于 Google 的多个不同的 SQL 产品,包括 BigQuery、Spanner、F1、Bigtable、Dremel 和 Procella,既用于公开产品,也用于内部产品。Shute 及其同事总结道:
管道语法开启了全新的 SQL 使用方式、提升 SQL 工具的机会以及未来的语言创新(……)。取代 SQL 既不必要,也不理想,更不现实。我们可以从语言内部解决 SQL 最严重的问题。
谷歌并不是唯一一家采用管道式 SQL 的超大规模云服务提供商;微软也在 Azure Data Explorer 和使用 Kusto Query Language (KQL) 的 Fabric KQL DB 中提出了类似的做法。SQLite 的创建者 Richard Hipp 对此 并不十分认可,YugabyteDB 的数据库专家兼开发者倡导者 Franck Pachot 则认为这并 不是什么好主意。Pachot 写道:
这种管道语法在编写简洁 SQL 代码方面非常糟糕(……)。在所有语言中,以函数的签名、名称、输入参数和返回类型作为开头是有充分理由的(……),SQL 查询也是如此。SELECT 子句定义了返回给程序的内容:表格结果的列及其名称(……)。你能用管道语法查看上面的查询吗?你该如何猜测结果的结构?
在 Reddit 上的一个热门话题中,用户 Jabes 评论道:
我认为这看起来非常有趣。如果我的数据库能够支持它,并且假设优化器仍能将语句作为一个整体来考虑,我愿意试一试。我在想,是否有可能实现一个翻译层。
新语法也可用于 GoogleSQL 的开源版本 ZetaSQL。
Renato Losio,拥有丰富的云架构师、技术负责人和云服务专家经验。他目前居住在柏林和的里雅斯特之间,远程担任首席云架构师。他的主要兴趣领域包括云服务和关系数据库。他是 InfoQ 的编辑,也是公认的 AWS 数据英雄。
原文链接:
https://www.infoq.com/news/2024/09/google-sql-pipe-syntax/\\"
","description":"在最近一篇题为“SQL 有问题,我们可以解决”(SQL Has Problems. We Can Fix Them)的论文中,谷歌的一个研究团队建议在 SQL 中引入新的管道语法。谷歌为解决 SQL 被认为存在的局限性而提出的这一解决方案目前已在 GoogleSQL 和 ZetaSQL 方言中提供,但社区对此的反馈却褒贬不一。 为了解决 SQL 的设计挑战并使其成为一种更灵活的语言,谷歌的研究团队提出通过引入管道数据流语法来扩展 SQL。这种设计遵循了与 MongoDB 查询语言 等新兴数据语言相似的模式。谷歌的软件工程师 Jeff Shute…","guid":"https://www.infoq.cn/article/zuOjSXstvUwLWJP0bYrJ","author":"作者:Renato Losio","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-10-25T00:04:00.982Z","media":[{"url":"https://static001.geekbang.org/wechat/images/f2/f29b1ce117010babef602e3797f09c4e.png","type":"photo","width":0,"height":0,"blurhash":""}],"categories":["大数据","后端"],"attachments":null,"extra":null,"language":null},{"title":"拥抱 JVM 上的反应式应用:深入理解现代 I/O 模型和 Vert.x","url":"https://www.infoq.cn/article/Cs1QzZ7BZj74lUdRxXDT","content":"本文探讨了从阻塞式 I/O 转向非阻塞式 I/O 和异步 I/O 的过程,强调了它们在现代软件开发中的重要性。文章强调了云计算、大数据和 IoT 驱动的反应式应用程序的兴起。具体来讲,文章主要关注 Vert.x,这是一个在 JVM 上构建反应式应用程序的强大工具包,其知名的特性包括 Multi-Reactor 模式、事件总线和 Verticle。基准测试结果表明,Vert.x 性能卓越,是高并发环境的理想选择。真实使用案例和 COVID-19 全球仪表盘的案例研究说明了 Vert.x 的实际优势和应用。
BIO(阻塞式 I/O):这种模型是同步和阻塞的。由专门的线程处理每个客户端连接,这会导致资源使用效率的低下,尤其是在高负载的情况下。NIO(非阻塞式 I/O):NIO 同步运行,但不阻塞。服务器上的单个线程可同时管理多个客户端请求,这提升了可扩展性。NIO 架构包含三个主要的组件:Buffer、Channel 和 Selector。AIO(异步 I/O 或 NIO 2.0):AIO 通过引入一个异步、非阻塞的模型扩展了 NIO,该模型使用回调来处理相关的操作。这种模型非常适合需要维持大量连接或者需要较长连接持续时间的应用程序。
最近,应用程序的需求发生了明显的变化,尤其是伴随着 云计算、大数据 和 IoT 的兴起。要在现代应用程序领域存活下来,采用反应式架构风格是至关重要的。Play 和 Vert.x 等框架的流行彰显了对非阻塞 I/O 日益增长的需求。Play 利用 Akka 和非阻塞 I/O,集成了 Netty 和 Akka HTTP 以优化操作。Vert.x 的设计是事件驱动和非阻塞的,使其能够以较少的线程高效支持数量众多的并发用户。按照 TechEmpower 的 Web 框架基准测试,使用 Vert.x 开发的应用程序在各种标准测试中都超过了其竞争对手。这些技术的典型实现包括 MasterCard 对 Vert.x 的使用 以及 Netflix 的网关转向异步 NIO。但是,很多像 Capital One 和 Red Hat 这样的许多组织也在其技术栈中使用了 Vert.x。
例如,MasterCard 之所以选择使用 Vert.x 作为支付网关就在于其事件驱动、非阻塞的架构,这确保了高吞吐量和低延迟。Vert.x 处理大量并发事务的能力对于每天处理数亿笔支付的场景至关重要。该框架的横向和纵向可扩展性使 Mastercard 能够满足不断增长的需求。除此之外,Vert.x 工作者(worker)verticle 能够管理长时间运行的任务,而不会阻塞主事件循环,从而保持系统的响应速度。这使得 Vert.x 成为构建有韧性、高性能和高可用性支付系统的理想方案。
另外一个有趣的使用场景是 Dream11,它需要一个高性能、可靠的框架来处理体育比赛期间难以预测的流量激增。单场比赛的观众人数可能会达到 5 亿。粉丝们登录 Dream 11 创建梦之队、观看比赛状态、进行交流等等,这都给扩展性带来了严峻的挑战。在对现有的框架进行评估之后,Dream11 发现它还需要满足性能、函数式编程和 ZIO 支持等要求。Vert.x 提供了非常好的性能,但是缺少函数式的 Scala 特性。由于时间紧迫,Dream11 利用自己在可扩展性系统方面的专业技能,在公司内部构建了 ZIO HTTP。Dream11 对 ZIO HTTP 进行了广泛地优化,实现了超越 Vert.x 和其他框架的性能。现在,ZIO HTTP 能够高效处理数百万个并发请求,成为 Dream11 为 Scala 开发的性能和功能最强的 HTTP 库。
Vertx-rest:对 resteasy-vertx 的抽象,简化基于 JAX-RS 注解的 vert.x REST 应用程序的编写。AeroSpike Client:Vert.x Aerospik 客户端,提供了与 Aerospike 服务器交互的异步 API。
体育比赛都是有季节性的。具体的比赛还取决于参赛队伍、观众以及它们的号召力。Dream11 的用户数量超过了 1 亿。我们看一些使用场景,以更好地理解 Vert.x 是如何满足这些需求的。
样例 1:赛前激增
在大型的板球比赛开始前,数百万的用户涌入 Dream11 来创建他们的梦之队。这会导致流量在短时间内激增。在此期间,用户会:
登录账户浏览球员的统计数据确定他们的梦之队在比赛前做最后的更改
样例 2:赛中参与
在比赛期间,平台的用户流量依然会比较高:
查看实时的比分和球员表现参与论坛和社交功能的讨论如果平台允许赛中更改或更新,那么用户可以做出实时决策
样例 3:赛后分析
比赛结束后,用户会返回平台:
回顾自己球队的表现查看排名和积分提取奖金或为未来的比赛组件球队
如果想要了解更多详细信息,请参阅 Hackerrank 博客上对 Dream11 首席技术官 Amit Sharma 的访谈全文。
“我们在编程语言和框架方面做了一些标准化工作——90% 以上的服务都是使用 vert.x 编写的。”——Dream11 首席技术官 Amit Sharma
我们深入探讨一下 Vert.x 为何适用于大型分布式应用程序的构建,然后介绍一个基准测试和参考案例的研究。
Reactor 模型是事件驱动架构的基石。它的特点是单线程事件循环。在该模型中,事件(包括像数据库就绪或缓冲区完成这样的 I/O 事件)在发生时会进行排队。例如,一个轻量级的高性能 web 应用需要处理数千个并发连接。服务器需要管理客户端请求,包括 HTTP 请求、数据库查询和文件 I/O 操作。传统的多线程方式是资源密集型的,每个客户端请求都可能产生一个新的线程,最终会导致很高的内存占用率和上下文切换开销,尤其是在面临高负载的情况下。但是,Reactor 模型使用事件循环来处理连接,不会阻塞 I/O。
Reactor:该组件在一个称为事件循环的专属线程上运行,它能够高效地将传入的 I/O 事件路由到指定的处理程序。它可以自主运行,确保无缝的事件处理与分发。
处理程序(Handler):Reactor 负责协调 I/O 事件,指导处理程序在不阻塞的情况下处理特定的任务。这种方式利用了 NIO 的核心优势,支持非阻塞通信和事件驱动处理。处理程序管理未处理的 I/O 活动,并快速高效地执行操作。这个模型的基础是 NIO 的强大功能,确保系统性能流畅和响应迅速。
正如反应式宣言(Reactive Manifesto) 所述,反应式系统的设计目标是:
响应性(Responsive):系统始终能够及时响应,确保稳定的用户体验。韧性(Resilient):即便在遇到故障时,系统也能保持响应性。这种韧性是通过副本、封闭、隔离和委托来实现的。弹性(Elastic):系统可以高效地调整其资源,以适应不同的负载,确保在不同的运行条件下具备一致的性能表现。消息驱动(Message-Driven):系统依赖于异步的消息传递,以确保松耦合、隔离和位置透明。这种方式也增强了负载管理和错误处理能力。
图片来源
\\"Eclipse Vert.x 是一个在 JVM 上构建反应式应用的工具包。\\"我们需要将 Vert.x 视为一个工具包,而不是框架。这种差异凸显了其灵活性和模块化的特点,允许开发人员选择应用程序所需的组件。
Vert.x 使用 Netty 项目构建,该项目以其在 JVM 上的高性能和异步网络功能而闻名。这个坚实的基础使得 Vert.x 成为开发高效、可扩展和非阻塞 I/O 操作的反应式应用程序的理想选择。
Multi-Reactor 模式增强了 Vert.x 中处理并发操作的可扩展性和效率。与使用单事件循环的传统模型不同,Vert.x 使用了多事件循环,通常机器上每个可用的 CPU 核心对应一个事件循环,但这个数量也可以进行手动调整。事件总线是 Vert.x 应用程序中的通信基石,可以实现应用程序不同组成部分之间的各种通信模式。它支持:点对点消息:双方之间的直接通信。请求 - 响应消息:一种双向通信模式,在请求之后返回响应。发布 / 订阅:允许向多个订阅者广播消息。Verticle 是 Vert.x 中代码执行的基本单位,封装了 Vert.x 部署和管理的逻辑。Vertice 运行在事件循环之上来处理事件。比如,网络数据、定时器事件或 vertical 之间的消息。Verticle 主要有两种类型:标准 Vertice:始终运行在事件循环线程上,确保非阻塞操作。工作者 Verticle:在工作者池的线程上运行,这个池是为可能阻塞事件循环的任务专门设计的。executeBlocking()方法允许执行阻塞式的代码。它使用工作者池中的线程来运行特定的处理程序,因此,能够防止主事件循环被阻塞,这确保了应用程序的响应速度和性能。
性能:Vert.x 和 Akka 都是为高性能、非阻塞操作而设计的,能够在多个核心之间良好扩展,而 Jetty,尽管也很高效,但是由于其同步的特征,传统上处理的并发连接数较少。复杂性:Jetty 易于使用,可满足简单 Web 服务器的要求;Vert.x 为反应式应用提供了一个灵活的工具包,不过它更为复杂一些;Akka 提供了强大的抽象,但在掌握 Actor 模型方面的学习曲线较为陡峭。适用性:对于传统的 web 应用以及需要嵌入 HTTP/servlet 功能时,可以选择 Jetty;Vert.x 非常适合 JVM 上的异步、反应式应用程序;Akka 最适合需要健壮性、优秀并发性和基于 Actor 编排的系统。
如下是一个使用 Vert.x 在 Java 中创建 HTTP 服务器的样例。服务器监听 8080 端口,并对每个请求均响应一条简单的消息。
import io.vertx.core.Vertx;\\nimport io.vertx.core.http.HttpServer;\\n\\n\\npublic class SimpleHttpServer {\\n public static void main(String[] args) {\\n Vertx vertx = Vertx.vertx();❶\\n HttpServer server = vertx.createHttpServer();❷\\n server.requestHandler(request -> {❸\\n request.response()\\n .putHeader(\\"content-type\\", \\"text/plain\\")\\n .end(\\"Hello from Vert.x HTTP Server!\\");\\n });\\n server.listen(8080, result -> {❹\\n if (result.succeeded()) {\\n System.out.println(\\"Server is now listening on port 8080!\\");\\n } else {\\n System.out.println(\\"Failed to bind to port 8080: \\" + result.cause().getMessage());\\n }\\n });\\n }\\n}
❶ 创建 Vertx 实例:本行代码初始化一个新的 Vertx 实例。Vert.x 提供了低层级的 API 和构建块。很多 Vert.x 扩展均使用 Vert.x 核心。
❷ 创建 HTTP 服务器:本行代码创建一个新的 HTTP 服务器实例。
❸ 处理传入的请求:这个代码块创建一个请求处理程序,并使用一个简单的文本消息“Hello from Vert.x HTTP Server!”来响应每个传入的 HTTP 请求。
❹ 监听 8080 端口:这个代码块启动服务器并将其绑定到 8080 端口。如果服务器启动成功,它会打印一条成功的消息。如果失败的话,则会打印一条错误信息,并说明失败原因。
随着 web 应用程序的复杂性和用户群的增加,web 服务器技术的选择变得至关重要。不同的 web 服务器在处理并发连接、快速处理请求和有效管理资源方面的能力各不相同。
在实际负载的条件下对不同的 web 服务器的性能进行基准测试至关重要。本节比较了两种广泛使用的 web 服务器框架的吞吐量性能,即 Jetty9 和 Vert.x。
所用工具:
WRK:一款现代化的基准测试工具,在单个多核 CPU 上运行时能够生成大量的负载。
硬件规格:
处理器名称:Quad-Core Intel Core i7
处理器速度:2.3 GHz
处理器数量:1
核心总数:4
超线程技术:已启用
内存:32 GB
软件规格:
操作系统:macOS Ventura 13.0
JDK:OpenJDK 17
本次基准测试的首要目标是评估和比较两个主要 web 服务器的吞吐量:
Jetty9 HTTP Web ServerVert.x HTTP Web Server
吞吐量是一个关键的度量指标,表明一个 web 服务器每秒钟可以处理多少个请求。吞吐量越高,就意味着性能越好,就能同时为更多的用户提供服务。
基准测试的命令:
wrk -t10 -c100 -d30s http://127.0.0.1:8080/v1/ -s post.lua
-t10:使用的线程数(10 个线程)。-c100:保持打开的连接数(100 个连接)-d30s:测试的持续时间(30 秒)-http://127.0.0.1:8080/v1/:被测服务的\\" URL-s post.lua:用于更复杂请求场景的 Lua 脚本(如果需要的话)
要在本地重现测试结果的话,请检出该 git 仓库。
根据基准测试的结果,与 Jetty9 HTTP Web 相比,Vert.x HTTP Web Server 是高吞吐应用程序的更好选择。它每秒可处理的请求数更高,因此适合需要高性能和高可扩展性的应用程序。
这些结果为高性能应用程序在选择 Web 服务器时做出明智决策提供了有价值的信息。
概览:在本案例研究中,我们将会创建一个 Web 应用程序,使用 CollectAPI 服务按照国家和全球展示 COVID-19 的统计数据和最新的新冠病毒新闻。我们采用的方式包括维护定期刷新的本地缓存,以存储统计数据,同时始终将对最新新闻的请求直接委托给CollectAPI。
我们将使用 Maven 构建一个 Spring Boot 应用程序,并使用 Vert.x(NIO)工具集实现高吞吐,它不会因为阻塞操作而产生不必要的开销。核心应用程序将部署一个初始的 Vert.x verticle,作为 HTTP web 服务器,并监听 8080 端口。主(primary)verticle 处理所有的 REST API 请求,并根据 Vert.x 路由器中定义的路由对其进行处理。
辅助(secondary)verticle 接收来自主 verticle 的所有请求,并担当请求转发器,将请求路由至相应的服务处理程序。我们将实现两个额外的 verticle 来处理这些请求:
Redis Manager:该 verticle 将会管理仪表盘查询请求,并定期刷新缓存数据。CollectAPI Manager:该 verticle 将作为代理,将请求委托给后端 CollectAPI 服务。
所有的 verticle 将通过 Vert.x 事件总线以事件的方式发送和接收请求 / 响应,从而确保 verticle 之间的高效通信,并确保可扩展的无阻塞架构。
时序图
入口点负责搭建 Spring Boot 应用程序、初始化 Vert.x 实例并部署名为CovidDashboardService的 verticle。
@SpringBootApplication\\n@ComponentScan(\\"server\\")\\npublic class MainApplication {\\n\\n\\n @Autowired\\n private CovidDashboardService serverVerticle;\\n\\n\\n public static void main(String[] args) {\\n SpringApplication.run(MainApplication.class, args); ❶\\n }\\n\\n\\n @PostConstruct\\n public void deployVerticles() {\\n Vertx vertx = Vertx.vertx(); ❷\\n vertx.deployVerticle(serverVerticle, response -> {❸\\n // Log response status \\n });\\n }\\n}
❶ 运行 Spring Boot 应用:本行代码启动 Spring Boot 应用。❷ 创建 Vertx 实例:本行代码初始化一个新的 Vertx 实例,即 Vert.x 的核心。
❸ 部署第一个 Verticle:该代码块会部署CovidDashboardService Verticle。如果部署成功的话,则打印成功消息。如果失败的话,则会打印一条包含失败原因的错误消息。
这个类使用特定的路由和处理程序设置 HTTP 服务器。它集成了 Vert.x 事件总线,可以处理缓存的 GET 请求并部署额外的工作者变量。
@Component\\n@NoArgsConstructor\\n\\n\\npublic class CovidDashboardService extends AbstractVerticle {\\n public CovidDashboardService(Vertx vertx) {\\n this.vertx = vertx;\\n }\\n @Override\\n public void start() throws Exception {\\n super.start();\\n final Router router = Router.router(vertx); ❶\\n router.route().handler(BodyHandler.create()); \\n\\n\\n addCachedGETRoute(router, List[\\"/cache1\\",\\"/cache2\\",\\"cache3\\"]) ❷ \\n addProxyGETRoute(router, List[\\"/proxy1\\",\\"/proxy2\\",\\"proxy3\\"]) ❸\\n\\n\\n HttpServer httpServer = vertx.createHttpServer() ❹\\n .requestHandler(router)\\n .exceptionHandler(exception -> {//Log exception })\\n .connectionHandler(res -> {//Log new connection });\\n httpServer.listen(port);\\n\\n\\n // deploy next verticle RequestRouteDispatcher \\n vertx.deployVerticle(RequestRouteDispatcher::new, ❺\\n new DeploymentOptions().setWorker(true).setWorkerPoolName(\\"API-Router\\")\\n .setWorkerPoolSize(20),result -> { //Log result status });\\n }\\nprivate void addCachedGETRoute(Router router, List pathList) {❻\\n Arrays.stream(pathList).iterator()\\n .forEachRemaining(apiPath -> router.get(apiPath.value)\\n .handler(this::handleCachedGetRequest));\\n}\\nprivate void handleCachedGetRequest(RoutingContext ctx) {❼ vertx.eventBus().request(\\"CACHED\\", ctx.normalizedPath(), response -> {\\n if (response.succeeded()) { // ctx.response().end(\\"{result}\\")}\\n else { // ctx.setStatusCode(500))}\\n });\\n}\\n}
❶ 路由器初始化:本行代码初始化一个新的 Router 实例。
❷ 添加缓存路由:将缓存查询的所有 API 路径添加到 Router。
❸添加代理路由:将代理查询的所有 API 路径添加到 Router。
❹ 创建并启动 HTTP 服务器:该代码块启动服务器并将其绑定到 8080 端口。
❺ 部署 RequestRouteDispatcher Verticle:用来进行请求派发的下一个 vertical。
❻ 添加和处理缓存的 GET 路由:该方法将缓存查询的 GET 路径添加到路由器中。
❼ 添加和处理代理的 GET 路由:该方法将代理查询的 GET 路径添加到路由器中。
这个类为缓存和代理相关的事件总线设置了消费者,并部署了用来管理 Redis 和数据收集功能的额外 verticle。每个消费者负责处理特定类型的请求,而部署方法则确保相关的 verticle 能够初始化和运行。
@Component\\npublic class RequestRouteDispatcher extends AbstractVerticle {\\n\\n\\n @Override\\n public void start() throws Exception {\\n super.start();\\n vertx.eventBus().consumer(\\"CACHED\\") ❶\\n .handler(handleCachedRequest()); \\n vertx.eventBus().consumer(\\"PROXY\\") ❷\\n .handler(handleProxyRequest());\\n\\n\\n deployRedisManagerVerticle(); ❸\\n deployCollectManagerVerticle();❹\\n}
❶ 为“CACHED”请求设置事件总线消费者:本行代码为地址为“CACHED”的消息设置事件总线消费者。每当消息到达时,它会调用handleCachedRequest方法。
❷ 为“PROXY”请求设置事件总线消费者:本行代码为地址为“PROXY”的消息设置事件总线消费者。每当消息到达时,它会调用handleProxyRequest方法。
❸ 部署 RedisManagerVerticle:本方法部署RedisManagerVerticle并记录部署结果。
❹ 部署 CollectManagerVerticle:本方法部署CollectManagerVerticle并记录部署结果。
该类设置了一个事件总线消费者,通过检查 Redis 来处理缓存的请求,如果数据不存在的话,则可能会委托给其他的服务来进行处理。它还包含了一个刷新缓存的机制,确保数据定期更新。Redis 客户端配置为具备管理池和处理等待限制的选项,可优化在高负载情况下的性能。
import io.vertx.redis.client.Redis;\\n\\n\\n@Component\\npublic class RedisClientManager extends AbstractVerticle {\\n private RedisAPI redisAPI;\\n\\n\\n @Override\\n public void start() {\\n vertx.eventBus().consumer(\\"CACHED\\")❶\\n .handler(handleRedisRequest()); \\n vertx.setPeriodic(5000, id -> refershCache());❷ //refresh every 5 sec\\n\\n\\n Redis client = Redis.createClient(vertx, new RedisOptions() ❸\\n .setMaxPoolSize(10)\\n .setMaxWaitingHandlers(50));\\n redisAPI = RedisAPI.api(client);\\n refershCache();\\n }\\nprivate Handler> handleRedisRequest() { ❹\\n // Check if present in redis else delegate to proxy CollectAPI \\n}
❶ 为“CACHED”请求设置事件总线消费者:本行代码为地址为“CACHED”的消息设置事件总线消费者。每当消息到达时,它会调用handleRedisRequest方法。
❷ 设置定期刷新缓存:本行代码设置了一个定期的任务,该任务会每 5000 毫秒(5 秒)调用一次refreshCache方法。
❸ 创建 Redis 客户端:本代码块使用指定的选项创建 Redis 客户端,并初始化redisAPI对象。
❹ 处理 Redis 请求:该方法检查请求的数据是否位于缓存中。如果存在的话,返回缓存的值。如果不存在,它将请求委托给“PROXY”地址并缓存结果。
这个类设置了一个事件总线消费者,用于处理对CollectAPI的代理请求。它会使用 Vert.x WebClient 向 API 发送 HTTP GET 请求,并添加必要的头信息,用于内容类型的确定和授权。在收到响应或遇到错误时,它会用相应的响应或错误消息回复原始消息。这有助于应用程序的不同部分以及外部CollectAPI服务之间的无缝集成和通信。
@Component\\npublic class CollectAPIManager extends AbstractVerticle {\\n\\n\\n public static final String COLLECT_API_URL = \\"api.collectapi.com\\";\\n private WebClient client;\\n\\n\\n @Override\\n public void start() {\\n vertx.eventBus().consumer(\\"PROXY\\") ❶\\n.handler(handleCollectAPIRequest());\\n client = WebClient.create(vertx, new WebClientOptions()); ❷\\n }\\n\\n\\nprivate Handler> handleCollectAPIRequest() { ❸\\n return msg -> {\\n client\\n .get(COLLECT_API_URL, msg.body()) \\n .putHeader(\\"content-type\\", \\"application/json\\")\\n .putHeader(\\"authorization\\", \\"apikey your api key\\")\\n .send()\\n .onSuccess(response -> {\\n msg.reply(response.bodyAsString());\\n })\\n .onFailure(err -> {\\n msg.reply(\\"Failed to connect CollectAPI\\" + err.getCause());\\n });\\n };\\n }
❶ 为 PROXY”请求设置事件总线消费者:本行代码为地址为“PROXY”的消息设置事件总线消费者。
❷ 创建 WebClient 实例:本行代码使用默认选项初始化一个新的WebClient实例。如果需要,可以自定义 WebClientOptions。
❸ 处理 CollectAPI 请求:本方法使用WebClient向CollectAPI发送 GET 请求。如果请求成功的话,它将以响应体作为回复。如果请求失败,则回复一条错误信息。
本文深入探讨了 I/O 模型从阻塞式 I/O(BIO)到非阻塞式 I/O(NIO)和异步 I/O(AIO) 的演变过程及其对现代软件开发的影响,所解决的主要问题是传统阻塞式 I/O 模型在处理高负载和大量并发连接时的低效率和可扩展性限制,在云计算、大数据和物联网的时代,传统模型的不足变得越发明显。
我们所提出的解决方案是反应式架构,这种架构的目标是实现响应性、弹性、韧性和消息驱动。Vert.x 是在 JVM 上构建反应式应用程序的工具包,它提供了 Multi-Reactor 模式、事件总线和 Verticle 等功能,可高效处理高并发的问题,是一款功能强大的工具。基准测试结果表明,Vert.x 的性能优于其他工具,更加适合现代高性能应用程序。
本文提供了一个为 COVID-19 全球仪表盘构建 MultiReactor web 应用程序的详细案例研究。该应用使用 Vert.x 高效处理高吞吐、非阻塞的操作。它包括 Redis Manager 和 CollectAPI Manager 等组件,用于管理缓存数据和代理请求。MasterCard 和 Dream11 等公司的实际实施案例说明了 Vert.x 在构建可扩展高性能系统方面的实际应用和优势。这一全面分析证明了 Vert.x 在应对现代 I/O 和反应式应用程序开发挑战方面的有效性。
Mohit Palriwal 是 Netflix 的高级软件工程师,是 Netflix Observability 团队的重要成员。他是 Netflix Atlas 项目团队成员,该项目是一个开源的多维时间序列数据库,旨在处理大规模场景下的需求。在加入 Netflix 之前,Mohit 是 Salesforce 的首席软件工程师,负责在 AWS 上构建 Observability Cloud。Mohit 的职业经历还包括了亚马逊云科技(AWS),在那里他花了四年多的时间开发并推出了无服务架构的 AWS Pinpoint。
查看英文原文:
https://www.infoq.com/articles/reactive-java-vertx-deep-dive/\\"
","description":"概述 本文探讨了从阻塞式 I/O 转向非阻塞式 I/O 和异步 I/O 的过程,强调了它们在现代软件开发中的重要性。文章强调了云计算、大数据和 IoT 驱动的反应式应用程序的兴起。具体来讲,文章主要关注 Vert.x,这是一个在 JVM 上构建反应式应用程序的强大工具包,其知名的特性包括 Multi-Reactor 模式、事件总线和 Verticle。基准测试结果表明,Vert.x 性能卓越,是高并发环境的理想选择。真实使用案例和 COVID-19 全球仪表盘的案例研究说明了 Vert.x 的实际优势和应用。\\n\\n探索 I/O 模型的演进\\n\\nBIO(阻塞式 I/O)…","guid":"https://www.infoq.cn/article/Cs1QzZ7BZj74lUdRxXDT","author":"作者:Mohit Palriwal","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-10-24T00:00:00.730Z","media":[{"url":"https://static001.geekbang.org/wechat/images/f2/f215fa37730f13d9ac32fa4188f00b4d.jpg","type":"photo","width":1080,"height":442,"blurhash":"LGSF@S?b%K^,_3ofR*ae~qocV]a_"},{"url":"https://static001.geekbang.org/wechat/images/16/165ea3328a42d41a38527ff16edc83fd.jpg","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/wechat/images/fc/fc06f7805903f392ab8d81ce9d2c2404.jpg","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/wechat/images/2d/2dd66e04067d4e70ae7435e90b52e5b6.jpeg","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/wechat/images/c4/c4973ad90165fe33301c6c52ebc9297c.jpg","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/wechat/images/d2/d27234ae33d5b5ce0bd05bc801962aa7.jpg","type":"photo","width":1080,"height":842,"blurhash":"LASPX_~q-;_3_3IURjxuIURjIUM{"}],"categories":["编程语言"],"attachments":null,"extra":null,"language":null},{"title":"国产数据库登顶TPC-DS榜单,实现双榜第一","url":"https://www.infoq.cn/article/LsFKC2f4wlK4Thi4viK6","content":"10月22日,据国际事务处理性能委员会官网信息,在数据库“决策支持类”性能测试TPC-DS中,腾讯云数据库TDSQL以7260万分、37.52元同时刷新性能和性价比纪录,登顶世界第一。
TPC针对数据库各项性能推出的基准测试,被誉为数据库界的“奥林匹克”。去年,腾讯云TDSQL已经在数据库“事务处理类”性能测试TPC-C中刷新世界纪录。这标志着在数据库最核心的两个应用场景下,腾讯云TDSQL都取得了世界最佳性能纪录,成为“双榜”第一。
中国工程院院士郑纬民对此表示,国产数据库多次打破性能瓶颈,体现了国内基础软件持续打磨内功的决心,以及稳定输出技术能力的底蕴。
原国家科技部秘书长、党组成员、国际欧亚科学院院士张景安表示,数据库作为信息技术的基石,其性能与稳定性直接关系到各行各业的数字化转型进程。我国软件企业在两项国际标准测试中屡破纪录,标志着中国在数据库这一核心软件技术领域正迈向国际先进水平,有助于增强我国的国际科技竞争力。
TPC-DS是一个针对数据库管理系统分析性能的基准测试。它模拟一个大型零售商销售数据的在线数据分析(OLAP)场景,通过 99 个不同类型的分析任务,考察底层数据库的处理耗时、并发性能和导数性能等指标,是数据库产品分析处理能力和技术先进性的金标准。
腾讯云数据库研发总经理潘安群介绍,此次腾讯云参与打榜的TPC-DS 测试数据量级达10TB,相当于10亿页电子书,包含销售纪录、退货记录、时间信息等17项维度的24张表格。其中,最大的一张表高达288亿行数据。
在海量数据中,腾讯云TDSQL需要历经数据导入、单任务计算、多任务并行计算、数据变更等多项测试,关联十几个“亿级”表格,联合计算出例如“销量排名前十的商品从何时开始网店销量超过门店”等信息。在这个过程中,TPC甚至还会在数据变更时随机销毁数据增加难度。
结果显示,腾讯云TDSQL项测试耗时均大幅领先榜单其他厂商,99个复杂分析任务单任务平均耗时4秒以内,领先榜单第二名一倍;多任务并行计算平均耗时8秒以内,领先两倍,以7260万分的性能评分,将决策支持类榜单纪录提升3.8倍。
在复杂任务处理能力大幅提升的基础上,TDSQL将每1000评分的价格相比同类产品减少1/3,同时刷新TPC-DS性能与性价比纪录。
联机分析处理(OLAP)场景下,如何充分发挥每个算力单元的极致潜力,以及确保每个任务之间不等待和阻塞,一直是数据库领域的重点攻关方向。
潘安群介绍,腾讯云TDSQL在分布式交互、并行计算、单核极致性能三个方向深度自研,保障了计算从多核到多进程再到多节点,能充分并行无阻塞运行,实现了性能的大幅提升。
TDSQL通过自研MPP执行框架,优化了主流 OLAP 数据库应用“pull”模型存在的数据传输“拥堵”瓶颈,保证所有计算任务全速顺畅运行,通用性能提升40%。
而在性能无法线性跟随CPU核数增加的业界难题上,TDSQL通过自研并行执行框架,彻底去除并行进程间阻塞依赖,CPU 利用率提高至 95% 以上,能充分利用多核资源。
对于单核计算效率,TDSQL团队也有着极致追求。在以上并行框架的基础上,TDSQL 自研了列式存储和向量化执行引擎,在算法、结构、新一代CPU结合等方面深度优化单核任务执行效率,实现单核效率提升1倍以上。
数据库世界性能榜单第一的每次易主,都标志着数据处理技术的向前推进。
去年,腾讯云数据库TDSQL顺利通过TPC-C基准测试,性能达到每分钟8.14亿笔交易(tpmC),打破世界纪录。期间,TDSQL持续稳定运行这一超大规模集群,实现8小时无抖动,保障了超过8600亿总事务、4万亿条订单详细信息不出错。
“TPC-C的特点是多、稳、快、高频小任务,考验的是高并发场景下数据库的极致性能和稳定性;TPC-DS特点则是少、快、大、低频大任务,考验的是复杂任务场景下数据库的综合能力。在两个核心场景下,腾讯云TDSQL都实现了性能纪录的极大突破。”潘安群说。
双榜第一也为产业发展筑牢了更强的基座。据腾讯云数据库总经理王义成介绍,腾讯云数据库TDSQL已形成了金融级分布式、云原生、分析型等多引擎融合的完整数据库产品体系,能高效应对OLTP、OLAP、HTAP等多样化的计算场景,满足企业多样化的国产数据管理需求。
在腾讯云TDSQL的助力下,数字广东粤省事实现流程再造和决策优化,实现民众少跑路,数据多跑路;“第七次全国人口普查”以“OLTP+OLAP”技术融合架构支持了十亿级用户数据、七百万个终端和百万级峰值TPS。
除此之外,这些优化能力还应用在了腾讯云大数据TChouse(云数据仓库)上,与芯片、服务器、操作系统、云底座一同构建起核心领域自研产品体系,已具备软硬一体的全栈融合创新能力。
","description":"10月22日,据国际事务处理性能委员会官网信息,在数据库“决策支持类”性能测试TPC-DS中,腾讯云数据库TDSQL以7260万分、37.52元同时刷新性能和性价比纪录,登顶世界第一。 TPC针对数据库各项性能推出的基准测试,被誉为数据库界的“奥林匹克”。去年,腾讯云TDSQL已经在数据库“事务处理类”性能测试TPC-C中刷新世界纪录。这标志着在数据库最核心的两个应用场景下,腾讯云TDSQL都取得了世界最佳性能纪录,成为“双榜”第一。\\n\\n中国工程院院士郑纬民对此表示,国产数据库多次打破性能瓶颈,体现了国内基础软件持续打磨内功的决心,以及稳定输出技术能力的底蕴。…","guid":"https://www.infoq.cn/article/LsFKC2f4wlK4Thi4viK6","author":"李冬梅","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-10-22T13:07:02.278Z","media":[{"url":"https://static001.geekbang.org/infoq/29/29fe96c99fd59591ea30db283cc97ff0.png","type":"photo","width":0,"height":0,"blurhash":""}],"categories":["腾讯","数据库"],"attachments":null,"extra":null,"language":null},{"title":"Java近期新闻:OpenJDK JEP、Spring 7.0开发计划、JobRunr 7.3、Keycloak 26.0、Debezium 3.0","url":"https://www.infoq.cn/article/tofruR0hwBsmIQ7kzFOE","content":"经过评审,JEP 475(G1延迟屏障扩展\\")从Proposed to Target进入\\"到Targeted状态,计划在JDK 24中发布。该JEP建议将G1垃圾收集器的屏障扩展从C2 JIT编译器的早期阶段推迟到后期阶段,以此来简化G1垃圾收集器屏障的实现。这些屏障记录了有关应用程序内存访问的信息。目标是在使用G1收集器时减少C2的执行时间。
在从JEP Draft 8340841进入到候选状态两天后,JEP 489(向量API(第九次孵化)\\")进一步从候选进入\\"到提议目标状态,并计划在JDK 24中发布。这个JEP在前八次孵化的基础上进行了增强,这八次孵化分别是:在JDK 23中交付的JEP 469(向量API(第八次孵化)\\");在JDK 22中交付的JEP 460(向量API(第七次孵化)\\");在JDK 21中交付的JEP 448(向量API(第六次孵化)\\");在JDK 20中交付的JEP 438(向量API(第五次孵化)\\");在JDK 19中交付的JEP 426(向量API(第四次孵化)\\");在JDK 18中交付的JEP 417(向量API(第三次孵化)\\");在JDK 17中交付的JEP 414(向量API(第二次孵化)\\");以及在JDK 16中作为孵化模块\\"交付的JEP 338(向量API(孵化器)\\")。最初考虑通过重用原始的Incubator状态进行再次孵化,但最终决定继续使用编号。向量API将继续孵化,直到Project Valhalla\\"的关键特性预览可用。到那时,向量API团队将调整向量API及其实现,并将向量API从Incubation提升到Preview。评审在2024年10月9日结束。
JEP 484(类文件API\\")从Candidate进入\\"到Proposed to Target状态,并计划在JDK 24中发布。这个JEP提议在经过了两轮预览后,在JDK 24中最终确定这个特性,这两轮预览分别是:在JDK 23中交付的JEP 466(类文件API(第二次预览)\\")和在JDK 22中交付的JEP 457(类文件API(预览)\\")。这个特性提供了一个用于解析、生成和转换Java类文件的API,最初作为ASM\\"(ASM是Java字节码操作和分析框架)的内部替代品,在JDK中使用,现在计划将其作为公共API开放。Goetz将ASM描述为“一个有很多遗留包袱的旧代码库”,并提供了关于这个特性将如何发展并最终取代ASM的相关背景信息\\"。评审在2024年10月8日结束。
JEP 492(灵活的构造函数体(第三次预览)\\")从JEP Draft 8338287进入\\"到Candidate状态。这个JEP提议进行第三轮预览,相较于前两轮,变化不大,目的是为了收集更多的经验和反馈。前面两轮预览分别是:在JDK 23中交付的JEP 482(灵活的构造函数体(第二次预览)\\")以及在JDK 22中交付的JEP 447(super()的前置语句(预览)\\")。这个特性允许在构造函数中的this()或super()调用之前执行不引用正在创建的实例的语句,并保留构造函数现有的安全性和初始化保证。这个JEP的变更包括:对局部类的处理;放宽字段在显式构造函数调用之前不能访问的限制,改为字段在显式构造函数调用之前不能读取的要求。Oracle的技术顾问Gavin Bierman\\"为Java社区提供了这个JEP的初始规范\\"供评审和反馈。
JEP 491(不固定虚拟线程同步\\")从JEP Draft 8337395进入\\"到Candidate状态。这个JEP提议:
通过允许在同步方法和语句中阻塞的虚拟线程释放底层平台线程,以便其他虚拟线程能够使用这些线程,从而提高Java代码在使用同步方法和语句时的可扩展性。这一改进将显著减少虚拟线程被固定到特定平台线程的情况,这种固定严重限制了能够用于处理应用程序工作负载的虚拟线程数量。
JEP 488(模式、instanceof和switch中的原始类型(第二次预览)\\")从JEP Draft 8335876进入\\"到Candidate状态。这个JEP由Project Amber\\"提供支持,提议进行第二轮预览,与上一轮或预览相比没有变化,目的是获得更多的反馈。上一轮预览是在JDK 23中交付的JEP 455(模式、instanceof和switch中的原始类型(预览)\\")。这个特性允许在所有模式上下文中使用原始类型模式,并扩展instanceof和switch,可以使用所有原始类型,以此来增强模式匹配。更多细节可以在Oracle技术顾问Aggelos Biboudis\\"提供的草稿规范\\"中找到。
JEP 487(作用域值(第四次预览)\\")已经从JEP Draft 8338456进入到Candidate状态。这个JEP提议进行第四次预览,其中包含了一个变化,目的是为了获得更多的反馈。之前的一轮孵化和三轮预览分别是:在JDK 23中交付的JEP 481(作用域值(第三次预览)\\");在JDK 22中交付的JEP 464(作用域值(第二次预览)\\");在JDK 21中交付的JEP 446(作用域值(预览)\\");以及在JDK 20中交付的JEP 429(作用域值(孵化器)\\")。这个特性之前叫作作用域本地变量(孵化器),允许在线程内部和跨线程共享不可变数据。这比线程本地变量更受欢迎,尤其是在处理大量虚拟线程的场景下。
JEP 14(库开发尖端与尾部模型\\")是一个新的JEP,旨在将自2018年起与OpenJDK发布实践相结合的“尖端和尾部”发布模型正式化。“尖端”指的是六个月一次的OpenJDK发布周期,而“尾部”指的是每季度的关键补丁更新,分别在每年的一月、四月、七月和十月发布。该JEP的目的是减少从“尖端”到“尾部”的回溯工作,以便改进维护流程。鼓励Java库的维护者采用“尖端和尾部”发布模型。
JDK 24早期访问构建\\"版本Build 18\\"已发布,包含了从Build 17以来的更新\\",修复了各种问题\\"。有关这个版本的更多细节可以在发布说明\\"中找到。
对于JDK 24\\",开发者可以通过Java Bug数据库\\"报告错误。
GlassFish\\" 7.0.18(第十八个维护版本\\")包含了错误修复、文档改进和新特性,例如:能够从命令行启动GlassFish Embedded Server\\";能够在不需要重启服务器的情况下通过新的GlassfishUrlClassLoader\\"类动态更新公共类加载器。有关这个版本的更多细节可以在发布说明\\"中找到。
Oracle Labs GraalVM团队研发负责人Fabio Niephaus\\"宣布\\" ,他们发布了一个新的GitHub仓库\\",包含了GraalPy\\"、GraalJS\\" 和 GraalWasm\\" 项目的新演示和指南。这个仓库与最近发布的GraalVM for JDK 23保持一致,在这个版本中,GraalPy和GraalWasm已经是稳定版,适合用于处理生产环境的工作负载。
TornadoVM\\" 1.0.8(第八个维护版本\\")包含了错误修复和改进,例如:在TornadoExecutionPlan\\"封印类中定义了新的方法 printTraceExecutionPlan() 和 getTraceExecutionPlan(),用于记录和转储TornadoVM执行计划的操作;移除了在PowerMetric\\" 接口中定义的getHandleByIndex(),因为它调研了内部的底层能力,而这些不需要在设备上下文中暴露出来;基准测试的小幅改进。有关这个版本的更多细节可以在发布说明\\"中找到。
随着Spring Framework\\" 6.2即将在2024年11月发布,Spring团队已经在为预定于2025年11月发布的Spring Framework 7.0制定计划\\"。正如所述:
我们将把基线升级到Jakarta EE 11(Tomcat 11、Hibernate ORM 7、Hibernate Validator 9),拥抱即将到来的JDK 25 LTS,同时与Java生态系统保持一致,维持JDK 17作为基线。对于Kotlin应用程序,我们打算基于Kotlin 2来支持Spring Framework 7。
团队还计划使用JSpecify\\" 注解来实现空值安全策略。有关JSpecify的更多细节可以在这篇InfoQ新闻报道\\"中找到。
Helidon\\" 4.1.2\\"包含了依赖项升级和一些显著的变化,例如:改进了WebServer\\"组件的服务器端事件(SSE)实现;在DataReader\\"类的 findNewLine() 方法中添加了必要的验证逻辑,确保内部索引始终在界限内。关于这个版本的更多细节可以在变更日志\\"中找到。
同样地,Helidon 3.2.10\\"也包含了依赖项升级和一些重要的改进。其中包括:在 HTTP 连接空闲超过五分钟后自动关闭连接;在 WebServer 组件中,用套接字配置取代了原有的服务器配置。关于这个版本的更多细节可以在更新日志\\"中找到。
JobRunr\\" 7.3.0和JobRunr Pro已经发布\\",新特性包括:与Quarkus 3.15和Kotlin 2.0.20完全兼容;在BackgroundJobServer\\"类中增强了线程安全性;能够通过属性设置来调整BackgroundJobServerConfiguration\\"类中定义的serverTimeoutPollIntervalMultiplicand属性。关于这个版本的更多细节可以在发布说明\\"中找到。
Hibernate Reactive\\"发布2.4.2.Final\\"版本,解决了以下问题:在检索带有Jakarta Persistence @IdClass\\"注解的复合表实体时出现的ClassCastException;数据库中不正确映射的嵌入式JSON值。关于这个版本的更多细节可以在发布说明\\"中找到。
Micrometer Metrics\\" 1.13.5包含了依赖项升级,并解决了由于Keycloak服务器实例无法启动而导致的ConcurrentModificationException,以及在已经注册了指标后允许配置MeterFilter\\"接口。关于这个版本的更多细节可以在发布说明\\"中找到。
Grails\\" 6.2.1包含了错误修复、依赖项升级和一些显著的变化,例如:与Groovy 3.0.22兼容;能够自定义ErrorsViewStackTracePrinter\\"类的级联样式表中的类。关于这个版本的更多细节可以在发布说明\\"中找到。
Infinispan\\" 15.1.0.Dev04和15.0.10.Final包含了依赖项升级和一些显著的变化,包括对Redis Serialization Protocol\\"(RESP)操作的增强,确保序列化都以RESP3格式返回响应;消除了由于SimpleCacheImpl\\"类中的get()方法处理内存到期并返回CompletableFuture\\"类实例而导致的死锁。关于这些版本的更多细节可以在15.1.0.Dev04\\"和15.0.10.Final\\"的发布说明中找到。
Keycloak\\" 26.0.0发布\\",新特性包括:其专有库(Java管理客户端、Java授权客户端、Java策略执行器)的发布周期与Keycloak发布周期独立;用户会话现在默认是持久化的;新的默认登录主题;OpenTelemetry跟踪功能预览。关于这个版本的更多细节可以在发布说明\\"中找到。InfoQ将跟进更详细的新闻报道。
Testcontainers for Java\\" 1.20.2包含了错误修复、文档改进、依赖项升级以及新特性/增强,例如:实现了MongoDB Atlas\\";新的模块支持Databend\\"和Timeplus\\";对Cassandra\\"模块的增强,消除了运行时异常。关于这个版本的更多细节可以在发布说明\\"中找到。
Improving\\"(一家提供培训、咨询、招聘和项目服务的IT服务公司)软件顾问Jim Bethancourt\\"发布RefactorFirst\\" 0.6.1和0.6.0,这是一款用于识别应用程序中需要进行重构的组件的工具。这些版本提供了:只有在showDetails属性设置为true时才计算循环中类的提交计数平均值的变化,因为这一计数与循环中涉及的类的数量有很强的相关性;从报告模块中移除了JGraphT\\"模块jgrapht-core和jgapht-ext,因为它们对JGraphX\\" Swing组件有传递性依赖;解决了CVE-2017-18197\\",该漏洞导致mxGraphViewImageReader\\"类容易受到XML外部实体(XXE)攻击。关于这些版本的更多细节可以在0.6.1\\"和0.6.0\\"的发布说明中找到。
距离开源分布式平台Debezium\\" 2.0.0.Final发布\\"将近两年,Debezium 3.0.0.Final发布\\",新特性包括:将JDK 17作为最低版本;支持Kafka 3.8.0;移除了弃用的增量信号字段additional-condition;增加了每个数据库表的详细指标。所有受支持的数据库连接器也进行了更新。关于这个版本的更多细节可以在发布说明\\"中找到。InfoQ将跟进更详细的新闻报道。
原文链接:
https://www.infoq.com/news/2024/10/java-news-roundup-sep30-2024/\\"
","description":"OpenJDK 经过评审,JEP 475(G1延迟屏障扩展\\")从Proposed to Target进入\\"到Targeted状态,计划在JDK 24中发布。该JEP建议将G1垃圾收集器的屏障扩展从C2 JIT编译器的早期阶段推迟到后期阶段,以此来简化G1垃圾收集器屏障的实现。这些屏障记录了有关应用程序内存访问的信息。目标是在使用G1收集器时减少C2的执行时间。\\n\\n \\n\\n在从JEP Draft 8340841进入到候选状态两天后,JEP 489(向量API(第九次孵化)\\")进一步从候选进入\\"到提议目标状态,并计划在JDK 24中发布…","guid":"https://www.infoq.cn/article/tofruR0hwBsmIQ7kzFOE","author":"作者:Michael Redlich","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-10-22T02:35:23.629Z","media":null,"categories":["编程语言"],"attachments":null,"extra":null,"language":null},{"title":"函数式编程如何帮助你编写高效、优雅的 Web 应用程序","url":"https://www.infoq.cn/article/r4DJeq48hJNvl4H2WwYC","content":"本文要点
要保持一种内部可变状态并非易事。每次与程序交互时,我们都会更改后续交互的上下文。面向对象编程(OOP)和函数式编程(FP)试图提供处理软件可维护性和复杂性的解决方案。OOP 封装了复杂性,而 FP 则专注于数据及其转换。函数式编程概念提高了可预测性、促进了代码重用并管理了副作用——FP 对不变性和可组合性的重视带来了更强大和更易维护的系统。FP 将 Web 应用程序视为数据转换管道,从而提升程序水平。它鼓励人们使用纯函数将输入数据转换为输出数据,从而实现透明的数据流、更轻松的测试和更可预测的行为。Kotlin 无缝融合了面向对象和函数式两种编程范式,并允许开发人员在现有代码库中逐步采用函数式概念。这会带来更具表现力、更简洁、更安全的代码,从而提高可维护性并减少错误。
许多因素都会让软件更难理解,从而更难维护。最困难和最成问题的一个因素是管理内部可变状态。这个问题特别麻烦,因为它直接影响软件的行为和发展方式。听上去理所当然的一件事是,每次与程序交互时,我们都会更改后续交互的上下文。这意味着应用程序必须为每个用户维护一种内部状态\\"并不断更新。当内部状态管理不善时,软件的行为会出乎意料,导致错误和修复,从而带来不必要的复杂性。因此,它使软件更难调试和扩展。
函数式编程乍一看可能令人生畏,学术味儿过浓,但一旦你掌握了它,它就会改变游戏规则,而且非常有趣!为了更好地理解函数式编程如何帮助我们构建更易维护的软件,我们先从头开始,了解为什么程序变得越来越难维护,问题愈加突出。
我们首先要说的是,有效管理软件的可变状态是构建可靠且可维护的软件的关键所在。我指的不是某种理论风格,而是指代码易于更改且易于识别错误的。
纵观编程历史\\",每种范式\\"都有不同的方法来处理软件的内部状态。
在过程编程\\"范式中,内部状态是可变且可全局访问的,可以轻松读取和更改。这种方法类似于较底层的 CPU 内部发生的情况,可以非常快速地编译和执行代码。当程序很小的时候,让所有东西都可变和全局化不是问题,因为开发人员可以记住一切并编写正确的代码。
但当项目变大时,修复错误和添加新功能会越来越困难。随着软件应用程序变得日趋复杂,代码维护也愈加艰难,可能出现许多流程和复杂的逻辑,就像“意大利面条式代码”。
可以将大的问题分解为一些小问题来克服这个困难,让它们更容易处理。模块化编程\\"范式让你一次只关注一个部分,暂时将其余部分放在一边。
函数式编程和面向对象编程\\"范式的目标都是让我们的代码更容易管理和修复,即使项目规模不断扩大也能应对。编写高质量代码的方法有很多种。
自 20 世纪 90 年代以来,面向对象设计一直是最流行的解决方案。在它最纯粹的形式中,一切都是对象。对象可以具有它们自己的可变状态,但对应用程序的其余部分隐藏。它们仅通过相互发送消息来通信。这样,你就为每个对象分配了工作,并相信它会完成自己的工作。
例如,Java 就遵循这种方法,虽说它不是纯粹的面向对象范式。应用程序的状态分散给每个对象,每个对象负责一项特定任务。这样,即使应用程序逐渐成长,修改起来也还是不难。此外,Java 的性能几乎与过程编程语言一样好,有时甚至更好,这让它成为了一种有价值且成功的折衷方案。
函数式编程\\"范式采用了完全不同的方法。它使用纯函数\\",专注于数据及其转换,这些函数不依赖于任何全局上下文。在函数式编程中,状态是不可改变的,就像不可分割的原子一样。函数会转换这些原子,将简单的操作组合成更复杂的操作。这些函数是“纯”的,这意味着它们不依赖于系统的其他部分。
换句话说,纯函数的结果仅由其输入决定,因此可预测且容易调试。此外,由于它们是自包含的,且容易理解,因此它们很容易在代码的不同部分中重用。
纯函数的另一个优点是它们易于测试,原因如上所述。开发人员无需模拟对象,因为每个函数仅依赖于其输入,并且无需在测试结束时设置和验证内部状态,因为它们没有任何内部状态。
最后,使用不可变数据和纯函数大大简化了网络上多个 CPU 和机器之间的任务并行化操作。出于这个原因,许多所谓的“大数据”解决方案都采用了函数式架构。
但是,计算机编程领域中没有银弹。函数式方法和面向对象方法都有自己的权衡。
如果你的应用程序具有非常复杂的可变状态,并且主要是本地的,则在函数式设计中建模可能需要大量工作。例如,复杂的桌面界面、视频游戏和像模拟器一样工作的应用程序通常更适合面向对象设计。
另一方面,函数式编程在程序对明确定义的输入和输出流转换进行操作的场景中尤其出色,例如 Web 开发。在这种范式中,每个任务都变成一个接收一些数据并返回其他一些数据的函数。这种方法对应了 Web 服务的操作:它们接收请求并返回响应。
下面,我们将探讨函数式编程如何让 Web 开发受益(代码示例以 Kotlin 语言提供)。这种方法可以简化流程,同时生成更易访问、容易理解和可维护的代码。也不要忘记有趣的部分——它也使编程更有意思了!
那么,函数式编程可以简化某些应用程序意味着什么呢?以函数式方式编写代码就像解决逻辑难题。我们必须将问题分解为一组函数,每个函数执行特定的转换,并且它们必须作为一个连贯的整体来协同工作。
我们需要定义函数及其操作的数据的结构,确保它们可以组合在一起。与使用全局状态和单例的宽松方法相比,这些限制要严格得多,通常会让应用程序更加复杂。另一方面,一旦编译完成,函数式应用程序的错误应该会少一些,因为许多潜在的错误源已经在设计时就规避掉了。
例如,在编写一个 Web 应用程序时,我们设计了所有必要的函数,每个函数都有特定的任务,诸如提取用户个人资料和创建 HTML 页面等等。当这些函数以逻辑方式组合在一起时,真正的魔力就会显现出来,产生一个优雅而实用的解决方案。这种方法跑通的时候,就像是完美的拼图一样,做出的图像感觉很正确。
函数式编程就是这样。它不仅是一种编写代码的方式;它还是一种思考和解决问题,识别和利用数据之间联系的方法。
传统的编程思维涉及很多过程、函数和方法,将它们作为执行某些操作的代码片段。在函数式编程中则应该采用略微不同,且更数学化的观念:“纯函数是将输入转换为输出的实体”。
我们从 Kotlin 中的一些简单纯函数开始来说明这个概念。
fun celsiusToFahrenheit(celsius: Double): Double =\\n celsius * 9.0 / 5.0 + 32.0
celsiusToFahrenheit 函数接收一个单位为摄氏 degrees 的温度值,并将其转换为华氏温度。它不依赖任何外部状态,也不修改任何外部变量,因此我们可以称其为纯粹的函数。它会做计算,但这是一个技术细节。它也可以使用某种预定义值的表格来解决问题。重要的是它能将温度从一个单位转换为另一个单位。
在 Kotlin 中,我们可以用箭头表示每个函数的类型。任何函数都可以描述为从类型 A 到类型 B 的箭头,其中 A 和 B 也可以是同一类型。
A -> B
在这个例子中,它接收一个 Double 作为参数,并返回另一个 Double,是转换后的温度值。我们可以将其类型描述为 (Double) -> Double。这种简洁的函数类型箭头语法是让 Kotlin 中的函数式工作变得愉快惬意的小细节之一。与 Java 对比来看,Java 中的等效函数是 Function,以及其他一些具有不同数量参数的类型,如 BiFunction、Supplier 和 Consumer。
还要注意,非常多的函数有着相同的类型和签名。例如,这个函数也有同样的签名:
fun square(x: Double): Double = x * x
现在想象一下,在从 A 到 B 的函数之上,我们还有另一个从 B 到 C 的函数,返回一个新类型 C。
第一个关于“组合”的例子是:“我们可以组合这两个函数吗?”“是的!我们可以!”我们需要像处理数据一样处理函数。
fun compose(fn1: (A)->B, fn2: (B)->C): (A)->C = ???
为了实现这种函数组合,我们需要将第二个函数应用于第一个函数的结果。在 Kotlin 中我们可以这样定义它:
fun compose(fn1: (A)->B, fn2: (B)->C): (A)->C = \\n {a -> fn2(fn1(a))}
乍一看这可能很奇怪,因为我们将其描述为先执行 fn1,然后执行 fn2,但在实现中,第二个函数出现在第一个函数之前。这是因为计算机使用括号语法从内到外计算函数。
我们看一个实际的例子,演示如何使用它通过组合两个现有函数来创建一个新函数,而无需编写任何额外代码:
val isInLeapYear = compose(LocalDate::parse, LocalDate::isLeapYear)\\nisInLeapYear(\\"2024-02-01\\")
在这个示例中,compose 将 LocalDate::parse(将一个 String 转换为 LocalDate)与 LocalDate::isLeapYear(检查给定的 LocalDate 是否为闰年)结合起来。由此而生的函数 isInLeapYear 直接以一个 String(日期)作为输入,并返回一个 Boolean,指示是否为闰年。
实现相同效果的另一种方法是使用 let(Kotlin 作用域函数\\"之一)。
使用作用域函数时,前面的示例可以写成如下形式:
\\"2024-02-01\\"\\n .let(LocalDate::parse)\\n .let(LocalDate::isLeapYear)
在 Kotlin 中使用 let 的优势在于其可读性和对不变性的增强。在 let 块内链接转换后,从类型 A 到 B 再到 C 的进展变得更加明确,从而增强了代码的清晰度和简洁性。
请注意,你也可以将 lambda 块与作用域函数一起使用,但使用函数引用可以更明确地揭示意图。
函数组合是函数式编程的基石,标志着一种重大的视角转变:它不仅将函数视为执行任务的代码单元,还将其视为一等实体。这些实体可以作为参数传递,从其他函数返回,并以各种方式组合。这种方法是函数式程序员工作的基础,丰富了他们用来优雅解决复杂问题的工具包。
假设我们有一个从数据库获取用户的函数。这个函数需要两件事(请记住,函数式编程中没有隐藏的依赖项或单例):与数据库的连接和用户 ID。
fun fetchUser(db: DbConnection, userId: UserId): User =
在函数内部,它查询数据库、检索用户,并将该用户返回给调用该函数的对象。
该函数完全符合我们的需求。但我们有一个问题:这里的数据库连接仅在应用程序的外层可用,但我们需要在域代码的中间调用它,在那里我们有用户 ID,但没有数据库连接等基础设施细节。
让数据库连接穿过几层代码以到达我们需要使用这个函数的位置也能做到,但很尴尬且不切实际。换句话说,这个函数的两个输入(用户 ID 和数据库连接)位于我们代码中相隔很远的位置。
解决这个常见问题的一种干净方法是部分应用该函数。我们可以首先只为其提供一个参数(例如数据库连接),我们得到的是一个新函数,它只需要剩下的那个参数(用户 ID)即可运行并返回所需的结果。这就像将函数分成两个阶段:首先我们输入第一个参数,然后接收一个需要第二个参数的新函数来完成该过程并传递响应。
这个概念乍一听可能很复杂,但代码示例应该会让它更清楚一些:
fun userFetcherBuilder(db: DbConnection): (UserId)->User =\\n{ id: UserId -> fetchUser(db, id) }
userFetcherBuilder 函数接收 DB 连接但不返回用户。其结果是另一个将为用户提供用户 ID 的函数。如果不清楚,请再次查看代码和签名。
这一技术还可以推广到所有接收两个参数的函数。换句话说,我们有一个接受 A 和 B 以返回 C 的函数。我们想要一个接受 A 并返回一个接受 B 以返回 C 的函数。
fun partialApply(a: A, operation: (A, B)->C): (B)->C = \\n { b: B -> operation(a, b) }
现在,我们可以以更简洁的形式重写我们的函数:
fun userFetcherBuilder(db: DbConnection): (UserId)->User =\\n partialApply(db, ::fetchUser)
我们如何使用这个应用程序片段来解决我们一开始的问题呢?先从原始函数开始,该函数从数据库中检索用户。然后,在进入域逻辑之前,一旦我们可以访问基础设施(应用程序片段),我们就应用这个数据库连接。
这会产生一个只需要用户 ID 即可获取用户的新函数。域逻辑不需要关心数据库连接细节;它可以简单地调用这个嵌入了数据库连接的新函数来检索用户。
我们不必将连接传递到所有层,但必须传递那个片段应用的函数。传递函数是一种更灵活的解决方案,它允许我们在各种场景中使用不同的函数,例如用于测试的模拟函数,或从远程 HTTP 调用,而不是通过数据库来获取用户的另一个函数。如果函数返回一个被赋予用户 ID 的用户,函数的接收者才会关心实现细节。
换句话说,通过应用程序片段,我们有效地将域逻辑与基础设施问题分离开来,简化了获取数据的过程,而不会用不必要的细节扰乱业务逻辑。这种方法简化了我们的代码并增强了其模块化和可维护性。
fun fetchUserFromDb(db: DbConnection, userId: UserId): User? =\\n \\n \\nfun initApplication() {\\n \\n val dbConnection = DatabaseConnection()\\n \\n val fetchUser: (UserId) -> User? =\\n partialApply(dbConnection, fetchUser)\\n \\n settingUpDomain(fetchUser)\\n}\\nfun somewhereInDomain() {\\n val userId = readUserId()\\nval user = fetchUser(userId)\\ndoSomethingWithUser(user)\\n}
在这个示例中,partialApply 是一个高阶函数,它将其他函数作为输入和输出。它预先获取原始函数 (dbConnection) 的第一个参数并返回一个新函数 (fetchUser)。这个新函数只需要剩下的参数 (UserId) 即可执行。
这样做以后,我们就将数据库连接细节封装在了域逻辑之外,使域逻辑可以专注于业务规则,而无需考虑数据库连接等基础设施细节。这使我们的代码更简洁、更模块化、更易维护。
这种方法优雅实用,但抽象地思考函数有时会颇具挑战性。Kotlin 提供了一种更直接、更符合习惯的方法来实现这一点,那就是使用对象。
我们可以创建一个从一个函数类型继承的类。这听起来可能很奇怪,但它是一种非常顺手的模式。这种技术允许我们在需要某个独立函数的任何地方使用该类的实例,从而提供一种更直观、面向对象的方式来处理函数式编程概念。以下是它的实现方法:
data class UserFetcher(val db: DbConnection) : (UserId) -> User? {\\n override fun invoke(id: UserId): User = fetchUser(db, id)\\n}
在这个示例中,UserFetcher 是一个数据类(但也是一个函数!),它以 DbConnection 作为构造器参数,并从函数类型 (UserId) -> User 继承。
当我们从一个函数类型继承时,我们必须定义该类的调用(invoke)方法\\",该方法要有与我们要继承的函数相同的签名。 在我们的例子中,此函数获取用户 ID 作为输入并返回用户。
UserFetcher 可以像常规函数一样使用,获取 UserId 并返回 User。 这种方法简化了代码,并将函数式编程的初学者熟悉的面向对象概念与函数式范式融合在一起,为他们提供了更平滑的学习曲线
虽然我喜欢函数式编程的简单性,但面向对象模式有时非常方便。 Kotlin 同时利用了这两种范式。
上面的代码揭示了函数式编程和面向对象编程之间的一些主要区别,尤其是在依赖管理方面。 在面向对象编程中,这一任务可能需要创建具有多种方法的接口并让一个类来实现它。这可能会为相对简单的要求引入复杂的依赖关系网。
相反,函数式编程依靠 lambda\\" 或匿名函数\\"来完成类似的任务。例如,如果我们需要通过用户的 ID 获取用户,我们只需将相关函数作为参数传递给负责生成用户网页的另一个函数,而无需费心定义数据库访问层的完整接口。
这种策略尽可能减少了对接口、抽象类或其他复杂结构的需求,简化了代码并消除了不必要的耦合。
我们用一个 Kotlin 中的实际示例来演示这一点,展示如何应用前文展示的所有概念来创建一个显示关于我们“用户”的一些信息的 Web 应用程序。它必须从 HTTP 路径获取用户的 ID,然后从数据库中检索详细信息。我们将使用 Ktor\\",这是 Kotlin 中广泛使用的 Web 应用程序框架。
我们首先实现一个页面来显示包含用户详细信息的页面。这里的 URI 将是 /user/{userId},并将显示从数据库获取的,带有该 userId 的用户详细信息。
Ktor 中的“Hello World”如下所示:
fun main() {\\n embeddedServer(Netty, port = 8080) {\\n routing {\\n get(\\"/\\") { \\n call.respond(HtmlContent(HttpStatusCode.OK){\\n body(\\"Hello World\\")\\n })\\n }\\n }.start(wait = true)\\n}
上面的代码很好也很清晰,但是我们如何函数式地实现我们的 API 呢?
如果我们用函数式的眼光来观察 Web 服务器的工作方式,我们会看到一个函数将 HTTP 请求(通常来自用户浏览器)转换为 HTTP 响应(可以是页面 HTML)。
我们如何在代码中应用这种直觉呢?先考虑一下请求 -> 响应类型的函数需要做什么才能生成包含用户详细信息的页面。
考虑这里的数据流,数据的旅程从包含用户 ID 的 HTTP 请求开始。这个 ID 可能嵌入在请求的各个部分中——可以是查询参数、URL 路径的一段或其他元素——因此第一步是提取它。
private fun getId(parameters: Parameters): Outcome =\\n parameters[\\"id\\"]?.toIntOrNull()
一旦我们有了用户 ID,就可以使用类似我们之前遇到的 UserFetcher 可调用类来检索相应的用户实体。
下面就是我们使用 UserFetcher 和数据库连接来获取我们需要的 fetchUser 函数:
val dbConnection = DbConnection()\\nval fetchUser: (UserId)->User? = UserFetcher(dbConnection)
此处的 fetchUser 函数不是纯函数:它将根据数据库数据返回不同的用户。但是,最关键的部分是我们将其视为纯函数。这意味着我们代码的其余部分仍然是纯函数,我们将不纯函数区域仅限制在这个函数中。
其他技术(在这本书\\"中讨论到的)可以更精确地限制和标记不纯函数。例如,一些函数式编程模式(如 monad\\" 或代数数据类型)可以帮助我们更好地管理副作用。但作为第一步,这种方法已经比更宽松的方法在纯度方面有了显著改进。
通过隔离不纯函数,我们让代码库变得更清洁、更可预测且更易测试了。这里的第一步是朝着编写更强大和更可维护的代码迈出的一大步。
现在我们有了用户数据。下一步是将这个用户实体转换为适合 HTTP 响应的格式。在这个示例中,我们希望生成用户数据的最小 HTML 表示。
fun userHtml(user: User): HtmlContent =\\n HtmlContent(HttpStatusCode.OK) {\\n body(\\"Welcome, ${user.name}\\")\\n }
我们还需要生成一个 HTML 页面,以在数据库中不存在该用户时显示错误:
fun userNotFound(): HtmlContent =\\n HtmlContent(HttpStatusCode.NotFound) {\\n body { \\"User not found!\\" }\\n}
然后,我们可以创建一个函数,将上述所有函数链接在一起,并生成 Ktor 显示页面所需的 HtmlContent:
fun userPage(request: ApplicationRequest): HtmlContent =\\n getUserId(request)\\n ?.let(::fetchUser)\\n ?.let(::userHtml)\\n ?: userNotFound()
最后,我们可以调用我们的函数来从路由获取用户详细信息:
get(\\"/user/{id}\\") {\\n call.respond(userPage(call.parameters))\\n}
就这样,我们在 Web 服务器上实现了第一个函数式 API!过程非常简单。以这种方式工作,一次一个函数和一个类型,难道不是一种乐趣吗?
当然,这并不是旅程的终点。我们还可以通过更有效地处理数据库连接、返回精细调整的错误、添加审计等方式来改进这段代码。
但是,作为对函数式世界的首次探索,这一步非常具有启发性,让你明白了从协作对象思维转变为转换思维意味着什么。
让我们快速总结一下我们所做的工作以及我们如何将请求处理分解为四个函数:
从 HTTP 请求中提取用户 ID:第一步是解析 HTTP 请求以提取用户 ID。根据请求结构,这里的工作可能涉及 URL 路径、查询参数或请求正文。检索用户数据:有了用户 ID,我们就能使用一个函数来获取此 ID 并返回用户的域表示。这就是我们之前关于函数组合和应用片段的讨论发挥作用的地方。我们可以设计这个函数,以便快速与其他函数组合,实现灵活性和可重用性。将用户数据转换为 HTTP 响应格式:获取用户实体后,我们将其转换为适合 HTTP 响应的格式。根据应用程序的要求,这可以是 HTML、JSON 或其他任何格式。生成 HTTP 响应:最后,我们将格式化的用户数据封装到 HTTP 响应中,设置适当的状态代码、标头和正文内容。
这个小例子说明了为什么函数式编程在 Web 服务器应用程序中表现非常好,因为它们天然适合处理定义明确的输入和输出转换。这恰恰对应了 Web 服务的操作,也就是接收、处理请求并发回响应。
这种方法特别吸引人的是它的模块化。从提取用户 ID 到生成 HTTP 响应,该过程中的每个步骤都是一个离散的、独立的任务。这种模块化设计简化了每个任务,并提升了我们代码的清晰度和可维护性。通过将问题分解为更小、更易于管理的多个部分,我们将一个可能较为复杂的过程转变为一系列简单的任务。
每个任务都会产生一个或多个明确定义的函数和特定类型,这些函数和类型可以单独测试并在代码库的其他部分复用,而无需从原始上下文中引入依赖项。这使得代码更易维护、更强大,因为开发人员可以独立开发、测试和改进各个组件。
此外,这种方法还兼具灵活性和实验性。虽然总体框架保持一致,但提取用户 ID、将用户数据转换为响应友好格式以及将数据封装在 HTTP 响应中的具体方法可能会有所不同。这种灵活性鼓励创新和适应,确保我们的解决方案在不同场景和要求下保持稳健性。
我们利用函数式编程的模块化优势来创建更灵活、更易于维护的代码库。这使得我们的开发过程更加愉快,并带来更可靠、适应性更强的应用程序,能够随着需求和技术的变化而发展。
作者介绍
Uberto Barbini 是一位经验丰富的软件开发人员,在测试驱动开发、领域驱动设计和事件源方面拥有丰富的经验。他对这些最佳实践的深厚专业知识和对函数式编程的热情使他开始着手一个雄心勃勃的项目:撰写一本关于 Kotlin 函数式编程的综合书籍。经过四年的专注工作,Uberto 出版了他的巨作\\",该书长达 400 多页。本书借鉴他的实践经验,展示了函数式编程如何有效地应用于现代后端开发。它指导读者使用函数式编程技术构建一个完整、不普通的应用程序,展示这种范式的实际应用。作为精确、高效编码实践的倡导者,Uberto 用他的书来挑战人们对函数式编程的常见误解。通过他的写作和与世界各地开发人员的互动,他努力证明函数式编程不仅仅是一个植根于复杂数学的理论概念,而是一种实用、直接且有益的软件开发方法。Uberto 的目标是激励和教育开发人员了解函数式编程的强大功能和简单性。他利用自己在软件工程最佳实践方面的丰富背景,提出了在专业开发工作中采用这种范式的令人信服的案例。
原文链接:
How Functional Programming Can Help You Write Efficient, Elegant Web Applications\\"
","description":"本文要点 要保持一种内部可变状态并非易事。每次与程序交互时,我们都会更改后续交互的上下文。面向对象编程(OOP)和函数式编程(FP)试图提供处理软件可维护性和复杂性的解决方案。OOP 封装了复杂性,而 FP 则专注于数据及其转换。函数式编程概念提高了可预测性、促进了代码重用并管理了副作用——FP 对不变性和可组合性的重视带来了更强大和更易维护的系统。FP 将 Web 应用程序视为数据转换管道,从而提升程序水平。它鼓励人们使用纯函数将输入数据转换为输出数据,从而实现透明的数据流、更轻松的测试和更可预测的行为。Kotlin…","guid":"https://www.infoq.cn/article/r4DJeq48hJNvl4H2WwYC","author":"作者:Uberto Barbini","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-10-22T02:30:41.213Z","media":[{"url":"https://static001.geekbang.org/infoq/9a/9a5be653f4b63c898db30f780ccfce15.webp","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/37/3761927fcfac7669f20c43f22c0e203b.webp","type":"photo","width":311,"height":441,"blurhash":"UHR{[P~q-V_3%#RjM|%LIq%1M{Wotms:$*oc"},{"url":"https://static001.geekbang.org/infoq/3b/3be4160ea4679571d1438300eba015a5.webp","type":"photo","width":0,"height":0,"blurhash":""}],"categories":["编程语言"],"attachments":null,"extra":null,"language":null},{"title":"Kubernetes Autoscaler Karpenter 达到 1.0 里程碑","url":"https://www.infoq.cn/article/P6hSxSImVMO18iGilMLM","content":"Amazon Web Services(AWS) 发布开源 Kubernetes 集群自动扩展工具 Karpenter 的 1.0 版本。这标志着 Karpenter 已经完成 Beta 测试。该版本带来了稳定的 API 和多项新特性。
Karpenter 最初于 2021 年 11 月推出,现已经发展成为一个全面的 Kubernetes-native 节点生命周期管理器。正如我们今年早些时候报道的那样,这个项目在 Slack 等行业领导者中越来越受欢迎,并已成为 GitHub 上十大最受欢迎的 AWS 开源项目之一。
在 Infracloud 的一篇文章中,Himanshu Verma 解释了 Karpenter 如何消除了预配置节点组和调整资源大小的需求,并直接使用 Launch Templates 来管理实例。Karpenter 根据需要自动提供新节点,实时响应 Unschedulable pod。它可以动态调整集群计算容量,优化性能和成本效益。
1.0 版本修复了许多 Bug,并带来了多项新特性。Karpenter 1.0 的主要特性包括:
增强中断控制: 用户现在可以按原因设置中断预算,以便对节点中断进行细粒度控制,以应对利用率不足、空闲或漂移等情况。重命名合并策略: 为清楚起见,“WhenUnderutilized”策略已被重命名为“WhenEmptyOrUnderutilized”。新增合并控制: 在添加或删除 pod 时,“consolidateAfter”参数允许用户指定 Karpenter 在合并节点之前等待多长时间。终止宽限期: 新增的“terminationGracePeriod”设置使集群管理员对节点生存期和优雅终止有了更多控制。漂移特性升级: 漂移特性,即替换偏离期望状态的节点,现在默认启用。AMI 选择更改:“amiSelectorTerms”字段现在是必需的,并且新增的“alias”术语使用户可以选择 Amazon EKS-optimized AMI 的特定版本。实例元数据服务(IMDS)访问限制: 为了提高安全性,默认禁止 pod 对 IMDS 的访问。Kubelet 配置位置更改:Kubelet 设置改到了 EC2NodeClass API 中。NodeClaims 不可变:NodeClaims 在创建后不能再修改,从而保证与预期的行为一致。NodePool nodeClassRef 更改: 所有的 nodeClassRef 字段现在都是必需的,“apiVersion”字段被重命名为“group”。指标更改: 修改了几个 Prometheus 指标,这可能需要用户更新他们的仪表板。
该版本还包括一些计划中的弃用,包括删除某些注解和基于 ConfigMap 的配置。
对于希望从 Beta 版升级的用户,AWS 提供了一个使用 Kubernetes webhook 转换的迁移路径,前提是用户已经使用了包含最新 API 的版本。该过程可以就地升级 API 而不需要替换节点。但是,建议用户在进行升级之前查看完整的迁移文档,并在非生产环境中测试升级过程。
在 X(以前的 Twitter)上的一段演练视频中,Olalekan Taofeek 详细解释了他是如何将 Karpenter 从 0.37 升级到 1.0 的——这个版本差异比迁移路径提供的版本差异更大。他强调,有几个破坏性的变化需要特别注意:
用户数据不再用于 Kubernetes 配置。节点池 / 组配置更改——API 版本和字段名称发生了变化,用户需要更新配置。新增一个“启动时间”字段,需要用户在自己的工作负载中加以考虑。将一些字段从节点池移到了节点类配置中。
Karpenter 1.0 发布的消息大受欢迎,例如 Vatsal Bajpai 在 X(以前的 Twitter)上写道:
“在云上,Karpenter 已经成为 k8s 的必需品,真让人高兴!”
在 Reddit 上的一个帖子中,用户普遍对这个版本赞赏有加。有人指出,Azure 上已经有可用的移植版本,但令人遗憾的是,GCP 上没有。其他人则在考虑,Karpenter 的功能是否可以完全集成到 EKS 的控制平面中。
用户可以通过 Kubernetes Slack #karpenter 频道或 GitHub 了解更多信息或提供反馈。
查看原文链接:
https://www.infoq.com/news/2024/09/karpenter-10/\\"
","description":"Amazon Web Services(AWS) 发布开源 Kubernetes 集群自动扩展工具 Karpenter 的 1.0 版本。这标志着 Karpenter 已经完成 Beta 测试。该版本带来了稳定的 API 和多项新特性。 Karpenter 最初于 2021 年 11 月推出,现已经发展成为一个全面的 Kubernetes-native 节点生命周期管理器。正如我们今年早些时候报道的那样,这个项目在 Slack 等行业领导者中越来越受欢迎,并已成为 GitHub 上十大最受欢迎的 AWS 开源项目之一。\\n\\n在 Infracloud 的一篇文章中…","guid":"https://www.infoq.cn/article/P6hSxSImVMO18iGilMLM","author":"作者:Matt Saunders","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-10-21T00:00:05.368Z","media":[{"url":"https://static001.geekbang.org/wechat/images/4a/4ae2caabe93df82c545462e18131c7ac.png","type":"photo","width":0,"height":0,"blurhash":""}],"categories":["编程语言","云计算"],"attachments":null,"extra":null,"language":null},{"title":"Llama 3 In Action:部署策略和高级特性应用","url":"https://www.infoq.cn/article/aBeKiq8ksih4BCsm6HjG","content":"本文是实用生成式人工智能应用系列文章的一部分。在这一系列文章里,我们呈现了来自顶尖生成式人工智能实践者的现实世界解决方案和实操经验。
Meta 在 2023 年初发布了他们的第一个开源、开放权重的大语言模型——LLaMA 的第一个版本。这个模型性能与 GPT-3 和 PaLM 等模型相当,但与这些模型不同的是,Meta 允许用户下载 LLaMA 的权重。2023 年 7 月,LLaMA 很快被 Llama 2 取代。这个模型也是开源的,并且比第一代模型具有更高的准确性和更长的上下文长度。
2024 年 4 月 19 日,LLM 开源社区再次迎来狂欢。在 Llama 2 发布九个月后,Meta 发布了 Llama 3 的官方版本。Llama 3 包含 8 亿参数(Llama3-8B)和 70 亿参数(Llama3-70B)两种规模的模型,每个版本都有基础版和指令调优版,且均已开源。它们也免费开放给商业用途,前提是月活跃用户数不超过 7 亿。
总体而言,Llama 2 和 Llama 3 在模型架构上几乎没有明显的差异。这对已有的 Llama 2 用户来说是个好消息,因为使用 Llama 2 模型的应用程序可以无缝迁移到 Llama 3。
要深入理解细节,最好的方式是深入研究源代码。在 Meta 的 Llama 3 和 Llama 2 官方代码库中,以 8B 和 7B 为例,你会发现 model.py 文件几乎是一样的。
Llama 3 引入了更复杂的嵌入技术——VocabParallelEmbedding,它优化了模型并行分片中的词汇分布。
两者都采用了“仅解码器”架构,并以 “SwiGLU” 作为激活函数,集成了“旋转嵌入(RoPE)” 和“分组查询注意力(GQA)”机制进行位置编码,以提高序列位置感知能力,这是模型对自然语言理解能力的一个重要部分。此外,在分词和模型初始化方面也有一些细微的差异。
通过比较 HuggingFace 仓库中的 “config.json” 文件,我们可以发现两个模型都是 “LlamaForCausalLM” 架构,这说明模型结构保持不变。主要差异在于维度配置,参数从 7B 增加到 8B ,文件大小增加了 2464M。
图 1:Llama 2 (左) 和 Llama 3 (右) 的 config.json 文件比较
训练数据规模:在预训练阶段,Llama 3 使用了超过 15T Token 的公开可用资源,是 Llama 2 训练数据总量的七倍以上。与 Llama 2 相比,编码数据量也增加了四倍以上。在微调阶段,除了使用公开的指令数据集外,Meta 还生成了超过 1000 万个手动注释的示例数据集。数据质量:Meta 表示,“为了确保 Llama 3 高质量的数据训练,我们开发了一系列数据过滤管道,包括使用启发式过滤器、NSFW 过滤器、语义去重方法和文本分类器来预测数据质量”。在指令微调方面,“模型质量的最大改进之一是进行了精心的数据策划,并对人类注释者提供的注释进行多轮质量保证”。数据混合比例:“我们还进行了广泛的实验,评估了在最终的预训练数据集中混合不同来源数据的最佳方式。这些实验使我们能够选择最佳的数据混合比例,确保 Llama 3 在各种用例中表现良好,包括琐事问题、STEM、编码、历史知识等”。
此外,你可以通过阅读这篇文章了解 Meta 用于训练 Llama 的 GenAI 基础设施的详细信息。
根据 Meta 的说法,Llama 3 已经通过各种基准测试的评估,包括 MMLU(本科水平知识)、GSM-8K(小学数学)、HumanEval(编码任务)、GPQA(研究生问题)和 MATH(数学问题)。这些基准测试表明,8B 模型的性能优于谷歌的 Gemma 7B 和 Mistral 7B Instruct 等开放权重模型,而 70B 模型可与 Gemini Pro 1.5 和 Claude 3 Sonnet 一较高下。
Llama 3 的发布进一步凸显了数据工程的重要性:在保持模型架构不变的情况下,更多高质量的数据可以显著提升模型性能。虽然目前还不支持长序列和多模态等常见功能,但 Meta 表示即将推出 400B+ 版本,新版本将支持多模态、多语言对话、更长的上下文窗口和更强大的总体能力。
现在,你可以在多个平台上与 Llama 3 进行对话,包括但不仅限于官方的 meta.ai(在欧洲不可用)、HuggingFace 的 HuggingChat、Perplexity Labs、Groq 等。
要在生产环境中部署 Llama 3,你需要考虑推理速度和成本等因素,必须分配足够的计算资源、RAM/VRAM 空间和磁盘空间。首先,你可以在没有 GPU 的情况下部署并运行 Llama 3。我在一台只配备了 CPU 且大约有 60GB 可用 RAM 的 M1 Macbook Pro 上运行了完整的 FP16 Llama3-8B。但延迟非常大,每个 Token 的处理时间大约需要 30 秒,这显然不适合生产用途。
要将 Llama 3 部署到生产环境,你需要提供配备足够 VRAM 容量的 GPU 实例来支持模型的运行。你还需要足够的磁盘空间来存储模型文件,并确保有足够的 VRAM 来加载它们。表 1 列出了 8B 和 70B 模型的要求。你可以通过将模型部署到下面描述的 EC2 实例来验证这些数据。
表 1:部署 Llama 3 模型所需的计算资源
使用最高精度的权重表示,float16 或 bfloat16,每个模型权重使用 16 位(或 2 个字节)。因此,如果你想以模型的完整原始精度运行模型,以便获得最高质量的输出和模型的全部能力,你需要为每个权重参数分配 2 个字节,再加上更多的显存空间,因为在模型加载和推理时还需要其他推理依赖项、操作系统的消耗等。
根据具体的可用显存空间和 GPU 配置,模型将被加载到 RAM 中,并在 CPU 上运行,或者在层之间进行频繁的交换。这两种情况都可能导致无法充分利用机器上的所有计算资源。你可以考虑使用更小尺寸的量化模型,当然,这是性能和成本之间的一种权衡,尤其是在商业用途中。虽然量化到大约 q_5 精度仍然可以保留大部分的语言理解能力,但值得注意的是,编码能力可能会因为量化而显著下降。
这里有一篇文章详细介绍了计算开销,还有一篇 文章 介绍如何计算 LLM 的内存需求。
让我们以 AWS 为例,这是生产环境中最常见的云平台之一。在 AWS 上部署 Llama 3 有几种方法。
首先,在 AWS 上可以选择多种为不同用例优化的 EC2 实例,这些实例提供了不同版本和大小的 GPU 以及其他显卡。在加速计算实例类型页面可以看到各种基于 GPU 的实例,如 AWS P 系列和 G 系列,或配备 AWS Inferentia2 的 Inf2 实例,AWS Inferentia2 是 AWS 开发的硅芯片,与同类 GPU 相比,为生成式 AI 推理工作负载提供高达 40% 的性价比优势。
表 2:在 AWS 中部署 Llama 3 的 EC2 实例示例
你至少需要一个 g5.2xlarge 实例来运行 Llama3-8B FP16,使用以下指令。
图 2:在 AWS 中启动 EC2 实例来部署 Llama 3
在实例运行起来以后,你可以连上去,然后从 Meta、HuggingFace、Ollama 等网站下载 Llama3-8B。
我建议从 HuggingFace 的这个链接下载模型,按照网站提供的指令下载。HuggingFace 会下载 HuggingFace 格式和原始版本的模型,在下载过程中不太可能遇到错误。
下载完成后,请执行以下命令来验证模型文件的校验和是否与 HuggingFace 提供的 SHA256 密钥相匹配。如果不一致,在推理过程中可能会遇到问题。
sha256sum ./original/consolidated.00.pth
# Install virtual environment\\nconda create -n llama3 python=3.11\\nconda activate llama3\\n\\n\\n# Clone Meta Llama3 official repo to your path\\ngit clone https://github.com/meta-llama/llama3.git\\n\\n\\ncd llama3\\n\\n\\n# Install dependencies required\\npip install -e .
然后,你可以运行基于 Transformer 的推理脚本。确保你至少有 24GB VRAM,这样才能成功加载模型的检查点。
import transformers\\nimport torch\\n\\n\\n# Your model path\\nmodel = \\"./Meta-Llama-3-8B\\"\\n\\n\\npipeline = transformers.pipeline(\\n \\"text-generation\\",\\n model=model,\\n model_kwargs={\\"torch_dtype\\": torch.bfloat16},\\n device=\\"cuda\\",\\n max_length=128 # Set this up to limit the length of completion\\n)\\nprint(pipeline(\\"Hey how are you doing today?\\"))
推理结果如下:
图 3:控制台输出的 Llama 3 推理结果
使用 vLLM 启动推理服务器
或者,你可以使用 vLLM 将模型推理部署成服务。vLLM 是一个库,用于快速轻松地进行 LLM 推理和部署。它的效率归功于各种复杂方法,包括分页注意力(用于高校管理注意力键值内存)、批量实时处理传入查询,以及个性化的 CUDA 内核。
首先,运行以下命令安装 vLLM。
pip install vllm
使用 vLLM 的两种推理模式。
1. Completion 模式
部署推理服务:
python -m vllm.entrypoints.openai.api_server --model ./Meta-Llama-3-8B --dtype auto --api-key \\"your_string\\"
使用以下脚本运行推理:
from openai import OpenAI\\n\\n\\n# Modify OpenAI\'s API key and API base to use vLLM\'s API server.\\nopenai_api_key = \\"EMPTY\\" # Same as --api-key in the deployment command\\nopenai_api_base = \\"http://localhost:8000/v1\\"\\n\\n\\nclient = OpenAI(\\n # defaults to os.environ.get(\\"OPENAI_API_KEY\\")\\n api_key=openai_api_key,\\n base_url=openai_api_base,\\n)\\n\\n\\nprint(\\"Connection Success!\\")\\n\\n\\n# Completion API\\ncompletion = client.completions.create(\\n model=\\"./Meta-Llama-3-8B\\", # Same as --model in the deployment command\\n prompt=\\"A robot may not injure a human being\\",\\n max_tokens=128,\\n)\\n\\n\\nprint(\\"Completion results:\\", completion)
设置 “max_tokens”,限制生成输出的长度。推理结果如下:
图 4:使用 vLLM 的 Llama 3 推理结果
2. Chat 模式
同样,对于指令调优的版本:
python3 -m vllm.entrypoints.openai.api_server --model ./Meta-Llama-3-8B-Instruct --dtype auto --api-key 123456\\nfrom openai import OpenAI\\n\\n\\n# Modify OpenAI\'s API key and API base to use vLLM\'s API server.\\nopenai_api_key = \\"EMPTY\\" # Same as --api-key in the deployment command\\nopenai_api_base = \\"http://localhost:8000/v1\\"\\n\\n\\nclient = OpenAI(\\n # Defaults to os.environ.get(\\"OPENAI_API_KEY\\")\\n api_key=openai_api_key,\\n base_url=openai_api_base,\\n)\\n\\n\\nprint(\\"Connection Success!\\")\\n\\n\\nchat_completion = client.chat.completions.create(\\n messages=[{\\n \\"role\\": \\"system\\",\\n \\"content\\": \\"You are a helpful assistant.\\"\\n }, {\\n \\"role\\": \\"user\\",\\n \\"content\\": \\"Who won the world series in 2020?\\"\\n }, {\\n \\"role\\":\\n \\"assistant\\",\\n \\"content\\":\\n \\"The Los Angeles Dodgers won the World Series in 2020.\\"\\n }, {\\n \\"role\\": \\"user\\",\\n \\"content\\": \\"Where was it played?\\"\\n }],\\n model=\\"./Meta-Llama-3-8B-Instruct\\", # Same as --model in the deployment command\\n max_tokens=128,\\n)\\n\\n\\nprint(\\"Chat completion results:\\", chat_completion.choices[0].message)
通过 Amazon SageMaker Jumpstart 来部署
你还可以通过像 Amazon SageMaker 这样的托管 AWS 服务来部署 Llama 3。
借助 SageMaker JumpStart,用户可以选择一系列公开可用的基础模型。用户可以在网络隔离环境中将基础模型部署到专用的 SageMaker 实例,并使用 SageMaker 自定义模型进行训练和部署。
目前,SageMaker JumpStart 上提供了八个 Llama 3 变体,如下所示。你可以在 Amazon SageMaker Studio 中通过几次点击就可以轻松配置和部署 Llama 3 模型,或者通过 SageMaker Python SDK 以编程方式进行。还有基于 AWS Inferentia 的 Neuron 版本,你可以在基于 AWS Inferentia 的实例上部署。你还可以使用 AWS Trainium 实例上的 AWS Neuron,在 AWS Trainium 和基于 AWS Inferentia 的实例上运行深度学习工作负载进行模型微调。
图 5:使用 Amazon Sagemaker 部署 Llama 3
现在,你可以享受到 Llama 3 的性能与 MLOps 控件和 Amazon SageMaker 特性(如 SageMaker Pipelines、SageMaker Debugger 或容器日志)的组合所带来的优势。此外,模型将在你的 VPC 环境中安全部署,确保了数据的安全性和隐私保护。
最后,你可以在 Amazon Bedrock 中通过聊天界面或网络服务 API 访问 Llama3-8B-instruct 和 Llama3-70B-instruct,你可以轻松地将它们以完全托管的方式集成到生产应用程序中。
自 Meta 发布首批四个 Llama 3 版本以来,在不到一个月的时间里,HuggingFace 上已经出现了超过 3000 个模型变体。这些变体扩展了原始模型的能力,扩大了上下文窗口长度,还有量化版本,可以支持不同语言和高度专业化的场景。
一些令人兴奋的应用包括:
1. 更大的上下文窗口
如之前提到的,HuggingFace 上有一个 Llama3-8B-Instruct-Gradient-1048k 版本。通过将 “rope_theta” 参数调整为 3580165449.0,该版本成功地将上下文窗口长度从 8k 扩展至 1048k。这一改进展示了如何在保持训练要求最小化的同时有效地管理并扩展上下文长度。
图 6:Huggingface 上的 Llama3-8B-Instruct-Gradient-1048k
2. 离线检索增强生成(RAG)
Llama 3 的增强特性将显著推动基于 LLM 的企业级应用程序的生产化。现在,你可以轻松地在本地计算机上构建无需互联网连接的 RAG 应用程序。对于有敏感数据法规要求的公司,100% 本地 RAG 等需求现在变得更加可行。
参考 LangChain 的代码示例 1 和 LlamaIndex 的代码示例 2,开发基于 Llama 3 的 RAG 应用程序。
3. 针对垂直领域的微调
有许多针对 Llama 3 进行微调的版本,个人可以在他们自己的机器上轻松微调 8B 版本。一个很好的例子是英伟达发布的 Llama3-70B 微调版本 Llama3-ChatQA-1.5-70B,这是一个针对问答和信息检索任务进行微调的 QA/RAG 版本,可在 HuggingFace 上获取。
图 7:Huggingface 上的 Llama3-ChatQA-1.5-70B
4. 调用函数和使用工具
Llama 3 原始版本不支持函数调用。
图 8:Llama 3 不支持函数调用
然而,市场上也出现了一些专门针对函数调用数据进行微调的 Llama 3 版本,例如 Meta-Llama-3-8B-Instruct-function-calling 和 Hermes-2-Pro-Llama-3-8B,它们提供了结构化输出和调用工具解析标签。
下面是一个提示词模板示例:
<|begin_of_text|><|start_header_id|>function_metadata<|end_header_id|>\\nYou have access to the following functions. Use them if required:\\n[\\n {\\n \\"type\\": \\"function\\",\\n \\"function\\": {\\n \\"name\\": \\"search_merchant\\",\\n \\"description\\": \\"Search for merchants in the catalog based on the term\\",\\n \\"parameters\\": {\\n \\"type\\": \\"object\\",\\n \\"properties\\": {\\n \\"name\\": {\\n \\"type\\": \\"string\\",\\n \\"description\\": \\"name to be searched for finding merchants.\\",\\n }\\n },\\n \\"required\\": [\\"name\\"],\\n },\\n },\\n },\\n {\\n \\"type\\": \\"function\\",\\n \\"function\\": {\\n \\"name\\": \\"search_item\\",\\n \\"description\\": \\"Search for items in the catalog based on various criteria.\\",\\n \\"parameters\\": {\\n \\"type\\": \\"object\\",\\n \\"properties\\": {\\n \\"term\\": {\\n \\"type\\": \\"string\\",\\n \\"description\\": \\"Term to be searched for finding items, with removed accents.\\",\\n },\\n \\"item_price_to\\": {\\n \\"type\\": \\"integer\\",\\n \\"description\\": \\"Maximum price the user is willing to pay for an item, if specified.\\",\\n },\\n \\"merchant_delivery_fee_to\\": {\\n \\"type\\": \\"integer\\",\\n \\"description\\": \\"Maximum delivery fee the user is willing to pay, if specified.\\",\\n },\\n \\"merchant_payment_types\\": {\\n \\"type\\": \\"string\\",\\n \\"description\\": \\"Type of payment the user prefers, if specified.\\",\\n \\"enum\\": [\\n \\"Credit Card\\",\\n \\"Debit Card\\",\\n \\"Other\\",\\n ],\\n },\\n },\\n \\"required\\": [\\"term\\"],\\n },\\n },\\n }\\n]<|eot_id|><|start_header_id|>user<|end_header_id|>\\n\\n\\nGet the list of the five most preferred payment types<|eot_id|><|start_header_id|>assistant<|end_header_id|>\\n\\n\\nGenerated Response:\\n\\n\\n{\\n \\"name\\": \\"search_item\\",\\n \\"arguments\\": {\\n \\"number\\": 5,\\n \\"region\\": \\"US\\"\\n }\\n}<|eot_id|>
你可以使用以下脚本切换到相应的模型版本来运行支持函数调用的推理。
from openai import OpenAI\\nopenai_api_key = \\"EMPTY\\" #same as --api-key in the deployment command\\nopenai_api_base = \\"http://localhost:8000/v1\\"\\n\\n\\nprint(\\"Connection Success!\\")\\n\\n\\nclient = OpenAI(\\n # defaults to os.environ.get(\\"OPENAI_API_KEY\\")\\n api_key=openai_api_key,\\n base_url=openai_api_base,\\n)\\n\\n\\nresponse = client.chat.completions.create(\\n model=\\"./Hermes-2-Pro-Llama-3-8B\\", #your model path\\n messages = [\\n {\\n \\"role\\": \\"system\\",\\n \\"content\\": \\"You are a digital waiter Pay attention to the user requests and use the tools to help you.\\"\\n },\\n {\\n \\"role\\": \\"user\\",\\n \\"content\\": \\"search for burger and a maximum price of 10 dollars. at the same time, look for merchant named \'Burger King\'\\"\\n },\\n ],\\n tools = [\\n {\\n \\"type\\": \\"function\\",\\n \\"function\\": {\\n \\"name\\": \\"search_merchant\\",\\n \\"description\\": \\"Search for merchants in the catalog based on the term\\",\\n \\"parameters\\": {\\n \\"type\\": \\"object\\",\\n \\"properties\\": {\\n \\"name\\": {\\n \\"type\\": \\"string\\",\\n \\"description\\": \\"name to be searched for finding merchants.\\",\\n }\\n },\\n \\"required\\": [\\"name\\"],\\n },\\n },\\n },\\n {\\n \\"type\\": \\"function\\",\\n \\"function\\": {\\n \\"name\\": \\"search_item\\",\\n \\"description\\": \\"Search for items in the catalog based on various criteria.\\",\\n \\"parameters\\": {\\n \\"type\\": \\"object\\",\\n \\"properties\\": {\\n \\"term\\": {\\n \\"type\\": \\"string\\",\\n \\"description\\": \\"Term to be searched for finding items, with removed accents.\\",\\n },\\n \\"item_price_to\\": {\\n \\"type\\": \\"integer\\",\\n \\"description\\": \\"Maximum price the user is willing to pay for an item, if specified.\\",\\n },\\n \\"merchant_delivery_fee_to\\": {\\n \\"type\\": \\"integer\\",\\n \\"description\\": \\"Maximum delivery fee the user is willing to pay, if specified.\\",\\n },\\n \\"merchant_payment_types\\": {\\n \\"type\\": \\"string\\",\\n \\"description\\": \\"Type of payment the user prefers, if specified.\\",\\n \\"enum\\": [\\n \\"Credit Card\\",\\n \\"Debit Card\\",\\n \\"Other\\",\\n ],\\n },\\n },\\n \\"required\\": [\\"term\\"],\\n },\\n },\\n }\\n ],\\n tool_choice=\\"auto\\"\\n)\\n\\n\\nprint(response)
Hermes-2-Pro-Llama-3-8B 在 Groq 上展示出了出色的工具调用能力,高效且具有成本效益。这里提供了代码示例。
开源 Llama 3 的发布及其衍生产品的迅速扩散突显了开源生成式 AI 发展的强大动力和价值。它赋予全球社区开发者自由构建、完善和定制这些基础语言模型的能力,以应对多样化的挑战和应用场景。我迫不及待地想看到 400B+ 版本的发布!
查看英文原文链接:
https://www.infoq.com/articles/llama3-deployment-applications/\\"
","description":"本文是实用生成式人工智能应用系列文章的一部分。在这一系列文章里,我们呈现了来自顶尖生成式人工智能实践者的现实世界解决方案和实操经验。 Meta 在 2023 年初发布了他们的第一个开源、开放权重的大语言模型——LLaMA 的第一个版本。这个模型性能与 GPT-3 和 PaLM 等模型相当,但与这些模型不同的是,Meta 允许用户下载 LLaMA 的权重。2023 年 7 月,LLaMA 很快被 Llama 2 取代。这个模型也是开源的,并且比第一代模型具有更高的准确性和更长的上下文长度。\\n\\n2024 年 4 月 19 日,LLM 开源社区再次迎来狂欢。在…","guid":"https://www.infoq.cn/article/aBeKiq8ksih4BCsm6HjG","author":"作者:Tingyi Li","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-10-18T00:00:06.428Z","media":[{"url":"https://static001.geekbang.org/wechat/images/95/95e13ef6a5d72b3a39b97b59064e49af.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/wechat/images/08/08102f07b3baceefc9af4b0fd13ac459.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/wechat/images/d2/d28e6ef1bbd2f62534babe18959e5825.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/wechat/images/e3/e3d13138478ee96ba0b2ea138757c363.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/wechat/images/06/0633460160fa8e277a1188d31935130e.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/wechat/images/6b/6b611fd0b49ec816d01ce65b47b20f90.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/wechat/images/db/db02b35b3e3e4d7bd7480376588a0bf8.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/wechat/images/bf/bf74a596612d584d1d91cb04e5bddbe0.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/wechat/images/f3/f3711fe5ee1dd4837153695314d48c9e.png","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/wechat/images/94/9438075e0130f71b165953be5a79a0fb.png","type":"photo","width":0,"height":0,"blurhash":""}],"categories":["编程语言"],"attachments":null,"extra":null,"language":null},{"title":"谷歌发布最新报告: Rust 可显著减少安全漏洞","url":"https://www.infoq.cn/article/x4a9NNWsjuLEEFhiJ4dG","content":"谷歌表示,过去六年来,其优先考虑内存安全软件开发的努力已大幅减少安卓操作系统中的内存安全漏洞数量。
在最近发布的报告\\"中,谷歌透露,因内存安全问题导致的安卓漏洞比例已从 2019 年的 76%下降至预计 2024 年底的 24%,这显著低于行业标准的 70%。
这是安卓代码风险状况的显著改善,安卓安全团队成员 Jeff Vander Stoep 和谷歌高级软件工程师 Alex Rebert 将此归功于采用了安全编码\\"(Safe Coding)。这是一套软件开发实践,旨在通过内存安全编程语言(包括 Rust)、静态分析和 API 设计来避免引入漏洞。
据安卓团队观察,Rust 变更的回滚率不到 C++ 的一半。
Vander Stoep 和 Rebert 说:“前几代人向安全编码所做的转变可以通过开发代码时所做断言的可量化性来体现。”
“安全编码使我们能够对代码的属性以及基于这些属性可能发生或不可能发生的情况做出强有力的断言,而不是关注所应用的干预措施(如缓解和模糊测试),或试图利用过去的表现来预测未来的安全性。”
使用 C#、Go、Java、Python、Swift 和 Rust 等内存安全编程语言开发软件是安全编码的重要组成部分。在大型代码库中,大多数的严重安全漏洞都源于缓冲区溢出等内存安全缺陷。这一认识促使公共和私营部门广泛推动减少内存安全漏洞的发生。
为了实现这一目标,我们主要建议避免使用 C 和 C++,因为这两种语言需要手动进行内存管理,除非开发人员特别敬业,否则容易导致内存漏洞。(这一点在 C/C++ 社区中也得到了关注,内存安全已成为\\"该社区的首要任务。)
对谷歌而言,国际内存安全运动\\"意味着在安卓和其他项目中更多地采用 Rust 进行开发,这在大多数情况下能够提供内存安全保障而不影响性能。同时,这种做法还提高了工作效率。
Vander Stoep 和 Rebert 说到,“安全编码将缺陷查找工作进一步向左转移,甚至在代码提交之前,从而提高了代码的正确性和开发人员的工作效率”。
“我们看到这种转变体现在一些重要的指标上,比如回滚率(因意外错误导致的代码紧急回退)。安卓团队观察到,Rust 变更的回滚率不到 C++ 的一半。”
对于拥有大量不安全遗留代码的企业来说,好消息是可能不需要用新语言重写旧代码。正如 Vander Stoep 和 Rebert 所指出的,漏洞是有半衰期的——它们会随着时间的推移而衰减。他们说,“举例来说,根据平均漏洞寿命,5 年前的代码比新代码的漏洞密度低 3.4 倍(基于研究结果中的寿命)到 7.4 倍(基于在安卓和 Chromium 中观察到的寿命),”。
这并不是说旧漏洞会奇迹般地变得不可利用。相反,漏洞总体密度的降低,这是统计上的胜利,但并不意味着安全有了保障。
即便如此,通过使旧代码与内存安全代码实现互操作,以及使用内存安全语言编写新代码,现有漏洞的自然衰减率往往会使大型代码库随着时间的推移变得更加安全,而无需进行繁琐的代码修订。如果你停止制造新的内存安全漏洞,旧的漏洞至少在总体上就不会成为问题。
Vander Stoep 和 Rebert 说,“在新代码中采用安全编码是一种范式转变,使我们能够利用漏洞的固有衰减特性来发挥我们的优势,即使在大型现有系统中也是如此。”
“这个概念很简单:一旦我们切断了新漏洞的源头,这些漏洞就会呈指数级减少,从而使我们所有的代码更加安全,提高安全设计的有效性\\",并缓解与现有内存安全策略相关的可扩展性挑战,使这些策略能够更加有效和更加有针对性地得到应用。”
作者简介:
Thomas Claburn,The Register 网络杂志的资深记者。他的专长在于政府信息技术、软件开发以及人工智能的伦理使用。Thomas 在技术出版领域拥有近 30 年的经验,曾担任过从杂志版块编辑到特约编辑的多种职务。
原文链接:
https://www.theregister.com/2024/09/25/google_rust_safe_code_android\\"
声明:本文为 InfoQ 翻译整理,未经许可禁止转载。
","description":"谷歌表示,过去六年来,其优先考虑内存安全软件开发的努力已大幅减少安卓操作系统中的内存安全漏洞数量。 \\n\\n在最近发布的报告\\"中,谷歌透露,因内存安全问题导致的安卓漏洞比例已从 2019 年的 76%下降至预计 2024 年底的 24%,这显著低于行业标准的 70%。\\n\\n \\n\\n这是安卓代码风险状况的显著改善,安卓安全团队成员 Jeff Vander Stoep 和谷歌高级软件工程师 Alex Rebert 将此归功于采用了安全编码\\"(Safe Coding)。这是一套软件开发实践,旨在通过内存安全编程语言(包括 Rust)、静态分析和 API 设计来避免引入漏洞。\\n\\n \\n\\n据安…","guid":"https://www.infoq.cn/article/x4a9NNWsjuLEEFhiJ4dG","author":"Thomas Claburn","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-10-16T08:50:51.144Z","media":null,"categories":["编程语言"],"attachments":null,"extra":null,"language":null},{"title":"增量垃圾收集器的“重大更改”使 Python 3.13 推迟发布","url":"https://www.infoq.cn/article/szZseD4Q0mc51gQocmfT","content":"CPython 3.13 的完整版本被推迟了一周发布,原因是为了移除增量垃圾收集器(GC),此前有报道称它会导致代码速度变慢,尽管这一更改的初衷是提高性能。
CPython 核心开发人员 Thomas Wouters 发布了他对“3.13 中增量 GC 更改的影响”的担忧,并补充说“目前尚不清楚增量 GC 是否提供了显著的改进(尽管较短的暂停时间可能还不错),它在常见情况下显然开销有点大,而且我们还在发现一些新的问题。”
虽然在这个非常晚的阶段移除它是“一项重大更改”,但 Wouters 认为,一个新的候选版本(没有增量 GC)并将 3.13 的发布推迟一周就足够了。“我们正在回滚到已知的旧代码,这比试图解决新代码中出现的各种问题的做法风险更小,”他说。
新的增量式 GC 目前仍保留在 CPython 3.14 的代码中,该版本计划于明年此时发布,但 Wouters 对此表示怀疑,他说“我们需要为这一更改提供更多的价值主张。”
微软 Faster CPython 团队的技术负责人 Mark Shannon 于去年 8 月提出了该特性,他表示:“当前的 GC 效率低下,而且可能会有非常长的暂停时间……我们应该使用增量式收集器,它可以提高效率并大大减少最大暂停时间。”
删除它的原因是 Sphinx 的性能下降,Sphinx 是 Python 团队使用的文档工具。使用 Python 3.13 时,构建 Sphinx 的时间从大约 1.28 秒增加到大约 1.80 秒,使用 Sphinx 构建 CPython 文档的时间从 45.5 秒增加到 62.7 秒。移除增量式 GC 已解决该问题。
另一位核心开发人员 Neil Schemenauer 指出,对 GC 的更改本质上可能会加快某些程序的速度并降低其他程序的速度。此外,“这可能会导致它们使用更多或更少的内存。或者,加快或减慢文件描述符和套接字等资源的释放速度。”
该特性发布过程中出现的一个问题是,试用发布候选版本的用户相对较少,因此很难衡量像这样的,结果好坏参半的更改的总体影响。“我们不知道这些 [减速] 是罕见情况还是常见情况。给它更多时间,让它在 3.14 分支中变得更成熟是一种谨慎的做法,我认为这是个好决定,”Schemenauer 说。
在某些情况下,移除增量 GC 会略微降低性能,像另一位开发人员报告的那样,特别是在 macOS 上。
","description":"CPython 3.13 的完整版本被推迟了一周发布,原因是为了移除增量垃圾收集器(GC),此前有报道称它会导致代码速度变慢,尽管这一更改的初衷是提高性能。 \\n\\nCPython 核心开发人员 Thomas Wouters 发布了他对“3.13 中增量 GC 更改的影响”的担忧,并补充说“目前尚不清楚增量 GC 是否提供了显著的改进(尽管较短的暂停时间可能还不错),它在常见情况下显然开销有点大,而且我们还在发现一些新的问题。”\\n\\n \\n\\n虽然在这个非常晚的阶段移除它是“一项重大更改”,但 Wouters 认为,一个新的候选版本(没有增量 GC)并将 3.13…","guid":"https://www.infoq.cn/article/szZseD4Q0mc51gQocmfT","author":"Tim Anderson","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-10-16T07:23:48.893Z","media":null,"categories":["编程语言"],"attachments":null,"extra":null,"language":null},{"title":"Kubernetes v1.31 发布:提升安全性和稳定性并提供 AI/ML 支持","url":"https://www.infoq.cn/article/Om506pjzFVfzIOOzN6XR","content":"
Kubernetes 项目最近宣发了代号“Elli”的 1.31 版本,该版本中集成了 45 项增强功能,其中 11 项为稳定版,22 项为 Beta 版,还有 12 项新引入的 Alpha 版功能。本次发布中的主要功能包括利用 AppArmor 增强容器安全性、提高负载均衡器的可靠性、对 PersistentVolume 阶段转换的见解,以及对 OCI 镜像卷的支持。
Kubernetes 发布通信团队中的 Matteo Bianchi、Edith (Edi) Puclla、Rashan Smith 和 Yiğit Demirbaş 在一篇博文中宣布了这一消息。Kubernetes v1.31 是该项目在十周年纪念日后的首个版本发布。
在这次发布的稳定版功能中,Kubernetes 现已完全支持 AppArmor 以提高容器安全性。工程师们可使用容器的 securityContext 中 appArmorProfile.type 字段进行配置,建议从 v1.30 版本中使用的注解迁移到这个新字段。
Kubernetes v1.31 现还为负载均衡器的入口连接提供了稳定且改进的可靠性,最大限度地减少了节点终止时的流量下降。该功能需要将 kube-proxy 用作默认服务代理并有一个支持连接排空的负载均衡器,因为该功能在 v1.30 后已默认启用,所以也就不需要其他的配置了。
这次的新版本还引入了跟踪 PersistentVolume 阶段转换时间的新功能,这是通过在 PersistentVolumeStatus 中添加 lastTransitionTime 字段实现的,这个字段记录了 PersistentVolume 每次变更阶段时的时间戳(比如从 Pending 转换成 Bound)。这种信息对测量 PersistentVolume 可供使用的时间非常有价值,可用于监控和提高供应速度。此外,该功能还提供了宝贵的数据,可用于设置 Kubernetes 中存储调配相关的指标和服务等级目标(SLO)。
另一项 Alpha 版的功能是支持与开放容器倡议(OCI)兼容的镜像卷。Kubernetes v1.31 引入了一项实验性功能,允许在 POD 中直接使用 OCI 镜像作为卷,从而让访问容器化数据和模型更加轻松,有助于 AI/ML 工作流程。
云原生技术社区对这项功能分外激动。Kubernetes 子论坛的用户也关注到了 这则公告,一位 Reddit 的用户表示,这项功能“非常酷炫”,并在同一讨论帖中解释了将模型作为镜像的优势所在。Defense Unicors(一个 Medium 网站的发帖团队) 中的 AI 与 Kubernetes 专家们也对使用 OCI 镜像管理和共享 AI 模型表示了欢迎,这种方式会让流程更加顺畅,和其他工具也更加集成。
同样进入到 Beta 版本的功能还有 nftables API,这是 iptables API 的升级版,其性能和可扩展性都有所提高。值得关注的是,nftable 代理模式在处理服务端点变化和数据包方面的效率要比 iptable 高,尤其是在拥有大量服务的集群的情况中。
关于更多详情,用户可加入 Slack 或 Discord 上的 Kubernetes 社区,或者是在 Stack Overflow 上发布问题。Kubernetes v1.31 可于其官网或 GitHub 中下载。
查看英文原文:
https://www.infoq.com/news/2024/09/kubernetes-elli-released/\\"
","description":"Kubernetes 项目最近宣发了代号“Elli”的 1.31 版本,该版本中集成了 45 项增强功能,其中 11 项为稳定版,22 项为 Beta 版,还有 12 项新引入的 Alpha 版功能。本次发布中的主要功能包括利用 AppArmor 增强容器安全性、提高负载均衡器的可靠性、对 PersistentVolume 阶段转换的见解,以及对 OCI 镜像卷的支持。 Kubernetes 发布通信团队中的 Matteo Bianchi、Edith (Edi) Puclla、Rashan Smith 和 Yiğit Demirbaş…","guid":"https://www.infoq.cn/article/Om506pjzFVfzIOOzN6XR","author":"作者:Aditya Kulkarni","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-10-16T01:06:00.476Z","media":null,"categories":["后端"],"attachments":null,"extra":null,"language":null},{"title":"安全专家利用 SQL 注入攻击机场安检漏洞","url":"https://www.infoq.cn/article/IPZgF4jx3wMVv8GNLfTf","content":"在“通过 SQL 注入绕过机场安检”一文中,两名安全研究人员最近展示了他们如何对一项服务执行简单的 SQL 注入攻击,使飞行员和空乘人员能够绕过机场的安检。据研究人员称,这一漏洞能允许他们创建虚拟用户,使他们能够跳过安检,并有可能进入商用客机的驾驶舱。
安全研究人员 Ian Carroll(Seats.aero 的创始人)和 Sam Curry(黑客兼漏洞赏金猎人)在 FlyCASS 中发现了一个漏洞,FlyCASS 是一种第三方基于 Web 的服务,
一些航空公司使用它来管理已知机组人员(Known Crewmember,KCM)计划和驾驶舱访问安全系统(Cockpit Access Security System,CASS)。
KCM 是美国运输安全管理局(Transportation Security Administration,TSA)的一项倡议,允许飞行员和空乘人员绕过安检,而 CASS 则允许飞行员在飞行时使用驾驶舱内的逃生座椅。Carroll 解释说:
就业状况检查是这些流程中最关键的组成部分。如果某人目前不在航空公司工作,那么他们就没有接受过背景调查,就不应该被允许绕过安检或进入驾驶舱。
研究人员在调查管理授权系统的供应商时,发现了 FlyCASS,这是一个为小型航空公司设计的平台,提供基于 Web 界面的网站。Carroll 写道:
有趣的是,我们注意到每家航空公司都有自己的登录页面,例如国际航空运输公司(8C)的登录页面可以在 /ati 上找到。由于只暴露了一个登录页面,我们认为我们已经走到了死胡同。不过,为了确保万无一失,我们在用户名中尝试输入一个单引号作为 SQL 注入测试,并立即收到了 MySQL 错误。
由于用户名被直接插入到了登录 SQL 查询中,研究人员能够以管理员身份登录 FlyCASS。由于 FlyCASS 同时管理其参与的航空公司的 KCM 和 CASS 系统,因此他们可以访问和管理与这些航空公司相关的飞行员和空乘人员名单。此外,他们发现,无需进一步的检查或身份验证即可为航空公司添加新员工。Carroll 写道:
作为航空公司的管理员,我们可以将任何人添加为 KCM 和 CASS 的授权用户。
来源:Carroll 的博客
SQL 注入(SQL Injection)是一种常见的安全漏洞,当攻击者提供的数据作为 SQL 代码执行时,就会引发这种漏洞。在一个很受欢迎的 Reddit 帖子 中,大多数用户讨论后认为这种攻击不太可能发生在现代 Web 应用程序上,其中一位用户 martijnonreddit 写道:
在 2024 年,在如此关键的系统中,会出现可见的基于错误的 SQL 注入?这简直骇人听闻。这值得更多关注。
在 另一个帖子 中,用户 k-mcm 补充道:
在过去的 20 年里,SQL 注入在任何事情上都是有效的,这一事实简直荒谬至极… 你必须竭尽全力才能把这件事搞砸。
Carroll 的文章中有很大一部分是专门讨论披露的挑战的,包括安全研究人员在确定适当的联系点时所面临的困难以及国土安全部(Department of Homeland Security)的反应:
我们在 4 月 23 日向国土安全部披露了这个问题,国土安全部承认了这一问题,并确认他们会“非常认真地对待这个问题”。FlyCASS 随后在 KCM/CASS 中被禁用,后来似乎已经解决了这一问题(…)在问题得到解决后,我们试图协调该问题的安全披露。不幸的是,国土安全部没有与我们合作,而是停止了对我们的回应,美国运输安全管理局(TSA)新闻办公室就这一漏洞发表了危险的错误声明,否认了我们所发现的漏洞。
虽然研究人员声称“美国运输安全管理局(TSA)试图掩盖我们的发现”,但美国运输安全局强调,他们的系统并不完全依赖于这个数据库来验证机组人员的身份。在研究人员的报告发布后,软件工程师兼安全研究员 Alesandro Ortiz 报告称,FlyCASS 似乎在 2 月份遭受了 MedusaLocker 勒索软件攻击,分析结果揭示了加密文件和勒索信。
Rafal Gancarz 是一位经验丰富的技术领导者和专家。他目前正在帮助星巴克打造具有可扩展性、弹性和成本效益的商务平台。此前,Rafal 曾为思科、埃森哲、凯德、ICE、Callsign 等公司设计和构建大规模、分布式和基于云的系统。他的兴趣涵盖了架构与设计、持续交付、可观测性和可操作性,以及软件交付的社会技术和组织方面。
原文链接:
https://www.infoq.com/news/2024/09/sql-injection-airport-security/\\"
","description":"在“通过 SQL 注入绕过机场安检”一文中,两名安全研究人员最近展示了他们如何对一项服务执行简单的 SQL 注入攻击,使飞行员和空乘人员能够绕过机场的安检。据研究人员称,这一漏洞能允许他们创建虚拟用户,使他们能够跳过安检,并有可能进入商用客机的驾驶舱。 安全研究人员 Ian Carroll(Seats.aero 的创始人)和 Sam Curry(黑客兼漏洞赏金猎人)在 FlyCASS 中发现了一个漏洞,FlyCASS 是一种第三方基于 Web 的服务,\\n\\n一些航空公司使用它来管理已知机组人员(Known Crewmember,KCM)计划和驾驶舱访问安全系统…","guid":"https://www.infoq.cn/article/IPZgF4jx3wMVv8GNLfTf","author":"作者:Renato Losio","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-10-12T00:06:00.562Z","media":[{"url":"https://static001.geekbang.org/wechat/images/e8/e8005a95381b9626404b6ccad7649d83.png","type":"photo","width":0,"height":0,"blurhash":""}],"categories":["数据库","安全"],"attachments":null,"extra":null,"language":null},{"title":"vivo 猛练操作系统“内功”,用 Rust 完成全栈自研","url":"https://www.infoq.cn/article/55B4XNOPESS2cTRjs8rr","content":"九月,Sam Altman 发布长文称,超级智能将在数千天内实现,而每个人都将有一个属于自己的 AI 团队。
这一判断呈现出几个关键信息:当下的 AI 能力仍然不是最终形态,但支撑未来 AI 的“内功”,要在未来几年内练好,以迎接超级智能落地。而这套“内功”需要在交互层面做出革新,因为届时将有数个 AI Agent 接入,形式不同于传统的人机交互。
考虑到生成式 AI 的快速发展,安全性也须多加注意,用 Sam Altman 的话说,是“最小化其危害”。
这一判断,实际上与 vivo 最近一年多在操作系统层面的动作不谋而合——vivo 关注“内功层面”的修炼很久了。蓝河内核及蓝河操作系统 2 的发布,在内存安全、智慧交互等方面做足了文章。
对于 2024 VDC 的发布而言,用 Rust 语言完成蓝河内核自研,最为吸引眼球。C/C++ 在内存安全方面的设计,长期以来饱受诟病,而近几年与之相关的安全事件频发,实在是有些骇人。
7 月,CrowdStrike 作为全球最负盛名的安全公司之一,却引发了一场全球性的安全事故——未通过基本 DevOps 流程的代码,被人为地进行全量发布。
此前的 WannaCry、NotPetya 等事件,都是以内存为攻击对象。因为 C 语言不支持原生垃圾回收机制,所以尽管经过了多年的锤炼,还是留下了很多隐患。
反观 Rust,在堆栈保护上更加完善,且不支持操作原始指针,从根儿上绝了许多网络攻击的路。
但是否要因此用 Rust 编写完整的操作系统内核呢?对于 vivo 来说,是的。
一方面,手机厂商自研操作系统,几乎成为大势所趋,使用 Rust 来自研,并没有战略上的分歧,只是具体的技术路线抉择。蓝河操作系统完成全栈自研,几乎是一个信号——没有自研操作系统,也就无法围绕 AI 深度定制智能体验,等于放弃了去往 AI 时代的“船票”。
另一方面,vivo 几乎是最看重 Rust 语言的手机厂商。2023 年年底,vivo 就在开发者大会上官宣成为行业首家用 Rust 编写系统框架的企业,但还没有发布自研操作系统内核。因此在实际的代码中,少不了带着“unsafe”关键字的 Rust 函数(unsafe:绕过 Rust 安全机制禁止的操作)。某种程度上,这更像个研发进度问题——继续使用 Rust 完成内核自研,几乎是必然的。
此外,Rust 在技术社区内,几乎是默认的 C/C++ 上位替代语言。据 InfoQ 此前报道,软件工程师 Alex Gaynor 在社区内强调,“数据已经一再证明,当项目使用内存不安全语言(例如 C 和 C++)时,就会受到大量安全漏洞的困扰。”
而微软 Azure 首席技术官 Mark Russinovich 则直接呼吁开发人员弃用 C 和 C++,转投 Rust 的怀抱。
总结下来,用 Rust 编写底层代码,是在规避现有内核天然的安全隐患时,最为彻底且有效的方式。尽管考虑到资源投入,这事看起来不太轻松。
如果单纯的是开发成本受限,拥抱 Rust 这事儿还没那么难以接受。最让 CTO 们叹气的是,Rust 的人才缺口太大了。
Rust 是新晋的热门语言,本身生态还处于发展早期。此外,Rust 以学习难度高而著称,比如其“享誉”开发者圈的“所有权系统”。望而却步的程序员太多,社区的整体活跃度就较低,参考资料也少,对新人更加不友好。受此影响,一份来自 Rust 中文社区的职位调查报告显示,海外 Rust 招聘,以高级、中级岗位为主,面向初级岗位的招聘相当少见。
VDC 发布会上,vivo 副总裁周围正式宣布,vivo 将对基于 Rust 语言编写的蓝河实时内核进行开源。这意味着国内开发者社区,自此多了一个可参考性更强、更完整的 Rust 项目,是难得学习机会。
vivo 和开放原子开源基金会的合作也很深入,尤其是在赛事上的合作——vivo 自 2023 年起,已经连续两届参加开放原子大赛。
开放原子大赛是由开放原子开源基金会组织举办的开源技术领域专业赛事,2024 年的第二届开放原子大赛,在 2024 开放原子开源生态大会上,由工业和信息化部总经济师、办公厅主任高东升,中国工程院院士倪光南,开放原子开源基金会理事长程晓明,中国石油股份有限公司副总地质师兼勘探开发研究院党委书记李国欣,重庆市经济和信息化委员会党组成员、副主任吴涛,中国科学院软件研究所副所长武延军,以及来自 vivo、华为、腾讯、浪潮、软通动力等共建方代表,共同揭幕。
第二届开放原子大赛特别设置了奖金最高、难度最大的巅峰挑战赛,仅包含两道赛题,而其中之一就是vivo发起的《vivo蓝河操作系统创新赛-C/C++与Rust生态互通工具自动化解决方案》,奖金池高达一百万元。同时,vivo还在2024 VDC大会上宣布了将携手开放原子开源基金会,致力于把蓝河操作系统创新赛打造成为行业内最具含金量和影响力的Rust顶尖赛事(感兴趣的开发者可在文末了解)。
vivo 内功的第二个“修炼重点”,在于智慧交互。
自生成式 AI 爆发,将近两年时间件过去了,像 perplexity 般的应用仍然很稀有,且和现有的智能硬件融合困难,基本谈不上有什么化学反应。
其中一个根本在于,生成式 AI 的能力目前仅在 Web 或 App 端有所体现,极少得到系统级的集成。因此受限于交互形式,没有对产品体验做出根本性变化。
当下市场的大部分产品,尚处于与 AI 智能体交互的早期阶段,需要根据不同的应用场景,唤起不同的终端应用。vivo 在交互上的理念是,保证 AI 的启动享有最高优先级,能够全界面一步调起智能体助手,使之享有全域零层级。在输入实现多层级输入方式,在最终的反馈上,给与用户清晰的所见即所得。
为此,vivo 十分关注基于蓝河操作系统提供服务时,大模型的推理的连续性,也就是所谓模型的记忆力。vivo 在蓝河操作系统中,为此构建了一个独立进程的数据管理服务,集中管理用户各类数据,为感知服务和搜索功能提供数据来源。
这也意味着蓝河操作系统 2 实现了所谓的“全域智能”。
全域智能是个大话题,最早起源于物联网领域,核心是全场景、全平台的实时智能连接。而放到移动设备上,尤其是手机、手表、pad 等设备,还要对 AI 的主动调起和被动调起做区分。
智能终端设备,长期以来,一直向“个人助理”的角色靠拢,比如手机是通信和资讯助理,手环是个人健康助理。但这种靠拢的价值十分有限——人的需求很多时候是藏在水面下的。传统设备没有认知智能,所以无法先用户一步,发现其需求,全部的体验都依赖用户的主动调起,几乎不存在被动调起。
真正意义上的被动调起,在生成式 AI 崛起后成为可能,按时下流行的说法,叫做“意图框架”。“意图框架”的设计目标是先用户一步,发现需求,调起 AI 和一些快应用,服务用户的便捷生活。
可以看出,vivo 的意图框架,关键在于数据输入和多端协同。
蓝河操作系统支持的数据输入是多模态的,包含常见的文字、语音、图片。以及移动设备独有的拖曳、长按等物理操作。输入入口则把智能助手、负一屏、搜索、桌面等模块都包括在内,基本适配了 vivo 目前旗下终端设备的全部场景。
应该说,这套方案未来的想象空间很大,如果能横跨各厂商形成统一的行业标准,可能会井喷式的爆发“Killer APP”。
至于 vivo 自己,则是在手表这一产品上,做了大胆的尝试。
前面无论是安全问题,还是连接问题,回归到本源,实际都是为未来的交互变革做好铺垫。
而率先在手表上发力,多少有些“秀肌肉”的成分在里面。
首先手表的算力弱于手机,对蓝河大模型的预训练质量、模型蒸馏情况,都提出了比较高的要求;此外手表覆盖的场景其实更加丰富,除了日常 APP 的使用,还需要考虑各类运动场景。
本次 vivo 推出了首款搭载蓝河操作系统的手表 vivo WATCH 3 ,在此基础上又推出全新 vivo WATCH GT 系列手表。主打功能就是蓝心小 V 语音助手,以及与 AIGC 相关的各类便携式功能。
蓝心小 V 语音助手可以提供个性化的垂类问答、本地技能、健康百科知识以及智能教练的问答能力。其目的是让用户可以随时随地获取健康方面的知识,也可以对自身的健康数据进行查询和获得更有针对性的健康建议,让智能手表不仅局限于时间和通讯,也兼备了健康管理功能。
在健康管理方面,vivo WATCH 3 集成的 AI 运动教练与手机内集成的版本是联通的,给用户提供私教式的使用体验。它可以监测用户的运动状态,并进行运动计划的个性化定制和指导,使得用户能够更科学、更有效地进行健身锻炼。
AI 运动教练能够为用户量身定制专业的运动计划,根据用户个人的身体情况和健身目标,提供相应的运动课程,并允许用户根据需要创建、调整、查询或退出运动计划。
在运动中,AI 运动教练可以感知用户的身体情况,向用户提供实时的语音指导,并播报专业的运动建议,帮助用户更好地进行运动锻炼。同时,AI 运动教练还可以进行动作要点的讲解,使用户能够更深入地理解如何正确进行运动动作。
如果 AI 运动教练和手表的硬件功能结合度够好,对于几年前流行的健身魔镜类产品,甚至会成为“降维打击”。
至于 AIGC 类的功能,主要是 AI 表盘编辑、AI 速记等。比如用户对说蓝心小 V 说,生成长城表盘,蓝心小 V 就会直接跳转到 AI 表盘工坊,并进行生成。
生成后的 AI 表盘支持编辑能力,保留支持布局调整,更换表盘颜色,增加部件等选项。
而 AI 速记,对于文字类工作者,或经常参加会议的同学而言非常友好。记录后的内容,会自动同步到 OriginOS 的原子笔记中,进行 AI 处理,如润色,简化,总结,或者生成格式化的文案。
无论是内存安全、智慧交互,还是在智能手表上的实践,都意味着 vivo 的护城河之一是落在生态上。英伟达过去 20 余年的成功,给了国内企业太多的启发。
这里的生态,不仅包括以蓝河为基础的国产操作系统开发生态,也包括企业间合作。
对于前者,蓝河操作系统开放了 12 大模块的系统能力,并以两套 API 开放给开发者。此外还提供了蓝河开发套件,包含蓝河 Studio、设计师工具、蓝河 SDK、开发者网站等开发工具。这其中也包含开放智能体平台——让人人可自定义专属智能体应用,系统分发将三方应用、三方服务、快应用和智能体连接在一起,实现服务快速分发和流量变现。尤其是对个人开发者来说,这是个重大利好。
至于后者,蓝河操作系统开放了 Native 开发框架,并从 0 到 1 搭建了基于 canvas 的渲染引擎,实现地图瓦片渲染能力。同时提供了完整的底层系统能力接口,和百度地图一起接入 Native 开发框架,在手表端升级了在线地图导航能力。
在汽车出行方向,蓝河操作系统和多家车企达成合作,包括零跑汽车、比亚迪汽车、宝马汽车、特斯拉汽车等车企都已接入蓝河生态。车企可以基于蓝河操作系统开放的 BlueXlink 互联技术的支持,构建智能控车方案,包含 NFC 控车、蓝牙控车、云控车等方案,更适应未来的购车需求。
随着时间的推移,类似的合作只会越来越多,从前国产操作系统在办公软件、设备驱动等兼容性方面的尴尬,已经成为历史。
对于国内的开发者而言,我们只需耐心等待头部厂商的生态圈,开花结果。
Oracle发布\\"Java编程语言和虚拟机的第23个版本\\",其中包含12个JEP的最终特性集。要了解更多细节,可以阅读InfoQ的这篇新闻报道\\"。
JDK 24的早期访问构建\\"Build 16\\"发布,它是Build 15的升级\\",修复了各种问题。要了解关于这个构建的更多细节,请查看发布说明\\"。
对于JDK 24\\",我们鼓励开发者通过Java Bug数据库\\"报告缺陷。
随着JDK 23的发布\\",Oracle实验室也发布\\"了GraalVM for JDK 23\\"。该版本的新特性包括:实现多个JDK 23 JEP;新增一个标记和压缩(mark and compact)垃圾收集器,用于Serial GC\\"的老年代收集,其主要目标是减少最大内存使用量;新增资源视图,让开发人员可以探索本机镜像中包含的Java资源。要了解关于此版本的更多细节,可以查看发布说明\\",或在YouTube上观看GraalVM for JDK 23发布的视频\\"。InfoQ后续将会带来更详细的新闻报道。
为了与Micronaut 4.6.0保持一致,Oracle实验室还发布\\"了Micronaut Graal开发工具包\\"的4.6.0.1版本。Micronaut开发工具包之前的名字是Graal Cloud Native\\",旨在提供一组精心设计的Micronaut框架模块来简化云应用程序的开发。该版本的新特性包括:与Microsoft Azure集成;供应链安全验证;使用Oracle实验室开发的供应链安全分析工具Macaron\\"进行SLSA(Supply-Chain Levels for Software Artifacts)合规性检查。要了解关于此版本的更多细节,请查看发布说明\\"。
Ivar Grimstad\\"是Eclipse基金会的Jakarta EE开发大使。他在其每周博客Hashtag Jakarta EE\\"中介绍了关于Jakarta EE 11的最新进展\\"和Jakarta EE 12的计划,他写道:
Jakarta EE Platform TCK的重构工作正在进行当中。虽然目前还没有一个最终的日期,但看起来可能可以在11月中下旬的某个时间完成。JakartaOne Livestream\\"大会上可能会有一项重大发布。 Jakarta EE 12的计划草案\\"也正在制定当中。该计划的目标是在2026年上半年发布Jakarta EE 12。值得注意的是,Jakarta EE 12的实现必须在Java 21或Java 25上进行认证,或者同时认证。像这样以两个Java版本为目标,这符合Jakarta EE 9以来的一贯做法。
2024年JakartaOne Livestream大会预计于2024年12月3日举行。
亚马逊发布\\"了Amazon Corretto 23,这是他们提供的OpenJDK 23的一个下游发行版,可以用于Linux、Windows和macOS。开发人员可从这个网站上下载最新版本\\"。
同样,BellSoft也发布\\"了OpenJDK 23的下游发行版Liberica JDK 23。开发人员可以从这个网站上下载最新版本\\"。
伴随着JDK 23和GraalVM的发布,BellSoft还发布\\"了Liberica Native Image Kit\\"的24.1.0版本。该版本包含以下功能增强:新增命令行选项-Os,优化构建过程,缩小本机镜像;改进Serial GC\\",现在对老年代执行压缩垃圾收集,减少了内存消耗。
Azul发布\\"Azul Zing Builds of OpenJDK\\" 24.08,这是他们在Azul Platform Prime\\"中优化过的一个Java运行时,其中包括2024年4月\\"和2024年7月\\"的Oracle关键补丁更新。该版本的其他改进包括:通过实现Java Array类中定义的get()方法提升了性能;Falcon JIT编译器\\"新增一个多级(Multi-Tiering)特性,使它可以根据不同的优化级别调度编译方法,以改进应用程序预热期间的性能。要了解关于此版本的更多细节,请查看发布说明\\"。
对于Spring来说,这是忙碌的一周,因为各个团队交付了许多里程碑版本和点版本,涉及Spring Boot\\"、Spring Cloud Dataflow\\"、Spring Security\\"、Spring Authorization Server\\"、Spring Integration\\"、Spring Modulith\\"、Spring Batch\\"、Spring AMQP\\"和Spring for Apache Pulsar\\"。要了解更多细节,可以查看InfoQ的这篇新闻报道\\"。
Eclipse JNoSQL\\"和Eclipse JNoSQL数据库\\"的1.1.2版本是Jakarta Data和Jakarta NoSQL规范的兼容实现,具有如下改进:升级数据库驱动程序库;提升性能;安全性和兼容性。该版本还提供了Jakarta Data TCK(技术兼容性工具包)。独立软件顾问、操作系统专家兼JNoSQL规范负责人Otávio Santana\\"表示:
这是我们致力于使Jakarta生态系统保持最高标准的兼容性和互操作性的一个重要里程碑。
要了解关于这些版本的更多细节,请查看JNoSQL\\"和JNoSQL数据库\\"的发布说明。
Micronaut基金会推出\\"了一个新的Micronaut模块:Micronaut GraalPy\\"。它以GraalPy\\"项目为基础,是基于GraalVM构建的JVM的Python语言实现。Micronaut基金会计划在即将发布的Micronaut Framework 4.7.0中加入这个新模块。
WildFly\\" 33.0.2是第二个维护版本\\",提供了Bug修复和依赖项升级,以解决如下问题:CVE-2024-8391\\",一个影响Eclipse Vert.x 4.3.0版本到4.5.9版本的漏洞,该漏洞源于gRPC服务器没有限制消息有效负载的最大长度,导致内存过度消耗;CVE-2024-7885\\",这是Undertow\\"中的一个漏洞,其中ProxyProtocolReadListener类的实例在多个请求中重用相同的StringBuilder实例,导致不同的请求可能共享相同的StringBuilder实例,进而导致信息泄漏。
Hibernate Reactive\\" 2.4.1.Final发布\\",提供了依赖项升级和ClassCastException的一个解决方案。该异常发生在试图用Jakarta Persistence注解@EmbeddedId加载多个实体时。该版本与Hibernate ORM 6.6.1.Final和Vert.x SQL Client 4.5.10兼容。要了解关于此版本的更多细节,可以查看发布说明\\"。
作为上周发布的后续版本,Apache Tomcat 11.0.0-M26\\"和9.0.95\\"版本解决了HTTP/2处理中“一旦任何客户端发送一个HTTP/2重置帧,所有客户端都可能中断”的问题。要了解关于这些版本的更多细节,请查看11.0.0-M26\\"和9.0.95\\"版本的发布说明。
Apache Camel\\" 4.8.0发布\\",这是一个长期版本,带来了Bug修复、依赖项升级和一些新特性,包括:在Camel JBang\\"组件中支持Kubernetes Secrets\\"和Hashicorp Vault\\";改进了对Java Path接口的支持,使其用Java File类实例注册的那些转换器来传递消息。要了解关于此版本的更多细节,请查看发布说明\\"。
JHipster\\" 8.7.1发布\\",改进包括:升级Spring Boot 3.3.4、Angular 18.2.4、Vue 3.5.5和ESLint 9.10.0等依赖项;默认启用Docker对Spring Boot的支持。要了解关于此版本的更多细节,请查看发布说明\\"。
JHipster Lite\\" 1.19.0发布\\",提供了Bug修复、依赖项升级和一些新特性,包括:custom-jhlite实例现在会生成处理npm自定义依赖项所需的内容;通过改变JHipsterModule类中定义的text()和regex()方法的行为来改进ElementReplacer接口,使其不总是执行替换;在ReplacementCondition接口中添加辅助方法以简化替换的编写。要了解关于此版本的更多细节,请查看发布说明\\"。
OpenXava\\" 7.4发布\\",提供了一些Bug修复和一些新特性,包括:新增多个注解,@Chart用于将集合的数据显示成图表,@LargeDisplay用大格式显示属性值,@SimpleList用于把集合显示为列表,没有操作、过滤器、分页和排序;在列表、集合和引用方面的多项改进。要了解关于此版本的更多细节,请查看发布说明\\"。
JDKUpdater\\"是一个新的实用程序,旨在使开发人员能够跟踪与OpenJDK和GraalVM构建相关的更新。该工具由Azul首席工程师Gerrit Grunwald\\"于3月中旬推出,14.0.57+78版本解决了与更新CVE相关的问题。要了解关于此版本的更多细节,请查看发布说明\\"。
原文链接:
https://www.infoq.com/news/2024/09/java-news-roundup-sep16-2024/\\"
","description":"JDK 23 Oracle发布\\"Java编程语言和虚拟机的第23个版本\\",其中包含12个JEP的最终特性集。要了解更多细节,可以阅读InfoQ的这篇新闻报道\\"。\\n\\nJDK 24\\n\\nJDK 24的早期访问构建\\"Build 16\\"发布,它是Build 15的升级\\",修复了各种问题。要了解关于这个构建的更多细节,请查看发布说明\\"。\\n\\n \\n\\n对于JDK 24\\",我们鼓励开发者通过Java Bug数据库\\"报告缺陷。\\n\\nGraalVM\\n\\n随着JDK 23的发布\\",Oracle实验室也发布\\"了GraalVM for JDK 23\\"。该版本的新特性包括:实现多个JDK 23 JEP…","guid":"https://www.infoq.cn/article/rWhTrwoxJCRZ8SbOCOdR","author":"Michael Redlich","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-10-10T09:13:50.086Z","media":null,"categories":["编程语言"],"attachments":null,"extra":null,"language":null},{"title":"Uber 持续部署优化:在大型 Monorepos 中自动化微服务","url":"https://www.infoq.cn/article/rfYuMG1heUTVpCF3X9gO","content":"在最近的一篇文章中,优步(Uber)分享了开发团队如何管理微服务的持续部署,以应对使用大型单一代码库(Monorepos)的挑战。
优步的微服务架构由数千个服务组成,需要一个可靠且高效的系统来部署更新、安全补丁和新特性。为了确保这一过程的安全性和及时性,优步采用了持续部署(CD),自动化部署到生产环境中。这对维护代码质量和最大限度地减少交付更改的延迟是至关重要的。然而,随着优步的代码库和服务需求的增长,现有的部署系统面临着与规模、标准化和安全性相关的挑战,尤其是在包含多个微服务的 Monorepos 中。
优步认识到需要一个更加精简且更加自动化的持续部署系统。2022 年,该公司开展了一个重新设计其 CD 流程的项目,旨在为部署微服务创建一个更加统一且更加自动化的解决方案。当时,优步在三个 Monorepos 上管理着大约 4500 个微服务,每周处理 5600 次提交和 7000 次部署。然而,这些服务中只有 7% 是使用 CD 自动部署的,许多部署需要人工干预。这种分散且高度灵活的系统导致了效率低下和安全风险,特别是由于有 100 多个独特的部署模板是没有公司范围内的标准的。
新设计的系统名为 Up CD,旨在提高自动化和安全性。它与优步的内部云平台和可观测性工具紧密集成,确保部署默认遵循标准化和可重复的流程。新系统优先考虑简单性和透明度,特别是在管理 Monorepos 方面。一个关键的改进是通过查看每次提交都会影响哪些服务来优化部署,而不是在每次代码更改时部署所有服务。这减少了不必要的构建,并使工程师更清楚地了解影响其服务的更改。
CD 系统架构
Up 为所有服务引入了统一的提交流,确保每个服务都会经过一系列的部署阶段,每个阶段都有自己的安全检查。检查条件包括时间延迟、部署窗口和服务报警,确保仅在安全的情况下才会触发部署。每个阶段都是独立运行的,在保持安全性的同时,可以灵活地定制部署流程。这种新方法减少了手动错误,并提供了更结构化的部署体验。
Up CD 成功的一个关键部分是其用户友好的界面,该界面使工程师能够直观地查看其服务的提交历史和部署状态。界面折叠了非必要的提交,使跟踪更改和识别潜在问题变得更加容易。工程师还可以看到部署状态的实时更新,使他们能够快速识别哪些提交已部署了,以及部署到了哪些环境中。
提交历史的折叠视图
自推出 Up CD 以来,优步在服务部署自动化方面有了大幅的提升。自动部署的服务比例在一年内从不到 10% 上升到近 70%。尽管部署的频率增加了,但每 1000 次代码更改的生产事故率下降了 50% 以上,这凸显了系统安全管理更频繁部署的能力。然而,部署更改的速度加快,特别是那些影响 monorepos 中共享代码的更改,这带来了新的风险。优步通过在服务层之间交错部署此类更改来解决这些问题,如果优先级较低的服务出现了问题,则停止部署。
使用 monorepos 具有挑战性,其他科技公司也开发了自己的内部工具来改进这一开发流程,比如 TikTok 发布了 Sparo 工具来优化大型 monorepos 的 git 操作性能。
总之,优步改进后的持续部署系统已经成功地实现了大规模的自动化和标准化部署,显著提高了部署微服务的安全性、效率和透明度。通过与现有工具紧密集成并优先考虑自动化,Up CD 使优步能够应对快速的增长,同时最大限度地减少生产事故。
Claudio Masolo 是一名云工程师。闲暇时,他喜欢跑步、阅读和玩老式电子游戏。
原文链接:
https://www.infoq.com/news/2024/09/uber-continuous-feployment/
","description":"在最近的一篇文章中,优步(Uber)分享了开发团队如何管理微服务的持续部署,以应对使用大型单一代码库(Monorepos)的挑战。 优步的微服务架构由数千个服务组成,需要一个可靠且高效的系统来部署更新、安全补丁和新特性。为了确保这一过程的安全性和及时性,优步采用了持续部署(CD),自动化部署到生产环境中。这对维护代码质量和最大限度地减少交付更改的延迟是至关重要的。然而,随着优步的代码库和服务需求的增长,现有的部署系统面临着与规模、标准化和安全性相关的挑战,尤其是在包含多个微服务的 Monorepos 中。\\n\\n优步认识到需要一个更加精简且更加自动化的持续部署系统…","guid":"https://www.infoq.cn/article/rfYuMG1heUTVpCF3X9gO","author":"作者:Claudio Masolo","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-10-09T00:00:00.313Z","media":[{"url":"https://static001.geekbang.org/infoq/94/94ca823a07c0fd1c2c484a5c6d4b603b.webp","type":"photo","width":0,"height":0,"blurhash":""},{"url":"https://static001.geekbang.org/infoq/0b/0b24e449e1deeeaaddf9bfb5a3834f6d.webp","type":"photo","width":0,"height":0,"blurhash":""}],"categories":["编程语言","管理/文化"],"attachments":null,"extra":null,"language":null},{"title":"Figma 从 ECS 迁移到 Kubernetes,以从 CNCF 生态系统中受益并降低成本","url":"https://www.infoq.cn/article/HZ8pdBwcRrvgqM0wI1oH","content":"Figma 在不到 12 个月的时间里将其计算平台 从 AWS ECS 迁移到 Kubernetes(EKS),并做到了对客户影响最小。该公司决定采用 Kubernetes 来运行其容器化工作负载,主要是为了利用 CNCF 所支持的大型生态系统。此外,该举动也是为了节省成本、改善开发人员体验并提高弹性。
在 2023 年初,Figma 转向在容器内运行应用程序服务,并采用弹性容器服务(Elastic Container Service,ECS)作为其容器编排平台。使用 ECS 使公司能够快速推出容器化的工作负载,但从那时起,工程师们在使用 ECS 时遇到了某些局限性的问题,主要表现为缺乏对 StatefulSets、 Helm 图表的支持,或者无法轻松运行诸如 Temporal 之类 OSS 软件。
此外,该公司意识到,它错过了 CNCF 社区为 Kubernetes 提供的广泛功能,包括使用 Keda 或 Karpenter 的高级自动扩缩能力、使用 Istio/Envoy 的服务网格以及许多其他工具和功能。该组织还考虑了为满足其需求而定制 ECS 所需的大量工程工作,以及就业市场上是否有经验丰富的 Kubernetes 工程师。
Kubernetes 迁移时间表(来源:Figma 工程博客)
在决定切换到 Kubernetes(EKS)之后,团队就迁移的范围达成了一致,重点是尽量减少服务所需的更改,以避免延迟和风险。尽管限制了项目的范围,但该公司希望涵盖一些特定的改进,例如简化资源定义以改善开发人员体验,并通过将部署拆分为三个 Kubernetes 集群来提高可靠性,以避免缺陷和操作错误的影响。
Figma 的软件工程经理 Ian VonSeggern 讨论了迁移项目的成本优化目标:
在迁移过程中,我们不想处理太多复杂的成本效益工作,但有一个例外:我们决定从一开始就支持节点自动向外扩展。对于 EC2 上的 ECS 服务,我们只是过度配置了我们的服务,这样我们就有足够的机器能在部署过程中激增。但这个设置是昂贵的,所以我们决定将这个额外的成本优化范围添加到迁移中,因为我们能够以相对较少的工作量来节省大量的资金。我们使用开源 CNCF 项目 Karpenter 根据需求动态扩展和缩减节点。
为了确保项目取得成功,Figma 组建了一个人员配备齐全的团队来推动迁移工作,并与更广泛的组织接触以获得他们的支持。工程师们通过对 Kubernetes 设置进行负载测试以避免意外,使用加权 DNS 条目以实现增量切换机制,并在流程的早期将服务部署到临时 Kubernetes 集群中以解决任何问题,从而为生产部署做好准备。计算平台团队与服务所有者合作,提供了一条黄金之路,并确保了一致性和易维护性。
最初的迁移花了不到 12 个月的时间,在迁移完核心服务后,团队才开始考虑后续活动,比如引入基于 Keda 的自动扩缩能力。此外,根据用户反馈,工程师简化了开发人员工具,使其可以使用三个 Kubernetes 集群和新的细粒度 RBAC 角色。
Rafal Gancarz 是一位经验丰富的技术领导者和专家。他目前正在帮助星巴克打造具有可扩展性、弹性和成本效益的商务平台。此前,Rafal 曾为思科、埃森哲、凯德、ICE、Callsign 等公司设计和构建大规模、分布式和基于云的系统。他的兴趣涵盖了架构与设计、持续交付、可观测性和可操作性,以及软件交付的社会技术和组织方面。
原文链接:
https://www.infoq.com/news/2024/09/figma-ecs-kubernetes-eks/\\"
","description":"Figma 在不到 12 个月的时间里将其计算平台 从 AWS ECS 迁移到 Kubernetes(EKS),并做到了对客户影响最小。该公司决定采用 Kubernetes 来运行其容器化工作负载,主要是为了利用 CNCF 所支持的大型生态系统。此外,该举动也是为了节省成本、改善开发人员体验并提高弹性。 在 2023 年初,Figma 转向在容器内运行应用程序服务,并采用弹性容器服务(Elastic Container Service,ECS)作为其容器编排平台。使用 ECS 使公司能够快速推出容器化的工作负载,但从那时起,工程师们在使用 ECS…","guid":"https://www.infoq.cn/article/HZ8pdBwcRrvgqM0wI1oH","author":"作者:Rafal Gancarz","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-10-08T00:00:00.165Z","media":[{"url":"https://static001.geekbang.org/wechat/images/79/79b221d60cf15865839175c8ef6a03ff.png","type":"photo","width":0,"height":0,"blurhash":""}],"categories":["数据库","技术选型"],"attachments":null,"extra":null,"language":null},{"title":"Cloudflare 引入自动化 SSL/TLS 以保护和简化源服务器连接","url":"https://www.infoq.cn/article/VCOhDQYa1uNLgduoS4Ba","content":"Cloudflare 最近引入了新的自动化 SSL/TLS 设置,以简化供应商与源服务器通信的加密模式。这个特性提供了自动化配置,确保安全性,同时不会有站点停机的风险。
自动化的 SSL/TLS 通过利用 Cloudflare SSL/TLS 推荐系统来强化 Cloudflare 和源服务器之间的加密模式。这个推荐系统会自动执行一系列从 Cloudflare 到自定义源的请求,请求中会带有不同的 SSL/TLS 设置,以确定后端通信是否可以升级到当前配置以外的模式。Cloudflare 的产品经理 Alex Krivit、Cloudflare 软件研究工程师 Suleman Ahmad、Cloudflare 软件工程师 J Evans 和 Cloudflare 系统工程师 Yawar Jamal 解释了该特性的重要性:
确保在源服务器上正确配置证书,并告知 Cloudflare 应该如何与源进行通信,这种方式可能会让人心怀忐忑,因为如果没有正确部署或配置,错误配置可能会导致停机现象的出现。
虽然 Cloudflare 已经提供了各种技术,比如,认证源拉取(Authenticated Origin Pulls)、Cloudflare 通道(Cloudflare Tunnels) 和证书授权,以帮助客户配置与源服务器之间的通信,但这些方案仍然需要在源服务器和 Cloudflare 设置中进行手动配置的更改。
图片来源:Cloudflare 博客
Cloudflare 为与源服务器的 SSL/TLS 连接提供了五个选项,分别是 Off、Flexible、Full、Full(Strict)和 Strict。在 Strict 模式下,从浏览器到 Cloudflare 的所有请求,无论是 HTTP 还是 HTTPS,都将始终通过 HTTPS 连接到源服务器,并验证源服务器的证书。
十年前,Cloudflare 推出了通用 SSL(Universal SSL),并在 2022 年承诺为客户提供“从 Cloudflare 到源服务器最安全的自动化连接”,同时阐明了大规模配置源 SSL 所面临的挑战。该提供商现在承认,推出这一功能所花费的时间比预期的要长。Krivit、Ahmad、Evans 和 Jamal 补充说:
我们花了更多的时间来平衡增强的安全性和无缝的网站功能,尤其是源服务器的安全配置和功能超出了 Cloudflare 直接控制的范围。
由于 Cloudflare 是客户端和客户源服务器之间的中介,因此需要建立两个独立的 TLS 连接:一个是用户浏览器和 Cloudflare 网络之间的连接,另一个是 Cloudflare 网络和源服务器之间的连接。与保护客户端和 Cloudflare 之间的连接不同,管理源服务器的安全功能更具挑战性。在 Hacker News 的一个热门主题中,用户 amluto 发表了这样的评论:
Cloudflare 正在谈论 Cloudflare 通道的安全优势。它们很可能非常安全,但我希望 Cloudflare 能清理一下他们的配置系统,使配置真正与行为相匹配。从 DNS 名称到路由的映射设置不应该称为 DNS,也绝对不应假装成 CNAME。
其他用户讨论了“零信任(Zero Trust)”门户的可用性,并对越来越多的可用选项表示担忧。用户 LinuxBender 补充说:
这会将人工操作从证书源的循环中排除,我可以看到在 Encrypted Client Hello(ECH)在所有设备上得到普遍支持之前,增加一个隐私保护步骤的机会。
该云提供商已经开始向启用 SSL/TLS 推荐系统的客户推出该功能。剩余的免费和专业版客户预计将从 9 月 16 日开始启用,商业和企业级客户也将陆续启用。
查看英文原文:
https://www.infoq.com/news/2024/08/cloudflare-automatic-ssl-origin/\\"
","description":"Cloudflare 最近引入了新的自动化 SSL/TLS 设置,以简化供应商与源服务器通信的加密模式。这个特性提供了自动化配置,确保安全性,同时不会有站点停机的风险。 自动化的 SSL/TLS 通过利用 Cloudflare SSL/TLS 推荐系统来强化 Cloudflare 和源服务器之间的加密模式。这个推荐系统会自动执行一系列从 Cloudflare 到自定义源的请求,请求中会带有不同的 SSL/TLS 设置,以确定后端通信是否可以升级到当前配置以外的模式。Cloudflare 的产品经理 Alex Krivit、Cloudflare…","guid":"https://www.infoq.cn/article/VCOhDQYa1uNLgduoS4Ba","author":"作者:Renato Losio","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-10-07T00:00:00.220Z","media":[{"url":"https://static001.geekbang.org/wechat/images/b0/b06cfd9bbfe0b38889f5d6400d32df22.png","type":"photo","width":0,"height":0,"blurhash":""}],"categories":["框架","编程语言"],"attachments":null,"extra":null,"language":null},{"title":"CockroachDB取消免费Core版本,引社区担忧","url":"https://www.infoq.cn/article/TZMqBaCvr6ruAwdov3Qz","content":"CockroachDB Labs 最近宣布对其分布式 SQL 数据库许可模式进行重大调整,取消了免费的 Core 版本,仅提供 Enterprise 版本。这一转变紧随其从开源许可证的转变之后,引发了社区对单一供应商管理的开源解决方案未来的进一步讨论和关注。
自发布以来,CockroachDB 就提供了两种自托管版本:免费的 Core 版本,专为个人用户和追求可扩展性的初创公司设计;以及为企业级应用量身定制的 Enterprise 版本。Enterprise 版本提供了集群优化、灾难恢复、增强安全和专家支持等高级功能。Cockroach Labs 首席执行官 Spencer Kimball 解释了公司为何决定淘汰 Core 版本:
越来越多的规模化企业在使用 CockroachDB 的功能时,出于成本的考虑,选择了免费的 Core 版本而非 Enterprise 版……随着产品的不断成熟,越来越多的用例可以在生产环境中以最小的运维成本和支持需求顺利运行。
在 LinkedIn 的一个热门讨论帖中,Percona 创始人和开源布道师 Peter Zaitsev 评论道:
随着 CockroachDB 退出开源生态圈,原生分布式开源关系数据库的未来再次受到关注。尽管我们还有 PingCAP 的 TiDB 和 Yugabyte 等选择,但它们均由单一供应商控制,同样面临潜在的许可“变更”风险。我好奇的是否有治理模式类似 PostgreSQL 的分布式关系数据库,能够从根本上降低许可发生变更的风险。
为了满足新项目和已有小型客户的需求,CockroachDB 将引入两种新的许可选项:Enterprise Trial 许可,有效期为 30 天,提供社区支持;以及 Enterprise Free 许可,这是一个免费的、每年可续期的许可,适用于个人开发者、学生、学术研究人员以及年收入低于 1000 万美元的企业。Kimball 补充道:
这一新架构将为用户带来以往仅在自托管企业版许可中才能享有的强大数据库功能。同时,CockroachDB 将继续确保其源代码的可用性。
随着 CockroachDB 将其自托管产品归到单一的企业许可之下,并在多年前就已脱离了开源,社区对其他供应商可能做出许可变更感到担忧。关于是否应该由单一供应商管理“真正的”开源项目的讨论愈发激烈。在 HackerNews 上,Andrew Mutz 写道:
当一个开源项目由风险投资支持的公司运营,最终往往会走向商业化。看来“开源”只是吸引人们注意的诱饵,当投资者追求收益增长时,人们往往会被蒙在鼓里。
PingCAP(作为少数仍坚持开源的分布式数据库公司之一)首席执行官 Max Liu 试图向社区保证,写道:
开源的意义远不止于为项目赢得广泛的关注和开发者的参与,它更是软件世界中构建信任和社区的核心价值。我很荣幸能成为这个社区的一员。我不理解 CockroachDB 为何做出这样的决定,但在我看来,这显然是出于对短期利益的考虑。
CockroachDB 的许可变更将于 11 月正式生效,与 24.3 版本的发布同步进行。届时,CockroachDB Labs 将淘汰 Core 产品,并为自托管用户引入新的企业许可结构。此外,这些变更也将适用于 23.1 及后续版本的补丁。
查看原文链接:
https://www.infoq.com/news/2024/09/cockroachdb-license-concerns/\\"
","description":"CockroachDB Labs 最近宣布对其分布式 SQL 数据库许可模式进行重大调整,取消了免费的 Core 版本,仅提供 Enterprise 版本。这一转变紧随其从开源许可证的转变之后,引发了社区对单一供应商管理的开源解决方案未来的进一步讨论和关注。 自发布以来,CockroachDB 就提供了两种自托管版本:免费的 Core 版本,专为个人用户和追求可扩展性的初创公司设计;以及为企业级应用量身定制的 Enterprise 版本。Enterprise 版本提供了集群优化、灾难恢复、增强安全和专家支持等高级功能。Cockroach Labs…","guid":"https://www.infoq.cn/article/TZMqBaCvr6ruAwdov3Qz","author":"作者:Renato Losio","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-10-04T00:00:00.346Z","media":null,"categories":["业务架构","数据库"],"attachments":null,"extra":null,"language":null},{"title":"【鸿蒙生态学堂】HarmonyOS应用上架","url":"https://www.infoq.cn/article/qUf8YNP73YrduKXUbv6O","content":"点击图片开始学习
课程简介:本课程将指导开发者了解HarmonyOS应用上架的全流程,包括应用的全网发布、分阶段发布和测试发布策略。课程将详细解读上架标准,介绍华为提供的测试工具,帮助开发者进行预审能力检测和隐私托管,确保应用符合上架要求,优化发布流程。
课程标签:全网发布、分阶段发布、测试发布、预审能力、隐私托管
","description":"点击图片开始学习 课程简介:本课程将指导开发者了解HarmonyOS应用上架的全流程,包括应用的全网发布、分阶段发布和测试发布策略。课程将详细解读上架标准,介绍华为提供的测试工具,帮助开发者进行预审能力检测和隐私托管,确保应用符合上架要求,优化发布流程。\\n\\n课程标签:全网发布、分阶段发布、测试发布、预审能力、隐私托管","guid":"https://www.infoq.cn/article/qUf8YNP73YrduKXUbv6O","author":"鸿蒙生态学堂","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-09-30T07:42:15.367Z","media":[{"url":"https://static001.geekbang.org/infoq/8a/8aa9b9d0245f29d66ae4e453358d220e.png","type":"photo","width":1280,"height":720,"blurhash":"L67A[R%40g9b~TxW9vItD#t8t7t7"}],"categories":["华为","AI&大模型","后端"],"attachments":null,"extra":null,"language":null},{"title":"【鸿蒙生态学堂】HarmonyOS应用测试","url":"https://www.infoq.cn/article/B3YDkF7t0FGI8K7HtGQ7","content":"点击图片开始学习
课程简介:本课程专注于HarmonyOS应用测试,旨在帮助开发者掌握应用测试的标准和实践。课程将详细解读HarmonyOS应用测试标准,介绍多种测试工具,包括DevEco Testing,以及如何针对典型场景问题进行有效的测试。通过演示测试工具的使用,本课程将指导开发者如何实施性能测试、兼容性测试、稳定性测试和安全测试,确保应用在HarmonyOS平台上的优质体验。
课程标签:标准解读、测试工具介绍、典型场景问题、测试工具演示
","description":"点击图片开始学习 课程简介:本课程专注于HarmonyOS应用测试,旨在帮助开发者掌握应用测试的标准和实践。课程将详细解读HarmonyOS应用测试标准,介绍多种测试工具,包括DevEco Testing,以及如何针对典型场景问题进行有效的测试。通过演示测试工具的使用,本课程将指导开发者如何实施性能测试、兼容性测试、稳定性测试和安全测试,确保应用在HarmonyOS平台上的优质体验。\\n\\n课程标签:标准解读、测试工具介绍、典型场景问题、测试工具演示","guid":"https://www.infoq.cn/article/B3YDkF7t0FGI8K7HtGQ7","author":"鸿蒙生态学堂","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-09-30T07:40:13.955Z","media":[{"url":"https://static001.geekbang.org/infoq/21/21f0622af35a22f4a2f46e59ab8af78d.png","type":"photo","width":1280,"height":720,"blurhash":"L671Wz$,0g9b~T$~9vIrDht7t7t7"}],"categories":["华为","AI&大模型","后端"],"attachments":null,"extra":null,"language":null},{"title":"【鸿蒙生态学堂】并发能力最佳实践","url":"https://www.infoq.cn/article/Gk6slCPdc126Vq12P8c2","content":"点击图片开始学习
课程简介:本课程将深入探讨HarmonyOS的并发能力,特别是FFRT并发编程模型。您将学习如何设计高效的应用并发架构,识别并解决启动缓慢问题,提高应用的冷启动速度。课程还将涵盖使用HTTP访问网络资源的方法,以及用户首选项的详细介绍,包括如何按需加载优化、并发优化、IPC优化和代码逻辑优化,以提升应用性能和用户体验。
课程标签:应用并发设计、FFRT并发编程模型
","description":"点击图片开始学习 课程简介:本课程将深入探讨HarmonyOS的并发能力,特别是FFRT并发编程模型。您将学习如何设计高效的应用并发架构,识别并解决启动缓慢问题,提高应用的冷启动速度。课程还将涵盖使用HTTP访问网络资源的方法,以及用户首选项的详细介绍,包括如何按需加载优化、并发优化、IPC优化和代码逻辑优化,以提升应用性能和用户体验。\\n\\n课程标签:应用并发设计、FFRT并发编程模型","guid":"https://www.infoq.cn/article/Gk6slCPdc126Vq12P8c2","author":"鸿蒙生态学堂","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-09-30T07:37:25.395Z","media":[{"url":"https://static001.geekbang.org/infoq/a5/a5e384ea65d866b29383fafb06732ff3.png","type":"photo","width":1280,"height":720,"blurhash":"L77nCDxc0ME3~TxWE3Iq4mt8xvt7"}],"categories":["华为","AI&大模型","后端"],"attachments":null,"extra":null,"language":null},{"title":"【鸿蒙生态学堂】ArkUI性能优化、丢帧分析、响应优化","url":"https://www.infoq.cn/article/tORqfSLQV3vO9Kpigv32","content":"点击图片开始学习
课程简介:本课程将深入探讨HarmonyOS的ArkUI框架,提供全面的UI性能优化指南。您将学习到如何通过ArkUI框架进行高效UI开发,并掌握常见的性能优化措施,包括丢帧问题的原理分析和优化技巧。课程将涵盖UI优化、按需加载、并发处理、IPC通信优化以及代码逻辑优化,同时探讨如何提升视觉感知流畅度,确保用户界面既快速又吸引人。
课程标签:ArkUI框架基本介绍、ArkUI常见性能优化措施、丢帧问题原理、并发优化、IPC优化、代码逻辑优化、视觉感知优化
","description":"点击图片开始学习 课程简介:本课程将深入探讨HarmonyOS的ArkUI框架,提供全面的UI性能优化指南。您将学习到如何通过ArkUI框架进行高效UI开发,并掌握常见的性能优化措施,包括丢帧问题的原理分析和优化技巧。课程将涵盖UI优化、按需加载、并发处理、IPC通信优化以及代码逻辑优化,同时探讨如何提升视觉感知流畅度,确保用户界面既快速又吸引人。\\n\\n课程标签:ArkUI框架基本介绍、ArkUI常见性能优化措施、丢帧问题原理、并发优化、IPC优化、代码逻辑优化、视觉感知优化","guid":"https://www.infoq.cn/article/tORqfSLQV3vO9Kpigv32","author":"鸿蒙生态学堂","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-09-30T07:35:37.725Z","media":[{"url":"https://static001.geekbang.org/infoq/6c/6c394a3ccd16ca13d47e2bde9930e6fe.png","type":"photo","width":1280,"height":720,"blurhash":"L88NeUnn4:E3~AxXE3NK9Dxubdog"}],"categories":["华为","AI&大模型","后端"],"attachments":null,"extra":null,"language":null},{"title":"【鸿蒙生态学堂】冷启动优化、合理使用动画、长列表加载性能优化最佳实践","url":"https://www.infoq.cn/article/ibR0aR25obK6gJbOUk2u","content":"点击图片开始学习
课程简介:本课程深入探讨HarmonyOS应用的冷启动优化技巧,从应用冷启动概述到具体实施策略,提供全面的优化方案。课程内容包括合理使用动画提升用户感知流畅度、数据驱动UI更新机制、以及长列表加载性能优化的最佳实践。你将学习到如何通过懒加载、缓存列表项、组件复用和布局优化等技术手段,有效提高冷启动速度,减少用户等待时间,从而打造更流畅、更高效的HarmonyOS应用体验。
课程标签:应用冷启动概述、应用冷启动流程、识别启动缓慢问题、提高冷启动速度、提升动画感知流畅度、提高动画运行流畅度、懒加载、缓存列表项、组件复用、布局优化
","description":"点击图片开始学习 课程简介:本课程深入探讨HarmonyOS应用的冷启动优化技巧,从应用冷启动概述到具体实施策略,提供全面的优化方案。课程内容包括合理使用动画提升用户感知流畅度、数据驱动UI更新机制、以及长列表加载性能优化的最佳实践。你将学习到如何通过懒加载、缓存列表项、组件复用和布局优化等技术手段,有效提高冷启动速度,减少用户等待时间,从而打造更流畅、更高效的HarmonyOS应用体验。\\n\\n课程标签:应用冷启动概述、应用冷启动流程、识别启动缓慢问题、提高冷启动速度、提升动画感知流畅度、提高动画运行流畅度、懒加载、缓存列表项、组件复用、布局优化","guid":"https://www.infoq.cn/article/ibR0aR25obK6gJbOUk2u","author":"鸿蒙生态学堂","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-09-30T07:25:30.703Z","media":[{"url":"https://static001.geekbang.org/infoq/69/690d8feb7bf52fad55af9668d1c2e0d0.png","type":"photo","width":845,"height":475,"blurhash":"LB6[5lxwM{t8xbj?WAoe4mRjt7WA"}],"categories":["华为","AI&大模型","后端"],"attachments":null,"extra":null,"language":null},{"title":"【鸿蒙生态学堂】网络和数据存储","url":"https://www.infoq.cn/article/3YphPsjvJRLj3bJq0OeW","content":"点击图片开始学习
课程简介:本课程深入探讨HarmonyOS中的网络和数据存储管理,特别是使用HTTP协议访问网络资源和用户首选项的详细介绍。您将学习如何在HarmonyOS应用中发起HTTP请求,处理响应数据,以及如何利用用户首选项进行轻量级的数据持久化存储。课程将通过实例演示如何高效地管理应用配置和用户偏好设置。
课程标签:使用HTTP访问网络、用户首选项介绍
","description":"点击图片开始学习 课程简介:本课程深入探讨HarmonyOS中的网络和数据存储管理,特别是使用HTTP协议访问网络资源和用户首选项的详细介绍。您将学习如何在HarmonyOS应用中发起HTTP请求,处理响应数据,以及如何利用用户首选项进行轻量级的数据持久化存储。课程将通过实例演示如何高效地管理应用配置和用户偏好设置。\\n\\n课程标签:使用HTTP访问网络、用户首选项介绍","guid":"https://www.infoq.cn/article/3YphPsjvJRLj3bJq0OeW","author":"鸿蒙生态学堂","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-09-30T07:20:02.307Z","media":[{"url":"https://static001.geekbang.org/infoq/03/0360867e265ad191df5f57a0280da0a0.png","type":"photo","width":1280,"height":720,"blurhash":"L87^+Hxc0ME4~UxVE3M}4mt7xvof"}],"categories":["华为","AI&大模型","后端"],"attachments":null,"extra":null,"language":null},{"title":"【鸿蒙生态学堂】ArkUI开发基础(下)","url":"https://www.infoq.cn/article/MyTWLkCw3X0jOzxWrXe9","content":"点击图片开始学习
课程简介:本课程深入探讨HarmonyOS的ArkUI框架,特别是数据驱动UI更新和组件导航的高级概念。您将学习如何使用ArkWeb技术构建动态网页内容,掌握数据绑定技巧以确保UI与底层数据源同步更新。此外,课程将指导您通过设置组件导航来增强应用的用户体验,实现流畅的页面过渡和有效的用户交互。
课程标签:使用ArkWeb构建页面、数据驱动UI更新、设置组件导航
","description":"点击图片开始学习 课程简介:本课程深入探讨HarmonyOS的ArkUI框架,特别是数据驱动UI更新和组件导航的高级概念。您将学习如何使用ArkWeb技术构建动态网页内容,掌握数据绑定技巧以确保UI与底层数据源同步更新。此外,课程将指导您通过设置组件导航来增强应用的用户体验,实现流畅的页面过渡和有效的用户交互。\\n\\n课程标签:使用ArkWeb构建页面、数据驱动UI更新、设置组件导航","guid":"https://www.infoq.cn/article/MyTWLkCw3X0jOzxWrXe9","author":"鸿蒙生态学堂","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-09-30T07:16:49.475Z","media":[{"url":"https://static001.geekbang.org/infoq/c0/c0581545100841fd18bc37b1fc91337a.png","type":"photo","width":1280,"height":720,"blurhash":"L67n96ss0f9c~TxBE5I@4m%Mogof"}],"categories":["华为","AI&大模型","后端"],"attachments":null,"extra":null,"language":null},{"title":"【鸿蒙生态学堂】ArkUI开发基础(上)","url":"https://www.infoq.cn/article/WHbR2WJYF838obHYXLyh","content":"点击图片开始学习
课程简介:本课程将介绍HarmonyOS的ArkUI框架,包括其基础语法和如何使用常用组件构建页面。ArkUI是HarmonyOS应用的UI开发框架,提供简洁的UI语法、丰富的组件和实时界面预览工具。您将学习到ArkUI的关键特性,如极简的UI信息语法、丰富的内置UI组件、多维度的状态管理机制,以及如何支持多设备开发
。通过课程,您将能够掌握使用ArkUI框架进行高效UI开发的技能。
课程标签:ArkUI(方舟UI框架)介绍、使用常用组件构建页面
","description":"点击图片开始学习 课程简介:本课程将介绍HarmonyOS的ArkUI框架,包括其基础语法和如何使用常用组件构建页面。ArkUI是HarmonyOS应用的UI开发框架,提供简洁的UI语法、丰富的组件和实时界面预览工具。您将学习到ArkUI的关键特性,如极简的UI信息语法、丰富的内置UI组件、多维度的状态管理机制,以及如何支持多设备开发\\n\\n。通过课程,您将能够掌握使用ArkUI框架进行高效UI开发的技能。\\n\\n课程标签:ArkUI(方舟UI框架)介绍、使用常用组件构建页面","guid":"https://www.infoq.cn/article/WHbR2WJYF838obHYXLyh","author":"鸿蒙生态学堂","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-09-30T07:05:25.862Z","media":[{"url":"https://static001.geekbang.org/infoq/96/96a0dde74dbf275f70e0b75ad8450384.png","type":"photo","width":1280,"height":720,"blurhash":"L77dkWnn57E5~AxWE4Iq9D%MkDof"}],"categories":["华为","AI&大模型","后端"],"attachments":null,"extra":null,"language":null},{"title":"【鸿蒙生态学堂】应用程序框架基础","url":"https://www.infoq.cn/article/4XT0Gfx8l9zTBUDJSuBS","content":"点击图片开始学习
课程简介:本课程将带领开发者深入了解HarmonyOS的应用程序框架基础,重点探讨UIAbility组件的工作原理和生命周期管理。通过学习,开发者将能够掌握如何在HarmonyOS中创建和使用UIAbility组件,包括其启动模式和窗口管理。同时,课程还将介绍DevEco Studio工具的使用,它是专为HarmonyOS应用开发设计的IDE,支持代码编写、调试和应用构建等功能,助力开发者高效开发HarmonyOS应用。
课程标签:应用程序框架基础、UIAbility组件概述
","description":"点击图片开始学习 课程简介:本课程将带领开发者深入了解HarmonyOS的应用程序框架基础,重点探讨UIAbility组件的工作原理和生命周期管理。通过学习,开发者将能够掌握如何在HarmonyOS中创建和使用UIAbility组件,包括其启动模式和窗口管理。同时,课程还将介绍DevEco Studio工具的使用,它是专为HarmonyOS应用开发设计的IDE,支持代码编写、调试和应用构建等功能,助力开发者高效开发HarmonyOS应用。\\n\\n课程标签:应用程序框架基础、UIAbility组件概述","guid":"https://www.infoq.cn/article/4XT0Gfx8l9zTBUDJSuBS","author":"鸿蒙生态学堂","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-09-30T06:59:33.674Z","media":[{"url":"https://static001.geekbang.org/infoq/28/2869c81a9b66ff42426be19b52c85b08.png","type":"photo","width":1280,"height":720,"blurhash":"L87-Khs=0MIX~AxWE3M}4mt8xvof"}],"categories":["华为","AI&大模型","后端"],"attachments":null,"extra":null,"language":null},{"title":"【鸿蒙生态学堂】ArkTS语法介绍","url":"https://www.infoq.cn/article/OrSuYA1QfKR6yyy7Pva6","content":"点击图片开始学习
课程简介:本课程将深入介绍HarmonyOS的应用开发语言——ArkTS。您将学习到ArkTS的基本语法,包括变量声明、类型系统、运算符等,以及如何使用ArkTS进行声明式UI开发。课程还将展示如何利用DevEco Studio这一强大的集成开发环境,进行代码编写、调试和应用构建,帮助您快速上手HarmonyOS应用开发。
课程标签:ArkTS基础语法、声明式UI语法
","description":"点击图片开始学习 课程简介:本课程将深入介绍HarmonyOS的应用开发语言——ArkTS。您将学习到ArkTS的基本语法,包括变量声明、类型系统、运算符等,以及如何使用ArkTS进行声明式UI开发。课程还将展示如何利用DevEco Studio这一强大的集成开发环境,进行代码编写、调试和应用构建,帮助您快速上手HarmonyOS应用开发。\\n\\n课程标签:ArkTS基础语法、声明式UI语法","guid":"https://www.infoq.cn/article/OrSuYA1QfKR6yyy7Pva6","author":"鸿蒙生态学堂","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-09-30T06:59:13.595Z","media":[{"url":"https://static001.geekbang.org/infoq/f6/f61766298b7fc02425ba371bf967f244.png","type":"photo","width":1280,"height":720,"blurhash":"L77Kc1xc4;It~TxVE3NJ9Et8t8j["}],"categories":["华为","AI&大模型","后端"],"attachments":null,"extra":null,"language":null},{"title":"【鸿蒙生态学堂】HarmonyOS介绍","url":"https://www.infoq.cn/article/RfXt52pwFiBuPYdxTKeO","content":"点击图片开始学习
课程简介:本课程将带您快速了解HarmonyOS,深入探讨HarmonyOS的核心特性,包括其分布式架构和跨设备能力。课程还将介绍华为提供的赋能套件,帮助开发者高效开发应用。最后,您将掌握DevEco Studio,HarmonyOS官方集成开发环境,用于构建、调试和部署应用。无论您是初学者还是有经验的开发者,本课程都将为您提供必要的工具和知识,让您在HarmonyOS平台上大展宏图。
课程标签:HarmonyOS简介、赋能套件和学习资源介绍、DevEco Studio的使用
","description":"点击图片开始学习 课程简介:本课程将带您快速了解HarmonyOS,深入探讨HarmonyOS的核心特性,包括其分布式架构和跨设备能力。课程还将介绍华为提供的赋能套件,帮助开发者高效开发应用。最后,您将掌握DevEco Studio,HarmonyOS官方集成开发环境,用于构建、调试和部署应用。无论您是初学者还是有经验的开发者,本课程都将为您提供必要的工具和知识,让您在HarmonyOS平台上大展宏图。\\n\\n课程标签:HarmonyOS简介、赋能套件和学习资源介绍、DevEco Studio的使用","guid":"https://www.infoq.cn/article/RfXt52pwFiBuPYdxTKeO","author":"鸿蒙生态学堂","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-09-30T06:53:34.616Z","media":[{"url":"https://static001.geekbang.org/infoq/d3/d3692253bc6573c8d4025458a49f9632.png","type":"photo","width":1280,"height":720,"blurhash":"L67A_Z$,0ME4~9%09wIqD#t7t8og"}],"categories":["华为","AI&大模型","后端"],"attachments":null,"extra":null,"language":null},{"title":"Swift 可组合架构为 iOS 应用开发带来Redux模型","url":"https://www.infoq.cn/article/CXH97oyzE1YGouWU45gx","content":"可组合架构(TCA,最近发布了 1.13 版本)是一个“符合人体工程学”的 Swift 库。它提供了一个通用框架用于解决构建应用程序时经常遇到的问题,包括状态管理、特性组合、副作用管理和测试。
可组合架构基于几个关键的概念,包括 state(状态)、action(动作)、reducer 和 store(存储)。Reducer 和 store 这两个概念,使用 Redux 的 React 程序员应该都熟悉,但对于原生 iOS 开发来说,它们却是两个非常新颖的设计。按照库的创建者 Brandon Williams 和 Stephen Celis 的说法,这种方法可以将大而复杂的特性分解成多个更小的部分然后组合在一起。
据库的创建者介绍,虽然可组合架构可以与 UIKit 和 Swift 一起使用,但它的设计很大程度上是受了 SwiftUI 的启发,并且对它是个很好的补充。因此,对于熟悉 SwiftUI 及其模式的开发人员来说,这个库特别符合人体工程学。
特别地,TCA 提供了一个@ObservableState宏,它的工作方式类似于 iOS 16 的@Observable,并且可以像 SwiftUI 一样检测任何的状态变化。TCA 还借用了 SwiftUI 的方法来实现可组合性,其中每个特性都是一个提供body属性的类型,并且会模拟 SwiftUI @Environment属性封装器的行为,进而使用@Dependency属性封装器来处理依赖规范。
下面的代码片段展示了如何为一个简单的加减计数器特性建模:
@Reducer\\nstruct Feature {\\n @ObservableState\\n struct State: Equatable {\\n var count = 0\\n var numberFact: String?\\n }\\n enum Action {\\n case decrementButtonTapped\\n case incrementButtonTapped\\n case numberFactButtonTapped\\n case numberFactResponse(String)\\n }\\n\\n\\n var body: some Reducer {\\n Reduce { state, action in\\n switch action {\\n // 在这里实现所有的动作;\\n // 它们会修改状态或产生副作用\\n }\\n }\\n }\\n}\\n
如上所示,App 的状态和供用户使用的动作都是使用特定的类型进行建模的,而body方法负责更新每个动作的状态。
TCA 的一个关键方面是状态共享,它是通过宏@Shared实现的。可以看到,它的工作原理类似于 SwiftUI @Binding,公开一个publisher属性,使其可以检测应用程序任何部分对引用做的更改。@Shared属性封装器还支持将数据持久化到内存、用户默认设置、通用文件或使用自定义机制。
在很大程度上,TCA 依赖于 SwiftUI 中常用的 UI 元素,比如sheet(item:)、popover(item:)和NavigationStack,但它自己也提供了更适合于状态驱动应用的导航机制。该库主要支持两种导航模式:基于树的导航和基于栈的导航。
库的作者承认,采用一个库作为应用程序架构的基础可能是一个相当具有挑战性的决定,但在某些情况下,那可能是最好的方法,而不是试图从头开始重新实现所有内容:
如果一个库的核心原则与你构建应用程序时优先考虑的事项一致,那么采用这个库可能就是一个明智的选择。最好是将一组定义良好的工具与连贯的维护历史和强大的社区结合在一起,而不是将分散在互联网博文中的许多“建议和技巧”粘合在一起。
Swift 可组合架构可以 从 GitHub 克隆或从 Swift Package Index 安装。它在 GitHub 上拥有超过 12000 颗星和 1400 个分支,以及 200 多位贡献者,这使它成为 Swift Package Index 上最受欢迎的 Swift 架构库。
原文链接:
https://www.infoq.com/news/2024/08/swift-composable-architecture/\\"
","description":"可组合架构(TCA,最近发布了 1.13 版本)是一个“符合人体工程学”的 Swift 库。它提供了一个通用框架用于解决构建应用程序时经常遇到的问题,包括状态管理、特性组合、副作用管理和测试。 可组合架构基于几个关键的概念,包括 state(状态)、action(动作)、reducer 和 store(存储)。Reducer 和 store 这两个概念,使用 Redux 的 React 程序员应该都熟悉,但对于原生 iOS 开发来说,它们却是两个非常新颖的设计。按照库的创建者 Brandon Williams 和 Stephen Celis 的说法…","guid":"https://www.infoq.cn/article/CXH97oyzE1YGouWU45gx","author":"作者:Sergio De Simone","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-09-30T00:00:00.749Z","media":null,"categories":["后端","Android/iOS"],"attachments":null,"extra":null,"language":null},{"title":"鸿蒙生态学堂合集来啦,从0到1玩转鸿蒙应用开发!","url":"https://www.infoq.cn/article/JYJVOBv8kiUCQNg1vVgU","content":"#鸿蒙实践 #鸿蒙实训 #鸿蒙学习 #鸿蒙资料 #Harmony#HarmonyOS#HarmonyOS 生态
#HarmonyOS 学习 #HarmonyOS 生态课堂 #HarmonyOS Next#HarmonyOS 5.0#HarmonyOS 课程 #HarmonyOS 实战 #HarmonyOS 开发 #HarmonyOS 实践 #HarmonyOS 实训 #HarmonyOS 学习 #HarmonyOS 资料
鸿蒙生态学堂1-11全视频合集大放送,从语法学习到应用搭建,一站式学会鸿蒙应用开发!
点击以下课程图片开启鸿蒙学习之旅~
点击图片开始学习
课程简介:本课程将带您快速了解HarmonyOS,深入探讨HarmonyOS的核心特性,包括其分布式架构和跨设备能力。课程还将介绍华为提供的赋能套件,帮助开发者高效开发应用。最后,您将掌握DevEco Studio,HarmonyOS官方集成开发环境,用于构建、调试和部署应用。无论您是初学者还是有经验的开发者,本课程都将为您提供必要的工具和知识,让您在HarmonyOS平台上大展宏图。
课程标签:HarmonyOS简介、赋能套件和学习资源介绍、DevEco Studio的使用
点击图片开始学习
课程简介:本课程将深入介绍HarmonyOS的应用开发语言——ArkTS。您将学习到ArkTS的基本语法,包括变量声明、类型系统、运算符等,以及如何使用ArkTS进行声明式UI开发。课程还将展示如何利用DevEco Studio这一强大的集成开发环境,进行代码编写、调试和应用构建,帮助您快速上手HarmonyOS应用开发。
课程标签:ArkTS基础语法、声明式UI语法
点击图片开始学习
课程简介:本课程将带领开发者深入了解HarmonyOS的应用程序框架基础,重点探讨UIAbility组件的工作原理和生命周期管理。通过学习,开发者将能够掌握如何在HarmonyOS中创建和使用UIAbility组件,包括其启动模式和窗口管理。同时,课程还将介绍DevEco Studio工具的使用,它是专为HarmonyOS应用开发设计的IDE,支持代码编写、调试和应用构建等功能,助力开发者高效开发HarmonyOS应用。
课程标签:应用程序框架基础、UIAbility组件概述
点击图片开始学习
课程简介:本课程将介绍HarmonyOS的ArkUI框架,包括其基础语法和如何使用常用组件构建页面。ArkUI是HarmonyOS应用的UI开发框架,提供简洁的UI语法、丰富的组件和实时界面预览工具。您将学习到ArkUI的关键特性,如极简的UI信息语法、丰富的内置UI组件、多维度的状态管理机制,以及如何支持多设备开发
。通过课程,您将能够掌握使用ArkUI框架进行高效UI开发的技能。
课程标签:ArkUI(方舟UI框架)介绍、使用常用组件构建页面
点击图片开始学习
课程简介:本课程深入探讨HarmonyOS的ArkUI框架,特别是数据驱动UI更新和组件导航的高级概念。您将学习如何使用ArkWeb技术构建动态网页内容,掌握数据绑定技巧以确保UI与底层数据源同步更新。此外,课程将指导您通过设置组件导航来增强应用的用户体验,实现流畅的页面过渡和有效的用户交互。
课程标签:使用ArkWeb构建页面、数据驱动UI更新、设置组件导航
点击图片开始学习
课程简介:本课程深入探讨HarmonyOS中的网络和数据存储管理,特别是使用HTTP协议访问网络资源和用户首选项的详细介绍。您将学习如何在HarmonyOS应用中发起HTTP请求,处理响应数据,以及如何利用用户首选项进行轻量级的数据持久化存储。课程将通过实例演示如何高效地管理应用配置和用户偏好设置。
课程标签:使用HTTP访问网络、用户首选项介绍
点击图片开始学习
课程简介:本课程深入探讨HarmonyOS应用的冷启动优化技巧,从应用冷启动概述到具体实施策略,提供全面的优化方案。课程内容包括合理使用动画提升用户感知流畅度、数据驱动UI更新机制、以及长列表加载性能优化的最佳实践。你将学习到如何通过懒加载、缓存列表项、组件复用和布局优化等技术手段,有效提高冷启动速度,减少用户等待时间,从而打造更流畅、更高效的HarmonyOS应用体验。
课程标签:应用冷启动概述、应用冷启动流程、识别启动缓慢问题、提高冷启动速度、提升动画感知流畅度、提高动画运行流畅度、懒加载、缓存列表项、组件复用、布局优化
点击图片开始学习
课程简介:本课程将深入探讨HarmonyOS的ArkUI框架,提供全面的UI性能优化指南。您将学习到如何通过ArkUI框架进行高效UI开发,并掌握常见的性能优化措施,包括丢帧问题的原理分析和优化技巧。课程将涵盖UI优化、按需加载、并发处理、IPC通信优化以及代码逻辑优化,同时探讨如何提升视觉感知流畅度,确保用户界面既快速又吸引人。
课程标签:ArkUI框架基本介绍、ArkUI常见性能优化措施、丢帧问题原理、并发优化、IPC优化、代码逻辑优化、视觉感知优化
点击图片开始学习
课程简介:本课程将深入探讨HarmonyOS的并发能力,特别是FFRT并发编程模型。您将学习如何设计高效的应用并发架构,识别并解决启动缓慢问题,提高应用的冷启动速度。课程还将涵盖使用HTTP访问网络资源的方法,以及用户首选项的详细介绍,包括如何按需加载优化、并发优化、IPC优化和代码逻辑优化,以提升应用性能和用户体验。
课程标签:应用并发设计、FFRT并发编程模型
点击图片开始学习
课程简介:本课程专注于HarmonyOS应用测试,旨在帮助开发者掌握应用测试的标准和实践。课程将详细解读HarmonyOS应用测试标准,介绍多种测试工具,包括DevEco Testing,以及如何针对典型场景问题进行有效的测试。通过演示测试工具的使用,本课程将指导开发者如何实施性能测试、兼容性测试、稳定性测试和安全测试,确保应用在HarmonyOS平台上的优质体验。
课程标签:标准解读、测试工具介绍、典型场景问题、测试工具演示
点击图片开始学习
课程简介:本课程将指导开发者了解HarmonyOS应用上架的全流程,包括应用的全网发布、分阶段发布和测试发布策略。课程将详细解读上架标准,介绍华为提供的测试工具,帮助开发者进行预审能力检测和隐私托管,确保应用符合上架要求,优化发布流程。
课程标签:全网发布、分阶段发布、测试发布、预审能力、隐私托管
","description":"#鸿蒙实践 #鸿蒙实训 #鸿蒙学习 #鸿蒙资料 #Harmony#HarmonyOS#HarmonyOS 生态 #HarmonyOS 学习 #HarmonyOS 生态课堂 #HarmonyOS Next#HarmonyOS 5.0#HarmonyOS 课程 #HarmonyOS 实战 #HarmonyOS 开发 #HarmonyOS 实践 #HarmonyOS 实训 #HarmonyOS 学习 #HarmonyOS 资料\\n\\n鸿蒙生态学堂1-11全视频合集大放送,从语法学习到应用搭建,一站式学会鸿蒙应用开发!\\n\\n点击以下课程图片开启鸿蒙学习之旅~\\n\\n1、【鸿蒙生态学堂…","guid":"https://www.infoq.cn/article/JYJVOBv8kiUCQNg1vVgU","author":"鸿蒙生态学堂","authorUrl":null,"authorAvatar":null,"publishedAt":"2024-09-29T08:21:09.167Z","media":[{"url":"https://static001.geekbang.org/infoq/d3/d3692253bc6573c8d4025458a49f9632.png","type":"photo","width":1280,"height":720,"blurhash":"L67A_Z$,0ME4~9%09wIqD#t7t8og"},{"url":"https://static001.geekbang.org/infoq/f6/f61766298b7fc02425ba371bf967f244.png","type":"photo","width":1280,"height":720,"blurhash":"L77Kc1xc4;It~TxVE3NJ9Et8t8j["},{"url":"https://static001.geekbang.org/infoq/28/2869c81a9b66ff42426be19b52c85b08.png","type":"photo","width":1280,"height":720,"blurhash":"L87-Khs=0MIX~AxWE3M}4mt8xvof"},{"url":"https://static001.geekbang.org/infoq/96/96a0dde74dbf275f70e0b75ad8450384.png","type":"photo","width":1280,"height":720,"blurhash":"L77dkWnn57E5~AxWE4Iq9D%MkDof"},{"url":"https://static001.geekbang.org/infoq/c0/c0581545100841fd18bc37b1fc91337a.png","type":"photo","width":1280,"height":720,"blurhash":"L67n96ss0f9c~TxBE5I@4m%Mogof"},{"url":"https://static001.geekbang.org/infoq/03/0360867e265ad191df5f57a0280da0a0.png","type":"photo","width":1280,"height":720,"blurhash":"L87^+Hxc0ME4~UxVE3M}4mt7xvof"},{"url":"https://static001.geekbang.org/infoq/69/690d8feb7bf52fad55af9668d1c2e0d0.png","type":"photo","width":845,"height":475,"blurhash":"LB6[5lxwM{t8xbj?WAoe4mRjt7WA"},{"url":"https://static001.geekbang.org/infoq/6c/6c394a3ccd16ca13d47e2bde9930e6fe.png","type":"photo","width":1280,"height":720,"blurhash":"L88NeUnn4:E3~AxXE3NK9Dxubdog"},{"url":"https://static001.geekbang.org/infoq/a5/a5e384ea65d866b29383fafb06732ff3.png","type":"photo","width":1280,"height":720,"blurhash":"L77nCDxc0ME3~TxWE3Iq4mt8xvt7"},{"url":"https://static001.geekbang.org/infoq/21/21f0622af35a22f4a2f46e59ab8af78d.png","type":"photo","width":1280,"height":720,"blurhash":"L671Wz$,0g9b~T$~9vIrDht7t7t7"},{"url":"https://static001.geekbang.org/infoq/8a/8aa9b9d0245f29d66ae4e453358d220e.png","type":"photo","width":1280,"height":720,"blurhash":"L67A[R%40g9b~TxW9vItD#t8t7t7"}],"categories":["华为","后端"],"attachments":null,"extra":null,"language":null}],"readCount":46788,"subscriptionCount":57,"analytics":{"feedId":"72893695848375296","updatesPerWeek":11,"subscriptionCount":57,"latestEntryPublishedAt":null,"view":0}}')