zoukankan      html  css  js  c++  java
  • 电商秒杀系统:电商微服务框架组件

    为什么需要框架组件

    可以对比参考ABP框架中的微服务示例的通讯,abp的微服务示例是使用“异步消息通信”方式。与cp的微服务对比理解下

    就是为了方便,把重复的代码都封装好。 

    参考

    Abp Vnext2.0核心组件源码解析与简单应用

    abp官网文档:微服务解决方案示例

     

    组件所在位置:Framework=》Cores

     

    组件和服务的调用关系

    中台调用组件(Middleware) ,没调用

    注册中心组件(Registry),没调用

    断路器Polly组件(Pollys),没调用

    框架异常组件(Exceptions),没调用

    负载均衡组件(Cluster) ,调用了

    • 注册中心组件(Registry)

    动态中台调用组件(DynamicMiddleware) ,调用了

    • 中台调用组件(Middleware) 
    • 注册中心组件(Registry)
    • 负载均衡组件(Cluster)

    微服务客户端组件(MicroClients),调用了

    • 动态中台调用组件(DynamicMiddleware)
    • 断路器Polly组件(Pollys)

    ----------------------------------上面的是组件调用组件,下面的是服务调用组件----------------------------------

    都是在Startup中使用组件

    SeckillAggregateServices(秒杀聚合服务),Startup 调用了

    • 微服务客户端组件(MicroClients)
      • 使用了该组件的AddMicroClient方法来添加微服务客户端,该方法内实现了以下功能
        • 注册AddMiddleware
        • 注册客户端工厂
        • 注册客户端集合
        • 注册代理对象
                services.AddMicroClient(options =>
                {
                    //程序集名称
                    options.AssmelyName = "RuanMou.Projects.SeckillAggregateServices";
                    //动态中台选项
                    options.dynamicMiddlewareOptions = mo =>
                    {
                        //服务发现选项
                        mo.serviceDiscoveryOptions = sdo =>
                        //服务发现地址
                        { sdo.DiscoveryAddress = "http://localhost:8500"; };
                    };
                });

    OrderServices(订单服务)、PaymentServices(支付服务)、ProductServices(商品服务)、SeckillServices(秒杀服务)、UserServices(用户服务),Startup 调用了

    • 注册中心组件(Registry)
      • 使用了该组件的AddServiceRegistry方法来服务注册,该方法内实现了以下功能
        • 配置选项到 IOC
        • 注册consul注册
        • 注册开机自动注册服务

    下面是OrderServices(订单服务)使用注册中心组件示例:

                services.AddServiceRegistry(options =>
                {
                    options.ServiceId = Guid.NewGuid().ToString(); //服务ID
                    options.ServiceName = "OrderServices"; //服务名称
                    options.ServiceAddress = "https://localhost:5002"; //服务地址
                    options.HealthCheckAddress = "/HealthCheck"; //服务健康检查地址
                    options.RegistryAddress = "http://localhost:8500"; //服务注册地址
                });

    中台调用组件(Middleware)

    如果要扩展为grpc框架通讯,只要创建一个另外一个类,实现IMiddleService接口的方法就好 

    中台结果:MiddleResult

    JsonConvert.DeserializeObject:将JSON反序列化为指定的.NET类型

    变量:

    ErrorNo:0是成功,其他都是失败

    ErrorInfo:失败信息

    属性:
    resultDic:用于非结果集返回

    resultList:用于结果集返回

    Result:返回动态结果(通用)

    方法:

    //把Json格式的字符串反序列化为MiddleResult

    public static MiddleResult JsonToMiddleResult(string jsonStr)

    构造函数:

    //将JSON反序列化为指定的.NET类型

    public MiddleResult(string jsonStr)

    using Newtonsoft.Json;
    using System.Collections.Generic;
    
    namespace RuanMou.Projects.Cores.Middleware
    {
        /// <summary>
        /// 中台结果:
        /// 变量:
        /// SUCCESS:?
        /// ErrorNo:0是成功,其他都是失败
        /// ErrorInfo:失败信息
        /// 
        /// 属性:
        /// resultDic:用于非结果集返回
        /// resultList:用于结果集返回
        /// Result:返回动态结果(通用)
        /// 
        /// 方法:
        /// JsonToMiddleResult:把Json格式的字符串反序列化为MiddleResult
        /// 
        /// 构造函数:根据传入的参数更新上面的变量和属性,都没有用到?需要调式确认
        /// 
        /// </summary>
        public class MiddleResult
        {
            public const string SUCCESS = "0"; //没有被用过?调式看看
            /// <summary>
            /// 是否成功状态:0是成功,其他都是失败
            /// </summary>
            public string ErrorNo { set; get; } 
            /// <summary>
            /// 失败信息
            /// </summary>
            public string ErrorInfo { set; get; }
            /// <summary>
            /// 用于非结果集返回
            /// </summary>
            public IDictionary<string, object> resultDic { set; get; }
            /// <summary>
            /// 用于结果集返回
            /// </summary>
            public IList<IDictionary<string, object>> resultList { set; get; }
            /// <summary>
            /// 返回动态结果(通用),使用动态解释数据类型dynamic
            /// </summary>
            public dynamic Result { set; get; }
    
            /// <summary>
            /// 构造函数():无参,
            /// resultDic(用于非结果集返回)=字典,
            /// resultList(用于结果集返回)=集合<字典>
            /// </summary>
            public MiddleResult()
            {
                resultDic = new Dictionary<string, object>();
                resultList = new List<IDictionary<string, object>>();
            }
    
            /// <summary>
            /// 构造函数(string):把Json格式的字符串反序列化为MiddleResult
            /// </summary>
            /// <param name="jsonStr"></param>
            public MiddleResult(string jsonStr)
            {
                MiddleResult result = JsonConvert.DeserializeObject<MiddleResult>(jsonStr);
            }
            /// <summary>
            /// 把Json格式的字符串反序列化为MiddleResult
            /// JsonConvert.DeserializeObject:将JSON反序列化为指定的.NET类型
            /// </summary>
            /// <param name="jsonStr"></param>
            /// <returns></returns>
            public static MiddleResult JsonToMiddleResult(string jsonStr)
            {
                MiddleResult result = JsonConvert.DeserializeObject<MiddleResult>(jsonStr);
                return result;
            }
    
            /// <summary>
            /// 构造函数:
            /// </summary>
            /// <param name="errorNo"></param>
            /// <param name="errorInfo"></param>
            public MiddleResult(string errorNo, string errorInfo)
            {
                this.ErrorNo = errorNo;
                this.ErrorInfo = errorInfo;
                resultDic = new Dictionary<string, object>();
                resultList = new List<IDictionary<string, object>>();
            }
            //构造函数,引用上面2个参数的构造函数?
            public MiddleResult(string errorNo, string erroInfo, IDictionary<string, object> resultDic, IList<IDictionary<string, object>> resultList) : this(errorNo, erroInfo)
            {
                this.resultDic = resultDic;
                this.resultList = resultList;
                this.resultDic = resultDic;
                this.resultList = resultList;
            }
        }
    }
    View Code

    中台服务接口:IMiddleService

    用MiddleResult类声明的方法名,如下

    • Get:获取/查询
    • Post:创建/新增
    • Delete:删除
    • Put:更新/修改
    • PostDynamic:post请求动态参数
    • PutDynamic:put请求动态参数

    Http中台请求结果:HttpMiddleService(重点)

    IHttpClientFactory:组件的工厂抽象,该组件可使用自定义配置为给定逻辑名称创建 HttpClient 实例

    IHttpClientFactory.CreateClient(String):使用与 name 指定的逻辑名称相对应的配置来创建和配置 HttpClient 实例。

    HttpClient:提供基本类,用于发送 HTTP 请求和接收来自通过 URI 确认的资源的 HTTP 响应。

    HttpClient.PostAsync(string requestUri, HttpContent content):以异步操作将 POST 请求发送给指定 URI。

    HttpContent:表示 HTTP 实体正文和内容标头的基类。

    StringContent(String, Encoding, String):创建 System.Net.Http.StringContent 类的新实例

    HttpResponseMessage:表示包括状态代码和数据的 HTTP 响应消息。

    在 ASP.NET Core 中使用 IHttpClientFactory 发出 HTTP 请求

    JsonConvert.SerializeObject:将指定的对象序列化为JSON字符串

    核心的4行代码

    复制代码
    private readonly IHttpClientFactory httpClientFactory;
    //
    HttpClient httpClient = httpClientFactory.CreateClient(String); 
    //
    HttpContent hc = new StringContent(String, Encoding, String); 
    //
    HttpResponseMessage response = await httpClient.PostAsync(string requestUri, HttpContent content);
    复制代码

    另外添加的方法:

    • 将HttpResponseMessage转换成MiddleResult类的Json格式
      • private MiddleResult GetMiddleResult(HttpResponseMessage httpResponseMessage)

    实现接口IMiddleService的全部方法 :这些方法返回的都是上面的MiddleResult方法,返回Json格式

    • Get:获取/查询
      • public MiddleResult Get(string middleUrl, IDictionary<string, object> middleParam)
    • Post:创建/新增
      • public MiddleResult Post(string middleUrl, IDictionary<string, object> middleParam)
      • public MiddleResult Post(string middleUrl, IList<IDictionary<string, object>> middleParams)
    • Delete:删除
      • public MiddleResult Delete(string middleUrl, IDictionary<string, object> middleParam)
    • Put:更新/修改
      • public MiddleResult Put(string middleUrl, IDictionary<string, object> middleParam)
      • public MiddleResult Put(string middleUrl, IList<IDictionary<string, object>> middleParams)
    • PostDynamic:post请求动态参数
      • public MiddleResult PostDynamic(string middleUrl, dynamic middleParam)
    • PutDynamic:put请求动态参数
      • public MiddleResult PutDynamic(string middleUrl, dynamic middleParam)
    using Newtonsoft.Json;
    using RuanMou.Projects.Commons.Exceptions;
    using RuanMou.Projects.Cores.Middleware.transports;
    using RuanMou.Projects.Cores.Utils;
    using System.Collections.Generic;
    using System.Net;
    using System.Net.Http;
    using System.Text;
    
    namespace RuanMou.Projects.Cores.Middleware.support
    {
        /// <summary>
        /// Http中台请求结果:
        /// 实现接口IMiddleService的全部方法
        /// HttpClient:提供用于发送 HTTP 请求并从 URI 标识的资源接收 HTTP 响应的基类
        ///     .GetAsync、.PostAsync、.PutAsync、.DeleteAsync:以异步操作将这几种请求发送给指定URI
        ///         .Result:获取此 System.Threading.Tasks.Task`1 的结果值
        /// IHttpClientFactory:组件的工厂抽象,该组件可使用自定义配置为给定逻辑名称创建 HttpClient 实例
        /// IHttpClientFactory.CreateClient:使用与 name 指定的逻辑名称相对应的配置来创建和配置 HttpClient 实例。
        /// HttpResponseMessage:表示包括状态代码和数据的 HTTP 响应消息
        /// HttpContent:表示 HTTP 实体正文和内容标头的基类
        /// JsonConvert.SerializeObject:将指定的对象序列化为JSON字符串。
        /// </summary>
        public class HttpMiddleService : IMiddleService
        {
            private IHttpClientFactory httpClientFactory;
            private const string HttpConst = "mrico";
    
            public HttpMiddleService(IHttpClientFactory httpClientFactory)
            {
                this.httpClientFactory = httpClientFactory;
            }
    
            public MiddleResult Delete(string middleUrl, IDictionary<string, object> middleParam)
            {
                // 1、获取httpClient
                HttpClient httpClient = httpClientFactory.CreateClient(HttpConst);
    
                // 2、Delete请求                                    以异步操作将 DELETE 请求发送给指定 URI。
                HttpResponseMessage httpResponseMessage = httpClient.DeleteAsync(middleUrl).Result;
    
                return GetMiddleResult(httpResponseMessage);
            }
    
    
            public MiddleResult Get(string middleUrl, IDictionary<string, object> middleParam)
            {
                // 1、获取httpClient
                HttpClient httpClient = httpClientFactory.CreateClient(HttpConst);
    
                // 2、参数转换为url方式
                string urlParam = HttpParamUtil.DicToHttpUrlParam(middleParam);
    
                // 3、Get请求                                        
                HttpResponseMessage httpResponseMessage = httpClient.GetAsync(middleUrl + urlParam).Result;
    
                return GetMiddleResult(httpResponseMessage);
            }
    
            public MiddleResult Post(string middleUrl, IDictionary<string, object> middleParam)
            {
                // 1、获取httpClient
                HttpClient httpClient = httpClientFactory.CreateClient(HttpConst);
    
                // 2、转换成json参数
                HttpContent httpContent = new StringContent(JsonConvert.SerializeObject(middleParam), Encoding.UTF8, "application/json");
    
                // 3、Post请求
                HttpResponseMessage httpResponseMessage = httpClient.PostAsync(middleUrl, httpContent).Result;
    
                return GetMiddleResult(httpResponseMessage);
            }
    
            public MiddleResult Post(string middleUrl, IList<IDictionary<string, object>> middleParams)
            {
                // 1、获取httpClient
                HttpClient httpClient = httpClientFactory.CreateClient(HttpConst);
    
                // 2、转换成json参数
                HttpContent httpContent = new StringContent(JsonConvert.SerializeObject(middleParams), Encoding.UTF8, "application/json");
    
                // 3、Post请求
                HttpResponseMessage httpResponseMessage = httpClient.PostAsync(middleUrl, httpContent).Result;
    
                return GetMiddleResult(httpResponseMessage);
            }
    
            public MiddleResult PostDynamic(string middleUrl, dynamic middleParam)
            {
                // 1、获取httpClient
                HttpClient httpClient = httpClientFactory.CreateClient(HttpConst);
    
                // 2、转换成json参数
                HttpContent httpContent = new StringContent(JsonConvert.SerializeObject(middleParam), Encoding.UTF8, "application/json");
    
                // 3、Post请求
                HttpResponseMessage httpResponseMessage = httpClient.PostAsync(middleUrl, httpContent).Result;
    
                return GetMiddleResult(httpResponseMessage);
            }
    
            public MiddleResult Put(string middleUrl, IDictionary<string, object> middleParam)
            {
                // 1、获取httpClient
                HttpClient httpClient = httpClientFactory.CreateClient(HttpConst);
    
                // 2、转换成json参数
                HttpContent httpContent = new StringContent(JsonConvert.SerializeObject(middleParam), Encoding.UTF8, "application/json");
                // 3、Put请求
                HttpResponseMessage httpResponseMessage = httpClient.PutAsync(middleUrl, httpContent).Result;
    
                return GetMiddleResult(httpResponseMessage);
            }
    
            public MiddleResult Put(string middleUrl, IList<IDictionary<string, object>> middleParams)
            {
                // 1、获取httpClient
                HttpClient httpClient = httpClientFactory.CreateClient(HttpConst);
    
                // 2、转换成json参数
                HttpContent httpContent = new StringContent(JsonConvert.SerializeObject(middleParams), Encoding.UTF8, "application/json");
    
                // 3、Put请求
                HttpResponseMessage httpResponseMessage = httpClient.PutAsync(middleUrl, httpContent).Result;
    
                return GetMiddleResult(httpResponseMessage);
            }
    
    
            public MiddleResult PutDynamic(string middleUrl, dynamic middleParam)
            {
                // 1、获取httpClient
                HttpClient httpClient = httpClientFactory.CreateClient(HttpConst);
    
                // 2、转换成json参数
                HttpContent httpContent = new StringContent(JsonConvert.SerializeObject(middleParam), Encoding.UTF8, "application/json");
                // 3、Put请求
                HttpResponseMessage httpResponseMessage = httpClient.PutAsync(middleUrl, httpContent).Result;
    
                return GetMiddleResult(httpResponseMessage);
            }
            /// <summary>
            /// 将HttpResponseMessage转换成MiddleResult类的Json格式
            /// </summary>
            /// <param name="httpResponseMessage"></param>
            /// <returns></returns>
            private MiddleResult GetMiddleResult(HttpResponseMessage httpResponseMessage)
            {
                // 3、将HttpResponseMessage转换成MiddleResult
                if (httpResponseMessage.StatusCode.Equals(HttpStatusCode.OK)
                    || httpResponseMessage.StatusCode.Equals(HttpStatusCode.Created) ||
                    httpResponseMessage.StatusCode.Equals(HttpStatusCode.Accepted))
                {
                    string httpJsonString = httpResponseMessage.Content.ReadAsStringAsync().Result;
    
                    // 3.1 创建MiddleResult
                    return MiddleResult.JsonToMiddleResult(httpJsonString);
                }
                else
                {
                    throw new FrameException($"{HttpConst}服务调用错误:{httpResponseMessage.Content.ReadAsStringAsync().ToString()}");
                }
            }
        }
    }
    View Code 

    中台配置选项:MiddlewareOptions

    两个属性:polly熔断降级选项、客户端名称

    • public Action<PollyHttpClientOptions> pollyHttpClientOptions { get; }
    • public string HttpClientName { set; get; }
    View Code

    中台ServiceCollection扩展方法:MiddlewareServiceCollectionExtensions

    使用上面的MiddlewareOptions类

    添加中台

    • 使用中台配置选项MiddlewareOptions
    • 使用自定义的Polly熔断组件
    • 注册中台组件:中台组件的接口与实现类注入
    using Microsoft.Extensions.DependencyInjection;
    using RuanMou.Projects.Cores.Cluster.Extentions;
    using RuanMou.Projects.Cores.HttpClientPolly;
    using RuanMou.Projects.Cores.Middleware.options;
    using RuanMou.Projects.Cores.Middleware.support;
    using RuanMou.Projects.Cores.Middleware.transports;
    using RuanMou.Projects.Cores.Middleware.Urls;
    using RuanMou.Projects.Cores.Middleware.Urls.consul;
    using RuanMou.Projects.Cores.Registry.Extentions;
    using System;
    
    namespace RuanMou.Projects.Cores.Middleware.Extentions
    {
        /// <summary>
        ///  中台组件的ServiceCollection扩展方法:以便在Startup类的ConfigureServices方法可以使用此组件
        /// </summary>
        public static class MiddlewareServiceCollectionExtensions
        {
            /// <summary>
            /// 添加中台
            /// </summary>
            /// <typeparam name="IMiddleService"></typeparam>
            /// <param name="services"></param>
            /// <returns></returns>
            public static IServiceCollection AddMiddleware(this IServiceCollection services)
            {
                AddMiddleware(services, options => {});
                return services;
            }
    
            /// <summary>
            /// 添加中台:
            /// 1 使用中台配置选项MiddlewareOptions
            /// 2 使用自定义的Polly熔断组件
            /// 3 注册中台组件:中台组件的接口与实现类注入
            /// </summary>
            /// <typeparam name="IMiddleService"></typeparam>
            /// <param name="services"></param>
            /// <returns></returns>
            public static IServiceCollection AddMiddleware(this IServiceCollection services, Action<MiddlewareOptions> options)
            {
                MiddlewareOptions middlewareOptions = new MiddlewareOptions();
                options(middlewareOptions);
    
                // 1、注册到IOC
                services.Configure<MiddlewareOptions>(options);
    
                // 2、添加HttpClient,使用自定义的Polly熔断组件
                // services.AddHttpClient(middlewareOptions.HttpClientName);
                services.AddPollyHttpClient(middlewareOptions.HttpClientName, middlewareOptions.pollyHttpClientOptions);
    
                // 3、注册中台组件:中台组件的接口与实现类注入
                //AddSingleton:将TService 中指定类型的单一实例服务和 TImplementation中指定类型的实现添加到指定的IServiceCollection 中。
                services.AddSingleton<IMiddleService, HttpMiddleService>();
    
                return services;
            }
        }
    }
    View Code

    断路器Polly组件封装(Pollys)

    注册中心组件封装(Registry)

    负载均衡组件封装(Cluster)

    动态中台调用组件封装(DynamicMiddleware)

    微服务客户端组件封装(MicroClients)

    框架异常组件封装(Exceptions)

     

  • 相关阅读:
    我的知识库(4) java获取页面编码(Z)
    知识库(3)JAVA 正则表达式 (超详细)
    The Struts dispatcher cannot be found. This is usually caused by using Struts tags without the associated filter. Struts
    某人总结的《英语听力的技巧 》,挺搞的
    我的知识库(5)java单例模式详解
    构建可扩展程序
    SerialPort (RS232 Serial COM Port) in C# .NET
    Python学习笔记——String、Sequences
    UI题目我的答案
    jQuery学习系列学会操纵Form表单元素(1)
  • 原文地址:https://www.cnblogs.com/qingyunye/p/13627728.html
Copyright © 2011-2022 走看看