[翻譯] 使用 Serverless 和 .NET Core 構建飛速發展的架構

来源:https://www.cnblogs.com/Rwing/archive/2019/12/02/fast-growing-architectures-with-serverless-and-net-core.html
-Advertisement-
Play Games

Serverless 技術為開發人員提供了一種快速而獨立的方式將實現投入生產。這種技術在企業的技術棧中日益流行,自 2017 年以來,它一直是 ThoughtWorks 技術雷達的實驗級別的技術[譯註:技術雷達是 ThoughtWorks 每半年發佈的前沿技術解析]。 本篇文章的第一部分介紹了... ...


原文:Fast growing architectures with serverless and .NET Core
作者:Samuele Resca

Serverless 技術為開發人員提供了一種快速而獨立的方式將實現投入生產。這種技術在企業的技術棧中日益流行,自 2017 年以來,它一直是 ThoughtWorks 技術雷達的實驗級別的技術[譯註:技術雷達是 ThoughtWorks 每半年發佈的前沿技術解析]。

本篇文章的第一部分介紹了有關 Serverless 計算的基本概念。第二部分展示瞭如何構建 .NET Core 的 Lambda 函數,其中使用了 AWS 的 Serverless 框架。

Serverless 計算的好處

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

此外,典型的軟體服務和系統會通過在記憶體中保留大量數據併在複雜數據源中寫入成批數據來完成操作。
然而一般而言,像 Serverless 一樣的 FaaS 技術旨在通過儘可能快地處理許多小請求和事件,來使我們的系統保持快速響應。Serverless 組件通常與運行它們的雲服務商所提供的事件緊密耦合:一個通知、一個隊列調度的事件或者一個來自 API 網關的請求,都被視為此組件中包含的一小部分計算的觸發器。這也就是雲服務商的定價系統基於請求數而不是基於計算時間的主要原因。

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

最後,我們還應該知道 serverless 函數是無狀態的。因此,基於此技術構建的每個系統都更加模塊化和松耦合。

Serverless 的痛點

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

其次,就像微服務架構一樣,它具有大量的服務,但是關註的範圍很小,因此很難對 serverless 的組件進行監控,某些問題也很難檢測。總之,很難對不同的 serverless 組件之間的體繫結構和依賴性有一個全面的認識。因此,雲提服務商和第三方公司都在提供監控和系統分析功能的一體式工具上投入了大量資金。

體驗一下 serverless 計算

現如今,根據業務需求快速進化的架構以往任何時候都更為重要。數據驅動的體驗是這個過程的一部分。此外,在發佈新功能之前,我們應該實現MVP(譯註:最小可行化產品)併在部分客戶群上測試它。如果實驗結果是肯定的,則值得在MVP上進行投資,以將其轉化為我們產品的功能。

是的,serverless 計算提供了這樣一種方法,可以在不考慮基礎設施的情況下快速進化我們的架構。Serverless 輕量級開銷提供了一種實現一次性 MVP 的方法,用於試驗新功能和新特性。此外,它們還可以很容易地啟動和關閉。

使用 .NET Core 來實現 AWS Lambda 函數

這一節將介紹使用 .NET Core 的一些 AWS Lambdas 的簡單實現。該例子涉及三個關鍵技術:

  • AWS 是承載我們 serverless 功能的雲服務商;
  • serverless 框架,它是將 Lambdas 放入 AWS 的非常有用的工具。作為一個通用的框架,它相容所有主要的雲服務商;
  • .NET Core 是微軟提供的開源的、跨平臺的框架;

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

AWS Lambda 項目遵循以下功能架構:

總結一下,該功能實現了對數據的一些讀取/寫入操作。客戶端通過API網關發出HTTP請求,lambda 項目定義了三個函數:GetItem、InsertItem 和 UpdateItem。它們都對 DynamoDB 表進行操作。

項目結構

我們將要實現的解決方案具有以下項目結構:

  • src/DotNetServerless.Application 該項目包含了由 Serverless 執行的核心邏輯;
  • src/DotNetServerless.Lambda 該項目包含了 Serverless 函數的入口點以及所有與 AWS 緊密耦合的組件;
  • tests/DotNetServerless.Tests 該項目包含了 Serverless 功能的單元測試和集成測試;

領域項目

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

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; }
  }
}

實體的欄位使用了一些特性進行修飾,以便使用 DynamoDb 存儲模型映射它們。Item 實體被 IItemsRepository 介面引用,該介面定義用於存儲數據的操作:

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 的實現定義了兩個基本操作:

  • Save,允許調用者插入和更新實體;
  • GetById,根據 ID 返回對象;

最後,DotNetServerless.Application 的頂層是 Handler 部分。並且
,整個 application 項目都基於中介模式,以保證 AWS 函數和核心邏輯之間的鬆散耦合。讓我們以創建項目處理程式的定義為例:

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 實現了 IRequestHandler,它使用內置的依賴註入來解析 IItemRepository 介面。處理程式的 Handler 方法僅將傳入的請求與Item實體映射,並調用IItemRepository介面提供的Save方法。

函數項目

函數項目包含 lambda 功能的入口點。它定義了三個函數類,它們表示 AWS 的 lambda:CreateItemFunction, GetItemFunction 和 UpdateItemFunction; 稍後我們將看到,每個函數都將使用 API 網關的特定路由進行映射。

讓我們以 CreateItem 函數為例,對函數定義進行一些深入探討:

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)};
    }
  }
}

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

依賴註入

該項目使用了 .NET Core 內置的依賴註入。Startup 類定義了 BuildContainer 靜態方法,該方法返回一個新的 ServiceCollection,其中包含實體之間的依賴關係映射:

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並與其一起解決依賴關係。此外,它還使用 BindAndConfigure 方法創建一些配置對象。BuildContainer方法將由函數調用,以解決依賴項。

測試我們的代碼

如前所述,測試一下我們的代碼,對於持續集成和交付是非常重要的,尤其是在lambda項目中。在這種情況下,測試將覆蓋 IMediator 介面和處理程式之間的集成。此外,它們還覆蓋了依賴項註入部分。讓我們看看 CreateItemFunctionTests 的實現:

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);
    }
  }
}

如您所見,上述代碼執行了我們的函數,並且對已註入的依賴項執行一些驗證,並驗證 IItemRepository 公開的 Save 方法是否被調用。因為一些原因,測試類並沒有覆蓋 DynamoDb 的特性。此外,當我們將複雜的實體和操作結合在一起時,可以使用 Docker 容器通過一些集成測試來覆蓋資料庫部分。對了,提到 .NET Core 和 AWS 的話題,.NET AWS 團隊有一個很好的工具來改進 lambda 的測試:LambdaTestTool

部署項目

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

serverless 框架是一個 CLI 工具,允許用戶構建和部署自動縮放、按執行付費、事件驅動的函數。

為了把 serverless 添加我們的項目,我們應該執行以下命令:

npm install serverless --save-dev

定義基礎架構

預設情況下,基礎架構的定義將放在 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 對基礎架構進行一些操作。provider 節點定義了有關 lambda 的某些信息,例如堆棧名稱、運行時以及有關AWS賬戶的一些信息。此外,它還描述了 lambda 的角色和授權,例如,應該允許 lambda 對 DynamoDb 表執行操作。 functions 節點定義了不同的 lambda 函數,並將其與特定的 HTTP 路徑進行映射。最後,resources 節點用於設置 DynamoDB 表模式。

配置文件

serverless.yml 定義通常與另一個 YAML 文件結合使用,該文件僅定義與環境相關的配置。例如,DynamoDbConfiguration__TableName 節點就是這種情況,該節點使用以下語法從另一個 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>

最後的想法

這篇文章涵蓋了一些關於 serverless 計算的理論主題,以及 .Net Core 實現 lambda 函數的例子。著重講解瞭如何使用 serverless 計算來快速推進我們的架構。此外,勇於嘗試是一個不斷發展的產品很關鍵的一方面,它對於快速適應業務的變化是很重要的。

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


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • Swoole進程間通信的方式 管道pipe 管道用於進程之間的數據交互,Linux系統本身提供了pipe函數用於創建一個半雙工通信管道。半雙工的通信方式中數據只能單向流動(一端只讀一端只寫),只能在具有親緣關係(父子進程)的進程之間使用。 管道是進程間通信IPC中最基礎的方式,管道有兩種類型分別是命 ...
  • 網上體育商城的主要功能包括:前臺用戶登錄退出、註冊、線上購物、修改個人信息、後臺商品管理等等。本系統結構如下:(1)商品瀏覽模塊: 首頁瀏覽最新上市商品,按銷量排行顯示商品 實現根據商品名稱搜索商品信息 實現根據商品分類瀏覽商品(2)登錄、註冊: 購物前需要登錄,如果沒有賬號則可以先註冊(3)線上留 ...
  • 用於註解說明解釋程式的文字就是註釋。 提高代碼的閱讀性;調試程式的重要方法。 java中的註釋類型: 單行註釋 // 多行註釋 /* */ 文檔註釋 /** *文檔註釋 *輸出hello world *@author fang *@version 1.0.0 */ 註釋是一個程式員必須具備的良好編程 ...
  • [TOC] 1. 對Django的認識? 2. Django 、Flask、Tornado的對比 3. 什麼是wsgi,uwsgi,uWSGI? 4. django請求的生命周期? 5. 簡述什麼是FBV和CBV? 6. 如何給CBV的程式添加裝飾器? 7. 簡述MVC和MTV 8. django路 ...
  • 1、步驟 將java代碼編寫到擴展名為.java的文件中(擴展名的查看) 新建文本文檔,重命名為Test.java 以記事本方式打開 寫入代碼 public class Test{ public static void main(String[] args){ System.out.print("H ...
  • 直接看網址吧,所有的GO GUI代碼!~~~~ "網址" ...
  • 1、下載JDK 下載地址 https://www.oracle.com/technetwork/java/javase/downloads/index.html 2、安裝JDK 傻瓜安裝 3、配置環境 新建JAVA_HOME環境變數 新建classpath環境變數 新增Path變數 4、查看是否安裝 ...
  • 1.報錯,too many open files 查詢方法:查看linux允許的最大句柄數,命令ulimit -a。然後使用命令lsof -p 進程id可以查看單個進程所有打開的文件詳情,使用命令lsof -p 進程id | wc -l可以統計進程打開了多少文件,如果文件數過多使用lsof -p 進 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...