(一)微服务(垂直AP/分布式缓存/装饰器Pattern)

article/2025/6/29 15:35:21

文章目录

  • 项目地址
  • 一、创建第一个垂直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.hkcw.cn/article/ulxXZLdQJw.shtml

相关文章

单依纯疑似回应演唱失误 沉浸演绎引共鸣

在歌手第三期的袭榜赛中,单依纯获得了第二名。一些网友对此表示惊讶,认为她连续两期夺冠后,这次居然输给了断眉,只拿到第二名。不过大多数网友认为直播中的失误是正常现象。单依纯在微博上回应了此事,她表示《爱情》这首歌很早就在她的备选歌单里,《Yesterday Once More》…

汽车被巨石砸中司机逃生 当地回应 地质灾害点已设警示牌

5月28日,贵州毕节市七星关区何官屯镇的一条通村公路上发生了一起突发落石事件。一块约300斤重的巨石砸中一辆过路汽车,导致车辆从路边高坎坠落。司机受轻伤,送医检查后当日返家,车损由保险公司处理。落石还击碎了附近民房的玻璃门,但没有造成人员受伤。当地多部门表示,事…

警方:进入兵马俑坑男子患精神疾病 警情通报发布

5月31日03时15分,平安临潼通过新浪微博发布了一则警情通报。责任编辑:zhangxiaohua

激光武器是否会重塑现代战争形态 以色列首次战场应用引发讨论

当地时间28日,以色列国防部宣布,在针对巴勒斯坦伊斯兰抵抗运动(哈马斯)的军事行动中,以军使用激光武器进行了数十次拦截。这是以色列首次承认在战场上使用激光武器,引发外界广泛关注。以色列国防部长卡茨认为这一技术将改变该地区的游戏规则。以色列公布了一段激光武器拦…

今夏首签!官方:利物浦签24岁荷兰边卫弗林蓬,付3500万解约金 五年长约锁定未来

利物浦宣布签下勒沃库森右边翼卫弗林蓬。据报道,红军支付了3500万欧元的解约金,双方签约五年。弗林蓬出生于荷兰,拥有加纳血统,7岁时随家人移居英国,并在9岁时加入曼城梯队。他在曼城各级梯队成长,2019年离开曼城,以38万欧元的转会费加盟凯尔特人。2021年冬窗,勒沃库森…

端午节北京云量较多 白天阴有阵雨最高气温28℃ 假期出行需带雨具

今天是端午节,北京云量较多,白天阴有阵雨,最高气温28℃。假期后两天,北京云量依然较多,可能会有雷雨,公众外出需带好雨具,小心慢行,注意交通安全。昨天,北京以晴天为主,最高气温达到29.2℃,午后出行体感微热。今晨,北京天空阴沉,海淀、门头沟等多地出现降雨。端午…

世俱杯夺冠赔率:皇马居首曼城拜仁三甲 2025赛事即将揭幕

2025年世俱杯将于6月15日拉开帷幕,目前皇马被认为是夺冠的最大热门。曼城以5.5的赔率紧随其后,拜仁则以7的赔率位列第三。利雅得新月和迈阿密国际的夺冠赔率均为67,并列第18位。以下是世俱杯夺冠赔率前十名的具体情况: - 皇马:4.5 - 曼城:5.5 - 拜仁:7 - 巴黎圣日耳曼:…

“车圈恒大”到底存不存在 中国车企财务更稳健

汽车产业中的高负债问题引发激烈讨论,有人将某些车企比作“车圈恒大”,但这种类比忽略了汽车与房地产的本质差异。车企的负债主要用于研发和生产投资,而非高杠杆囤地,因此资产流动性和现金流稳定性远超房企。比亚迪集团品牌及公关处总经理李云飞通过个人微博回应了这一观点…

玉渊谭天丨签证限制升级背后:美国的困局

当地时间5月28日,美国国务院发布公告称,将开始大力撤销中国留学生的签证。美国政府近年来多次在中国留学生签证的问题上使绊子,总结起来,大致分为四类:将大学和研究机构列入实体清单;签证管控;限制中美正常交流项目;对研究人员采取持续调查。这一次,主要聚焦在签证管控…

Transformer 通关秘籍11:Word2Vec 及工具的使用

将文字文本转换为词向量(word embedding&#xff09;的过程中&#xff0c;一个非常著名的算法模型应该就是 Word2Vec 了。 相信大家或多或少都听说过&#xff0c;本节就来简单介绍一下 Word2Vec 。 什么是 Word2Vec &#xff1f; Word2Vec 可以非常有效的创建词嵌入向量&…

数组做函数参数,嵌套调用与链式访问

文章目录 前言一、数组做函数参数二、嵌套调用和链式访问2.1 嵌套调用2.2 链式访问 前言 这一块内容是衔接上一节函数内容&#xff0c;从更层次分析函数之中的细节 一、数组做函数参数 在平时用函数解决问题的时候&#xff0c;难免会将数组作为参数传递给函数&#xff0c;在函…

央行降息 普通人该做什么 调整投资组合应对变化

2025年5月7日,央行宣布实施“双降”政策,“降准0.5%+ 降息0.1%”,释放长期流动性约1.2万亿元。这是继2024年9月后又一次超预期的货币政策调整。此次政策的核心目标是降低实体经济融资成本,刺激居民消费,稳定楼市,实现经济“软着陆”。“双降”政策对投资者会产生影响。主…

北京多区居民被巨响惊醒 系火流星 夜空奇观点亮京城

2025年5月31日凌晨2时51分,一颗火流星划过北京夜空。凌晨3时左右,北京通州、顺义、怀柔等多区居民在睡梦中被一声巨响惊醒,少数居民目击了漆黑夜空被“点亮”的奇观。中国科学院大学流星多站视频监测网的兴隆流星观测站成功捕捉到这次天文现象,记录下明亮的火流星照亮北京夜…

油价要涨!5月31日92号汽油价格 预计下周上调

今日最新油价调整资讯显示,5月31日的油价预计将在6月3日晚进行调整,上调幅度约为80元/吨(0.05元/升-0.07元/升)。这意味着刚刚在5月大幅下跌的油价将重新上涨。截至5月31日0时,国际原油市场的最新情况是纽约商品交易所(WTI)原油价格下跌0.44%,每桶报价60.67美元;布伦特原…

美的集团董事长方洪波再谈小米 战略上不惧竞争

5月30日下午,美的集团在佛山总部召开2024年度股东大会。今年小米在空调市场掀起低价竞争,其大家电业务一季度收入同比翻倍增长。此前,方洪波在访谈中提到“在战术上重视小米、在战略上不惧怕小米”。有投资者在美的股东大会上追问这句话的含义。方洪波解释说,家电业是高度竞…

龙舟赛上划最快的原来是救援队 去年也是他们最快

端午佳节,山东济南大明湖景区举行了一场盛大的龙舟赛,吸引了众多游客前来观赛。上午9时39分许,两只龙舟敲鼓出发进行比拼。然而比赛刚开始不久,围观人群中就传来呼声,一艘龙舟翻船了。现场目击者称,刚一开始,比赛就结束了。翻船的是落后的那只龙舟,但船员们都穿着救生衣…

古画里的端午氛围感拉满 解锁千年仪式感

端午节作为中国四大传统节日之一,在2000余年的历史长河中积累了丰富的仪式感。端午节前夕,山东博物馆通过古画和年画展示了多样的节俗。在文物鉴赏室,山东博物馆书画部研究馆员鲍艳囡展示了清朝大臣蒋溥所绘的《天中五瑞图》。这幅1米多长的画轴上,蜀葵、菖蒲、石榴花、枇杷…

“车圈恒大论”之下汽车行业谁最焦虑 负债真相解析

长城汽车董事长魏建军近期关于“汽车行业‘恒大’已经出现,只不过没爆”的言论引起了广泛关注。这一观点不仅揭示了新能源转型过程中部分企业的焦虑,也引发了对车企资产负债结构和盈利能力的深入讨论。将汽车行业简单类比为房地产行业的高杠杆模式并不准确。作为技术密集型制…

媒体人:杨瀚森第2站试训情况非常好 获积极反馈

北京时间5月31日,杨瀚森完成了NBA单独试训的第二站。据媒体人周鹏透露,杨瀚森的试训反馈非常不错,得到的消息是“非常不错!Good job!”这让人们感到踏实。在完成前两支球队的单独试训后,杨瀚森将先返回洛杉矶稍作休整,之后继续从洛杉矶出发,前往后续几支球队进行试训。…

四川通报59名医疗机构人员违规收费 廉洁整治行动展开

近期,相关部门收到关于某药企涉嫌向医生输送商业贿赂的举报信。对此,调查组迅速成立并展开调查核实工作。以下是调查处置进展情况。举报信涉及125名医疗机构人员,其中6人信息重复,1人信息不实,最终核实为118人,分布在36家医疗机构。经逐人核实,59人因参加病例收集、科普…