日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > asp.net >内容正文

asp.net

[翻译] 使用 Serverless 和 .NET Core 构建飞速发展的架构

發(fā)布時間:2023/12/4 asp.net 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [翻译] 使用 Serverless 和 .NET Core 构建飞速发展的架构 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

作者:Samuele Resca

Serverless 技術(shù)為開發(fā)人員提供了一種快速而獨(dú)立的方式將實現(xiàn)投入生產(chǎn)。這種技術(shù)在企業(yè)的技術(shù)棧中日益流行,自 2017 年以來,它一直是 ThoughtWorks 技術(shù)雷達(dá)的實驗級別的技術(shù)[譯注:技術(shù)雷達(dá)是 ThoughtWorks 每半年發(fā)布的前沿技術(shù)解析]。

本篇文章的第一部分介紹了有關(guān) Serverless 計算的基本概念。第二部分展示了如何構(gòu)建 .NET Core 的 Lambda 函數(shù),其中使用了 AWS 的 Serverless 框架。

Serverless 計算的好處

Serverless 技術(shù)是 FaaS(功能即服務(wù))技術(shù)體系的一部分。隨著云計算的采用,這些技術(shù)變得越來越受歡迎。如今,serverless 實現(xiàn)被提升為云計算提供商的首選技術(shù),無論是私有云還是公有云。

此外,典型的軟件服務(wù)和系統(tǒng)會通過在內(nèi)存中保留大量數(shù)據(jù)并在復(fù)雜數(shù)據(jù)源中寫入成批數(shù)據(jù)來完成操作。
然而一般而言,像 Serverless 一樣的 FaaS 技術(shù)旨在通過盡可能快地處理許多小請求和事件,來使我們的系統(tǒng)保持快速響應(yīng)。Serverless 組件通常與運(yùn)行它們的云服務(wù)商所提供的事件緊密耦合:一個通知、一個隊列調(diào)度的事件或者一個來自 API 網(wǎng)關(guān)的請求,都被視為此組件中包含的一小部分計算的觸發(fā)器。這也就是云服務(wù)商的定價系統(tǒng)基于請求數(shù)而不是基于計算時間的主要原因。

再者,serverless 組件通常在執(zhí)行時間上有一些限制。與每種技術(shù)一樣,serverless 并不適合每一個解決方案和系統(tǒng)。但是事實上,它確實簡化了軟件工程師的一些工作,lambda 部署周期通常很快,開發(fā)人員只需要做少量工作就可以快速將新功能投入生產(chǎn)。此外,使用 serverless 技術(shù)構(gòu)建組件意味著開發(fā)人員無需擔(dān)心擴(kuò)展問題或故障,讓云提供商去關(guān)心這些問題吧。

最后,我們還應(yīng)該知道 serverless 函數(shù)是無狀態(tài)的。因此,基于此技術(shù)構(gòu)建的每個系統(tǒng)都更加模塊化和松耦合。

Serverless 的痛點(diǎn)

但是這種能力和敏捷性卻不是沒有代價的。首先,serverless 函數(shù)是在云上執(zhí)行的,它們通常由與云提供商緊密耦合的事件觸發(fā),因此調(diào)試它們并不容易。這就是為什么要使它的作用域保持盡可能小,并且始終將函數(shù)的核心邏輯與外部組件和事件分隔開的原因。此外,用單元測試和集成測試覆蓋 serverless 代碼非常重要。

其次,就像微服務(wù)架構(gòu)一樣,它具有大量的服務(wù),但是關(guān)注的范圍很小,因此很難對 serverless 的組件進(jìn)行監(jiān)控,某些問題也很難檢測。總之,很難對不同的 serverless 組件之間的體系結(jié)構(gòu)和依賴性有一個全面的認(rèn)識。因此,云提服務(wù)商和第三方公司都在提供監(jiān)控和系統(tǒng)分析功能的一體式工具上投入了大量資金。

體驗一下 serverless 計算

現(xiàn)如今,根據(jù)業(yè)務(wù)需求快速進(jìn)化的架構(gòu)以往任何時候都更為重要。數(shù)據(jù)驅(qū)動的體驗是這個過程的一部分。此外,在發(fā)布新功能之前,我們應(yīng)該實現(xiàn)MVP(譯注:最小可行化產(chǎn)品)并在部分客戶群上測試它。如果實驗結(jié)果是肯定的,則值得在MVP上進(jìn)行投資,以將其轉(zhuǎn)化為我們產(chǎn)品的功能。

是的,serverless 計算提供了這樣一種方法,可以在不考慮基礎(chǔ)設(shè)施的情況下快速進(jìn)化我們的架構(gòu)。Serverless 輕量級開銷提供了一種實現(xiàn)一次性 MVP 的方法,用于試驗新功能和新特性。此外,它們還可以很容易地啟動和關(guān)閉。

使用 .NET Core 來實現(xiàn) AWS Lambda 函數(shù)

這一節(jié)將介紹使用 .NET Core 的一些 AWS Lambdas 的簡單實現(xiàn)。該例子涉及三個關(guān)鍵技術(shù):

  • AWS 是承載我們 serverless 功能的云服務(wù)商;

  • serverless 框架,它是將 Lambdas 放入 AWS 的非常有用的工具。作為一個通用的框架,它兼容所有主要的云服務(wù)商;

  • .NET Core 是微軟提供的開源的、跨平臺的框架;

我們將要討論的示例也放在了 GitHub 上,URL 如下:?serverless/examples/aws-dotnet-rest-api-with-dynamodb。該示例是 serverless 框架提供的一些模板項目的一部分。

AWS Lambda 項目遵循以下功能架構(gòu):

總結(jié)一下,該功能實現(xiàn)了對數(shù)據(jù)的一些讀取/寫入操作。客戶端通過API網(wǎng)關(guān)發(fā)出HTTP請求,lambda 項目定義了三個函數(shù):GetItem、InsertItem 和 UpdateItem。它們都對 DynamoDB 表進(jìn)行操作。

項目結(jié)構(gòu)

我們將要實現(xiàn)的解決方案具有以下項目結(jié)構(gòu):

  • src/DotNetServerless.Application 該項目包含了由 Serverless 執(zhí)行的核心邏輯;

  • src/DotNetServerless.Lambda 該項目包含了 Serverless 函數(shù)的入口點(diǎn)以及所有與 AWS 緊密耦合的組件;

  • tests/DotNetServerless.Tests 該項目包含了 Serverless 功能的單元測試和集成測試;

領(lǐng)域項目

讓我們從 application 層開始分析。項目的核心實體是 Item 類,它表示 DynamoDB(譯注:AWS的一種數(shù)據(jù)庫) 表中存儲的實體:

using Amazon.DynamoDBv2.DataModel;

namespace DotNetServerless.Application.Entity
{
public class Item
{
[DynamoDBHashKey]
public string Id { get; set; }
[DynamoDBRangeKey]
public string Code { get; set; }
[DynamoDBProperty]
public string Description { get; set; }
[DynamoDBProperty]
public bool IsChecked { get; set; }
}
}

實體的字段使用了一些特性進(jìn)行修飾,以便使用 DynamoDb 存儲模型映射它們。Item 實體被 IItemsRepository 接口引用,該接口定義用于存儲數(shù)據(jù)的操作:

using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.DataModel;
using Amazon.DynamoDBv2.DocumentModel;
using DotNetServerless.Application.Entities;
using DotNetServerless.Application.Infrastructure.Configs;

namespace DotNetServerless.Application.Infrastructure.Repositories
{
public interface IItemRepository
{
Task<IEnumerable<T>> GetById<T>(string id, CancellationToken cancellationToken);

Task Save(Item item, CancellationToken cancellationToken);
}

public class ItemDynamoRepository : IItemRepository
{
private readonly AmazonDynamoDBClient _client;
private readonly DynamoDBOperationConfig _configuration;

public ItemDynamoRepository(DynamoDbConfiguration configuration,
IAwsClientFactory<AmazonDynamoDBClient> clientFactory)
{
_client = clientFactory.GetAwsClient();
_configuration = new DynamoDBOperationConfig
{
OverrideTableName = configuration.TableName,
SkipVersionCheck = true
};
}

public async Task Save(Item item, CancellationToken cancellationToken)
{
using (var context = new DynamoDBContext(_client))
{
await context.SaveAsync(item, _configuration, cancellationToken);
}
}

public async Task<IEnumerable<T>> GetById<T>(string id, CancellationToken cancellationToken)
{
var resultList = new List<T>();
using (var context = new DynamoDBContext(_client))
{
var scanCondition = new ScanCondition(nameof(Item.Id), ScanOperator.Equal, id);
var search = context.ScanAsync<T>(new[] {scanCondition}, _configuration);

while (!search.IsDone)
{
var entities = await search.GetNextSetAsync(cancellationToken);
resultList.AddRange(entities);
}
}

return resultList;
}
}
}

IItemRepository 的實現(xiàn)定義了兩個基本操作:

  • Save,允許調(diào)用者插入和更新實體;

  • GetById,根據(jù) ID 返回對象;

最后,DotNetServerless.Application 的頂層是 Handler 部分。并且
,整個 application 項目都基于中介模式,以保證 AWS 函數(shù)和核心邏輯之間的松散耦合。讓我們以創(chuàng)建項目處理程序的定義為例:

using System;
using System.Threading;
using System.Threading.Tasks;
using DotNetServerless.Application.Entities;
using DotNetServerless.Application.Infrastructure.Repositories;
using DotNetServerless.Application.Requests;
using MediatR;

namespace DotNetServerless.Application.Handlers
{
public class CreateItemHandler : IRequestHandler<CreateItemRequest, Item>
{
private readonly IItemRepository _itemRepository;

public CreateItemHandler(IItemRepository itemRepository)
{
_itemRepository = itemRepository;
}

public async Task<Item> Handle(CreateItemRequest request, CancellationToken cancellationToken)
{
var item = request.Map();
item.Id = Guid.NewGuid().ToString();

await _itemRepository.Save(item, cancellationToken);

return item;
}
}
}

如您所見,代碼非常簡單。CreateItemHandler 實現(xiàn)了 IRequestHandler,它使用內(nèi)置的依賴注入來解析 IItemRepository 接口。處理程序的 Handler 方法僅將傳入的請求與Item實體映射,并調(diào)用IItemRepository接口提供的Save方法。

函數(shù)項目

函數(shù)項目包含 lambda 功能的入口點(diǎn)。它定義了三個函數(shù)類,它們表示 AWS 的 lambda:CreateItemFunction, GetItemFunction 和 UpdateItemFunction; 稍后我們將看到,每個函數(shù)都將使用 API 網(wǎng)關(guān)的特定路由進(jìn)行映射。

讓我們以 CreateItem 函數(shù)為例,對函數(shù)定義進(jìn)行一些深入探討:

using System;
using System.Threading.Tasks;
using Amazon.Lambda.APIGatewayEvents;
using Amazon.Lambda.Core;
using DotNetServerless.Application.Requests;
using MediatR;
using Microsoft.Extensions.DependencyInjection;
using Newtonsoft.Json;

namespace DotNetServerless.Lambda.Functions
{
public class CreateItemFunction
{
private readonly IServiceProvider _serviceProvider;

public CreateItemFunction() : this(Startup
.BuildContainer()
.BuildServiceProvider())
{
}

public CreateItemFunction(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}

[LambdaSerializer(typeof(Amazon.Lambda.Serialization.Json.JsonSerializer))]
public async Task<APIGatewayProxyResponse> Run(APIGatewayProxyRequest request)
{
var requestModel = JsonConvert.DeserializeObject<CreateItemRequest>(request.Body);
var mediator = _serviceProvider.GetService<IMediator>();

var result = await mediator.Send(requestModel);

return new APIGatewayProxyResponse { StatusCode = 201, Body = JsonConvert.SerializeObject(result)};
}
}
}

上面提到的代碼定義了函數(shù)的入口點(diǎn)。首先,它聲明一個構(gòu)造函數(shù),并使用Startup類公開的BuildContainer和BuildServiceProvider方法。稍后我們將看到,這些方法是為初始化依賴項注入容器而提供的。CreateItem 函數(shù)的 Run 方法使用 Lambda 序列器屬性進(jìn)行修飾,這意味著它是函數(shù)的入口點(diǎn)。此外,運(yùn)行函數(shù)使用 APIGatewayProxyRequest 請求和 APIGatewayProxyReposne 作為 lambda 計算的輸入和輸出。

依賴注入

該項目使用了 .NET Core 內(nèi)置的依賴注入。Startup 類定義了 BuildContainer 靜態(tài)方法,該方法返回一個新的 ServiceCollection,其中包含實體之間的依賴關(guān)系映射:

using System.IO;
using DotNetServerless.Application.Infrastructure;
using DotNetServerless.Application.Infrastructure.Configs;
using DotNetServerless.Application.Infrastructure.Repositories;
using DotNetServerless.Lambda.Extensions;
using MediatR;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;

namespace DotNetServerless.Lambda
{
public class Startup
{
public static IServiceCollection BuildContainer()
{
var configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddEnvironmentVariables()
.Build();

return ConfigureServices(configuration);
}


private static IServiceCollection ConfigureServices(IConfigurationRoot configurationRoot)
{
var services = new ServiceCollection();

services
.AddMediatR()
.AddTransient(typeof(IAwsClientFactory<>), typeof(AwsClientFactory<>))
.AddTransient<IItemRepository, ItemDynamoRepository>()
.BindAndConfigure(configurationRoot.GetSection("DynamoDbConfiguration"), new DynamoDbConfiguration())
.BindAndConfigure(configurationRoot.GetSection("AwsBasicConfiguration"), new AwsBasicConfiguration());

return services;
}
}
}

Startup使用ConfigureServices初始化新的ServiceCollection并與其一起解決依賴關(guān)系。此外,它還使用 BindAndConfigure 方法創(chuàng)建一些配置對象。BuildContainer方法將由函數(shù)調(diào)用,以解決依賴項。

測試我們的代碼

如前所述,測試一下我們的代碼,對于持續(xù)集成和交付是非常重要的,尤其是在lambda項目中。在這種情況下,測試將覆蓋 IMediator 接口和處理程序之間的集成。此外,它們還覆蓋了依賴項注入部分。讓我們看看 CreateItemFunctionTests 的實現(xiàn):

using System.Threading;
using System.Threading.Tasks;
using Amazon.Lambda.APIGatewayEvents;
using DotNetServerless.Application.Entities;
using DotNetServerless.Application.Infrastructure.Repositories;
using DotNetServerless.Application.Requests;
using DotNetServerless.Lambda;
using DotNetServerless.Lambda.Functions;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Moq;
using Newtonsoft.Json;
using Xunit;

namespace DotNetServerless.Tests.Functions
{
public class CreateItemFunctionTests
{
public CreateItemFunctionTests()
{
_mockRepository = new Mock<IItemRepository>();
_mockRepository.Setup(_ => _.Save(It.IsAny<Item>(), It.IsAny<CancellationToken>())).Returns(Task.CompletedTask);

var serviceCollection = Startup.BuildContainer();

serviceCollection.Replace(new ServiceDescriptor(typeof(IItemRepository), _ => _mockRepository.Object,
ServiceLifetime.Transient));

_sut = new CreateItemFunction(serviceCollection.BuildServiceProvider());
}

private readonly CreateItemFunction _sut;
private readonly Mock<IItemRepository> _mockRepository;

[Fact]
public async Task run_should_trigger_mediator_handler_and_repository()
{
await _sut.Run(new APIGatewayProxyRequest {Body = JsonConvert.SerializeObject(new CreateItemRequest())});
_mockRepository.Verify(_ => _.Save(It.IsAny<Item>(), It.IsAny<CancellationToken>()), Times.Once);
}

[Theory]
[InlineData(201)]
public async Task run_should_return_201_created(int statusCode)
{
var result = await _sut.Run(new APIGatewayProxyRequest {Body = JsonConvert.SerializeObject(new CreateItemRequest())});
Assert.Equal(result.StatusCode, statusCode);
}
}
}

如您所見,上述代碼執(zhí)行了我們的函數(shù),并且對已注入的依賴項執(zhí)行一些驗證,并驗證 IItemRepository 公開的 Save 方法是否被調(diào)用。因為一些原因,測試類并沒有覆蓋 DynamoDb 的特性。此外,當(dāng)我們將復(fù)雜的實體和操作結(jié)合在一起時,可以使用 Docker 容器通過一些集成測試來覆蓋數(shù)據(jù)庫部分。對了,提到 .NET Core 和 AWS 的話題,.NET AWS 團(tuán)隊有一個很好的工具來改進(jìn) lambda 的測試:LambdaTestTool

部署項目

讓我們來看看如何將項目導(dǎo)入AWS。為此,我們將使用?serverless 框架。該框架的定義是:

serverless 框架是一個 CLI 工具,允許用戶構(gòu)建和部署自動縮放、按執(zhí)行付費(fèi)、事件驅(qū)動的函數(shù)。

為了把 serverless 添加我們的項目,我們應(yīng)該執(zhí)行以下命令:

npm install serverless --save-dev

定義基礎(chǔ)架構(gòu)

默認(rèn)情況下,基礎(chǔ)架構(gòu)的定義將放在 serverless.yml 文件中。該文件看起來像這樣:

service: ${file(env.configs.yml):feature}

frameworkVersion: ">=1.6.0 <2.1.0"

provider:
name: aws
stackName: ${file(env.configs.yml):feature}-${file(env.configs.yml):environment}
runtime: dotnetcore2.1
region: ${file(env.configs.yml):region}
accountId: ${file(env.configs.yml):accountId}
environment:
DynamoDbConfiguration__TableName: ${file(env.configs.yml):dynamoTable}

iamRoleStatements:
- Effect: Allow
Action:
- dynamodb:*
Resource: "arn:aws:dynamodb:${self:provider.region}:*:table/${self:provider.environment.DynamoDbConfiguration__TableName}"

package:
artifact: bin/release/netcoreapp2.1/deploy-package.zip

functions:
create:
handler: DotNetServerless.Lambda::DotNetServerless.Lambda.Functions.CreateItemFunction::Run
events:
- http:
path: items
method: post
cors: true

get:
handler: DotNetServerless.Lambda::DotNetServerless.Lambda.Functions.GetItemFunction::Run
events:
- http:
path: items/{id}
method: get
cors: true

update:
handler: DotNetServerless.Lambda::DotNetServerless.Lambda.Functions.UpdateItemFunction::Run
events:
- http:
path: items
method: put
cors: true

resources:
Resources:
ItemsDynamoDbTable:
Type: 'AWS::DynamoDB::Table'
DeletionPolicy: Retain
Properties:
AttributeDefinitions:
- AttributeName: Id
AttributeType: S
- AttributeName: Code
AttributeType: S
KeySchema:
- AttributeName: Id
KeyType: HASH
- AttributeName: Code
KeyType: RANGE
ProvisionedThroughput:
ReadCapacityUnits: 1
WriteCapacityUnits: 1
TableName: ${self:provider.environment.DynamoDbConfiguration__TableName}

以上代碼使用 AWS 的 cloud formation 對基礎(chǔ)架構(gòu)進(jìn)行一些操作。provider 節(jié)點(diǎn)定義了有關(guān) lambda 的某些信息,例如堆棧名稱、運(yùn)行時以及有關(guān)AWS賬戶的一些信息。此外,它還描述了 lambda 的角色和授權(quán),例如,應(yīng)該允許 lambda 對 DynamoDb 表執(zhí)行操作。functions 節(jié)點(diǎn)定義了不同的 lambda 函數(shù),并將其與特定的 HTTP 路徑進(jìn)行映射。最后,resources 節(jié)點(diǎn)用于設(shè)置 DynamoDB 表模式。

配置文件

serverless.yml 定義通常與另一個 YAML 文件結(jié)合使用,該文件僅定義與環(huán)境相關(guān)的配置。例如,DynamoDbConfiguration__TableName?節(jié)點(diǎn)就是這種情況,該節(jié)點(diǎn)使用以下語法從另一個 YAML 文件獲取信息:${file(env.configs.yml):dynamoTable}。以下代碼段顯示了 env.config.yml 文件的一個示例:

feature: <feature_name>
version: 1.0.0.0
region: <aws_region>
environment: <environment>
accountId: <aws_account_id>
dynamoTable: <dynamo_table_name>

最后的想法

這篇文章涵蓋了一些關(guān)于 serverless 計算的理論主題,以及 .Net Core 實現(xiàn) lambda 函數(shù)的例子。著重講解了如何使用 serverless 計算來快速推進(jìn)我們的架構(gòu)。此外,勇于嘗試是一個不斷發(fā)展的產(chǎn)品很關(guān)鍵的一方面,它對于快速適應(yīng)業(yè)務(wù)的變化是很重要的。

最后,您可以在以下存儲庫中找到一些 serverless 的 lambda 示例。
serverless/examples/aws-dotnet-rest-api-with-dynamodb

原文鏈接:https://www.cnblogs.com/Rwing/p/fast-growing-architectures-with-serverless-and-net-core.html


.NET社區(qū)新聞,深度好文,歡迎訪問公眾號文章匯總?http://www.csharpkit.com?

總結(jié)

以上是生活随笔為你收集整理的[翻译] 使用 Serverless 和 .NET Core 构建飞速发展的架构的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。