练习 - 将整体内部的服务重构为微服务
现在,Fabrikam 已完成分析其应用程序,他们已准备好开始重构过程,将服务从整体体系结构移动到微服务中。 让我们修改应用程序,将包处理服务移动到微服务中。
重构应用程序
在部署更新的应用程序之前,让我们看看它是如何更新的。 单体应用包含一个处理包的服务,PackageProcessor.cs。 分析应用程序的性能后,此服务被确定为性能瓶颈。 随着客户增加无人机交付的需求,这项服务在处理无人机交付的计划和物流时变得负载很大。 专用团队完全管理此服务,因此将其迁移到微服务有助于提高性能,并提供改进的开发敏捷性。
让我们进一步了解所做更改。
无人机配送之前
该 PackageProcessor 类处理 PackageProcessor.cs 文件中包处理的核心功能。 在此示例中,它执行一些资源密集型工作。 实际方案可能包括计算传递时间和传递路由,以及使用此信息更新数据源。
public class PackageProcessor : IPackageProcessor
{
public Task<PackageGen> CreatePackageAsync(PackageInfo packageInfo)
{
//Uses common data store e.g. SQL Azure tables
Utility.DoWork(100);
return Task.FromResult(new PackageGen { Id = packageInfo.PackageId });
}
}
随着此服务请求的增加,资源利用率会增加,并限制分配给整体应用程序的物理资源。 如果此服务部署在 Azure 应用服务上,我们可以将其纵向扩展和横向扩展。理想情况下,你希望这种大量使用的资源能够独立缩放,以优化性能和成本。 在此方案中,我们使用 Azure Functions 来执行此作。
无人机配送之后
在部署它之前,让我们看看 DroneDelivery-after 应用代码。 可以看到该 PackageProcessor 类已更改为类 PackageServiceCaller 。 它仍然实现 IPackageProcessor 接口,而是对微服务进行 HTTP 调用。
public class PackageServiceCaller : IPackageProcessor
{
private readonly HttpClient httpClient;
public static string FunctionCode { get; set; }
public PackageServiceCaller(HttpClient httpClient)
{
this.httpClient = httpClient;
}
public async Task<PackageGen> CreatePackageAsync(PackageInfo packageInfo)
{
var result = await httpClient.PutAsJsonAsync($"{packageInfo.PackageId}?code={FunctionCode}", packageInfo);
result.EnsureSuccessStatusCode();
return new PackageGen { Id = packageInfo.PackageId };
}
}
微服务部署在 Azure 函数上。 可在 PackageServiceFunction.cs 中找到其代码,并包含以下代码。
public static class PackageServiceFunction
{
[FunctionName("PackageServiceFunction")]
public static Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Function, "put", Route = "packages/{id}")] HttpRequest req,
string id, ILogger log)
{
log.LogInformation("C# HTTP trigger function processed a request.");
//Uses common data store e.g. SQL Azure tables
Utility.DoWork(100);
return Task.FromResult((IActionResult)new CreatedResult("http://example.com", null));
}
}
将此代码放在 Azure Functions 上时,随着用户负载的增加,此服务可以独立缩放。 可以保留针对应用程序其余部分优化的剩余应用程序代码的服务。 随着更多无人机配送请求进入系统,包服务会横向扩展。
现在,让我们重新部署应用程序。 首先,我们在 Azure Functions 上部署重构服务。 然后,我们在应用服务上部署重构的应用程序,并将其指向函数。
部署函数应用
运行以下命令,设置指向我们的服务的环境变量。
APPSERVICENAME="$(az webapp list \ --resource-group "<rgn>[sandbox resource group]</rgn>" \ --query '[].name' \ --output tsv)" FUNCTIONAPPNAME="$(az functionapp list \ --resource-group "<rgn>[sandbox resource group]</rgn>" \ --query '[].name' \ --output tsv)"让我们生成并压缩函数应用的应用程序代码。
cd ~/mslearn-microservices-architecture/src/after dotnet build ./PackageService/PackageService.csproj -c Release cd PackageService/bin/Release/netcoreapp2.2 zip -r PackageService.zip .运行以下命令将代码推送到函数应用。
az functionapp deployment source config-zip \ --resource-group "<rgn>[sandbox resource group]</rgn>" \ --name $FUNCTIONAPPNAME \ --src PackageService.zip
部署更新的无人机交付应用程序
现在,我们的服务在 Azure Functions 上运行,我们需要将无人机应用程序指向该函数应用。
首先需要获取函数应用的访问代码,以便我们可以从应用程序成功调用它。 运行以下命令以检索此代码。 你将显示函数应用名称和代码,以便在后续步骤中使用。
RESOURCEGROUPID=$(az group show \ --resource-group "<rgn>[sandbox resource group]</rgn>" \ --query id \ --output tsv) FUNCTIONCODE=$(az rest \ --method post \ --query default \ --output tsv \ --uri "https://management.azure.com$RESOURCEGROUPID/providers/Microsoft.Web/sites/$FUNCTIONAPPNAME/functions/PackageServiceFunction/listKeys?api-version=2018-02-01") echo "FunctionName - $FUNCTIONAPPNAME" echo "FunctionCode - $FUNCTIONCODE"在 Azure Cloud Shell 中运行以下命令,在代码编辑器中打开 appsettings.json 。
cd ~/mslearn-microservices-architecture/src/after code ./DroneDelivery-after/appsettings.json在代码编辑器中,替换值
PackageServiceUri和PackageServiceFunctionCode。 在PackageServiceUri中,将<FunctionName>替换为您的函数应用程序的名称。在
PackageServiceFunctionCode中,将<FunctionCode>替换为检索到的函数代码。 appsettings.json 文件应类似于以下示例:{ "Logging": { "LogLevel": { "Default": "Warning" } }, "AllowedHosts": "*", "PackageServiceUri": "https://packageservicefunction-abc.azurewebsites.net/api/packages/", "PackageServiceFunctionCode": "SvrbiyhjXJUdTPXrkcUtY6bQaUf7OXQjWvnM0Gq63hFUhbH2vn6qYA==" }按 Ctrl+S 保存文件,然后按 Ctrl+Q 关闭代码编辑器。
运行以下命令,将更新的应用程序部署到应用服务。
zip -r DroneDelivery-after.zip . -x \*/obj/\* \*/bin/\* az webapp deploy \ --resource-group "<rgn>[sandbox resource group]</rgn>" \ --name $APPSERVICENAME \ --src-path DroneDelivery-after.zip重新部署网站后,刷新页面。 现在应该已经更新了。
测试新体系结构的性能
现在,资源约束服务已移动到在 Azure Functions 上运行的微服务,让我们看看此更改如何影响应用程序性能。
在网站的主页上,选择“ 发送请求”。 此操作将您的整体应用的请求提交到运行在 Azure 函数上的微服务。
第一次尝试可能会给出与整体应用程序类似的结果。 刷新页面,并在出现提示时重新提交请求。 执行此步骤多次,应看到 1 秒内发送的 100 条消息。
启动函数应用时初始尝试速度较慢。 启动并运行后,响应时间优于此代码在整体体系结构中运行时。
现在,此体系结构几乎可以无限扩展,同时仍提供相同的性能。 通过将此应用程序代码移动到微服务,我们提高了 5 到 10 倍的性能。 由于 Fabrikam 拥有此服务的专用开发团队,他们能够对这个微服务进行迭代开发,从而实现更高的敏捷性和更频繁的功能发布带来的好处。