首页 > 编程语言 >事务发件箱模式在 .NET 云原生开发中的应用(基于Aspire)

事务发件箱模式在 .NET 云原生开发中的应用(基于Aspire)

时间:2024-09-07 15:13:30浏览次数:9  
标签:builder 发送 Azure 消息 Aspire NET 发件箱

原文:Transactional Outbox in .NET Cloud Native Development via Aspire
作者:Oleksii Nikiforov

总览

这篇文章提供了使用 AspireDotNetCore.CAPAzure Service BusAzure SQLBicepazd 实现 Outbox 模式的示例。

源代码: https://github.com/NikiforovAll/cap-aspire

发件箱模式简介

发件箱模式是分布式系统领域中的一个重要组件。随着现代软件开发朝着更加分布式和解耦的架构发展,确保可靠的消息传递变得越来越重要。

在分布式系统中,不同的组件需要相互通信,通常通过异步消息传递。发件箱模式提供了一种可靠的方法来处理这些消息。它确保即使系统在执行本地事务之后但在发送消息之前发生故障,消息也不会丢失。相反,它会暂时存储在“发件箱”中,并在系统恢复时检索和发送。

通过使用发件箱模式,我们可以确保系统的所有组件以可靠的方式接收必要的消息,从而确保整个系统的完整性和一致性。

在没有发件箱模式的分布式系统中,有几种场景可能会出错,从而导致数据不一致或消息丢失。以下是几个示例:

  1. 事务提交和消息发送不是原子的:在通常情况下,Service 可能首先将事务提交到其数据库,然后向消息代理(Broker)发送消息。如果服务在事务提交之后但在消息发送之前崩溃,则消息将丢失。其他服务将不知道已提交到数据库的更改。
  2. 消息发送失败:即使服务没有崩溃,由于网络问题或消息代理问题,消息发送也可能失败。如果不重试消息发送操作,消息将丢失。
  3. 重复消息:如果服务在失败后重试消息发送操作,如果第一次发送实际上成功但确认丢失,则最终可能会多次发送同一条消息。如果消息使用者不是幂等的,这可能会导致重复处理。
  4. 顺序问题:如果单个事务发送了多条消息,并且这些发送不是原子性的,则这些消息可能会无序接收。如果消息的顺序很重要,这可能会导致不正确的处理。

发件箱模式通过确保事务提交和消息发送操作是原子的,并提供即使在出现故障时也能可靠地发送消息的机制来解决这些问题。

下面是一个序列图,说明了没有发件箱模式的系统所存在的的问题:

幂等消费者在发件箱模式中扮演着重要的角色。在分布式系统的背景下,幂等性是指系统无论执行特定操作多少次都能产生相同结果的能力。这对于确保分布式环境中的数据一致性和可靠性至关重要。

然而,这可能会导致同一条消息被多次发送,尤其是在系统在发送消息后但在发件箱中将消息标记为已发送之前发生故障的情况下。这就是幂等消费者发挥作用的地方。

幂等消费者旨在妥善处理重复消息。它们确保消除多次接收同一条消息的副作用。这通常通过跟踪所有已处理消息的 ID 来实现。当收到一条消息时,消费者会检查它是否已经处理了一条具有相同 ID 的消息。如果已经处理过,它就会忽略该消息。

下面是一个序列图,说明了发件箱模式如何解决问题:

发件箱模式的实现

现在您已经了解了发件箱模式的重要性和好处,让我们深入研究一下实现它需要什么:

发件箱模式的实现涉及以下步骤:

  1. 创建发件箱表:第一步是在数据库中创建发件箱表。此表将存储所有需要发送的消息。每条消息都应具有唯一的 ID 和一个指示消息是否已发送的状态字段。
  2. 修改应用程序代码:下一步是修改应用程序代码。每当您的应用程序需要将消息作为事务的一部分发送时,它都应将该消息作为同一事务的一部分添加到发件箱表中。
  3. 实现发件箱发布器:发件箱发布器是一个单独的组件,它会轮询发件箱表中未发送的消息。当它发现未发送的消息时,它会发送该消息并将发件箱表中该消息的状态更新为“已发送”。

DotNetCore.CAP 简介

幸运的是,有一个名为 DotNetCore.CAP 的 .NET 库可以为我们简化 Outbox 模式的实现。

DotNetCore.CAP 是一个开源库,它提供了一组 API,允许开发人员轻松地将消息作为数据库事务的一部分发送,将其存储在发件箱中,并确保即使在出现故障的情况下也能可靠地将它们传递给所有感兴趣的消费者。

该库还支持幂等消费者,这对于确保分布式环境中的数据一致性和可靠性至关重要。这意味着即使同一条消息被传递多次,也可以消除接收同一条消息的副作用。

通过使用DotNetCore.CAP,开发人员可以专注于其应用程序的业务逻辑,而库则负责确保分布式系统中可靠消息传递的复杂性。

例子

此代码演示了如何在 ASP.NET Core 应用程序中使用 CAP 库进行事件发布和处理。

在生产者中:

  • 定义了“/send”端点的路由处理程序。
  • 它启动一个事务,执行一个 SQL 命令来获取当前服务器时间,并将该时间的消息发布到“test.show.time”主题。
  • 消息发布延迟500毫秒。
  • 如果所有操作都成功,则事务被提交并返回响应。
// Producer/Program.cs  
app.MapGet("/send", async (  
	SqlConnection connection,  
	ICapPublisher capPublisher,  
	TimeProvider timeProvider) =>  
{  
	var startTime = timeProvider.GetTimestamp();  
	using var transaction = connection  
	.BeginTransaction(capPublisher, autoCommit: false);

	var command = connection.CreateCommand();
	command.Transaction = (SqlTransaction)transaction;
	command.CommandText = "SELECT GETDATE()";
	var serverTime = await command.ExecuteScalarAsync();

	await capPublisher.PublishDelayAsync(
		TimeSpan.FromMilliseconds(500),
		"test.show.time",
		new MyMessage(serverTime?.ToString()!));

	transaction.Commit();

	return TypedResults.Ok(new
	{
		Status = "Published",
		Duration = timeProvider.GetElapsedTime(startTime)
	});
});  

标签:builder,发送,Azure,消息,Aspire,NET,发件箱
From: https://www.cnblogs.com/savorboard/p/18401708/aspire-cap

相关文章

  • Monetization of Copywriting
    Copywritingisthepracticeofwritingpersuasivecontentwiththegoalofconvincinganaudiencetotakeaparticularaction.Thiscaninvolvecraftingads,productdescriptions,websitecontent,emailcampaigns,socialmediaposts,andmore.Theprimary......
  • 树莓派安装.netcore8 运行时离线安装
    莓派安装.netcore8运行时离线安装在树莓派上离线安装.NET8运行时的步骤如下:前提条件:确保您的树莓派已安装所需的依赖项,如libicu、libssl等。如果没有,您需要提前下载并离线安装这些依赖项的.deb包。步骤1:确定树莓派的架构使用以下命令检查......
  • Kubernetes 简介及部署方法
    目录1Kubernetes简介及原理1.1 应用部署方式演变1.2容器编排应用1.3kubernetes简介1.4K8S的设计架构1.5K8S各组件之间的调用关系1.6K8S的常用名词感念1.7k8S的分层架构2K8S集群环境搭建2.1k8s中容器的管理方式2.2k8s中使用的几种管......
  • kubernetes 中 利用yaml文件部署应用
    目录1用yaml文件部署应用有以下优点1.1声明式配置:1.2灵活性和可扩展性:1.3与工具集成:2资源清单参数介绍2.1获得资源帮助指令explain2.2编写示例2.2.1示例1:运行简单的单个容器pod2.2.2 示例2:运行多个容器pod2.2.3示例3:理解pod间的网络整合2.2.4......
  • 【小白深度教程 1.11】手把手教你使用 PSMNet 估计视差和计算深度,并映射到 3D 点云(含
    【小白深度教程1.11】手把手教你使用PSMNet估计视差和计算深度,并映射到3D点云(含Python代码)1.PSMNet简介2.环境配置3.下载预训练模型4.修改推理代码5.用PSMNet估计视差6.报错解决7.映射到3D点云8.对比传统方法9.点云可视化在之前的章节......
  • 关于Tailscale Subnet routers要说的
    国内的水文很多,Tailscale的部署就不说了。简单的都有讲到,但凡深度一点儿的只能找找外边儿的文章了。昨天刚给群晖装完Tailscale,打算着利用Subnetrouters功能来访问另外的2个子网。国内的水文在介绍这一段使用的时候是这样的:该文章提到:如果有多个网段添加,就多运行上面说到的......
  • 【第97课】云上攻防-云原生篇&Kubernetes&K8s安全&API&Kubelet未授权访问&容器执行
    免责声明本文发布的工具和脚本,仅用作测试和学习研究,禁止用于商业用途,不能保证其合法性,准确性,完整性和有效性,请根据情况自行判断。如果任何单位或个人认为该项目的脚本可能涉嫌侵犯其权利,则应及时通知并提供身份证明,所有权证明,我们将在收到认证文件后删除相关内容。文中所涉......
  • 记一次.net使用httpclient中代码中使用response.EnsureSuccessStatusCode()引发的误会
    1.问题背景有一个拉取第三方数据存储到本地的需求,使用.net开发,使用httpClient发送post请求。第三方接口里面会校验我们发送的json数据,如果我们的数据格式不正确会抛出异常。2.返回的结果不同?第一步,我用postman做了测试,对方的接口可以调用,正确和错误都可以返回。第二步,我使用代......
  • 1、.Net UI框架:Blazor Hybrid - .Net宣传系列文章
    BlazorHybrid是.NET6中引入的一个新特性,它允许开发者使用Blazor技术开发跨平台的桌面和移动应用程序。BlazorHybrid结合了BlazorWebAssembly和BlazorServer的优势,提供了一种在桌面和移动设备上运行Blazor应用的方法。BlazorHybrid的关键特性包括......
  • musl libc 与 glibc 在 .NET 应用程序中的兼容性
    muslLinux和glibc是两种不同的C标准库实现,它们在多个方面存在显著差异。历史和使用情况:glibc是较早且广泛使用的C标准库实现,具有较长的开发历史和广泛的社区支持。它被大多数Linux发行版采用,特别是在桌面和服务器环境中。musl是一个相对较新的实现,旨在提供更小、更快......