(一)微服務(垂直AP/分布式緩存/裝飾器Pattern)


文章目錄

  • 項目地址
  • 一、創建第一個垂直API
    • 1.1 創建Common層
      • 1. ICommand接口
      • 2. IQuery接口
    • 1.2 創建API
      • 1. 實體
      • 2. Handler
      • 3. endpoint
    • 1.3 使用Marten作為ORM
  • 二、Redis緩存
    • 2.1 使用緩存裝飾器
      • 1. 創建裝飾器
      • 2. 注冊裝飾器
    • 2.2 創建docker-compose
      • 1. docker-compose
      • 2. docker-compose.override


項目地址

  • 教程作者:
  • 教程地址:
  • 代碼倉庫地址:
  • 所用到的框架和插件:
dbt 
airflow

一、創建第一個垂直API

1.1 創建Common層

在這里插入圖片描述

1. ICommand接口

  1. ICommand.cs
using MediatR;
namespace BuildingBlocks.CQRS;
public interface ICommand : ICommand<Unit>; 
public interface ICommand<out TResponse> : IRequest<TResponse>;
  1. ICommandHandler.cs
using MediatR;
namespace BuildingBlocks.CQRS;
public interface ICommandHandler<in TCommand>  //無返回值: ICommandHandler<TCommand, Unit>where TCommand : ICommand<Unit>;public interface ICommandHandler<in TCommand, TResponse> //有返回值: IRequestHandler<TCommand, TResponse>where TCommand : ICommand<TResponse>where TResponse : notnull;

in(Contravariant):只在參數中使用的泛型類型

2. IQuery接口

  1. IQuery.cs
using MediatR;
namespace BuildingBlocks.CQRS;
public interface IQuery<out TResponse> : IRequest<TResponse>  where TResponse : notnull;
  1. IQueryHandler:
namespace BuildingBlocks.CQRS;
public interface IQueryHandler<in TQuery, TResponse>: IRequestHandler<TQuery, TResponse>where TQuery : IQuery<TResponse>where TResponse : notnull;

1.2 創建API

在這里插入圖片描述

1. 實體

namespace Catalog.API.Models;
public class Product
{public Guid Id { get; set; }public string Name { get; set; } = default!;public List<string> Category { get; set; } = new();public string Description { get; set; } = default!;public string ImageFile { get; set; } = default!;public decimal Price { get; set; }
}

2. Handler

namespace Catalog.API.Products.CreateProduct;
public record CreateProductCommand(string Name, List<string> Category, string Description, string ImageFile, decimal Price): ICommand<CreateProductResult>;
public record CreateProductResult(Guid Id);internal class CreateProductCommandHandler : ICommandHandler<CreateProductCommand, CreateProductResult>
{public async Task<CreateProductResult> Handle(CreateProductCommand command, CancellationToken cancellationToken){var product = new Product{Name = command.Name,Category = command.Category,Description = command.Description,ImageFile = command.ImageFile,Price = command.Price};return new CreateProductResult(Guid.NewGuid());        }
}

3. endpoint

namespace Catalog.API.Products.CreateProduct;
public record CreateProductRequest(string Name, List<string> Category, string Description, string ImageFile, decimal Price);
public record CreateProductResponse(Guid Id);
public class CreateProductEndpoint : ICarterModule
{public void AddRoutes(IEndpointRouteBuilder app){app.MapPost("/products",async (CreateProductRequest request, ISender sender) =>{var command = request.Adapt<CreateProductCommand>();var result = await sender.Send(command);var response = result.Adapt<CreateProductResponse>();return Results.Created($"/products/{response.Id}", response);}).WithName("CreateProduct").Produces<CreateProductResponse>(StatusCodes.Status201Created).ProducesProblem(StatusCodes.Status400BadRequest).WithSummary("Create Product").WithDescription("Create Product");}
}

1.3 使用Marten作為ORM

  • Marten只能用于postgresql的ORM使用

二、Redis緩存

2.1 使用緩存裝飾器

1. 創建裝飾器

  • 給basket添加裝飾器,原來的 var basket = await repository.GetBasket(userName, cancellationToken);被其他的方法包裹,這樣就被裝飾了
 namespace Basket.API.Data;public class CachedBasketRepository(IBasketRepository repository, IDistributedCache cache) : IBasketRepository
{public async Task<ShoppingCart> GetBasket(string userName, CancellationToken cancellationToken = default){var cachedBasket = await cache.GetStringAsync(userName, cancellationToken);if (!string.IsNullOrEmpty(cachedBasket))return JsonSerializer.Deserialize<ShoppingCart>(cachedBasket)!;var basket = await repository.GetBasket(userName, cancellationToken);await cache.SetStringAsync(userName, JsonSerializer.Serialize(basket), cancellationToken);return basket;}public async Task<ShoppingCart> StoreBasket(ShoppingCart basket, CancellationToken cancellationToken = default){await repository.StoreBasket(basket, cancellationToken);await cache.SetStringAsync(basket.UserName, JsonSerializer.Serialize(basket), cancellationToken);return basket;}public async Task<bool> DeleteBasket(string userName, CancellationToken cancellationToken = default){await repository.DeleteBasket(userName, cancellationToken);await cache.RemoveAsync(userName, cancellationToken);return true;}
}

2. 注冊裝飾器

  • 安裝需要的包
     <PackageReference Include="Scrutor" Version="4.2.2" /><PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="8.0.1" />
  • 注冊裝飾器
builder.Services.AddScoped<IBasketRepository, BasketRepository>(); //原來的方法
builder.Services.Decorate<IBasketRepository, CachedBasketRepository>();  //裝飾過后帶redis緩存的//注冊redis
builder.Services.AddStackExchangeRedisCache(options =>
{options.Configuration = builder.Configuration.GetConnectionString("Redis");//options.InstanceName = "Basket";
});  
  • 配置redis 的ConnectionString
 appsettings.json

2.2 創建docker-compose

1. docker-compose

  1. docker-compose.yml 用來說明微服務需要的Container有哪些
version: '3.4'
services:catalogdb:image: postgresbasketdb:image: postgresdistributedcache:image: rediscatalog.api:image: ${DOCKER_REGISTRY-}catalogapibuild:context: .dockerfile: Services/Catalog/Catalog.API/Dockerfilebasket.api:image: ${DOCKER_REGISTRY-}basketapibuild:context: .dockerfile: Services/Basket/Basket.API/Dockerfile
volumes:postgres_catalog:postgres_basket:

2. docker-compose.override

  • 用來配置本地具體環境
version: '3.4'services:catalogdb:container_name: catalogdbenvironment:- POSTGRES_USER=postgres- POSTGRES_PASSWORD=postgres- POSTGRES_DB=CatalogDbrestart: alwaysports:- "5432:5432"volumes:- postgres_catalog:/var/lib/postgresql/data/ basketdb:container_name: basketdbenvironment:- POSTGRES_USER=postgres- POSTGRES_PASSWORD=postgres- POSTGRES_DB=BasketDbrestart: alwaysports:- "5433:5432"volumes:- postgres_basket:/var/lib/postgresql/data/ distributedcache:container_name: distributedcacherestart: alwaysports:- "6379:6379"catalog.api:environment:- ASPNETCORE_ENVIRONMENT=Development- ASPNETCORE_HTTP_PORTS=8080- ASPNETCORE_HTTPS_PORTS=8081- ConnectionStrings__Database=Server=catalogdb;Port=5432;Database=CatalogDb;User Id=postgres;Password=postgres;Include Error Detail=truedepends_on:- catalogdbports:- "6000:8080"- "6060:8081"volumes:- ${APPDATA}/Microsoft/UserSecrets:/home/app/.microsoft/usersecrets:ro- ${APPDATA}/ASP.NET/Https:/home/app/.aspnet/https:robasket.api:environment:- ASPNETCORE_ENVIRONMENT=Development- ASPNETCORE_HTTP_PORTS=8080- ASPNETCORE_HTTPS_PORTS=8081- ConnectionStrings__Database=Server=basketdb;Port=5432;Database=BasketDb;User Id=postgres;Password=postgres;Include Error Detail=true- ConnectionStrings__Redis=distributedcache:6379depends_on:- basketdb- distributedcacheports:- "6001:8080"- "6061:8081"volumes:- ${APPDATA}/Microsoft/UserSecrets:/home/app/.microsoft/usersecrets:ro- ${APPDATA}/ASP.NET/Https:/home/app/.aspnet/https:ro

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/81977.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/81977.shtml
英文地址,請注明出處:http://en.pswp.cn/web/81977.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Spring AI系列之使用 Spring AI 轉錄音頻文件(基于OpenAI)

概述 企業常常需要從各種類型的音頻內容中提取有價值的數據&#xff0c;例如&#xff1a;將客戶支持通話轉錄用于情感分析、為視頻生成字幕&#xff0c;或整理會議紀要。然而&#xff0c;手動轉錄音頻文件既耗時又昂貴。 為了解決這一問題&#xff0c;OpenAI 提供了強大的語…

室內VR全景助力房產營銷及裝修

在當今的地產行業&#xff0c;VR全景已成為不可或缺的應用工具。從地產直播到樓市VR地圖&#xff0c;從效果圖到水電家裝施工記錄&#xff0c;整個地產行業的上下游生態中&#xff0c;云VR全景的身影無處不在。本文將探討VR全景在房產營銷及裝修領域的應用&#xff0c;并介紹眾…

Sentinel限流熔斷機制實戰

1、核心概念 1.1、流量控制 流量控制是為了 防止系統被過多的請求壓垮&#xff0c;確保資源合理分配并保持服務的可用性&#xff0c;比如對請求數量的限制。 流量控制的 3 個主要優勢&#xff1a; 防止過載&#xff1a;當瞬間涌入的請求量超出系統處理能力時&#xff0c;會…

深度解析 torch.mean 的替代方案

torch.mean 是什么意思 代碼效果解釋 segment_vector = torch.mean(segment_embedding, dim=1) # [1, hidden_dim] 這行代碼的作用是在指定維度上對張量 segment_embedding 求平均值,實現類似平均池化的效果。 具體來說,dim=1 表示沿著索引為1的維度進行操作。假設 segment…

Paraformer語音模型:一種語音模型加速方法

隨著智能語音技術的普及&#xff0c;語音識別&#xff08;ASR&#xff09;、語音合成&#xff08;TTS&#xff09;、聲紋識別等應用場景對模型推理效率提出了極高要求&#xff0c;本文介紹將Paraformer語音模型從預訓練模型導出為ONNX格式&#xff0c;并使用ONNX Runtime進行推…

本地部署FreeGPT+內網穿透公網遠程訪問,搞定ChatGPT外網訪問難題

?FreeGPT?是一個基于GPT 3.5/4的ChatGPT聊天網頁用戶界面&#xff0c;提供了一個開放的聊天界面&#xff0c;開箱即用?。ChatGPT是非常熱門的&#xff0c;但訪問體驗一直不太理想。為了解決這一問題&#xff0c;出現了各類方法和工具&#xff0c;其中FreeGPT是一款非常實用的…

ElasticSearch遷移至openGauss

Elasticsearch 作為一種高效的全文搜索引擎&#xff0c;廣泛應用于實時搜索、日志分析等場景。而 openGauss&#xff0c;作為一款企業級關系型數據庫&#xff0c;強調事務處理與數據一致性。那么&#xff0c;當這兩者的應用場景和技術架構發生交集時&#xff0c;如何實現它們之…

品優購項目(HTML\CSS)

項目效果可訪問 http://zhousunyu.3vdo.club 查看 主頁 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><titl…

因泰立科技:鐳眸T51激光雷達,打造智能門控新生態

在高端門控行業&#xff0c;安全與效率是永恒的追求。如今&#xff0c;隨著科技的飛速發展&#xff0c;激光雷達與TOF相機技術的融合&#xff0c;為門控系統帶來了前所未有的智能感知能力&#xff0c;開啟了精準守護的新時代。因泰立科技的鐳眸T51激光雷達&#xff0c;作為這一…

MyBatisPlus--快速入門

MyBatisPlus介紹 從名字中就可以感覺到MybatisPlus與MyBatis之間的淵源&#xff0c;而MyBatis是一個非常流行的持久層框架&#xff0c;主要來做數據庫的增刪改查&#xff0c;而MyBatisPlus這種命名方式讓人不得不往MyBatis的升級版去聯想&#xff0c;事實也確實如此&#xff0…

redis持久化策略

RDB 是通過生成數據快照來實現持久化的&#xff0c;相當于給內存中的數據拍一張"照片"保存到磁盤上。AOF 記錄所有寫操作命令&#xff0c;以Redis協議格式追加到文件末尾。 RDB 在滿足特定條件時觸發內存快照&#xff0c;生成新的RDB文件替換舊文件 AOF 先寫入內…

Spring Boot中使用@JsonAnyGetter和@JsonAnySetter處理動態JSON屬性

Spring Boot 中使用 @JsonAnyGetter 和 @JsonAnySetter 處理動態 JSON 屬性 在實際的后端開發中,尤其是使用 Spring Boot 構建 API 時,我們經常會遇到需要處理動態 JSON 屬性的場景。例如,前端傳遞過來的 JSON 數據結構不固定,或者業務需求變更頻繁,導致實體類無法預先定…

拉取gitlab項目

一、下載nvm管理node 先下載配置好nvm,再用nvm下載node 下載鏈接&#xff1a;開始 下載nvm - nvm中文官網 情況&#xff1a;npm i 下載依賴緩慢&#xff0c;可能是node版本不對&#xff0c;可能node版本太高 可能得問題&#xff1a;使用nvm 下載低版本的node時&#xff0c;…

【解決辦法】ubuntu重啟不起來,輸入用戶名和密碼進不去,又重新返回登錄頁。

項目場景&#xff1a; ubuntu重啟不起來&#xff0c;輸入用戶名和密碼進不去&#xff0c;又重新返回登錄頁。 問題描述 在華碩天選一代筆記本上面安裝了ubuntu22.04.5桌面版&#xff0c;但是重啟以后出現&#xff0c;輸入了用戶名和密碼&#xff0c;等待一會還讓輸入用戶名和…

# 云端大模型:智能時代的新引擎

云端大模型&#xff1a;智能時代的新引擎 在人工智能技術的迅猛發展中&#xff0c;云端大模型扮演著至關重要的角色。它們不僅推動了技術的邊界&#xff0c;也為各行各業帶來了前所未有的機遇。本文將結合一系列圖片和代碼示例&#xff0c;深入探討云端大模型的功能、應用及其…

(1)pytest簡介和環境準備

1. pytest簡介 pytest是python的一種單元測試框架&#xff0c;與python自帶的unittest測試框架類似&#xff0c;但是比unittest框架使用起來更簡潔&#xff0c;效率更高。根據pytest的官方網站介紹&#xff0c;它具有如下特點&#xff1a; 非常容易上手&#xff0c;入門簡單&a…

實驗設計與分析(第6版,Montgomery)第5章析因設計引導5.7節思考題5.5 R語言解題

本文是實驗設計與分析&#xff08;第6版&#xff0c;Montgomery著&#xff0c;傅玨生譯) 第5章析因設計引導5.7節思考題5.5 R語言解題。主要涉及方差分析&#xff0c;正態假設檢驗&#xff0c;殘差分析&#xff0c;交互作用圖。 dataframe <-data.frame( wrapc(17,20,12,9,…

線程池的詳細知識(含有工廠模式)

前言 下午學習了線程池的知識。重點探究了ThreadPoolExecutor里面的各種參數的含義。我詳細了解了這部分的知識。其中有一個參數涉及工廠模式&#xff0c;我將這一部分知識分享給大家~ 線程池的詳細介紹(含工廠模式) 結語 分享到此結束啦。byebye~

嵌入式開發學習(第二階段 C語言筆記)

內存操作 我們對于內存操作需要依賴于string.h頭文件中相關的函數庫。 內存操作函數 內存填充 頭文件&#xff1a;#include <string.h> 函數原型&#xff1a; void* memset(void *s,int c,size_t n)函數功能&#xff1a;將內存塊s的前n個字節填充為c&#xff0c;一般…

C++學習-入門到精通【9】面向對象編程:繼承

C學習-入門到精通【9】面向對象編程&#xff1a;繼承 目錄 C學習-入門到精通【9】面向對象編程&#xff1a;繼承一、基類與派生類CommunityMember類的繼承層次結構如何定義一個派生類呢 二、基類和派生類間的關系1.創建并使用類CommissionEmployee2.不使用繼承創建類BasePlusCo…