电商秒杀系统:电商微服务框架组件

为什么需要框架组件

可以对比参考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)

 

原文地址:https://www.cnblogs.com/qingyunye/p/13627728.html