.netcore 3.1 high-performance micro Services Architecture: Interface encapsulation method calls an external service --HttpClient client ideas analysis

As we all know, the micro-service architecture consists of a public service consisting of micro-projects in calls to other micro-service interface is more common operations. In order to facilitate external interface calls, our ideas are generally used encapsulating a client external interface, when used directly call the appropriate methods. webservice or WCF service is a reference to the practice of automatically generating client. In webapi2.0, we will manually wrap a static class. So in the era of micro-services .netcore3.1, and how do we deal with this problem? ---- idea is the same, an external service package, and dependency injection and HttpFactory factories .netcore unique way to enhance performance. The next step in our detailed step by step down, said:

Step 1: - Create Project

To facilitate generation nuget package build, we generally each external service creates a separate item; as shown below:

In the solution, we have created a project called: (project name for the company named General department name project name .xxx.) "JR.UPC.Template.OuterClient",.

Step 2: Create a IServiceCollection extension service to facilitate the service registration information. (Focus)

 

    public static  class MsgApiClientServiceCollectionExtensions
    {
        public  static IServiceCollection AddMsgApiClient ( this IServiceCollection services, configuration MsgClientConfiguration)
        {
            services.Configure<MsgClientConfiguration>(MsgClientConfiguration)
                    .AddHttpClient<IMsgApiClient, MsgApiClient>()
                    .ConfigureHttpClient(config=> {
                        config.BaseAddress = new Uri(MsgClientConfiguration.GetSection("url").Value);
                        config.Timeout = TimeSpan.FromSeconds(30);
                        });

            return services;
        }
    }

This code was short, but the most crucial part:

Execution code as follows:

(1) services a first operation example of the configuration register file:

services.Configure<MsgClientConfiguration>(MsgClientConfiguration)

 

(2) adding HttpClientFactory plant and associated services, the Client and the cast is IMsgApiClient (micro external service interface custom name):

.AddHttpClient <IMsgApiClient, MsgApiClient> (); // IMsgApiClient for customers to create next end

 

(3) Set the HttpClient configuration parameters:

 .ConfigureHttpClient(config=> {
                        config.BaseAddress = new new Uri (MsgClientConfiguration.GetSection ( " url " ) .Value); // external micro domain name service interface
                        config.Timeout = TimeSpan.FromSeconds ( 30 ); // interface call timeout
                        });

 

Note also the following points:

(1) static methods and classes in a static manner;

  (2) this IServiceCollection services, this argument I will not explain.

 (3) Generally, we all need to read appsettings.json configuration file parameters so here receives an argument --- IConfiguration MsgClientConfiguration; of course if you do not need to read the configuration parameters, you can ignore this parameter;

 

Step 3: Write external interface calls specific logic code:

(1) create an interface, such as IMsgApiClient

 ///  <Summary> 
    /// enterprise messaging client WeChat
     ///  </ Summary> 
    public  interface IMsgApiClient
    {

        ///  <Summary> 
        /// call interface Interface: sending a message to the micro-channel
         ///  </ Summary> 
        ///  <param name = "hrcodeStr"> hrcode, to a plurality of | spaced </ param> 
        ///  <param name = "msg"> message content </ param> 
        ///  <Returns> </ Returns> 
        the Task <the Result < String >> SendWxWorkMsgAsync ( String hrcodeStr, String MSG);
 
    }

(2) implement the interface:

  ///  <Summary> 
        /// call external interface: sending a message to the SD
         ///  </ Summary> 
        ///  <param name = "hrcodeStr"> hrcode, to a plurality of | spaced </ param> 
        ///  <param name = "msg"> message content </ param> 
        ///  <Returns> </ Returns> 
        public  the async the Task <the Result < String >> SendWxWorkMsgAsync ( String hrcodeStr, String MSG)
        {
            The Result < String > Result = new new the Result < String > ();
             String funname = " [external interface call: WeChat] Enterprise Messaging Interface push " ;
             the try
            { 
                 // specific business logic to write according to their business --- 
                MsgApiResult <WeiXinWorkMessageResponse> = sendRet the await UPCHttpClientExtensions.PostData <MsgApiResult <WeiXinWorkMessageResponse >> (_ Client, _logger, " / API / Weixin / Work / messages / Send " , msgReq) ;

                if (sendRet != null)
                {
                    _logger.LogInformation ($ " {funname}, {} hrcodeStr push message is successfully " );
                    result.state = true;
                    result.data = sendRet.Return_data.MessageId;
                }
                else
                {
                    result.state = false;
                    result.error_msg = sendRet.Return_msg;
                    _logger.LogError ($ " {} funname: {} hrcodeStr Push message failed: sendRet.Return_msg {} " );
                }

            }
            catch (Exception ex)
            {
                result.state = false;
                result.error_code = ErrorCode.OuterApiError;
                result.error_msg = funname + " call abnormal external interface:. " + ex.Message;
                _logger.LogError (EX, $ " {} to {hrcodeStr} funname push message handling exceptions: ex.Message {} " );
            }


            return result;

        }

For the Post method of HttpClient I deliberately encapsulates a general method, as follows :( can transform themselves according to their own projects)

 /// <summary>
   /// HttpClient扩展方法
   /// </summary>
    public class UPCHttpClientExtensions
    {
 
        ///  <Summary> 
        /// simple process httpclient-post method, packaged as a method to facilitate call
         ///  </ Summary> 
        ///  <typeParam name = "T"> </ typeParam> 
        ///  < name = param "_ Client"> </ param> 
        ///  <param name = "_ Logger"> </ param> 
        ///  <param name = "actionURL"> http://xxx.com/ address after the later < / param> 
        ///  <param name = "param"> object </ param> 
        ///  <param name = "the ContentType"> </ param> 
        ///  <param name = "BearerToken"> </ param> 
        ///  <Returns> </ Returns>
        public async static  Task<T> PostData<T>(HttpClient _client, ILogger _logger,string actionUrl, dynamic param, string ContentType = "application/json", string BearerToken = "")
        {
            string funName = "PostData";
            string paramStr = JsonConvert.SerializeObject(param);
            string jrclientguid = Guid.NewGuid().ToString("n");
            try
            {
                _logger.LogInformation ($ " {funName开始}, url = {_} client.BaseAddress, action = {} actionUrl, postData ParamStr = {} = {jrclientguid jrclientguid ---------} " );

                HttpResponseMessage response;
                using (HttpContent httpContent = new StringContent(paramStr, Encoding.UTF8))
                {
                    if (!string.IsNullOrWhiteSpace(BearerToken))
                    {
                        _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", BearerToken);
                    }

                    httpContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue(ContentType);

                    response = await _client.PostAsync(actionUrl, httpContent);

                }
                if (response != null && response.IsSuccessStatusCode)
                {
                    Type t = typeof(T);
                    if (typeof(T) == typeof(string))
                    {
                        string respStr = await response.Content.ReadAsStringAsync();
                        return (T)Convert.ChangeType(respStr, typeof(T));
                    }
                    else
                    {
                        string respStr = response.Content.ReadAsStringAsync().Result;
                        T resp = JsonConvert.DeserializeObject<T>(respStr);

                        return resp;
                    }
                }
                else
                {
                    return default(T);
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex,$"{funName}报错啦,url={_client.BaseAddress},action={actionUrl},postData={paramStr} ,jrclientguid={jrclientguid}---,ex={ex.Message}" );
                throw;
            }
            finally
            {
                _logger.LogInformation ($ " {funName结束}, url = {_} client.BaseAddress, action = {} actionUrl, postData ParamStr = {} = {jrclientguid jrclientguid ---------} " );
            }


        }


    }

 

Step 4: service into the container: Startup code ConfigureServices class's method:

 services.AddUpcMVC(Env)
               .AddUPCDbContext(Configuration)
.AddMsgApiClient (Configuration.GetSection (nameof (MsgApiClient))) // is this line

 

Step 5: Use: can be used in the Controller or elsewhere;

(1) First registered in the constructor:

  private readonly ILogger _logger;
        private IMsgApiClient _IMsgApiClient;

        public HealthController(ILogger<HealthController> logger,    IMsgApiClient iMsgApiClient)
        {
            _logger = log;
            _IMsgApiClient = iMsgApiClient;

        }

(2) call the method:

 /// <summary>
        /// 发消息
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public async Task<Result<string>> POk()
        { 
            Result<string> result = new Result<string>();
            the Result = the await _IMsgApiClient.SendWxWorkMsgAsync ( " 100 001 002 " , " I am Mu snow, please come to my office tomorrow trip! " );
             // result.state = to true;
             // result.data = "successful connection";

            return result;
        }

 

Guess you like

Origin www.cnblogs.com/puzi0315/p/12239442.html