引言

Catalog microservice(目录微服务)维护着所有产品信息,包括库存、价格。所以该微服务的核心业务为:

  1. 产品信息的维护
  2. 库存的更新
  3. 价格的维护

架构模式

如上图所示,本微服务采用简单的数据驱动的CRUD微服务架构,来执行产品信息的创建、读取、更新和删除(CRUD)操作。

这种类型的服务在单个 ASP.NET Core Web API 项目中即可实现所有功能,该项目包括数据模型类、业务逻辑类及其数据访问类。其项目结构如下:

核心技术选型:

  1. ASP.NET Core Web API
  2. Entity Framework Core
  3. SQL Server
  4. Swashbuckle(可选)
  5. Autofac
  6. Eventbus
  7. Polly

实体建模

该微服务的核心领域实体是商品,其类图如下:

对于实体这一块,有两个小知识点需要说明一下:

  1. 进行数据库字段映射时,主键都使用了ForSqlServerUseSequenceHiLo指定使用HI-LO高低位序列进行主键生成。
  2. 使用NoTracking提升查询速度

    CatalogController的构造方法中,明确指定以下代码来进行查询优化,这一点也是我们值得学习的地方。 ((DbContext)context).ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
  3. 在进行种子数据的预置时,使用了Polly开启了Retry机制。
private Policy CreatePolicy( ILogger<CatalogContextSeed> logger, string prefix,int retries = 3)
{
return Policy.Handle<SqlException>().
WaitAndRetryAsync(
retryCount: retries,
sleepDurationProvider: retry => TimeSpan.FromSeconds(5),
onRetry: (exception, timeSpan, retry, ctx) =>
{
logger.LogTrace($"[{prefix}] Exception {exception.GetType().Name} with message ${exception.Message} detected on attempt {retry} of {retries}");
}
);
}
public async Task SeedAsync(CatalogContext context,IHostingEnvironment env,IOptions<CatalogSettings> settings,ILogger<CatalogContextSeed> logger)
{
var policy = CreatePolicy(logger, nameof(CatalogContextSeed)); await policy.ExecuteAsync(async () =>
{
//...
});
}

数据库表结构



你肯定会好奇为什么会多了一张IntegrationEventLog表,这里先按住不表。

最后

如果eShopOnContainers采用的是单体式应用架构而非微服务架构,那么以上业务逻辑的实现并不复杂,使用简单的CRUD再辅以ACID事务就能很好的完成业务需求。本文的介绍也就可以到此为止了。

然而将其抽取出来成为独立的基础微服务,那么我们要考虑的问题就多了。比如:

  1. 修改产品价格时,需要同步更新购物车中保存的产品信息的价格。
  2. 下订单时,需要验证当前商品库存是否充足,进行锁库抢占,以避免库存不足导致的订单无效。

而这一切我们都不能再享受单体应用中直接使用ACID事务的便利了。因为在微服务应用里,产品表和购物篮表被各自的微服务所占有。任何微服务不应该在自己的事务中包含其他微服务的表或存储,即使是直接查询也是不可以的。目录微服务不能直接更新购物篮表,因为购物篮表被购物篮微服务占有。要更新购物篮微服务,产品微服务应该使用基于异步通信,如集成事件(消息和基于事件的通信)来实现最终一致性。

那下一节我们就来详细阐述eShopOnContainers是如何通过事件机制完成最终一致性的。

最新文章

  1. 缓存工具类CacheHelper
  2. java基础之——DecimalFormat格式化数字
  3. 【iCore3应用开发平台】发布 iCore3 应用开发平台出厂代码rev0.0.5
  4. 【Arduino】使用C#实现Arduino与电脑进行串行通讯
  5. 解码美国传奇网络券商:TradeStation
  6. Android系统默认Home应用程序(Launcher)的启动过程源代码分析
  7. Windows phone 8 学习笔记(7) 设备
  8. ashx入侵
  9. Nginx的配置文件详解
  10. 关于无法全然下载CyanogenMod代码的问题
  11. Java基础小知识笔记
  12. centos6.5环境下的web项目mysql编码方式导致的中文乱码问题
  13. 源码分析之RequestContextHolder
  14. Python校验文件MD5值
  15. spring bean 注入
  16. MySQL:刷脏页
  17. PHP: PCRE 函数- Manual
  18. Silverlight中使用MVVM(3)—进阶
  19. 【 D3.js 入门系列 — 11 】 入门总结
  20. MaxAlertView 强大的弹框试图

热门文章

  1. 在webpack里使用jquery.mCustomScrollbar插件
  2. [ Java面试题 ]数据库篇
  3. GraphicsMagick+im4java实现高质量大图的处理
  4. [SQL Server]用 C# 在 LinqPad 建立 Linked Server 跨服务器数据库操作
  5. Java 字符流文件读写
  6. 1.1 为什么要使用lambda 表达式
  7. SpringBoot(一)_快速实战搭建项目
  8. SpringBoot进阶教程(三十)整合Redis之Sentinel哨兵模式
  9. Java转Ruby【快速入门】
  10. 执行Python程序的两种方式