本文为原创文章:首发:http://www.zyiz.net/

众所周知,微服务架构是由一众微服务组成,项目中调用其他微服务接口更是常见的操作。为了便于调用外部接口,我们的常用思路一般都是封装一个外部接口的客户端,使用时候直接调用相应的方法。webservice或WCF的做法就是引用服务,自动生成客户端。在webapi2.0里,我们都会手动封装一个静态类。那么在.netcore3.1的微服务时代,我们该如何处理这个问题呢? ----思路都是一样的,封装一个外部服务,并且使用依赖注入和 HttpFactory工厂等.netcore特有的方式提升性能。接下来我们一步一步说下详细的步骤:

第1步:--创建项目

为了便于构建生成nuget包,我们一般都每个外部服务创建一个独立的项目;如下图:

在解决方案里,我们创建了一个项目名为:"MuXue.Zyiz.Template.OuterClient",(项目起名一般为 公司名.部门名.项目名.xxx)。

第2步:创建一个IServiceCollection扩展服务,便于将服务注册信息。(重点)

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

该段代码虽然很短,但是最关键的部分:

代码的执行过程如下:

(1)  services首先注册一个操作配置文件的实例 :

services.Configure<MsgClientConfiguration>(MsgClientConfiguration)

(2) 添加HttpClientFactory工厂并且关联到services里,并将Client强制类型为IMsgApiClient(自定义的外部微服务接口名称) :

.AddHttpClient<IMsgApiClient, MsgApiClient>();//IMsgApiClient为接下来要创建的客户端

(3)设置HttpClient的相关配置参数:

 .ConfigureHttpClient(config=> {
config.BaseAddress = new Uri(MsgClientConfiguration.GetSection("url").Value);//外部微服务接口域名
config.Timeout = TimeSpan.FromSeconds(); // 接口调用超时时间
});

还有如下注意点:

(1)以静态类和静态方法方式;

(2) this IServiceCollection services ,这个参数我就不多解释了。

(3) 一般我们都需要读取appsettings.json配置文件里的参数所以这里接收了一个参数---IConfiguration MsgClientConfiguration  ;当然如果你不需要读取配置参数,也可以忽略这个参数;

第3步:写外部接口调用的具体逻辑代码:

(1)创建一个接口,比如IMsgApiClient

 /// <summary>
/// 企业微信消息发送客户端
/// </summary>
public interface IMsgApiClient
{ /// <summary>
/// 调用接口接口:向微信发送消息
/// </summary>
/// <param name="hrcodeStr">hrcode,多个以|隔开</param>
/// <param name="msg">消息内容</param>
/// <returns></returns>
Task<Result<string>> SendWxWorkMsgAsync(string hrcodeStr, string msg); }

(2)实现该接口:

  /// <summary>
/// 调用外部接口:向SD发送消息
/// </summary>
/// <param name="hrcodeStr">hrcode,多个以|隔开</param>
/// <param name="msg">消息内容</param>
/// <returns></returns>
public async Task<Result<string>> SendWxWorkMsgAsync(string hrcodeStr, string msg)
{
Result<string> result = new Result<string>();
string funName = "【调用外部接口:微信企业消息推送接口】";
try
{
//具体的业务逻辑---根据自身业务来写
MsgApiResult<WeiXinWorkMessageResponse> sendRet = await ZyizHttpClientExtensions.PostData<MsgApiResult<WeiXinWorkMessageResponse>>(_client, _logger, "/api/weixin/work/messages/send", msgReq); if (sendRet != null)
{
_logger.LogInformation($"{funName},{hrcodeStr}推送消息成功");
result.state = true;
result.data = sendRet.Return_data.MessageId;
}
else
{
result.state = false;
result.error_msg = sendRet.Return_msg;
_logger.LogError($"{funName}:{hrcodeStr}推送消息失败:{sendRet.Return_msg}");
} }
catch (Exception ex)
{
result.state = false;
result.error_code = ErrorCode.OuterApiError;
result.error_msg = funName + "调用外部接口异常:。" + ex.Message;
_logger.LogError(ex, $"{funName}向{hrcodeStr}推送消息处理异常:{ex.Message}");
} return result; }

针对HttpClient的Post方法我特意封装了一个通用方法,如下:(可以根据自身项目自行改造)

 /// <summary>
/// HttpClient扩展方法
/// </summary>
public class ZyizHttpClientExtensions
{ /// <summary>
/// httpclient-post方法的简单处理,封装成一个方法,便于调用
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="_client"></param>
/// <param name="_logger"></param>
/// <param name="actionUrl">http://xxx.com/后面之后的地址</param>
/// <param name="param">一个对象</param>
/// <param name="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}---------");
} } }

第4步:将服务注入容器:代码在Startup类的ConfigureServices方法里:

 services.AddZyizMVC(Env)
.AddZyizDbContext(Configuration)
.AddMsgApiClient(Configuration.GetSection(nameof(MsgApiClient)))//就是这行

第5步:使用:在Controller或其他地方都可以使用;

(1)首先在构造函数里注册:

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

(2)调用方法:

 /// <summary>
/// 发消息
/// </summary>
/// <returns></returns>
[HttpGet]
public async Task<Result<string>> POk()
{
Result<string> result = new Result<string>();
result = await _IMsgApiClient.SendWxWorkMsgAsync("", "我是沐雪,请明天来我办公室一趟!");
//result.state = true;
//result.data = "连接成功"; return result;
}

.netcore 3.1高性能微服务架构:封装调用外部服务的接口方法--HttpClient客户端思路分析的更多相关文章

  1. Spring Cloud构建微服务架构(二)服务消费者

    Netflix Ribbon is an Inter Process Communication (IPC) cloud library. Ribbon primarily provides clie ...

  2. Spring Cloud构建微服务架构(五)服务网关

    通过之前几篇Spring Cloud中几个核心组件的介绍,我们已经可以构建一个简略的(不够完善)微服务架构了.比如下图所示: 我们使用Spring Cloud Netflix中的Eureka实现了服务 ...

  3. 整合SPRING CLOUD云服务架构 - 企业分布式微服务云架构构建

    整合SPRING CLOUD云服务架构 - 企业分布式微服务云架构构建 1.   介绍 Commonservice-system是一个大型分布式.微服务.面向企业的JavaEE体系快速研发平台,基于模 ...

  4. Android 使用AIDL调用外部服务

    好处:多个应用程序之间建立共同的服务机制,通过AIDL在不同应用程序之间达到数据的共享和数据相互操作, 本文包括: 1 .创建AIDL 服务端.2 .创建AIDL 客户端. 3.客户端调用服务端提供的 ...

  5. 微服务架构 | *3.5 Nacos 服务注册与发现的源码分析

    目录 前言 1. 客户端注册进 Nacos 注册中心(客户端视角) 1.1 Spring Cloud 提供的规范标准 1.2 Nacos 的自动配置类 1.3 监听服务初始化事件 AbstractAu ...

  6. Spring Cloud构建微服务架构(一)服务注册与发现

    Spring Cloud简介 Spring Cloud是一个基于Spring Boot实现的云应用开发工具,它为基于JVM的云应用开发中的配置管理.服务发现.断路器.智能路由.微代理.控制总线.全局锁 ...

  7. 第1章 Spring Cloud 构建微服务架构(一)服务注册与发现

      一.Spring Cloud 简介 Spring Cloud是一个基于Spring Boot实现的云应用开发工具,它为基于JVM的云应用开发中的配置管理.服务发现.断路器.智能路由.微代理.控制总 ...

  8. 微服务 通过EnableFeignClients调用其他服务的api

    今天在项目上遇到一个问题,通过当前service服务要调用到其他service服务的api接口时,可通过EnableFeignClients调用其他服务的api,大概的步骤如下: 1.在springb ...

  9. Win2008服务启动不能调用Office Word的解决方法

    本文为大家分享一下如何解决Windows Server 2008 服务启动不能调用Office Word的问题,分享这个教程的原因是,今天在Windows server2008上部署一个应用时发现了一 ...

随机推荐

  1. 面试必备!Java核心技术100+面试题

    一线互联网公司工作了几年,我作为求职者参加了不少面试,也作为面试官面试了很多同学,整理这份面试指南,一方面是帮助大家更好的准备面试,有的放矢,另一方面也是对自己知识框架做一个体系化的梳理. 这篇文章梳 ...

  2. C语言的安装及使用

    安装 vc6.0 使用方法 new    ---  win32 Console Application ---  ok-ok     ------c++ Source File      ------ ...

  3. 一份中规中矩的 iOS笔试题

    一.背景 因为一些原因,我从公司离职,在此之前,我需要帮忙招聘一个新人来做我的工作,于是就有了这篇文章. 由于公司项目16年就已经上线了,前同事写的项目中,有用xib.storyBoard.代码自动布 ...

  4. tmobst5an

    1.(单选题)SQL语言又称为() A)结构化定义语言 B)结构化控制语言 C)结构化查询语言 D)结构化操纵语言 解析:SQL语言又称为结构化查询语言 2.(单选题)只有满足联接条件的记录才包含在查 ...

  5. CCF_201312-5_I’m stuck!

    一次bfs从起点开始找到起点能到达的点,一次bfs从终点开始找到能到终点的点,最后输出答案即可. 刚开始写的时候,考虑找起点能到达的点的时候,用了dfs,提交只有20分,仔细想了一下,会存在无限循环的 ...

  6. window10 vs2013 SIFTGPU

    碰到的问题: 1.一大推语法错误: 所有For_EACH_OCTAVE的地方都出现了语法错误.后来查找了一下For_EACH_OCTAVE是个啥,发现是一个宏定义,也不知道宏定义定义的好好的,为啥会编 ...

  7. python学习(5)写一个二分算法的程序

    把之前学习的做一个小结.之前看二分查找法,只能是似而非地看懂大概.现在用这么多天的知识积累已经可以自己写了. 而且在算法书的基础上,把需要找的数字做一个人机互动操作. 另外,初步接触到了 __name ...

  8. 2020年,手把手教你如何在CentOS7上一步一步搭建LDAP服务器的最新教程

    同步滚动:关 什么是LDAP 什么是LDAP? 要想知道一个概念,最简单的办法就是wikipedia,当然也可以百科. LDAP全称是轻型目录访问协议(Lightweight Directory Ac ...

  9. 入侵检测基本准则(Basic principles of intrusion detection)【v1.0】

    所谓“入侵检测”,顾名思义,就是对入侵行为的发觉.他通过对计算机网络或计算机系统中若干关键点收集信息并对其进行分析,从中发现网络或系统中是否有违反安全策略的行为和被攻击的迹象.” 但实际上,所谓的“违 ...

  10. coroutine - 示例

    分享流畅的python一书, coroutine 章节中的出租车仿真的例子. from collections import namedtuple import queue import random ...