应用 Strangler 模式将遗留系统分解为微服务

2023-12-22 08:04

本文主要是介绍应用 Strangler 模式将遗留系统分解为微服务,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

许多来源在一般情况下提供了微服务的解释,但缺乏特定领域的示例。新来者或不确定从哪里开始的人可能会发现掌握如何将遗留系统过渡到微服务架构具有挑战性。本指南主要面向那些正在努力启动迁移工作的个人,它提供了特定于业务的示例来帮助理解该过程。

我想谈谈另一种模式 - Strangler模式 - 这是一种迁移模式,用于逐步从旧系统过渡到新系统,同时最大限度地降低风险。

让我们以传统杂货计费系统为例。现在是时候升级到微服务架构以利用其优势了。

Strangler 是一种逐步退役旧系统,同时逐步开发新系统的模式。这样,用户可以更快地开始使用新系统,而不是等待整个系统迁移完成。

在第一篇文章中,我将重点关注杂货店所需的微服务。例如,考虑这样一个场景:您当前有一个杂货店的遗留系统,并且您有兴趣将其升级到微服务架构并将其迁移到云。

杂货店遗留系统概述

首先,在线杂货店可能具有的模块是:

  1. 购物车服务

  2. 退款处理服务

  3. 库存管理服务:商品销售时减去商品数量,订单退款时加回商品数量。

根据 Strangler 模式,您应该能够用新的微服务替换一个模块,同时继续使用其他模块,直到更新的服务准备就绪。

在这里,您可以先用更新的服务替换购物车。由于购物车服务依赖于支付处理服务,因此您也需要开发该服务。

假设我们将逐步开发这些服务。出于演示目的,我将仅关注上述三个服务。但在现实场景中,您可能需要如下所示的其他服务来完成杂货店的整个电子商务网站:


public class Product
{public Guid Id { get; set; }public string Name { get; set; }public decimal Price { get; set; }public int StockQuantity { get; set; }public Category ProductCategory { get; set; }
}public class Category
{public Guid Id { get; set; }public string Name { get; set; }
}public class ShoppingCartItem
{public Product Product { get; set; }public int Quantity { get; set; }
}public class ShoppingCart
{public Guid Id { get; set; }public List<ShoppingCartItem> Items { get; set; }public Customer Customer { get; set; }public DateTime CreatedAt { get; set; }
}public class Order
{public Guid Id { get; set; }public List<ShoppingCartItem> Items { get; set; }public Customer Customer { get; set; }public decimal TotalAmount { get; set; }public DateTime CreatedAt { get; set; }
}

图片

现在让我们考虑每个服务所需的基本模型类和操作。

对于购物车服务,您需要以下模型类和操作:产品、产品类别、添加到购物车的商品、购物车和订单。它的结构如下:

购物车服务


public class Product
{public Guid Id { get; set; }public string Name { get; set; }public decimal Price { get; set; }public int StockQuantity { get; set; }public Category ProductCategory { get; set; }
}public class Category
{public Guid Id { get; set; }public string Name { get; set; }
}public class ShoppingCartItem
{public Product Product { get; set; }public int Quantity { get; set; }
}public class ShoppingCart
{public Guid Id { get; set; }public List<ShoppingCartItem> Items { get; set; }public Customer Customer { get; set; }public DateTime CreatedAt { get; set; }
}public class Order
{public Guid Id { get; set; }public List<ShoppingCartItem> Items { get; set; }public Customer Customer { get; set; }public decimal TotalAmount { get; set; }public DateTime CreatedAt { get; set; }
}

理想情况下,您应该创建一个共享项目来容纳所有模型和接口。首先必须确定必要的模型和操作。

在考虑客户可以在购物车中执行的操作时,通常只涉及一个主要操作,CreateOrder,即向购物车添加商品。然而,其他操作,例如支付处理、退款和库存调整,应作为单独的微服务来实现。这种模块化方法可以在管理业务流程的不同方面提供更大的灵活性和可扩展性。


public class BillingService : IBillingService
{public Order CreateOrder(Customer customer, List<ShoppingCartItem> items){return new Order{Id = Guid.NewGuid(), //Create a new order idItems = items,Customer = customer,TotalAmount = CalculateTotalAmount(items),CreatedAt = DateTime.Now};}private decimal CalculateTotalAmount(List<ShoppingCartItem> items){decimal totalAmount = 0;foreach (var item in items){totalAmount += item.Product.Price * item.Quantity;}return totalAmount;}
}

理想情况下,在共享项目中,您必须为 IBillingService 创建一个接口。它应该如下所示:

public interface IBillingService{   public Order CreateOrder(Customer customer, List<ShoppingCartItem> items);}

现在您可以对CreateOrder操作进行单元测试。

在现实世界中,通常的做法是创建IBillingRepository 将订单保存在数据库中。该存储库应包含在数据库中存储订单的方法,或者您可以选择使用下游服务来处理订单创建过程。

我不会解决用户身份验证、安全、托管、监控、代理以及本讨论中的其他相关主题,因为它们是不同的主题。我的主要关注点仍然是根据您的特定需求量身定制的微服务的设计方面。

创建购物车后,下一步涉及客户付款。让我们继续创建支付服务项目及其关联模型。

付款处理服务


public class Payment
{public Guid Id { get; set; }public decimal Amount { get; set; }public PaymentStatus Status { get; set; }public DateTime PaymentDate { get; set; }public PaymentMethod PaymentMethod { get; set; }
}public enum PaymentStatus
{Pending,Approved,Declined,
}
public enum PaymentMethod
{CreditCard,DebitCard,PayPal,
}public class Receipt
{public Guid Id { get; set; }public Order Order { get; set; }public decimal TotalAmount { get; set; }public DateTime IssuedDate { get; set; }
}public class PaymentService : IPaymentService
{private PaymentGateway paymentGateway;public PaymentService(){this.paymentGateway = new PaymentGateway();}public Payment MakePayment(decimal amount, PaymentMethod paymentMethod, string paymentDetails){// In a real system, you would handle the payment details and validation before calling the payment gateway.return paymentGateway.ProcessPayment(amount, paymentMethod, paymentDetails);}
}public class ReceiptService : IReceiptService
{public Receipt GenerateReceipt(Order order){var receipt = new Receipt{Id = Guid.NewGuid(),Order = order,TotalAmount = order.TotalAmount,IssuedDate = DateTime.Now};return receipt;}
}

在此服务项目中,您必须创建并实现以下接口:


public Interface IPaymentService
{public Payment MakePayment(decimal amount, PaymentMethod paymentMethod, string paymentDetails); 
}
public Interface IReceiptService
{public Receipt GenerateReceipt(Order order);
}public Interface IPaymentRepository
{public Payment ProcessPayment(decimal amount, PaymentMethod paymentMethod, string paymentDetails)
} public class PaymentGateway : IPaymentRepository
{public Payment ProcessPayment(decimal amount, PaymentMethod paymentMethod, string paymentDetails){// Simplified payment processing logic for demonstrationvar payment = new Payment{Id = Guid.NewGuid(),Amount = amount,Status = PaymentStatus.Pending,PaymentDate = DateTime.Now,PaymentMethod = paymentMethod};// In a real system, you would connect to a payment gateway and process the payment, updating the payment status accordingly.// For example, you might use an external payment processing library or API to handle the transaction.// Simulating a successful payment here for demonstration purposes.payment.Status = PaymentStatus.Approved;return payment;}
}

创建所有这些服务后,我们可以轻松地使用新系统停用购物车(假设您也有一个并行完成的新用户界面)。

接下来,我们必须解决下订单后的库存管理问题。库存管理服务负责在创建采购订单时补货。该服务项目的结构如下:

库存管理服务

public class Product
{public Guid Id { get; set; }public string Name { get; set; }public decimal Price { get; set; }public int QuantityInStock { get; set; }public Category ProductCategory { get; set; }
}
public class Category
{public Guid Id { get; set; }public string Name { get; set; }
}public class Supplier
{public Guid Id { get; set; }public string Name { get; set; }public string ContactEmail { get; set; }
}
public class PurchaseOrder
{public Guid Id { get; set; }public Supplier Supplier { get; set; }public List<PurchaseOrderItem> Items { get; set; }public DateTime OrderDate { get; set; }public bool IsReceived { get; set; }
}public class PurchaseOrderItem
{public Product Product { get; set; }public int QuantityOrdered { get; set; }public decimal UnitPrice { get; set; }
}public interface IInventoryManagementService
{void ReceivePurchaseOrder(PurchaseOrder purchaseOrder);void SellProduct(Product product, int quantitySold);
}public class InventoryManagementService : IInventoryManagementService
{public void ReceivePurchaseOrder(PurchaseOrder purchaseOrder){if (purchaseOrder.IsReceived){throw new InvalidOperationException("The order is already placed.");}foreach (var item in purchaseOrder.Items){item.Product.QuantityInStock += item.QuantityOrdered;}purchaseOrder.IsReceived = true;}public void SellProduct(Product product, int quantitySold){if (product.QuantityInStock < quantitySold){throw new InvalidOperationException("Item not in stock.");}product.QuantityInStock -= quantitySold;}
}

正如我所提到的,本指南主要面向那些正在努力启动迁移工作的个人,它提供了特定于业务的示例来帮助理解该过程。

我相信本文为如何在微服务架构中启动迁移项目提供了宝贵的见解。如果您正在开发杂货店或任何在线购物车系统,那么此信息对您来说应该特别有用。我希望你能从这里拿走它。在我的下一篇文章中,我将介绍另一个特定于领域的示例,因为您始终可以在其他地方探索有关微服务的更多一般信息。


作者:Somasundaram Kumarasamy

更多技术干货请关注公号【云原生数据库

squids.cn,云数据库RDS,迁移工具DBMotion,云备份DBTwin等数据库生态工具。

irds.cn,多数据库管理平台(私有云)。

这篇关于应用 Strangler 模式将遗留系统分解为微服务的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/523186

相关文章

SpringBoot中四种AOP实战应用场景及代码实现

《SpringBoot中四种AOP实战应用场景及代码实现》面向切面编程(AOP)是Spring框架的核心功能之一,它通过预编译和运行期动态代理实现程序功能的统一维护,在SpringBoot应用中,AO... 目录引言场景一:日志记录与性能监控业务需求实现方案使用示例扩展:MDC实现请求跟踪场景二:权限控制与

Windows系统宽带限制如何解除?

《Windows系统宽带限制如何解除?》有不少用户反映电脑网速慢得情况,可能是宽带速度被限制的原因,只需解除限制即可,具体该如何操作呢?本文就跟大家一起来看看Windows系统解除网络限制的操作方法吧... 有不少用户反映电脑网速慢得情况,可能是宽带速度被限制的原因,只需解除限制即可,具体该如何操作呢?本文

CentOS和Ubuntu系统使用shell脚本创建用户和设置密码

《CentOS和Ubuntu系统使用shell脚本创建用户和设置密码》在Linux系统中,你可以使用useradd命令来创建新用户,使用echo和chpasswd命令来设置密码,本文写了一个shell... 在linux系统中,你可以使用useradd命令来创建新用户,使用echo和chpasswd命令来设

电脑找不到mfc90u.dll文件怎么办? 系统报错mfc90u.dll丢失修复的5种方案

《电脑找不到mfc90u.dll文件怎么办?系统报错mfc90u.dll丢失修复的5种方案》在我们日常使用电脑的过程中,可能会遇到一些软件或系统错误,其中之一就是mfc90u.dll丢失,那么,mf... 在大部分情况下出现我们运行或安装软件,游戏出现提示丢失某些DLL文件或OCX文件的原因可能是原始安装包

电脑显示mfc100u.dll丢失怎么办?系统报错mfc90u.dll丢失5种修复方案

《电脑显示mfc100u.dll丢失怎么办?系统报错mfc90u.dll丢失5种修复方案》最近有不少兄弟反映,电脑突然弹出“mfc100u.dll已加载,但找不到入口点”的错误提示,导致一些程序无法正... 在计算机使用过程中,我们经常会遇到一些错误提示,其中最常见的就是“找不到指定的模块”或“缺少某个DL

C语言中位操作的实际应用举例

《C语言中位操作的实际应用举例》:本文主要介绍C语言中位操作的实际应用,总结了位操作的使用场景,并指出了需要注意的问题,如可读性、平台依赖性和溢出风险,文中通过代码介绍的非常详细,需要的朋友可以参... 目录1. 嵌入式系统与硬件寄存器操作2. 网络协议解析3. 图像处理与颜色编码4. 高效处理布尔标志集合

SpringBoot基于配置实现短信服务策略的动态切换

《SpringBoot基于配置实现短信服务策略的动态切换》这篇文章主要为大家详细介绍了SpringBoot在接入多个短信服务商(如阿里云、腾讯云、华为云)后,如何根据配置或环境切换使用不同的服务商,需... 目录目标功能示例配置(application.yml)配置类绑定短信发送策略接口示例:阿里云 & 腾

Nginx location匹配模式与规则详解

《Nginxlocation匹配模式与规则详解》:本文主要介绍Nginxlocation匹配模式与规则,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、环境二、匹配模式1. 精准模式2. 前缀模式(不继续匹配正则)3. 前缀模式(继续匹配正则)4. 正则模式(大

Java中的Lambda表达式及其应用小结

《Java中的Lambda表达式及其应用小结》Java中的Lambda表达式是一项极具创新性的特性,它使得Java代码更加简洁和高效,尤其是在集合操作和并行处理方面,:本文主要介绍Java中的La... 目录前言1. 什么是Lambda表达式?2. Lambda表达式的基本语法例子1:最简单的Lambda表

springboot项目如何开启https服务

《springboot项目如何开启https服务》:本文主要介绍springboot项目如何开启https服务方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录springboot项目开启https服务1. 生成SSL证书密钥库使用keytool生成自签名证书将