事件驱动的基于微服务的系统的架构注意事项

2022-03-04 13:10:27 浏览数 (1)

今天的 IT 系统正在生成、收集和处理比以往更多的数据。而且,他们正在处理高度复杂的流程(正在自动化)以及跨越典型组织边界的系统和设备之间的集成。同时,预计 IT 系统的开发速度更快、成本更低,同时还具有高可用性、可扩展性和弹性。

为了实现这些目标,开发人员正在采用架构风格和编程范式,例如微服务、事件驱动架构、DevOps 等。正在构建新的工具和框架来帮助开发人员实现这些期望。

开发人员正在结合事件驱动架构 (EDA) 和微服务架构风格来构建具有极强可扩展性、可用、容错、并发且易于开发和维护的系统。

在本文中,我将讨论使用这两种架构风格构建这些系统时的架构特征、复杂性、关注点、关键架构注意事项和最佳实践。尽管 API、API 网关和 UI 等组件在架构上很重要,但在本文中我将主要关注事件驱动的微服务。

◆ 事件驱动架构和微服务架构概述

事件驱动架构(EDA)已经存在了很长时间。云、微服务和无服务器编程范式以及复杂的开发框架正在提高 EDA 在实时解决关键任务业务问题中的适用性。Kafka、IBM Cloud Pak for Integration和Lightbend等技术和平台以及Spring Cloud Stream、Quarkus和Camel等开发框架都为 EDA 开发提供一流的支持。EDA 还扩展到流数据处理,这是开发实时人工智能或机器学习解决方案的要求。文章“事件驱动架构的优势” 定义了 EDA 并解释了为什么开发人员应该使用它。

微服务架构正在被广泛采用并用于转型项目,这些项目涉及将单体应用程序分解为使用域驱动设计识别的自包含、独立部署的服务。Martin Fowler 和 James Lewis 的文章很好地介绍了微服务架构及其特性。微服务可以公开 API,并具有用于生成和使用事件的接口,以与 EDA 无缝集成。它的许多特性使其成为将其与 EDA 相结合的理想选择。文章“微服务架构风格的挑战和好处”讨论了开发人员在实现微服务时面临的挑战。

下表显示了这两种架构风格如何相互补充:

EDA

微服务架构

组件/服务之间的松散耦合

提供关注点分离的有界上下文

扩展单个组件的能力

可独立部署和可扩展

处理组件可以相互独立开发

支持多语言编程

高云亲和力

云原生

异步性质。以及限制工作量的能力

弹性可扩展性

容错和更好的弹性

良好的可观察性,可快速检测故障

构建处理管道的能力

进化的本质

复杂事件代理的可用性降低了代码复杂性

一组标准的可重用技术服务,通常称为MicroServices Chassis

丰富的成熟企业集成模式

提供丰富的可重用实现模式存储库

通过结合这两种架构风格,开发人员可以构建分布式、高度可扩展、可用、容错和可扩展的系统。这些系统可以实时消费、处理、聚合或关联极其大量的事件或信息。开发人员可以使用行业标准的开源框架和云平台轻松扩展和增强这些系统。

◆ 架构问题和复杂性

通过结合 EDA 和微服务架构风格,开发人员可以轻松实现非功能性品质,例如性能、可扩展性、可用性、弹性和易于开发。然而,这两种架构风格也引入了一些主要问题。

其中一些担忧包括:

  • 大量分布式独立部署的组件或服务,其中引入了这些问题:
    • 设计和实现的复杂性。理解和调试这样的系统是困难的。事件处理工作流程不直观,需要记录在案。
    • 多点故障。增加了测试、调试和异常处理的复杂性。
    • 发布过程、部署和系统监控变得复杂,需要高度自动化。
    • 从开发的角度来看,需要实现的一致性、设计的一致性和实现标准。但是,有多个开发小组。这可能导致不一致的实施和质量问题。因此,开发一个参考架构,概述架构模式的使用、开发框架、可重用服务或实用程序的开发,以及建立一个健壮和有效的治理模型是必不可少的。
  • 由于与事件排序或排序、回调和异常处理相关的要求,与同步处理相比,异步事件处理比较困难。
  • 丢失信息或事件是不可取的(显然)。因此,对具有极高可用性、可扩展性和容错性的系统的要求尤为重要,这使得系统的设计和部署变得相当复杂。事件生产者和消费者的设计必须能够承受故障,能够重放失败的事件,并具有重复数据删除功能。
  • 缺乏对分布式事务的支持。这个问题意味着开发人员必须创建跨多个分布式系统的自定义和复杂的回滚和恢复实现。
  • 保持数据一致性。由于分布式特性和多个记录系统,维护数据一致性很复杂。在大多数情况下,由于缺乏跨多个分布式系统的原子事务,它是最终的一致性。
  • 事件消费者和生产者必须考虑特定于用于事件代理、数据缓存等的产品的属性。例如,交付保证会影响生产者和消费者的设计。

◆ EDA-微服务系统的架构蓝图

下图是一个基于EDA-微服务的企业系统的架构图。一些微服务组件和类型单独显示,以使架构更清晰。

此蓝图中的 EDA 和特定于微服务的组件是:

  • 事件主干。事件主干主要负责事件的传输、路由和序列化。它可以提供用于处理事件流的 API。事件主干提供对多种序列化格式的支持,并对架构质量(例如容错、弹性可伸缩性、吞吐量等)产生重大影响。也可以存储事件以创建事件存储。事件存储是恢复和弹性的关键架构模式。
  • 服务层。服务层由微服务、集成以及数据和分析服务组成。这些服务通过各种接口公开其功能,包括 REST API、UI 或作为 EDA 事件生产者和消费者。服务层还包含特定于 EDA 并解决横切关注点的服务,例如编排服务、流数据处理服务等。
  • 数据层。数据层通常由两个子层组成。在此蓝图中,未显示微服务拥有的各个数据库。
    • 缓存层,提供分布式和内存数据缓存或网格,以提高性能并支持 CQRS 等模式。它是水平可扩展的,并且还可能具有一定程度的复制和持久性以实现弹性。
    • 大数据层,由数据仓库、ODS、数据集市、AI/ML模型处理组成。
  • 微服务底盘。微服务底盘提供系统不同层所需的必要技术和横切服务。它提供开发和运行时功能。通过使用微服务机箱,您可以降低设计和开发的复杂性以及运营成本,同时缩短上市时间、交付质量和大量微服务的可管理性。
  • 部署平台:应使用弹性、成本优化、安全且易于使用的云平台。开发人员应尽可能多地使用 PaaS 服务,以减少维护和管理开销。该架构还应提供混合云设置,因此应考虑Red Hat OpenShift等平台。

◆ 主要架构考虑因素

架构方面的考虑会影响系统的架构。它们充当制定架构决策的指南。它们对系统的非功能特性有重大影响。以下架构注意事项对于事件驱动、基于微服务的系统极为重要:

  • 架构模式
  • 技术栈
  • 事件建模
  • 处理拓扑
  • 部署拓扑
  • 异常处理
  • 利用事件主干功能
  • 安全
  • 可观察性
  • 容错和响应

◆ 架构模式

选择架构和集成模式是事件驱动、基于微服务的系统的关键架构考虑因素。它们为许多所需的架构质量提供经过验证和测试的解决方案。以下架构模式在开发事件驱动、基于微服务的系统中非常有用:

  • 管道和过滤器
  • 分阶段事件驱动架构 (SEDA)
  • 事件溯源
  • 命令查询职责分离 (CQRS)
  • Saga
  • 流处理
  • 微服务底盘
  • 死信队列 (DLQ)

此外,许多企业集成模式和微服务模式为基于事件驱动的微服务系统提供了构建块。

需要根据系统所需的需求和架构质量来选择模式。

◆ 技术栈

事件代理、数据缓存或网格、微服务框架、安全机制、分布式数据库、监控系统和警报系统等组件构成了事件驱动、基于微服务的系统的技术骨干。该主干为关键架构质量(性能、可用性、可靠性、运营成本、容错性等)提供支持并简化了开发。它还影响一些设计和开发决策。

在选择您的技术堆栈时,请考虑以下特征:

  • 单个组件的水平可扩展性。扩展不应损害可用性。也就是说,节点的添加不应该需要停机时间。
  • 单个组件的高可用性。所选产品或框架应支持集群,具有跨不同可用区或区域的成员的能力,支持滚动升级,支持数据复制,并且应该是容错的,这意味着集群应该在节点丢失的情况下重新平衡自身。
  • 云亲和力,这意味着它应该很容易部署在云上。事实上,如果它们在 PaaS 平台上作为服务提供,那就更好了,因为它减少了管理和维护开销。必须支持容器化。
  • 运营成本低,这意味着它应该能够在商品硬件上运行,并且在 CPU、内存和存储方面应该节俭。
  • 无需停机即可对行为和非功能特性进行配置和调整。
  • 可管理性。
  • 应避免供应商锁定。选择基于开放标准或开源产品的产品。在选择开源产品时,要考虑产品被广泛采用的程度,是否有一个蓬勃发展的开发者社区,以及许可证应该是开放的而不是非常严格的(例如 Apache License V2.0)。
  • 对于事件代理和开发框架,它们应该支持:
    • 多种序列化格式(JSON、AVRO、Protobuf 等)
    • 异常处理和死信队列 (DLQ)
    • 流处理(包括对聚合、连接和窗口化的支持)
    • 分区和保持事件的顺序
  • 反应式编程支持很不错。
  • 多语言编程支持在 Event 主干中很不错。

下表列出了不同组件的流行选择:

组件类型

选择

事件主干网

Apache Kafka,集成平台,例如用于集成的 IBM cloud pak,Lightbend,AWS Eventbridge Kinesis

微服务开发框架

Spring 框架,例如Spring Boot、Spring Cloud Stream、Quarkus、Apache Camel

数据缓存/网格

阿帕奇点燃,Redis,Ehcache,弹性搜索,Hazelcast

可观察性

Prometheus  Grafana,ELK,StatsD  Graphite,Sysdig,AppDynamics,Datadog

◆ 事件建模

事件建模包括定义事件类型、事件层次结构、事件元数据和有效负载模式。仔细考虑这些事件建模特征:

  • 事件类型。在企业系统中,有多个业务领域,每个领域都在消费和产生不同类型的事件。建模的关键方面之一是识别事件类型和事件。使用领域驱动的设计和实践(例如事件风暴和事件源)来识别和分类事件。事件类型本质上可以是分层的,这有助于采用分层的事件处理方法。定义事件类型和事件以涵盖所有业务需求并将它们映射到不同的业务流程或工作流。事件类型的粒度对于避免组件之间的紧密耦合至关重要。事件类型是定义路由规则的关键。
  • 事件架构。事件模式由事件元数据(例如类型、时间、源系统等)和用于事件处理器处理的有效负载(即信息)组成。事件类型通常用于路由。事件元数据通常用于关联和排序事件,但它也可用于审计和授权目的。有效负载会影响队列、主题和事件存储的大小、网络性能、(反)序列化性能和资源利用率。避免重复内容。您始终可以通过在需要时重播事件来重新生成状态。
  • 版本控制。需求和实现会随着时间的推移而发展,它们通常会影响事件模型。对事件模型的更改可能会影响太多的微服务。同时更改所有受影响的服务是不切实际的。因此,事件模型应该支持多个版本并向后兼容,以便微服务可以在他们方便的时候进行更改。向有效负载添加新属性而不是更改现有属性(弃用而不是更改)也是一个好主意。版本控制取决于序列化格式。
  • 序列化格式。有多种序列化格式可用于对事件及其有效负载进行编码,例如JSON、protobuf或Apache Avro。这里的重要考虑因素是模式演变支持、(反)序列化性能和序列化大小。由于事件消息是人类可读的,因此开发和调试 JSON 非常容易,但 JSON 性能不高,可能会增加事件存储要求。虽然 Avro 或 Protobuf 减小了有效负载的大小,速度很快,并且支持模式演变,但它们需要额外的设计和开发工作。
  • 分区。事件的分区对于提高并发性、可伸缩性和可用性很重要。分区也是消息排序的关键。从架构的角度来看,选择分区键很重要。拥有一个非常粗粒度的密钥会影响可伸缩性和并发性。拥有一个非常细粒度的密钥可能无助于保持事件的顺序。在 Kafka 等事件代理中,分区限制了事件消费者的可伸缩性。
  • 订购。某些事件可能需要根据它们的到达时间进行排序(至少对于给定实体而言)。例如,必须按顺序处理给定帐户的帐户交易。识别需要排序的事件很重要。仅在必要时才应使用排序,因为它会影响性能和吞吐量。在 Apache Kafka 中,事件的顺序与分区直接相关。
  • 事件持久性持久性是指事件在队列或主题上可用多长时间。例如,您是否应该在使用事件后立即删除它。删除早于配置的保留期的事件。删除具有显式标记的事件(例如 Kafka 中的墓碑)。根据要求,应选择并配置其中之一。在使用基于时间的保留时,如果需要,请考虑事件应可用于重播多长时间。如果正在使用事件存储模式,则必须考虑有关需要维护的同一事件或有效负载的版本数量的附加问题。Kafka 等事件代理提供了各种配置选项,可以在主题级别进行设置,以指定事件的持久性。

◆ 事件处理拓扑

在 EDA 中,处理拓扑是指对生产者、消费者、企业集成模式以及主题和队列的组织,以提供事件处理能力。它们基本上是事件处理管道,其中部分功能逻辑(处理器)使用企业集成模式、队列和主题连接在一起。处理拓扑是 SEDA、EIP 和 Pipes & Filter 模式的组合。对于复杂的事件处理,多个处理拓扑可以相互连接。

处理拓扑中的另一个关键概念是编排与编排。编排是指拥有一个中央编排器,通过调用不同的组件来编排处理工作流。每当需要对处理进行严格控制时,都会选择编排,例如用于支付处理。编排通常用于采用 SAGA 模式的地方。编排需要在性能和可用性之间进行权衡(因为编排器可能会成为单点故障)。编舞指完全去中心化的处理方式。也就是说,事件被发布并且感兴趣的组件订阅主题。没有中央组件来控制处理流程。编排的实现和维护很复杂。

请考虑以下有关创建处理拓扑的指南:

  • 处理阶段(处理器)应使用持久队列和主题连接。
  • 在每个队列或主题上配置分区键和消息保留策略。
  • 处理的粒度很重要。如果处理器的粒度太细,那么处理器之间就有可能紧密耦合。理想情况下,每个处理器应该在逻辑上彼此独立。
  • 微服务可用于实现处理器。这允许松散耦合、职责分离和易于开发。
  • 处理并发应该可以在处理器级别进行配置。
  • 使用经过验证的企业集成模式 (EIP)。选择为 EIP 提供内置支持的开发框架,例如 Apache Camel 或 Spring Cloud Stream。
  • 构建模块化和分层处理拓扑,以便通过组装简单的处理管道来实现复杂的事件处理。这有助于使实现模块化且易于更新。
  • 如果处理器具有状态(随事件而变化),请考虑使用存储来支持状态,以提高容错性和可恢复性。

可以使用流程事件流和事件管理状态等架构实践来设计处理拓扑。在定义处理拓扑时详细了解事件代理功能也很好。例如,Kafka 流为定义事件流处理拓扑提供了一流的支持。当对事件流执行聚合和连接操作时,Kakfa 还提供对状态存储的自动支持。

下图描绘了处理拓扑的蓝图。

下图描述了在线购物的简化订单处理拓扑。路由器能够动态地将事件路由到多个主题。另请注意,事件处理器还将具有“事件过滤器”,以根据上下文控制事件的消费和生产。

◆ 部署拓扑

在 EDA 微服务架构中,需要部署许多组件。应该选择一个部署拓扑,以便满足与可伸缩性、可用性、弹性、安全性和成本相关的架构要求。但是,需要在冗余、性能和成本之间进行权衡。部署到云使架构更具性能、弹性和成本效益。应利用云部署(例如high availabilityKubernetes 中的设置)提供的功能。

考虑为您的部署拓扑考虑以下关键原则:

  • 每个已部署的组件都应可独立扩展并部署为集群,以提高并发性和弹性。
  • 确保每个集群跨越多个可用区。这种设置在数据中心出现故障的情况下提供了更大的弹性。这样做的另一个好处是,可以跨不同的可用区或区域进行主动-主动部署,而不是被动 DR。
  • 复制因子决定了事件或信息的复制数量。如果没有复制,单个实例的故障(即使是集群的)也会导致数据丢失。这对于事件代理和数据库尤其需要。然而,复制是以计算和存储为代价的。应根据可用区、数据区域、节点数等因素设置复制。
  • 在 Kafka 的情况下,主题分区的数量对消费者的并发性设置了上限。
  • 工作负载节流。配置线程池以及消费者和生产者的实例数量以限制吞吐量。根据下游处理器的容量和吞吐量,需要相应地调整这些参数。
  • 数据压缩。如果有效负载大小很大并且 CPU 可用性很高,则可以使用压缩来压缩传输前的事件。但是,压缩是网络利用率和 CPU 利用率之间的权衡。
  • 数据加密。根据组织中的安全标准,在事件代理与生产者和消费者(以及您的数据库)之间配置 TLS、身份验证和授权。请注意,启用 TLS 会增加 CPU 利用率。

此外,支持自动部署、自动故障转移、滚动升级或蓝绿部署以及配置的外部化以使部署工件的环境独立,这一点很重要。

◆ 异常处理策略

在 EDA 中,拥有全面且一致的异常处理策略对于提高弹性非常重要。异常处理策略由以下全部或部分组成:

  • 记录异常
  • 在指定的时间和指定的重试间隔内重试事件
  • 如果所有重试都用尽,则将事件移动到死信队列(或停止事件处理)
  • 发出警报
  • 在某些情况下会产生事件
  • 纠正异常原因并重放事件

异常可以有两种类型:业务异常和系统异常。当验证或业务条件失败时会引发业务异常。系统异常是由于组件(数据库、事件代理或其他微服务)不可用或由于资源问题(例如OutOfMemory错误)、网络或传输相关问题(例如有效负载序列化或反序列化错误)而导致的广泛故障类别,或意外的代码故障(例如NullPointerException或ClassCastException)。

处理不同类型异常的方式存在显着差异。下面列出了一些异常处理机制:

  • 预期的业务异常通常在代码中处理。处理可能涉及记录异常、更新实体及其状态、生成异常事件或使用异常并继续前进。
  • 由于无效负载(包括序列化或反序列化问题)导致的异常将无法通过重试来解决。此类事件在 Kafka 中被称为poision pills(因为它阻塞了该分区的后续消息)。此类事件可能需要干预。建议将它们移动到死信队列 (DLQ)。DLQ 消费者应该允许更正和重播事件。
  • 由于组件不可用而导致的系统异常本质上是暂时的。因此,应配置多次重试。另一个关键配置参数是退避乘数。它用于在连续重试之间具有指数增加的时间间隔。如果重试后失败仍然存在,不同的框架有不同的策略。例如,Camel 会将事件移动到 DLQ。Kafka 流将停止处理。建议在这种情况下使用框架的默认行为。
  • 资源问题(例如OutOfMemory错误)通常在组件级别,会导致组件不可用。由于事件代理的容错特性,这里丢失事件的风险很小。此外,当部署在 Kubernetes 环境中时,会启动新的 pod 来替换失败的 pod。
  • SAGA 模式用于数据一致性非常重要且处理涉及多个微服务的情况。对数据一致性要求非常严格的事件使用 SAGA 模式。
  • 应该从一开始就考虑恢复和重放,而不是事后才应用(以后会变得非常复杂)。恢复和重放组件通常是定制开发的,并且会根据事件处理而有所不同。最简单的重播组件可能只是拾取失败的事件并将其重新发布到输入主题。

您的开发框架应该支持在所有微服务中使用一致的异常处理策略。它应该为业务异常提供一组预定义的异常类,并提供一个通用的异常处理程序,该处理程序可以使用配置进行定制,但强制执行与异常处理相关的架构决策。大多数开发框架确实提供了这种支持。但是,它们需要正确配置或扩展以提供所需的功能。

◆ 事件主干能力和约束

不同的事件骨干产品或平台为架构质量提供不同的支持。同时,它们对设计和架构施加了限制。在定义架构时,应考虑其能力和约束以有效解决非功能性需求。例如,以下是Kafka的一些重要功能和约束。

  • Kafka 支持基于分区键的事件排序。它还确保有一个消费者(线程)在一个分区上监听。这使得只需选择适当的分区键就可以很容易地对事件进行排序。例如OrderId,当用作分区键时,将确保与特定订单相关的所有事件都将按照它们到达的顺序进行处理。
  • Kafka 支持idempotence生产者。这意味着 Kafka 确保一个事件由生产者只生产一次。开发人员无需担心。
  • Kafka 提供at least once交付保证。这意味着消费者应该能够处理重复的消息。开发人员需要了解他们的事件代理提供的保证。
  • Kafka 的另一个重要方面是offset-commit消费者策略,这意味着事件应该是自动确认还是手动确认。如果启用了自动提交,则产生错误的事件可能会丢失(如果消耗了异常),或者使用者可能会看到重复的消息。手动提交可以用来解决这个问题,但它需要额外的代码。auto-committing除了手动/自动提交之外,与 Kafka 无缝协作的框架(例如 spring-cloud-stream)提供了在发生错误时不处理或将失败事件移动到 DLQ 的选择。这是设计过程中需要考虑的一个重要方面。
  • Kafka Streams 提供了处理事件流的能力,并且可以轻松地对事件流执行各种高级和复杂的操作,例如聚合和连接。这使得实时执行分析变得非常容易。例如,计算按不同维度分组的事件的实时统计数据需要非常少的编码。这些是有状态的操作并保持状态。Kafka 还通过state-stores提供自动容错。

◆ 安全

开发人员必须考虑 EDA 微服务架构中的这些安全方面:

  • 运输级安全
  • 对事件生产和消费的认证和授权访问
  • 事件处理的审计跟踪
  • 数据安全(如授权访问和加密存储)
  • 消除代码中的漏洞
  • 周边安全设备和模式

◆ 可观察性

可观察性包括监控、记录、跟踪和警报。系统的每个组件都应该是可观察的,以避免故障并从故障中快速恢复。

大多数 EDA 产品和开发框架通过发布可导出到 Prometheus 和 Grafana、ELK、StatsD 和 Graphite、Splunk 或 AppDynamics 等行业标准可观察性工具的指标来提供对可观察性的支持。例如,Apache Kafka 提供了可以导出并与大多数这些工具集成的详细指标。此外,为事件主干 (IBM Event Streams) 提供托管服务的云平台为可观察性提供一流的支持。Spring 或 Camel 等微服务开发框架为代码检测提供了良好的支持以进行监控。

从 EDA 的角度来看,检测生产者和消费者的代码以发布指标、发布事件代理指标并通过指标仪表板关联这些是必不可少的,因为 EDA 中分布式组件的数量很多。从 EDA 的角度来看,一些关键指标是传入和传出消息的速率、消费滞后、网络延迟、队列和主题大小等。

有关监控微服务,请参阅我的监控 Spring Boot 微服务教程,了解有关检测和监控微服务的详细信息。

◆ 容错和响应

为了提供足够的容错能力,架构需要提供冗余、异常处理和弹性伸缩(当超出阈值时放大,当负载恢复正常时缩小)。借助 EDA 和云,其中大部分都可以轻松实现。事件主干通过支持队列和主题的集群和复制来满足容错。生产者和消费者可以部署多个实例。当在 Kubernetes 平台上部署为容器时,可以通过自动缩放(使用水平 pod 自动缩放器)轻松实现弹性缩放,但必须为生产者和消费者设计异常处理。

尽管基于 EDA 的系统通过分级架构提供弹性,但快速故障响应和恢复对于避免延迟和一致性问题至关重要。要实现这种快速恢复,您需要:

  • 用于启动和停止实例以及重新启动失败实例的自动化,可以在基于 Kubernetes 的平台(例如 Red Hat OpenShift)中轻松配置
  • 在发生故障时发出警报和事件
  • 定义明确的事件管理流程
  • 日志的可用性以及通过跟踪跨多个组件关联日志的能力。需要在微服务中启用跟踪。可以使用诸如 spring-sleuth 之类的开发框架。对于日志聚合,可以使用 ELK 或 Splunk 等工具。这将有助于团队确定根本原因并快速解决问题。

◆ 结论

开发者可以结合事件驱动架构和微服务架构风格来开发分布式、高可用、容错和高吞吐量的系统。这些系统可以处理非常大量的信息,并且可以具有极高的可扩展性。然而,在构建此类系统时,开发人员必须考虑许多架构问题和复杂性,并做出许多关键的架构决策。在本文中,讨论了关键的架构决策以及做出这些决策需要考虑的因素。通过遵循本文中的指导,可以定义一个健壮的 EDA 微服务架构来实现预期的目标。

来源:

https://www.toutiao.com/a7058632639380472357/?log_from=eae0ef2ae2b7e_1644802188555

“IT大咖说”欢迎广大技术人员投稿,投稿邮箱:aliang@itdks.com

来都来了,走啥走,留个言呗~

 IT大咖说  |  关于版权

由“IT大咖说(ID:itdakashuo)”原创的文章,转载时请注明作者、出处及微信公众号。投稿、约稿、转载请加微信:ITDKS10(备注:投稿),茉莉小姐姐会及时与您联系!

感谢您对IT大咖说的热心支持!

  • 相关推荐
  • 推荐文章
  • 2022年的五个大数据趋势
  • ClickHouse中分区(Partition)和分片(Shard)概念入门
  • 用Python写了一个上课点名系统(附源码)(自制考勤系统)
  • 微服务篇:什么是同步式微服务
  • RabbitMQ,RocketMQ,Kafka 事务性,消息丢失和消息重复发送的处理策略
  • 2022年最该收藏的8个数据分析模型
  • 系统集成服务集成交互技术:REST服务集成—Swagger接口文档规范
  • Bootstrap实战 - 响应式布局
  • 为什么 Redis 的查询很快,Redis 如何保证查询的高效
  • vue3-vite-elementplus-admin管理后台V1.0.2
  • 知网都搜不到的知识:湖仓一体

0 人点赞