Construct公司 从 0 到 1 基于 Kitex+Istio 的微服务系统建设

本文根据 2024 年 5 月 25 日在上海举办的“云原生✖️AI 时代的微服务架构与技术实践”CloudWeGo 技术沙龙上海站活动中,Construct 服务端总监 Jason 的演讲《从 0 到 1 基于 Kitex + Istio 的微服务系统建设》整理而来。

在微服务架构的浪潮中,企业面临着从单体应用到分布式系统的转型挑战。本文以 Construct 公司为例,探讨其如何利用 CloudWeGo 框架和 Istio 服务网格,从零开始构建起一个高效、稳定的微服务系统。

关于 Construct

Construct Tech(肯斯爪特),成立于 2019 年,目前旗下 Litmatch 等产品,已覆盖海外十几个国家,并处于各国社交榜前 10 的位置,每月数千万用户使用。

一、从 0 到 1 的微服务系统建设

  1. 服务端架构的演进

服务端架构的演进反映了互联网业务从简单到复杂的发展需求。Construct 公司见证了从单体架构,再到微服务架构的服务注册与发现机制,最终到服务网格(Service Mesh)的演进。

在互联网的早期阶段,应用相对简单,许多人可能还记得那个时代——个人站长主导的时期。那时的系统架构具有一种烟囱式结构,这种结构从上至下垂直延伸,简单直观,易于理解和使用。数据共享主要通过底层数据库实现。

随着业务需求的增长和互联网的快速发展,传统的烟囱式架构开始显得力不从心。为了解决这个问题,SOA 架构(Service Oriented Architecture)应运而生。SOA 引入了抽象层,以促进服务的更好复用,核心围绕着服务的解耦和服务总线的概念。服务总线作为通信的中介,使得服务调用方和服务提供方能够相互独立。然而,随着业务量的激增,服务总线逐渐成为系统的性能瓶颈。例如,当每秒查询率(QPS)飙升,用户数量大幅增长时,服务总线的任何故障都可能导致整个服务系统的瘫痪,这无疑是一场噩梦。

为了应对这一挑战,微服务架构应运而生。它进一步细化了服务的拆分,摒弃了中心化服务总线的概念,转而采用服务注册和发现机制来管理服务间的调用。这样,服务提供者和消费者可以通过注册中心相互发现并建立联系,有效解决了依赖问题。

在微服务架构的基础上,进一步发展出了服务网格(Service Mesh)架构,例如基于 Istio 的实现。服务网格进一步抽象了服务间的通信、注册和依赖关系,实现了语言无关性,使得不同编程语言编写的服务能够在同一架构下无缝交互和通信。这种解耦合的方法为多语言环境下的企业提供了更大的灵活性和扩展性。

  1. 背景、约束与技术选型

作为一家拥有多款海外社交产品的公司,Construct 公司需要处理数千万月活用户的数据。面对业务的全球化和复杂化,公司决定采用微服务架构来提升系统的灵活性和可维护性。

今天,我们主要讨论的是我们公司从单体架构向服务网格(Service Mesh)架构的转型,这一转型是基于 Istio 实现的。接下来,我将分享我们转型时面临的背景和约束条件。

在我们着手构建新的微服务架构之前,公司已经拥有了一个基于 Python 的成熟单体架构。面对这一现实,我们需要解决的一个关键问题是如何确保新系统与现有系统的无缝交互和兼容性。这不仅是一个技术挑战,更是我们必须达成的硬性目标。通过深入分析,我们决定采用单向依赖的方法来简化集成过程。在接下来的架构演示中,我将详细阐述这一点。

接下来是我们的技术选型问题。面对众多的微服务框架,我们经过深思熟虑,最终将选择范围缩小到了两种:广泛使用的 gRPC 和新兴的 Kitex。尽管 gRPC 因其流行度和长时间的市场验证而备受关注,但我们最终选择了 Kitex。这一决策基于几个核心因素:Kitex 的易用性高性能,尤其是在高并发环境下的出色表现。我们的基准测试显示,Kitex 的 QPS 是 gRPC 的两倍,而且在延迟方面表现更为优异。这些优势使得 Kitex 成为了我们的首选。

此外,考虑到我们需要构建的是基于服务网格的系统,我们必须确保所选技术能够与 Istio 兼容。当时,尽管缺乏现成的集成示例,并且我们是较早采用 Kitex 的公司之一,我们依然决定迎难而上。在 CloudWeGo 社区的大力支持下,我们不仅理解了 Kitex 与 Istio 集成的深层逻辑,还成功地将它们整合在一起。

我们通过逻辑分析和实践探索,证明了即使在当时没有示例的情况下,通过深入理解技术原理和逻辑,依然可以成功实现技术集成。我们选择的是 Kitex 的 gRPC 协议,因为它提供了高效的通信机制,并且与 Istio 有着良好的互操作性。

在集成过程中,我们遇到了一些关键技术点和挑战。在服务器端,我们特别关注了协议和命名的定义,因为 Istio 系统会基于这些定义进行操作约束。在客户端,我们明确定义了传输协议为 gRPC。通过与 CloudWeGo 社区的紧密互动和迭代,我们逐步解决了遇到的各种具体问题。

  1. 架构设计细节

这里是我们最终确定的整体架构图。我们可以从顶部开始,逐步追踪用户的流量请求是如何被处理的。首先,流量会通过一个名为 ALB Ingress 的负载均衡器进入,这是我们的入口点。随后,流量将进入 Istio 管理的服务网格系统。在服务网格的第一层,我们可以将其抽象为一个 Web Service 层,它类似于我们之前提到的一些框架,比如 Express 框架。接下来是我们的 Kitex RPC 服务层,这里主要部署了核心的内部服务,以及一些可复用的服务。这些服务被集中在 Kitex 的 RPC 层。

继续深入,我们可能会涉及到一些定时任务,这在微服务系统中是非常常见的。例如,CronJob 系统允许我们以 Kitex 客户端的形式去调用 Kitex 服务端,以处理周期性任务。

我们的系统从旧的 Python 单体应用迁移而来,在这个过程中,我们将其抽象为一个简单的 Web Server 依赖。在进行系统迁移时,我们必须解决新旧系统之间的调用问题。为此,我们设定了一个规则:只允许微服务单向调用旧的 Python Web Server。这样做的原因有两个:首先,简化了系统间的交互,减少了复杂性,从而避免了潜在的问题;其次,由于大多数情况下两套系统需要共存,我们需要确保线上流量能够在两个系统中顺畅流通。

对于新服务的开发,我们优先采用新的技术栈,比如使用 Go 语言的框架。这意味着从逻辑层面上,我们的 Go 服务器实际上是依赖于 Python 的。当然,也存在 Python 需要调用 Go 服务器的情况。这种情况下,我们可以将其视为一个迁移的机会,将 Python 服务迁移到 Go,从而促进整个系统向新技术栈的迭代。

二、可复用性与自动化流程

基于 CloudWeGo,Construct 公司建立了一套参考实现和公共库,包括日志记录、监控指标、ID 生成等通用功能,以及特定业务逻辑的封装,极大提升了代码的复用性。Construct 公司实施了自动化的 CI/CD 流水线,通过代码合并后的流水线自动触发,实现了快速迭代和部署。特别是引入的 nilaway code check 流水线,通过静态代码分析,显著降低了系统的崩溃率。接下来,我将具体阐述我们实现这一架构的方法和步骤。

  1. 可复用性

在微服务架构中,可复用性是一个至关重要的要素。我们都明白,转向微服务的初衷是为了更灵活地扩展和维护系统。但在拆分服务的过程中,我们不可避免地面临代码复用的问题。如果我们每次都要从零开始复制或实现服务,这不仅效率低下,而且会增加公司的维护成本。为了解决这一问题,我们提供了一套示例工程,这极大地降低了团队上手和创建新微服务的门槛,同时确保了公司代码的一致性和可维护性,无形中预防了许多潜在问题。

我还想推荐 CloudWeGo 的脚手架工具 cwgo。这个工具与我们之前提到的示例工程有相似之处。我们之所以没有在早期选择使用它,是因为在我们做出技术选型决定时,cwgo 还没有开源。但现在,社区功能已经非常完善。如果现在有人要从零开始构建微服务系统,完全可以利用这套脚手架工具来快速实现,而不必从基础做起。

第三部分与可复用性相关,即 Common lib 的建立。在公司层面或业务层面,我们考虑的是多个业务线之间是否有共通的部分。例如,日志记录、监控指标等公共功能,以及特定业务需求如 ID 生成等。每个公司的需求都不尽相同,因此我们的经验是,可以根据公司的具体情况,将公共库分为通用库各业务线的基线库,这样可以显著提升代码的复用率和迭代速度。

除了公司和业务层面的公共库,Kitex 官方也提供了许多专业的扩展实现,这些库可以在不同的场景下复用。正如之前提到的 kitex-contrib,我们可以在构建微服务时选用这些官方提供的组件,这不仅可以提升代码的可复用性,还能避免许多常见问题。官方的实现通常更为专业和可靠,其原理与我们自己建立的公共库相似,但适用于不同的应用场景。

  1. Pipeline

接下来,我将介绍我们的持续集成和持续部署(CI/CD)流水线。采用微服务架构意味着我们需要频繁发布众多服务。为了应对这一挑战,我们选择了自动化流程,以简化发布过程。我们的流水线设计遵循标准化步骤,包括镜像构建、小规模部署、全面部署等阶段。这些步骤可以根据团队的特定需求进行选择和调整。自动化流水线的设置,以及代码合并后的自动触发机制,极大地提高了研发团队的开发效率。

此外,我们流水线中还集成了一个关键的质量保证环节——代码检查。在代码合并前,我们设置了名为“nilaway code check”的检查点。这个环节的目的是在代码合并前,通过自动化的代码分析工具,识别潜在的空指针错误。如果发现问题,流水线将阻止代码合并,确保只有高质量的代码进入主分支。我们发现,线上问题中有高达 80%到 90%是由空指针引起的。通过在流水线中加入这一检查点,我们显著提高了系统的稳定性。实际上,我们通过这种方式将系统的 panic 率降低了 90%,从而极大地提升了系统的稳定性和可靠性。

总之,通过精心设计的 CI/CD 流水线和代码检查机制,我们不仅提高了开发效率,还确保了代码质量和系统稳定性,为团队带来了显著的收益。

三、流量管理与泳道系统

  1. Istio 的流量管理能力

我们刚才讨论了 Istio 作为服务网格代理,它负责接管并管理所有流量的分发。现在,我将重点介绍我们如何在 Istio 环境中成功集成 Kitex。

首先,服务发现是集成过程中的一个关键点。Kitex 本身支持多种服务发现机制,我们最终选择的落地方案是让 Kitex 依赖于 Istio 进行服务发现,进而依赖 Kubernetes 来实现。这种设计允许我们实现服务间的有效解耦。当然,根据不同团队的具体情况,也可以选择 Istio 支持的其他服务发现机制进行集成。

其次,我们来谈谈熔断(circuit breaker)机制。这是一个在实际生产环境中常见的需求,特别是当系统中某个依赖出现问题时,我们需要能够迅速将其隔离,以避免影响整个系统的稳定性。在基于 Istio 和 Service Mesh 的架构中,我们通过 Envoy 来管理这一流程。值得注意的是,Kitex 本身也提供了熔断和限流的能力,虽然在我们的调研中,Kitex 的熔断功能没有默认开启,但用户可以根据自己的需求灵活启用这一功能。

通过这样的设计,我们不仅确保了系统的高可用性,也提供了灵活的流量管理策略,以应对不同的业务场景和需求。

  1. 泳道系统的创新应用

Construct 公司利用 Istio 的流量染色功能,开发人员可以在不启动整个微服务集群的情况下,对特定流量进行测试和调试,实现了开发效率和线上用户体验的双重保障。

泳道系统的概念在微服务架构中与传统单体系统有所不同。在微服务场景中,微服务的数量很多,而开发人员只需要修改与他相关的几个微服务,而无需在本地搭建。例如,在大型企业如字节跳动,开发同学是不可能在本地完整搭建整个微服务系统的,硬件资源也不允许。因此,我们需要对流量进行精细管理,实现流量染色,这是 Istio 的强项,它可以高效地管理流量。

在这一过程中,我们使用 HTTP Header 来对流量进行标记和染色。在流量调度时,只有带有特定染色的流量才会被路由到相应染色的服务中,从而确保线上用户不受影响。在 Kitex 中,实现这一点相对直接,我们通过设置 HTTP Header 的键值对来定义泳道信息。

例如,我们可能会设置一个名为“x-asm-prefer-tag”的 header,以此来区分不同的泳道。关键在于如何将这些上下文信息在服务间传递。在 Kitex 中,这可以通过一行简单的代码实现,尽管我们的实现方式较为直接和底层。

此外,Kitex 官方也提供了其他一些实现方式如 OpenTelemetry 的 Baggage,是一套统一的标准且屏蔽了底层细节,可以作为参考。本质上,我们利用了内部的元数据库来传递追踪信息和 HTTP Header 信息,确保它们能够在服务调用链中正确传递。在 Istio 的 VirtualService 层面,我们可以定义路由规则,根据 HTTP Header 的特定值将流量路由到相应的服务。

以一个具体的例子来说,如果检测到value为“sl-test-1”的 HTTP Header,流量就会被路由到特定的服务。如果该服务不存在,流量将回退到线上服务。通过这种方式,我们可以实现泳道系统,使流量从线上服务跳转到灰度环境服务,实现类似这样的灵活跳转。

简而言之,通过 Istio 和 Kitex 的结合使用,我们能够实现复杂的流量管理策略,为开发人员提供了强大的工具来处理微服务架构中的挑战。

四、Mesh 可观测性

  1. 分布式追踪与性能监控

Construct 公司结合 Jaeger 和 OpenTelemetry,实现了对服务请求的全面监控。这不仅帮助团队深入理解服务间的调用关系,还为性能优化提供了数据支持。我们将讨论一些关键工具,如分布式追踪系统 Jaeger、性能监控工具 Prometheus 以及可视化界面 Grafana,以及它们与 Kitex 的集成方法。

  • 什么是追踪(Tracing)?

追踪,简单来说,就像是一根串联起整个服务调用链的线。如果将服务比作项链上的珍珠,追踪就是那根线,让我们能够沿着链路清晰地看到每个节点——即每个服务的具体信息。这些信息包括耗时、执行顺序和具体的方法调用等。在某种意义上,Tracing为我们对具体请求进行了一次 CT Scan,使我们能够清楚地了解每一层服务在做什么。这样,当出现问题时,我们可以迅速定位原因,比如服务为何响应缓慢。

  • Jaeger 与 OpenTelemetry

我们的追踪系统基于 Jaeger 和 OpenTelemetry 构建。Jaeger 是一个由 Uber Technologies 开源的分布式追踪平台,而 OpenTelemetry 则是一套 API、SDK 和工具的集合,用于收集和分析分布式系统的数据。它们帮助我们监控和排查分布式工作流,识别性能瓶颈,追踪根本原因,并分析服务依赖。

  • Kitex 与 OpenTelemetry 的集成

在 Kitex 中集成 Jaeger 和 OpenTelemetry 时,我们并没有进行大量定制化处理。因为 Kitex 与开源社区的标准非常契合,我们主要基于官方的追踪提供者进行配置,使其与 Kitex Server 无缝集成。一个关键点是追踪信息的传递。追踪本质上是自上而下串联起来的。我们在下游的收集服务器上定制了一个 middleware,其核心逻辑是将追踪的上下文信息传递下去,确保整个追踪信息能够连贯。

这种定制化的实现在当时是必要的,因为社区尚未有现成的解决方案。但现在,社区已经有了非常成熟的 OpenTelemetry 集成,为那些希望从零开始构建系统的用户提供了便利。当然,用户也可以选择完全自定义实现,这完全取决于具体需求和场景。

  1. 性能剖析与可视化监控

继追踪系统之后,我们引入了 Pyroscope,这是一种针对 Pod 级别的性能剖析工具。与追踪系统Tracing关注单个请求不同,Pyroscope 专注于 Pod 的性能问题。在服务端开发中,我们可能经常遇到系统上线后突然崩溃的情况。这时,Pyroscope 就发挥了作用。通过与 Kitex 集成,Pyroscope 可以帮助我们进行性能剖析,定位到具体的问题所在,并进行相应的修复。Pyroscope 的使用非常简单直观,通过与 OpenTelemetry 集成,我们可以轻松地将其应用于 Kitex,实现即插即用的功能。

接下来是 Prometheus 和 Grafana,这两种工具在监控领域广为人知。Istio 对 Prometheus 提供了良好的官方支持,我们在项目中也采用了这一集成方案。通过 Prometheus,我们可以在全局维度关注服务的关键指标,如 QPS 和时延等,并根据不同的 NAMESPACE 和服务进行细粒度的监控。Prometheus 的全局监控策略意味着,当我们引入新的微服务时,它们可以自动继承现有的监控配置,从而显著降低了维护成本。

此外,我们还建立了一个全局的监控报警系统 Alart Manager。它基于 Prometheus 的数据进行分析,并在特定条件下触发报警。例如,如果某个接口在 3 分钟内的平均时延超过 3 秒,Alart Manager 就会发出报警。这种灵活的报警机制可以根据具体的业务场景进行调整。

Kitex 本身也对 Prometheus 提供了支持,使得我们可以在 Istio 集成 Prometheus 的基础上,进一步对 Kitex 服务进行监控和度量,从而更好地了解服务的性能状况。

五、为什么选择 CloudWeGo

最后,我想谈谈我们为什么从零开始构建系统时选择了 CloudWeGo。我们的选择基于几个关键因素:

  1. 高性能与高可用性

CloudWeGo 的高性能和高可用性是 Construct 选择它的重要原因。

Kitex 在高并发场景下的性能优势,以及 Istio 的稳定性,为公司业务的持续发展提供了坚实的基础。实际上,在了解到 CloudWeGo 后,我们进行了一些基准测试,结果证实了它的性能确实卓越,这促使我们继续探索。

CloudWeGo 展现出的高可用性给我们留下了深刻印象,至少达到五个九(99.999%)的可用度,在面向消费者的(ToC)场景中表现出色。实际上,它的稳定性甚至超过了我们的预期。稳定性是选择开源组件或系统时的一个重要考虑因素。我们发现 CloudWeGo 的稳定性如此之高,以至于我们几乎感觉不到它的存在,就像我们日常生活中的水电煤以及空气一样,被它包围但又几乎感觉不到。

  1. 官方支持与社区生态

我们非常看重官方的支持。社区承诺在工作时间内 1-2 小时内响应,而我们的亲身体验甚至比这个时间还要短。在我们最初将 Kitex 与 Istio 集成时,如果没有官方的支持,我们将难以实现。因此,我们深刻感受到官方支持的重要性,它对于解决后续问题至关重要。

强有力的官方支持和活跃的社区生态,为 Construct 公司在技术选型和问题解决上提供了坚实后盾。CloudWeGo 社区的繁荣,不仅意味着丰富的资源和支持,也反映了该项目的成熟度和可靠性。CloudWeGo 背后的社区非常繁荣。全球有超过 16 万的用户关注和 2 万以上的 GitHub 星标,这意味着当你遇到问题时,很可能别人已经遇到过并解决了,这大大加快了问题解决的速度。一个繁荣的社区也反映了开源项目的强大实力。

结语

Construct 公司的案例不仅展示了如何利用 CloudWeGo 框架和 Istio 服务网格构建一个高效、稳定且易于管理的微服务系统,更为同行业其他企业提供了宝贵的转型经验和参考。随着技术的不断进步和社区的持续发展,我们期待看到更多企业在微服务架构转型的道路上取得成功。

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

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

相关文章

STM32学习和实践笔记(38):RTC实时时钟实验

1.STM32F1 RTC介绍 STM32 的实时时钟( RTC)是一个独立的定时器。 STM32 的 RTC 模块拥有一组连续计数的计数器,在相应软件配置下,可提供时钟日历的功能。修改计数器的值可以重新设置系统当前的时间和日期。 RTC模块和时钟配置…

事务的特性-原子性(Atomicity)、一致性(Consistency)、隔离性(Asolation)、持久性(Durability)

一、引言 1、数据库管理系统DBMS为保证定义的事务是一个逻辑工作单元,达到引入事务的目的,实现的事务机制要保证事务具有原子性、一致性、隔离性和持久性,事务的这四个特性也统称为事务的ACID特性 2、当事务保持了ACID特性,才能…

【精选】数据治理项目实施(合集)06——数据标准在数据治理中的落地实践

导读 本文对数据标准管理进行了深入探讨。重点介绍了数据标准的定义,实施路线和具体标准定义的内容,并总结了企业开展数据标准管理面临的常见问题,由于编写的水平和时间有限, 难免有所纸漏, 欢迎大家批评指正。 在现实…

MyBatis-关联查询的对象是集合的处理

用户和角色之间是多对多的关系,也就是说,一个用户可以有多个角色与之绑定,所以在User对象中,角色的属性就必须是一个集合Set或者List,这里我们就用List集合在做例子: 1.怎么在Mybatis中实现关联的List集合对…

k8s流控平台apiserver详解

一、简单理解认识apiserver 1.主要功能 认证 鉴权 准入 mutating validating admission 限流 2.概念 apiserver保护etcd,缓存机制,有缓存直接返回,没缓存再去查看etcd,apiserver是担任和其他平台同信并认证 3.访问控制概览…

精益生产KPI指标分析与管理系统,助力企业挖掘数据黄金焕发第二生命线

智慧工厂精益生产追求以越来越少的投入获取越来越多的产出,通过消除浪费、提高效率来实现生产效益的最大化。精益生产强调量化管理,通过与KPI的结合,可以将生产过程中的关键数据进行量化和分析,推动企业各部门更加关注运营效率&am…

嵌入式Linux的浮点运算能力测试

嵌入式Linux的浮点运算能力测试 今天需要对一款ARM CPU的浮点数运算能力进行测试,采用了台式机上常用的SuperPI相同的原理:计算一定小数位数的圆周率来测试硬件的浮点数计算能力和稳定性。 首先下载计算软件的源代码,可以使用下面命令&#…

Excel 宏录制与VBA编程 —— 12、文本字符串类型相关(转换、拆分、分割、连接、替换、查找、“Like“)

字符串分割,文末示例(文末代码3附有源码) 代码1 - 基础字符串 代码2 - 字符串拆分 代码3 - 字符串分割 Option ExplicitSub WorkbooksClear()Dim DataRange As RangeSet DataRange Range("C2:E12")DataRange.Clear End SubSub Wo…

NetSuite 隐藏功能之Memorized Transactions记忆交易

本周功课结束,想说说Memorized Transactions这个有时会被忽略的功能,顾名思义,记忆交易就是可以将一个原始的Transaction在创建后进行“记忆”,以保证后续可以在固定日期(周期性日期或者自定义日期)产生“被…

CISCN--西南半决赛--pwn

1.vuln 这是主函数,数一下就发现可以溢出最后的0x4008d0 然后会执行到这里,逻辑就是在v0上写shellcode,不过执行写0x10,不够sh,很明显要先read。 以下是exp: from pwn import * context.archamd64 ioprocess(./vuln)…

一大波客户感谢信来袭,感谢认可!

“自美的置业数据中台项目启动以来,贵公司实施团队与服务运营始终以专业、敬业、合作的态度扎根用户、服务用户、与用户共成长。在此,我司表示由衷的感谢!” 这是携手美的置业以来,我们收到的第二封客户感谢信。 △ 以上为美的置…

Windwos +vs 2022 编译openssl 1.0.2 库

一 前言 先说 结论&#xff0c;编译64位报错&#xff0c;查了一圈没找到解决方案&#xff0c;最后换了32位的。 使用qt访问web接口&#xff0c;因为是https&#xff0c;没有openssl库会报错 QNetworkReply* reply qobject_cast<QNetworkReply*>(sender());if (reply){…

《数据仓库与数据挖掘》 总复习

试卷组成 第一章图 第二章图 第三章图 第四章图 第五章图 第六章图 第九章图 第一章 DW与DM概述 &#xff08;特点、特性&#xff09; DB到DW 主要特征 &#xff08;1&#xff09;数据太多&#xff0c;信息贫乏&#xff08;Data Rich&#xff0c; Information Poor)。 &a…

2024最新美区TikTok选品全流程指南

打造TikTok爆款&#xff0c;3分靠运营&#xff0c;7分靠选品。 选择适合TikTok推广的商品至关重要&#xff0c;针对TikTok美区如何选品&#xff1f;怎么定价&#xff1f;SKU定多少&#xff1f; 本文总结出独家「美区TikTok选品全流程指南」方法论&#xff0c;说清楚选品最重要…

【项目一】全场景工业互联设备管理系统解决方案(PC上位机+中控+多传感器) 文章汇总

全场景工业互联设备管理系统解决方案(PC上位机中控多传感器) 配套硬件及资料 配套资料&#xff1a;https://pan.baidu.com/s/109e9Cr5nl-BWpct24Q6zOw?pwdroot 密码&#xff1a;root 交流论坛&#xff1a;https://forums.100ask.net/c/specialc/85 QQ交流群&#xff1a;865…

深入理解 XML 和 HTML 之间的区别

在现代网络技术的世界中&#xff0c;XML&#xff08;可扩展标记语言&#xff09;和 HTML&#xff08;超文本标记语言&#xff09; 是两个非常重要的技术。尽管它们都使用标签和属性的格式来描述数据&#xff0c;但它们在形式和用途上有显著的区别。 概述 什么是 XML&#xff…

告别 “屎山” 代码,务必掌握这14 个 SpringBoot 优化小妙招

插&#xff1a; AI时代&#xff0c;程序员或多或少要了解些人工智能&#xff0c;前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家(前言 – 人工智能教程 ) 坚持不懈&#xff0c;越努力越幸运&#xff0c;大家…

【论文阅读 Validation Free and Replication Robust Volume-based Data Valuation】

论文题目 免验证的对于复制鲁棒性的基于量的数据估值 1. 本文具体贡献 通过数据的体积形式化了数据多样性的度量&#xff0c;并在理论上和实证上证明了体积对数据估值的适用性&#xff1b;形式化了复制鲁棒性的概念&#xff0c;并设计了一种基于稳健体积&#xff08;RV&…

分布式服务测试各节点调用第三方服务连通性

背景&#xff1a;分布式部署 一个主节点往各个节点下发任务&#xff08;调用第三方服务&#xff09;&#xff0c;目的是为了测试各节点与第三方的连通性 思路&#xff1a; 主节点实现 创建Spring Boot项目&#xff1a;作为主节点的后端服务。 集成Eureka客户端&#xff1a;在…

Android 遥控器

遥控器源码 import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Path; import android.graphics.RadialGradient; import android.graphics.Region; import android.g…