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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

eShopOnContainers 知多少[7]:Basket microservice

發布時間:2023/12/4 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 eShopOnContainers 知多少[7]:Basket microservice 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

引言

Basket microservice(購物車微服務)主要用于處理購物車的業務邏輯,包括:

  • 購物車商品的CRUD

  • 訂閱商品價格更新事件,進行購物車商品同步處理

  • 購物車結算事件發布

  • 訂閱訂單成功創建事件,進行購物車的清空操作

  • 架構模式

    如上圖所示,本微服務采用數據驅動的CRUD微服務架構,并使用Redis數據庫進行持久化。 這種類型的服務在單個 ASP.NET Core Web API 項目中即可實現所有功能,該項目包括數據模型類、業務邏輯類及其數據訪問類。其項目結構如下:

    核心技術選型:

  • ASP.NET Core Web API

  • Entity Framework Core

  • Redis

  • Swashbuckle(可選)

  • Autofac

  • Eventbus

  • Newtonsoft.Json

  • 實體建模和持久化

    該微服務的核心領域實體是購物車,其類圖如下:

    其中 CustomerBasketBasketItem為一對多關系,使用倉儲模式進行持久化。

  • 通過對?CustomerBasket對象進行json格式的序列化和反序列化來完成在redis中的持久化和讀取。

  • 以單例模式注入redis連接?ConnectionMultiplexer,該對象最終通過構造函數注入到?RedisBasketRepository中。

  • services.AddSingleton<ConnectionMultiplexer>(sp =>

  • {

  • ? ?var settings = sp.GetRequiredService<IOptions<BasketSettings>>().Value;

  • ? ?var configuration = ConfigurationOptions.Parse(settings.ConnectionString, true);


  • ? ?configuration.ResolveDns = true;


  • ? ?return ConnectionMultiplexer.Connect(configuration);

  • });

  • 事件的注冊和消費

    在本服務中主要需要處理以下事件的發布和消費:

  • 事件發布:當用戶點擊購物車結算時,發布用戶結算事件。

  • 事件消費:訂單創建成功后,進行購物車的清空

  • 事件消費:商品價格更新后,進行購物車相關商品的價格同步


  • private void ConfigureEventBus(IApplicationBuilder app)

  • {

  • ? ?var eventBus = app.ApplicationServices.GetRequiredService<IEventBus>();


  • ? ?eventBus.Subscribe<ProductPriceChangedIntegrationEvent, ProductPriceChangedIntegrationEventHandler>();

  • ? ?eventBus.Subscribe<OrderStartedIntegrationEvent, OrderStartedIntegrationEventHandler>();

  • }

  • 以上都是基于事件總線來達成。

    認證和授權

    購物車管理界面是需要認證和授權。那自然需要與上游的 IdentityMicroservice進行銜接。在啟動類進行認證中間件的配置。

  • private void ConfigureAuthService(IServiceCollection services)

  • {

  • ? ?// prevent from mapping "sub" claim to nameidentifier.

  • ? ?JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();

  • ? ?var identityUrl = Configuration.GetValue<string>("IdentityUrl");


  • ? ?services.AddAuthentication(options =>

  • ? ?{

  • ? ? ? ?options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;

  • ? ? ? ?options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;

  • ? ?}).AddJwtBearer(options =>

  • ? ?{

  • ? ? ? ?options.Authority = identityUrl;

  • ? ? ? ?options.RequireHttpsMetadata = false;

  • ? ? ? ?options.Audience = "basket";

  • ? ?});

  • }

  • protected virtual void ConfigureAuth(IApplicationBuilder app)

  • {

  • ? ?if (Configuration.GetValue<bool>("UseLoadTest"))

  • ? ?{

  • ? ? ? ?app.UseMiddleware<ByPassAuthMiddleware>();

  • ? ?}

  • ? ?app.UseAuthentication();

  • }

  • 手動啟用斷路器

    在該微服務中,定義了一個中斷中間件FailingMiddleware,通過訪問 http://localhost:5103/failing獲取該中間件的啟用狀態,通過請求參數指定:即通過 http://localhost:5103/failing?enablehttp://localhost:5103/failing?disable來手動中斷和恢復服務,來模擬斷路,以便用于測試斷路器模式。 開啟斷路后,當訪問購物車頁面時,Polly在重試指定次數依然無法訪問服務時,就會拋出 BrokenCircuitException異常,通過捕捉該異常告知用戶稍后再試。

  • public class CartController : Controller

  • {

  • ? ?//…

  • ? ?public async Task<IActionResult> Index()

  • ? ?{

  • ? ? ? ?try

  • ? ? ? ?{ ? ? ? ? ?

  • ? ? ? ? ? ?var user = _appUserParser.Parse(HttpContext.User);

  • ? ? ? ? ? ?//Http requests using the Typed Client (Service Agent)

  • ? ? ? ? ? ?var vm = await _basketSvc.GetBasket(user);

  • ? ? ? ? ? ?return View(vm);

  • ? ? ? ?}

  • ? ? ? ?catch (BrokenCircuitException)

  • ? ? ? ?{

  • ? ? ? ? ? ?// Catches error when Basket.api is in circuit-opened mode ? ? ? ? ? ? ? ?

  • ? ? ? ? ? ?HandleBrokenCircuitException();

  • ? ? ? ?}

  • ? ? ? ?return View();

  • ? ?} ? ? ?

  • ? ?private void HandleBrokenCircuitException()

  • ? ?{

  • ? ? ? ?TempData["BasketInoperativeMsg"] = "Basket Service is inoperative, please try later on. (Business message due to Circuit-Breaker)";

  • ? ?}

  • }

  • 注入過濾器

    在配置MVC服務時指定了兩個過濾器:全局異常過濾器和模型驗證過濾器。

  • // Add framework services.

  • services.AddMvc(options =>

  • {

  • ? ?options.Filters.Add(typeof(HttpGlobalExceptionFilter));

  • ? ?options.Filters.Add(typeof(ValidateModelStateFilter));


  • }).AddControllersAsServices();


  • 1. 全局異常過濾器是通過定義?BasketDomainException異常和?HttpGlobalExceptionFilter過濾器來實現的。

    2. 模型驗證過濾器是通過繼承?ActionFilterAttribute特性實現的?ValidateModelStateFilter來獲取模型狀態中的錯誤。


  • public class ValidateModelStateFilter : ActionFilterAttribute

  • {

  • ? ?public override void OnActionExecuting(ActionExecutingContext context)

  • ? ?{

  • ? ? ? ?if (context.ModelState.IsValid)

  • ? ? ? ?{

  • ? ? ? ? ? ?return;

  • ? ? ? ?}


  • ? ? ? ?var validationErrors = context.ModelState

  • ? ? ? ? ? ?.Keys

  • ? ? ? ? ? ?.SelectMany(k => context.ModelState[k].Errors)

  • ? ? ? ? ? ?.Select(e => e.ErrorMessage)

  • ? ? ? ? ? ?.ToArray();


  • ? ? ? ?var json = new JsonErrorResponse

  • ? ? ? ?{

  • ? ? ? ? ? ?Messages = validationErrors

  • ? ? ? ?};


  • ? ? ? ?context.Result = new BadRequestObjectResult(json);

  • ? ?}

  • }

  • SwaggerUI認證授權集成

    因為默認啟用了安全認證,所以為了方便在SwaggerUI界面進行測試,那么我們就必須為其集成認證授權。代碼如下:

  • services.AddSwaggerGen(options =>

  • {

  • ? ?options.DescribeAllEnumsAsStrings();

  • ? ?options.SwaggerDoc("v1", new Info

  • ? ?{

  • ? ? ? ?Title = "Basket HTTP API",

  • ? ? ? ?Version = "v1",

  • ? ? ? ?Description = "The Basket Service HTTP API",

  • ? ? ? ?TermsOfService = "Terms Of Service"

  • ? ?});

  • ? ?options.AddSecurityDefinition("oauth2", new OAuth2Scheme

  • ? ?{

  • ? ? ? ?Type = "oauth2",

  • ? ? ? ?Flow = "implicit",

  • ? ? ? ?AuthorizationUrl = $"{Configuration.GetValue<string>("IdentityUrlExternal")}/connect/authorize",

  • ? ? ? ?TokenUrl = $"{Configuration.GetValue<string>("IdentityUrlExternal")}/connect/token",

  • ? ? ? ?Scopes = new Dictionary<string, string>()

  • ? ? ? ?{

  • ? ? ? ? ? ?{ "basket", "Basket API" }

  • ? ? ? ?}

  • ? ?});

  • ? ?options.OperationFilter<AuthorizeCheckOperationFilter>();

  • });

  • 其中有主要做了三件事:

    1. 配置授權Url

    2. 配置TokenUrl

    3. 指定授權范圍

    4. 注入授權檢查過濾器?AuthorizeCheckOperationFilter用于攔截需要授權的請求

  • public class AuthorizeCheckOperationFilter : IOperationFilter

  • {

  • ? ?public void Apply(Operation operation, OperationFilterContext context)

  • ? ?{

  • ? ? ? ?// Check for authorize attribute

  • ? ? ? ?var hasAuthorize = context.ApiDescription.ControllerAttributes().OfType<AuthorizeAttribute>().Any() ||

  • ? ? ? ? ? ? ? ? ? ? ? ? ? context.ApiDescription.ActionAttributes().OfType<AuthorizeAttribute>().Any();

  • ? ? ? ?if (hasAuthorize)

  • ? ? ? ?{

  • ? ? ? ? ? ?operation.Responses.Add("401", new Response { Description = "Unauthorized" });

  • ? ? ? ? ? ?operation.Responses.Add("403", new Response { Description = "Forbidden" });

  • ? ? ? ? ? ?operation.Security = new List<IDictionary<string, IEnumerable<string>>>();

  • ? ? ? ? ? ?operation.Security.Add(new Dictionary<string, IEnumerable<string>>

  • ? ? ? ? ? ?{

  • ? ? ? ? ? ? ? ?{ "oauth2", new [] { "basketapi" } }

  • ? ? ? ? ? ?});

  • ? ? ? ?}

  • ? ?}

  • }

  • 最后

    本服務較之前講的Catalog microservice 而言,主要是多了一個認證和redis存儲。

    總結

    以上是生活随笔為你收集整理的eShopOnContainers 知多少[7]:Basket microservice的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。