源宝导读:微服务架构与传统的单体式方案的最大不同是微服务将应用的核心功能拆分成多项服务。每项服务可以单独构建和部署。服务之间需要互相通信。假设服务间每次通信都需要在调用方编码操作,那么必定会增加很大的工作量,并且造成代码冗余并且无法维护。

一、背景

集成平台在整体架构上抽象了连接中心核心服务来负责对外的服务通信。而在内部的服务通信中。接口中心,事件中心,服务流等都需要在接收到外部请求和指令后将对应的请求通过连接中心转发到第三方服务/厂商。那么,在系统内部就存在连接中心会不断的被其他微服务调用。连接中心在被调用时目前需要经历如下几个步骤,服务发现->负载均衡->APM->ZIP->身份认证处理->服务质量。如果这些步骤在此调用的时候都需要被重复编码,那结果肯定是灾难性的。所以,我们给我们的核心服务连接中心提供了专门的调用SDK。

二、实现思路

2.1 行业实现思想

SDK定义:指一些被软件工程师用于为特定的软件包、软件框架、硬件平台及操作系统等创建应用软件的开发工具之集合。

在单体应用早期,我们往往使用SDK封装一些对外公开的功能代码,这样需要使用此功能就可以直接引用SDK,而不需要从头开发。在SOA时代服务SDK的概念其实就已经出现在我们使用的技术中。比如,WCF的客户端在某种程度上也是一种服务SDK,使用客户端可以快捷的调用WCF服务端。而通信,序列化,编码等过程对我们来说是隐式的。我们不需要去关心这些特定的实现细节。

现阶段在对于行业而言,我们熟知的厂商提供了许多的软件服务。比如百度的地图服务,讯飞的语音服务。从他们的技术文档可以得知,基本上每个厂商在提供核心服务的同时。一定会给我们提供配套的服务SDK来简化我们调用服务的过程。在使用的过程中,我们往往只需要使用SDK进行简单的配置。遵循这一思想,在核心服务就绪后,我们可以给核心服务配套对应的SDK来简化外部调用的过程。

2.2 实现过程分析

整体架构分析 :

遵循行业服务端SDK设计思想,我们需要给MIP核心服务连接中心设计配套的调用SDK。虽然连接中心不对外提供服务,但是它在架构中需要对其他微服务提供服务。对应其他服务而言,也需要简化对连接中心的调用。

内部服务只需要引用连接中心SDK,提供连接对应的Code(标识)和Path(调用路径)。就可以驱动连接中心访问第三方服务。

SDK功能分析:

  • 支持链式调用,在调用链中现有业务需要支持链路追踪,请求压缩,服务发现,负载均衡,身份认证,服务质量。

  • 连接数据缓存,并实时更新最新连接数据。

内部服务调用连接中心连接服务需要经历如图所示步骤

缓存能力:在SDK加载启动时,SDK应具有实时更新连接数据的能力。

设计思路:通过上述分析得知,SDK支持的功能实际上是一个链式调用的过程。链中的处理中间件是根据需求组装,改变HttpRequest。通过分析有我们有三种链式调用实现方案。

  1. 使用GOF设计模式中的责任链模式构建链式调用通道。

  2. 模仿ASP.NET中间件模式,构建链式调用通道。

  3. 使用DelegatingHandler为HttpClient创建附加消息处理程序从而构建链式调用通道。

缓存设计思路:使用集成平台中比较成熟的Consul Blocking Query组件实时监控Consul中连接Flag的更改并实时获取最新的连接配置数据。

三、实现方案

经过对三种链式调用方案的对比,我们决定使用HttpClient的HttpHandler构建连接中心SDK的链式通道,那么为什么使用DelegatingHandler呢?第一和第二种方案需要我们自己实现链式调用的头尾相连的过程。这个过程比较繁琐而且维护成本较高。而HttpClient天生就支持创建附加消息处理程序。这样HttpClient的调用链就是一个调用通道。我们可以根据需求在这个通道中插入自己的逻辑。

关键实现代码

定义通道中的SDK功能实现

/// <summary>/// 连接中心SDK链路追踪实现/// </summary>publicclassTracingHandler : DelegatingHandler{//声明变量private readonly ConnectionProvider _provider;private readonly MipDeployConfigProvider _deployConfigProvider;protected static readonly DiagnosticListener _diagnosticListenerEvent = new DiagnosticListener(MIPDiagnosticStrings.EventActionInvokeListenerName);protected static readonly DiagnosticListener _diagnosticListenerApigateway = new DiagnosticListener(MIPDiagnosticStrings.ApiGatewayActionInvokeListenerName);protected static readonly DiagnosticListener _diagnosticListenerFlow = new DiagnosticListener(MIPDiagnosticStrings.Flow_ApiConnectionListenerName);/// <summary>/// 构造函数/// </summary>/// <param name="provider">连接中心运行时提供者</param>/// <param name="deployConfigProvider">部署信息提供者</param>public TracingHandler(ConnectionProvider provider, MipDeployConfigProvider deployConfigProvider){_provider = provider;_deployConfigProvider = deployConfigProvider;}/// <summary>/// 将MIP连接中心请求,相应链路追踪加入到HTTPClient扩展通道中/// </summary>/// <param name="requestMessage">发送到连接API的Http请求</param>/// <param name="cancellationToken">令牌</param>/// <returns>连接中心API请求结果</returns>protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage requestMessage, CancellationToken cancellationToken){try{//省略代码ExecuteHttpAfter(requestMessage, response, carrier);return response;}else{return await base.SendAsync(requestMessage, cancellationToken);}}catch (Exception ex){ExecuteHttpError(requestMessage, ex);throw;}}
}

编排通道调用链

public static class HttpHandleExtension{public static void AddHttpClinet(this IServiceCollection services){//编排HttpClient的调用通道链条services.TryAddTransient<ConnectivityTokenHandler>();services.TryAddTransient<AuthenticationHandler>();services.TryAddTransient<LoadBalancerHandler>();services.TryAddTransient<TracingHandler>();services.TryAddTransient<CompatibleGzipHandler>();services.TryAddTransient<PollyCircuitBreakingHandler>();services.TryAddTransient<WebRequestHandler>();services.TryAddSingleton<MipDeployConfigProvider>();AddConnectivityApiClient(services);AddConnectionApiClient(services);AddFakeConnectionApiClient(services);}/// <summary>/// 配置HTTP行为/// </summary>/// <returns></returns>private static HttpMessageHandler CreateDefaultHttpClientHandler(){var handler = new HttpClientHandler{AllowAutoRedirect = false,AutomaticDecompression = DecompressionMethods.None,UseCookies = false,UseProxy = false,ServerCertificateCustomValidationCallback = Const.DangerousAcceptAnyServerCertificateValidator,};if (handler.MaxConnectionsPerServer < Const.DefaultMaxConnectionsPerServer)handler.MaxConnectionsPerServer = Const.DefaultMaxConnectionsPerServer;//return handler;return new WebRequestHandler {InnerHandler = handler};}}

至此,集成平台中的其他内部服务,只需要调用SDK的注册就可以通过连接Code/Path来调用连接中心中连接实例提供的Rest服务了。

四、后续思考

目前而言,连接中心SDK并未公开任何扩展点。虽然我们构建了调用通道,但是对通道的扩展能力并未对外公开。在后续的过程中。SDK可以根据需求变更进行如下两个优化。

1、支持通道扩展能力。

2、缓存目前只支持从Consul实时更新数据,这也可以在后续过程中根据需求增加更多的基础设施。

------ END ------

作者简介

刘同学: 集成平台的开发工程师,目前负责天际平台相关开发工作。

也许您还想看:

技术分享|Java SDK动态数据源和上下文机制

技术分享|NodeJS分布式链路追踪实现

技术分享 | Java SDK 元数据驱动的事件通信架构

技术分享|Hangfire深度实践

技术分享 | APT结合JavaPoet生成模板化Java源代码文件

技术分享 | 玩转高效UI自动化测试

更多明源云·天际开放平台场景案例与开发小知识,可以关注明源云天际开发者社区公众号:

【建模】文档服务提供高保真打印模式

明源云·天际硬核技术认可:获华为鲲鹏技术认证书

天际·开发者社区“重装发布”!

技术分享 | 【构建服务端SDK】之连接中心统一调用SDK相关推荐

  1. Java:socket服务端,socket服务端支持多连接,socket客户端,socket客户端支持发送和接受

    一.Java之socket服务端 新建一个Java工程 命名 给他先创建一个类 在类里面我们做一个main 这里面也需要,创建套接字,IP号,端口号 但是java中有一个类         Serve ...

  2. android原生调用nextjs方法,详解使用Next.js构建服务端渲染应用

    next.js简介 最近在学React.js,React官方推荐使用next.js框架作为构建服务端渲染的网站,所以今天来研究一下next.js的使用. next.js作为一款轻量级的应用框架,主要用 ...

  3. 客户端提示连接oracle出错,客户端登录报错:与服务端的网络连接发生异常,请您联系管理员处理...

    版本号:GS70 业务场景(如下): 异常信息(异常类型:Genersoft.Platform.Core.Error.GSPException) 异常标识:00000000-0000-0000-000 ...

  4. Unity中与WebSocket服务端建立长连接

    笔记记录,由于项目需求需要和用WebSocket编写的服务端建立长连接进行实时同步,因此封装的一个脚本,这边用到了BaseHTTP的插件,因此使用这个脚本时需要导入BaseHTTP插件.脚本可以直接拿 ...

  5. close wait 过多原因_干货分享!服务端 TCP 连接的 TIME_WAIT 问题分析与解决

    写在开头,大概 4 年前,听到运维同学提到 TIME_WAIT 状态的 TCP 连接过多的问题,但是当时没有去细琢磨:最近又听人说起,是一个新手进行压测过程中,遇到的问题,因此,花点时间,细深究一下. ...

  6. 直播技术(从服务端到客户端)一

    环境部署 2015年开始直播变得越来越流行,很多的直播平台也应运而生,直播是一个很有技术的项目,从服务端到客户端到web等等.我们将写一序列的博客来阐述直播中的技术,这包括服务端技术和客户端技术.包括 ...

  7. 直播技术(从服务端到客户端)二

    播放 在上一篇文章中,我们叙述了直播技术的环境配置(包括服务端nginx,nginx-rtmp-module, ffmpeg, Android编译,iOS编译).从本文开始,我们将叙述播放相关的东西, ...

  8. Eclipse构建Maven分包分模块项目并构建服务端

    首先说一下Maven 模块结构: 一个简单的Maven模块结构是这样的: ---- app-parent 一个父项目(app-parent)聚合很多子项目(app-util,app-dao,app-s ...

  9. 【华为云技术分享】使用CloudIDE快速体验基于华为云ModelArts SDK的AI开发

    华为云ModelArts一站式AI开发与管理平台,能够支撑开发者从数据到AI应用的全流程开发过程,包含数据处理.算法开发.模型训练.模型管理.部署等,支持图像分类.图像检测.视频分析.语音识别.产品推 ...

最新文章

  1. 妙用vector:根据第一个不等的元素比较两个序列大小的利器
  2. CloudStack学习-1
  3. VHD(Virtual Hard Disk)的解析(上篇)——PyVinil的使用
  4. Bfs++ open the lock
  5. git 与github 命令行操作与控制
  6. 零基础学Python【二十三、图形化界面设计 】(基础一篇全,欢迎认领)
  7. [转]SQL2008关于c001f011的错误解决办法
  8. c++ vector排序_儿童时间管理课6:便利贴时间排序法
  9. 网络模型介绍、数据网络传输过程与网络传输速率
  10. java实现带logo的二维码
  11. PDF417打印后扫描不出来(记录)
  12. 计算机教室标语6个字,教室标语60句
  13. FineReport 创建报表模板
  14. 一款轻量级的权限框架,轻松搞定项目权限
  15. 基于jQuery/express/socket.io实现的匿名聊天室
  16. 开放IPTV论坛(OIPF)的HBB TV标准规范
  17. wlop一张多少钱_回答:小白有个问题,为什么很多人都说 WLOP鬼刀 的画不够好?...
  18. [洛谷]P2298 Mzc和男家丁的游戏 题解
  19. 4.15 最短路 题
  20. 【java初学】面向对象继承

热门文章

  1. xmanager远程桌面控制linux
  2. 第二天:装饰模式及面向对象设计原则4则
  3. 惠新宸php教程_惠新宸:首位国人加入PHP语言官方开发组
  4. 用链表和数组实现HASH表,几种碰撞冲突解决方法
  5. 深入理解null的原理
  6. [Javascript] Avoid Creating floats if they are not needed
  7. UVA-1045 - The Great Wall Game(二分图最佳匹配)
  8. 使用AzureFunction开发最简单的Teams Outgoing Webhook
  9. 从无到有到完善 - Teams抽奖机器人开发历程
  10. UmiJS CDN 部署之 publicPath