5

Newbe.Claptrap 框架入门,第三步 —— 了解项目结构

 3 years ago
source link: https://www.newbe.pro/Newbe.Claptrap/Get-Started-3/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Newbe.Claptrap 框架入门,第三步 —— 了解项目结构

发表于 2021-02-28 更新于 2021-03-01

接上一篇 Newbe.Claptrap 框架入门,第二步 —— 创建项目 ,我们本篇了解一下使用 Newbe.Claptrap 的项目模板创建的项目结构。

Newbe.Claptrap 是一个用于轻松应对并发问题的分布式开发框架。如果您是首次阅读本系列文章。建议可以先从本文末尾的入门文章开始了解。

解决方案结构

使用 Visual Studio 或者 Rider 打开位于项目根目录的解决方案 HelloClaptrap.sln

解决方案中包含有若干个解决方案文件夹,其中分别的内容如下:

解决方案文件夹说明 0_Infrastructure 基础设施。这里可以放置一些常用的模型,公共类库等内容。他们通常被多个其他项目所引用 1_Business 业务逻辑。这里可以放置一些核心业务相关的类库。例如存储层、业务层等等。特别的,Actor 的具体实现一般也可以放置在此处 2_Application 应用程序。这里放置运行的应用程序,可以包含一些 WebApi、Grpc 服务、Actor 运行进程等等 SolutionItems 一些解决方案级别通用的文件,例如 nuget.config、tye.yml、Directory.Build.props 等等

以上只是为了项目演示所包含的最简解决方案结构。实际开发中往往还需要加入,仓储接口,单元测试,后台服务等等其他的一些内容。开发者可以根据团队规则进行合理摆放。

启用链路监控组件

为了更容易的了解整个系统的运行过程,我们先启用项目模板中的链路监控组件。通过链路监控来了解系统中各个组件的运行过程。

默认情况,即使没有启用这部分组件,项目也可以正常运行,因此前一篇进行 API 调用时并不会发生任何错误。

启用链路监控的方式非常简单:

使用项目模板创建好项目后,在解决方案文件夹下存在一个 docker-compose.yml 文件,这就可以用于开发者部署 seq 和 jaeger 等等辅助组件。

将此文件移动到单独的位置,使用 docker-compose up -d 便可以顺利启动服务。

启动成功之后,便可以下一些终结点查看到相关的 UI 界面:

了解调用链路

现在,我通过一个简单的调用链路来理解 Newbe.Claptrap 运行的过程。

我们来了解一下调用 GET /AuctionItems/{itemId} 所引发的过程。

调用 API 后,首先进入的自然是 MVC 中的 Controller。对应项目模板中的便是 HelloClaptrap.WebApi 项目下的 AuctionItemsController,以下截取与此 API 相关的部分:

AuctionItemsController.cs
using System.Threading.Tasks;
using Dapr.Actors;
using Dapr.Actors.Client;
using HelloClaptrap.IActor;
using HelloClaptrap.Models;
using Microsoft.AspNetCore.Mvc;
using Newbe.Claptrap;
using Newbe.Claptrap.Dapr;

namespace HelloClaptrap.WebApi.Controllers
{
[ApiController]
[Route("[controller]")]
public class AuctionItemsController : ControllerBase
{
private readonly IActorProxyFactory _actorProxyFactory;

public AuctionItemsController(
IActorProxyFactory actorProxyFactory)
{
_actorProxyFactory = actorProxyFactory;
}

[HttpGet("{itemId}/status")]
public async Task<IActionResult> GetStatus(int itemId = 1)
{
var id = new ClaptrapIdentity(itemId.ToString(),
ClaptrapCodes.AuctionItemActor);
var auctionItemActor = _actorProxyFactory.GetClaptrap<IAuctionItemActor>(id);
var status = await auctionItemActor.GetStatusAsync();
var result = new
{
status
};
return Ok(result);
}
}
}

这段代码表明:

  1. GetStatus 首先创建了 ClaptrapIdentity 这便是 Claptrap Identity,用于定位一个具体的 Claptrap
  2. 接下来调用_actorProxyFactory 获取一个 Actor 的代理。这是由 Dapr 提供的接口实现。
  3. 调用创建好的 auctionItemActor 代理对应的 GetStatusAsync,这样便可以调用对应的 Claptrap 实例的方法。
  4. 将从 Claptrap 返回的结果进行包装并作为 API 的返回结果。

这就是 API 层对简单的一种表现形式:通过创建 Actor 代理,调用 Actor 的方法。

Claptrap 层

接下来了解一下 Claptrap 层是如何运行的。通过 IDE 的 “查找实现” 功能,便可以找到 IAuctionItemActor 对应的实现类在 HelloClaptrap.Actors 项目中的 AuctionItemActor,以下是与 GetStatusAsync 方法有关的部分:

AuctionItemActor.cs
using System.Linq;
using System.Threading.Tasks;
using Dapr.Actors.Runtime;
using HelloClaptrap.Actors.AuctionItem.Events;
using HelloClaptrap.IActor;
using HelloClaptrap.Models;
using HelloClaptrap.Models.AuctionItem;
using HelloClaptrap.Models.AuctionItem.Events;
using Newbe.Claptrap;
using Newbe.Claptrap.Dapr;

namespace HelloClaptrap.Actors.AuctionItem
{
[Actor(TypeName = ClaptrapCodes.AuctionItemActor)]
[ClaptrapStateInitialFactoryHandler(typeof(AuctionItemActorInitialStateDataFactory))]
[ClaptrapEventHandler(typeof(NewBidderEventHandler), ClaptrapCodes.NewBidderEvent)]
public class AuctionItemActor : ClaptrapBoxActor<AuctionItemState>, IAuctionItemActor
{
private readonly IClock _clock;

public AuctionItemActor(
ActorHost actorHost,
IClaptrapActorCommonService claptrapActorCommonService,
IClock clock) : base(actorHost, claptrapActorCommonService)
{
_clock = clock;
}

public Task<AuctionItemStatus> GetStatusAsync()
{
return Task.FromResult(GetStatusCore());
}

private AuctionItemStatus GetStatusCore()
{
var now = _clock.UtcNow;
if (now < StateData.StartTime)
{
return AuctionItemStatus.Planned;
}

if (now > StateData.StartTime && now < StateData.EndTime)
{
return AuctionItemStatus.OnSell;
}

return StateData.BiddingRecords?.Any() == true ? AuctionItemStatus.Sold : AuctionItemStatus.UnSold;
}
}
}

本篇我们了解了安装项目模板和使用项目模板的基本步骤。

下一步,我们将介绍项目模板中包含的主要内容。

最后但是最重要!

如果读者对该内容感兴趣,欢迎转发、评论、收藏文章以及项目。

最近作者正在构建以 Actor 模式 和 事件溯源 为理论基础的一套服务端开发框架。希望为开发者提供能够便于开发出 “分布式”、“可水平扩展”、“可测试性高” 的应用系统 ——Newbe.Claptrap

本篇文章是该框架的一篇技术选文,属于技术构成的一部分。

项目文档库:claptrap.newbe.pro

联系方式: QQ 群 610394020

您还可以查阅本系列的其他选文:

理论入门篇

  1. Newbe.Claptrap - 一套以 “事件溯源” 和 “Actor 模式” 作为基本理论的服务端开发框架

术语介绍篇

样例实践篇

  1. 设计一个火车票销售系统

开发入门篇

开发工具篇

其他番外篇

GitHub 项目地址:https://github.com/newbe36524/Newbe.Claptrap

Gitee 项目地址:https://gitee.com/yks/Newbe.Claptrap

您当前查看的是先行发布于 www.newbe.pro 上的博客文章,实际开发文档随版本而迭代。若要查看最新的开发文档,需要移步 claptrap.newbe.pro

Newbe.Claptrap


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK