CN116257327B - 一种在jvm非阻塞系统中调用阻塞式客户端库的方法 - Google Patents
一种在jvm非阻塞系统中调用阻塞式客户端库的方法 Download PDFInfo
- Publication number
- CN116257327B CN116257327B CN202310539582.XA CN202310539582A CN116257327B CN 116257327 B CN116257327 B CN 116257327B CN 202310539582 A CN202310539582 A CN 202310539582A CN 116257327 B CN116257327 B CN 116257327B
- Authority
- CN
- China
- Prior art keywords
- blocking
- request
- http
- library
- client
- Prior art date
- Legal status (The legal status is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the status listed.)
- Active
Links
Classifications
-
- G—PHYSICS
- G06—COMPUTING; CALCULATING OR COUNTING
- G06F—ELECTRIC DIGITAL DATA PROCESSING
- G06F9/00—Arrangements for program control, e.g. control units
- G06F9/06—Arrangements for program control, e.g. control units using stored programs, i.e. using an internal store of processing equipment to receive or retain programs
- G06F9/44—Arrangements for executing specific programs
- G06F9/455—Emulation; Interpretation; Software simulation, e.g. virtualisation or emulation of application or operating system execution engines
- G06F9/45533—Hypervisors; Virtual machine monitors
- G06F9/45558—Hypervisor-specific management and integration aspects
-
- G—PHYSICS
- G06—COMPUTING; CALCULATING OR COUNTING
- G06F—ELECTRIC DIGITAL DATA PROCESSING
- G06F9/00—Arrangements for program control, e.g. control units
- G06F9/06—Arrangements for program control, e.g. control units using stored programs, i.e. using an internal store of processing equipment to receive or retain programs
- G06F9/44—Arrangements for executing specific programs
- G06F9/455—Emulation; Interpretation; Software simulation, e.g. virtualisation or emulation of application or operating system execution engines
- G06F9/45533—Hypervisors; Virtual machine monitors
- G06F9/45558—Hypervisor-specific management and integration aspects
- G06F2009/45562—Creating, deleting, cloning virtual machine instances
-
- G—PHYSICS
- G06—COMPUTING; CALCULATING OR COUNTING
- G06F—ELECTRIC DIGITAL DATA PROCESSING
- G06F9/00—Arrangements for program control, e.g. control units
- G06F9/06—Arrangements for program control, e.g. control units using stored programs, i.e. using an internal store of processing equipment to receive or retain programs
- G06F9/44—Arrangements for executing specific programs
- G06F9/455—Emulation; Interpretation; Software simulation, e.g. virtualisation or emulation of application or operating system execution engines
- G06F9/45533—Hypervisors; Virtual machine monitors
- G06F9/45558—Hypervisor-specific management and integration aspects
- G06F2009/45575—Starting, stopping, suspending or resuming virtual machine instances
-
- Y—GENERAL TAGGING OF NEW TECHNOLOGICAL DEVELOPMENTS; GENERAL TAGGING OF CROSS-SECTIONAL TECHNOLOGIES SPANNING OVER SEVERAL SECTIONS OF THE IPC; TECHNICAL SUBJECTS COVERED BY FORMER USPC CROSS-REFERENCE ART COLLECTIONS [XRACs] AND DIGESTS
- Y02—TECHNOLOGIES OR APPLICATIONS FOR MITIGATION OR ADAPTATION AGAINST CLIMATE CHANGE
- Y02D—CLIMATE CHANGE MITIGATION TECHNOLOGIES IN INFORMATION AND COMMUNICATION TECHNOLOGIES [ICT], I.E. INFORMATION AND COMMUNICATION TECHNOLOGIES AIMING AT THE REDUCTION OF THEIR OWN ENERGY USE
- Y02D10/00—Energy efficient computing, e.g. low power processors, power management or thermal management
Landscapes
- Engineering & Computer Science (AREA)
- Software Systems (AREA)
- Theoretical Computer Science (AREA)
- Physics & Mathematics (AREA)
- General Engineering & Computer Science (AREA)
- General Physics & Mathematics (AREA)
- Stored Programmes (AREA)
Abstract
本发明公开了一种在JVM非阻塞系统中调用阻塞式客户端库的方法,应用于配置有Kotlin语言库的JVM虚拟机中,在非阻塞业务系统中生成基于三方组件的Sdk非阻塞封装,所述基于三方组件的Sdk非阻塞封装设有对应Sdk的非阻塞api接口以及通用请求调用组件;也就是将第三方Sdk中的阻塞api采用一个伪装的Http客户端绕过,从而供非阻塞业务系统调用。本发明通过用第三方开源组件提供的特定Sdk,例如基于阻塞式的apachehttpclient、okhttp封装,来调用对应组件的Http服务端,从而实现在JVM非阻塞系统中调用阻塞式Http客户端库的方法。并且确保调用Http服务端的过程中不会导致非阻塞系统性能严重下降。
Description
技术领域
本发明属于分布式系统的跨系统、跨组件调用技术领域,尤其是一种在JVM非阻塞系统中调用阻塞式客户端库的方法。
背景技术
随着系统软件的工作量要求不断提升,相对于阻塞系统,非阻塞系统可以让相同数量的线程在相同时间内处理更多请求,提高整个系统的吞吐量。因此Jvm非阻塞系统被广泛研究和使用。但是现有技术中大部分三方库都是阻塞式的,例如现有技术中常用的Docker、Jenkins、Kubernetes的官方Java客户端,全部都是阻塞式系统。在Jvm非阻塞系统中,不能发生阻塞线程的调用。而这些阻塞式系统,每个系统里面的代码量数以万记,程序员无法为了使其能在非阻塞线程中使用而重新写一遍。为了在非阻塞系统中远程Http调用三方组件,现一般有两种方案来实现。
方案一:直接新开线程去调用三方组件的Sdk执行阻塞式IO操作,返回结果后就继续在原来的非阻塞线程里面运行。这种思路比较简单,也是最常用的方案,但缺点很明显,新开了线程,浪费了线程资源,加剧CPU的竞争,非阻塞系统相对于阻塞式系统的优势直接削弱了,如果大量api这样在新开的线程去调用,非阻塞系统也就变成阻塞式系统了。
方案二:直接忽略三方组件官方提供的Sdk,直接自己用原生的非阻塞Http客户端强行实现这个Sdk内的功能。这种方案的优点是和非阻塞的业务系统很契合;但缺点也非常明显,相当于重新造了一个不完整的Sdk,工作量巨大,还不敢保证自己的替代Sdk是否有bug等。由于工作量太大,这种方案实际上用的很少。
发明内容
为克服现有技术的不足及存在的问题,本发明通过用第三方开源组件提供的特定Sdk,例如基于阻塞式的ApacheHttpclient、OkHttp封装,来调用对应组件的Http服务端,从而实现在JVM非阻塞系统中调用阻塞式客户端库的方法。并且确保调用Http服务端的过程中不会导致非阻塞系统性能严重下降。
为实现上述目的,本发明创造采用如下技术方案:一种在JVM非阻塞系统中调用阻塞式客户端库的方法,应用于配置有Kotlin语言库的JVM虚拟机中,在非阻塞业务系统中生成基于三方组件的Sdk非阻塞封装,所述基于三方组件的Sdk非阻塞封装设有对应Sdk的非阻塞api接口以及通用请求调用组件;
在基于三方组件的Sdk非阻塞封装中生成对应该三方组件Sdk的客户端,为对应该三方组件Sdk新增一个伪装的Http客户端,在通用请求调用组件中新建方法该方法接收和Sdk对应方法相同的参数;
在通用请求调用组件中新建一个回调,回调内部直接调用Sdk;把回调、响应对象类型通用请求调用组件中;在通用请求调用组件中内执行回调;在回调过程中,Sdk组装访问服务端的Http请求,然后调用之前新增的伪装的Http客户端,然后在伪装的Http客户端内:利用通用发送请求的方法获取到请求Request对象,把其中的阻塞式Http库请求对象放到ThreadLocal本地线程变量;然后抛异常跳出组件库的执行逻辑;此时在通用请求调用组件内执行:捕获异常,忽略捕获到的异常并通过非阻塞Http库继续执行以下步骤:
从本地线程变量中取出请求对象;
把阻塞式Http库请求对象转化为非阻塞Http库请求对象;
用非阻塞Http库发送请求,中间经历耗时的异步非阻塞NIO,之后获取相应的响应;把非阻塞Http库获取的反序列化成传入的类型,并返回;
最终在通用请求调用组件内获取到通用请求封装返回的对象,并返回,完成调用。到此一个Http远程调用完成。新建方法是异步非阻塞的,和阻塞式的Sdk表现一致,完成了相同的功能。
优选的,所述利用通用发送请求的方法获取到Request对象时依次在Http请求包中的方法、路径、请求头、请求体位置获取请求对象。这样有序获取请求对象就很方便对接。
优选的,所述伪装的Http客户端的生成方法为:建立伪装的Http客户端类名,该伪装的Http客户端继承基础客户端对应的抽象类,覆盖所有请求必经的执行方法;覆盖的执行方法内部能接收到Http主机和Http请求的对象参数,将这两个对象参数放在线程变量里面,然后不运行实际发生阻塞IO的逻辑而是直接进入自定义异常从而退出执行。这样利用伪装的Http客户端获取到了Http主机和Http请求的对象参数。
优选的,该伪装的Http客户端继承对应原有的Http客户端对应的抽象类,实现响应的执行接口,当一个抽象类里面包含有多个执行方法时,只需确定覆盖的执行方法中包括了实现最终功能必然调用到的方法,如果覆盖的执行方法中不包括实现最终功能必然调用到的方法,则伪装的Http客户端建立失败。此时需要重新建立伪装的Http客户端。实现最终功能必然调用到的方法的整个调用过程如下:1.封装请求头和body;2.发起请求;3.提取响应结果。
优选的,Http对象转化实现方法为:通过多平台应用框架建立请求对象的非阻塞式Http库;获取阻塞式Http库请求包的链接uri、地址host、端口port、请求方法method,设置到非阻塞式Http库;遍历阻塞式Http库请求的请求头,逐个设置到请求对象非阻塞式Http库请求的请求头中;判断阻塞式Http库的请求中是否有请求体,如果有的话,以字节数组的形式获取到请求体内容,字符串的形式获取请求体类型,以这二者以非阻塞式Http库中字节数组内容(ByteArrayContent)对象设置为非阻塞式Http库请求的请求体。
优选的,Http响应结果解析方法为:获取到了非阻塞式Http库请求的请求体后这里使用非阻塞式Http库发送请求,然后获取到对应的响应(HttpResponse),直接调用基于泛型获取Http响应体的方法,自动把响应体转换成想要的类型,非阻塞式Http库内部会使用提前设置好的反序列化器,从响应体获取到该类型的实例。
优选的,所述三方组件的Sdk包括Jenkins、Kubernetes以及Docker,针对的阻塞式Http库包括ApacheHttpClient以及OkHttpClient,采用的非阻塞式Http库包括ktorClient和WebFluxWebClient。创建JenkinsSdk客户端对象JenkinsHttpClient时,传入伪装的Http客户端,调用诸如getJob方法时,即可按上述说明,获取到ApacheHttpRequest对象。
优选的,每个基于三方组件的Sdk非阻塞封装内仅有一套对应的三方组件,根据获取的对应Sdk的非阻塞api接口接入到该Sdk的非阻塞封装中。
本发明还包括一种在JVM非阻塞系统中调用阻塞式客户端库的方法,应用于配置有Kotlin语言库的JVM虚拟机中,在非阻塞业务系统中生成基于三方组件的Sdk非阻塞封装,所述基于三方组件的Sdk非阻塞封装设有为组件Sdk注入一个伪装的Http客户端,此时无法获取公开接口,采用动态代理、字节码来拦截。动态代理是利用代理模式的软件设计模式的一种具体应用,通过字节码的模式自动生成代理类。例如采用cglib库的动态代理技术,生成最终执行Http请求的类的代理类,在代理类覆盖重写Http请求方法,方法内部写伪装的Http的逻辑。在基于三方组件的Sdk非阻塞封装中生成对应该三方组件Sdk的客户端,为对应该三方组件Sdk新增一个伪装的Http客户端,在通用请求调用组件中新建方法该方法接收和Sdk对应方法相同的参数。这样的方法应用在无法获取公开接口的情况下。
本发明还包括一种设备,包括处理器以及与所述处理器相连接的存储器;
所述存储器用于存储计算机程序,所述计算机程序至少用于所述的在JVM非阻塞系统中调用阻塞式客户端库的方法;
所述处理器用于调用并执行所述存储器中的所述计算机程序。
通过本发明记载的技术方案,本发明在非阻塞系统中成功复用基于阻塞式api实现的三方组件客户端Sdk,而不对整个业务系统产生不利的影响。也就是将第三方Sdk中的阻塞api采用一个伪装的Http客户端绕过,从而供非阻塞业务系统调用。
此外,采用本发明的技术方案后,由于逻辑明确,使程序变得更清晰,有利于程序维护。在小组共同开发的过程中也可以提高程序开发的效率。
附图说明
图1是本发明在JVM非阻塞系统中调用阻塞式客户端库的方法的整体系统结构图;
图2是现有技术中常规doExcute执行方法示意图;
图3是本发明在JVM非阻塞系统中调用阻塞式客户端库的方法的中伪装的Http客户端的doExcute执行方法示意图;
图4是本发明在JVM非阻塞系统中调用阻塞式客户端库的方法的实施例1的时序图;
图5是本发明在JVM非阻塞系统中调用阻塞式客户端库的方法的Http对象转化示意图;
图6是本发明在JVM非阻塞系统中调用阻塞式客户端库的方法的物理装置示意图;
图7是实现实施例1时采用现有技术中方案一的线程数量示意图;
图8是本发明实现实施例1时的线程数量示意图;
图9是本发明实现实施例2时和对应现有技术中方案二的文件编辑量对比示意图。
具体实施方式
为了便于本领域技术人员的理解,下面结合附图和具体实施例对本发明创造作进一步描述。
在本发明中涉及多个Java术语及缩写,在此一并解释如下:
Java虚拟机:JavaVirtualMachine虚拟机,是运行所有Java程序的抽象计算机,是Java语言的运行环境,它是Java最具吸引力的特性之一。Java虚拟机有自己完善的硬体架构,如处理器、堆栈、寄存器等,还具有相应的指令系统。Java虚拟机屏蔽了与具体操作系统平台相关的信息,使得Java程序只需生成在Java虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改地运行。
Java方法:方法的本意是功能模块,是把一个公用功能抽出来作为一个方法,设计方法的时候,要保证方法的原子性,一个方法只完成一个功能,这样方便后期扩展。在Java中,方法是语句的集合,这个集合一起执行能完成某个功能。简单的说,Java的方法类似于其他语言的函数,是一段用来完成特定功能的代码组合体。抛出异常:程序出现异常时,并不将具体的异常打印出来,不做任何处理;程序中断。
捕获异常:程序出现异常时,详细的打印是什么原因导致了异常并且能够做出相应的处理,能够显示详细的日志,且程序不中断。
Kotlin:Kotlin是一个用于现代多平台应用的静态编程语言,由JetBrains开发。Kotlin可以编译成Java字节码,也可以编译成JavaScript,方便在没有JVM的设备上运行。除此之外Kotlin还可以编译成二进制代码直接运行在机器上,提升程序员的生产力,可以通过非常不同且更加简单的方式来解决一些常见的问题。
SDK:SoftwareDevelopmentKit软件开发工具包,是软件开发工程师用于为特定的软件包、软件框架、硬件平台、操作系统等建立应用软件的开发工具的集合。
API接口:ApplicationProgrammingInterface,应用程序编程接口,是一些预先定义的函数,目的是提供应用程序与开发人员基于某软件或硬件的以访问一组例程的能力,而又无需访问源码,或理解内部工作机制的细节。
ThreadLocal:本地线程变量。
RequestThreadLocal:本地线程变量请求,即在ThreadLocal中填充当前线程的变量,该变量对其他线程而言是封闭且隔离的,ThreadLocal为变量在每个线程中创建了一个副本,这样每个线程都可以访问自己内部的副本变量。对该线程的请求就是本地线程变量请求。
NIO:Non-BlockingIO,即非阻塞式IO模型。
BIO:BlockingIO,即阻塞式IO模型。
使用Kubernetes在集群中管理容器化应用程序时,使用Jenkins来自动化构建和部署这些应用程序是很常见的。Docker则为容器化技术提供了基础设施,可以打包应用程序及其依赖项,并将其部署到Kubernetes集群中。
Docker是一个开源容器化平台,可以用来打包应用程序及其所有依赖项,以便在不同的环境中运行。使用Docker,开发人员可以创建一个称为Docker容器的独立运行时环境,并将应用程序和所有必要的库和依赖项打包到容器中。Docker容器提供了一种轻量级的虚拟化方法,可以在任何操作系统上运行,而不需要任何其他依赖项。
Kubernetes是一个开源的容器编排平台,用于自动化管理和调度容器化应用程序。Kubernetes可以自动管理和扩展容器化应用程序,确保它们始终保持可用和可靠。Kubernetes可以将容器组合成更大的、分布式的应用程序,并在整个集群中进行管理,以确保应用程序始终保持可用状态。
Jenkins是一个开源的自动化工具,用于自动构建、测试和部署应用程序。使用Jenkins,开发人员可以创建一个名为"Job"的自动化流程,其中包括构建、测试和部署应用程序的步骤。Jenkins可以轻松地与Kubernetes集群集成,以自动化容器化应用程序的构建和部署流程。
综上所述,Docker提供了容器化基础设施,Kubernetes提供了容器编排和自动化管理,而Jenkins则提供了自动化构建和部署工具。它们可以在一起使用,为开发人员提供一个完整的DevOps工具链,可以自动化构建、测试和部署应用程序,并在整个生命周期中保持应用程序的可用性和可靠性。Kubernetes、Docker、Jenkins通常进行持续集成,Docker可被用作由Kubernetes编排的容器运行时。当Kubernetes将容器集调度到节点上时,该节点上的kubelet会指示Docker启动指定的容器。然后,kubelet持续从Docker收集这些容器的状态,并将该信息聚合到控制平面中。Docker将容器拉到该节点上,并且启动和停止这些容器。当JenkinsMaster出现故障时,Kubernetes会自动创建一个新的JenkinsMaster容器,并且将Volume分配给新创建的容器,保证数据不丢失,从而达到集群服务高可用。
需要注意的是,虽然在Java环境下,Kubernetes、Docker、Jenkins通常进行持续集成,但是这三者还是属于三个不同的Sdk,需要分别处理。
而分别处理时建立的任一个接口,都可以进行全局操作。例如创建环境接口,对应页面上面的创建环境按钮,会同时调用Kubernets、Jenkins,在Kubernetes创建命名空间、在Jenkins创建Job文件夹。
通常的阻塞式线程模型在连接建立请求时和接收数据时会发生阻塞,虽然可以通过多线程解决这个问题,但随之产生的问题就是每一个请求都会对应一个线程,当请求增加时,线程也会1比1的增加,非常消耗资源,一般服务器承受不起。
而非阻塞式线程模型在连接请求时和读取数据时,都不会阻塞。因此可以动态伸缩,合理使用资源。
如背景技术所述,为了在非阻塞系统中远程Http调用三方组件,现一般有两种方案来实现。实际上在JDK1.1之前,Java曾经支持过绿色线程(又称虚拟线程),但该功能在JDK1.1中移除了,因为当时该实现并没有比平台线程更好。
伪装的Http客户端:FakeHttpClient,通常用于单元测试,用于验证参数的准确性。而在本发明中,我们采用伪装的Http客户端获取Http主机和Http请求的对象参数。以供后续绕开阻塞式Sdk。
如图1至图3所示本发明则设计了一套方案用于对接改造。ApacheHttpClient、OkHttp是Java下常用的Http客户端,基于BIO技术、或者阻塞式api封装,被广泛用于各种业务系统、中间件,里面发生的调用是阻塞线程的调用。Java下常用的非阻塞Http客户端有如下,基于Netty的SpringWebfluxWebClient、Vert.xHttpClient;直接基于NIO的jdk11自带HttpClient、ApacheHttpAsyncClient;基于Kotlin协程的ktorclient。
实施例:在JVM非阻塞系统的环境下,想要对一个远程Http服务做操作。
Response是由服务端构建的,有实体类的情况下,客户端只需要一个通用的解码器就能完成转化;
请求Request是由客户端构建的,需要加各种参数、改url、加请求头、请求方法等操作,较复杂,几乎没办法统一处理,客户端库会通过提供的Sdk方法构建一个请求,现在只需要获取这个请求Request;
HttpRequest在方法、路径、请求头、请求体这4个位置依次寻找获取。这样就很方便对接。
在封装客户端内:
首先为组件Sdk注入一个伪装的Http客户端,新建方法getJob:接收和Sdk对应方法:getJob相同的参数。此时在此新建方法(getJob)中:该方法新建一个回调,回调内部直接调用Sdk;把回调、响应对象类型传入通用请求封装;
Jenkinsk8s插件分布式调度构建的场景下,当调用JenkinsJob对象的build方法,且该Job恰好为Jenkinsk8s插件分布式调度构建时。每次运行方法时,会自动创建一个JenkinsSlave,方法完成后,Slave自动注销并删除容器,资源自动释放。在整个过程中而且Kubernetes会根据每个资源的使用情况,动态分配Slave到空闲的节点上创建,降低出现因某节点资源利用率高,还排队等待在该节点的情况。当Kubernetes集群的资源严重不足而导致方法排队等待时,可以很容易的添加一个KubernetesNode到集群中,从而实现扩展。
接着在通用请求封装内执行回调,Sdk组装访问服务端的ApacheHttp请求,接下来调用之前注入的伪装的ApacheHttp客户端。伪装的Http客户端采用通用发送请求的方法获取到ApacheRequest对象,把ApacheRequest对象放到ThreadLocal;然后抛出异常状况,强制中止,从而跳出组件库的执行逻辑。
通用请求封装捕获到伪装的Http客户端所抛出的异常,忽略捕获到的异常并继续执行以下操作:
从ThreadLocal中取出ApacheRequest对象;
把ApacheRequest对象转化为ktorRequest对象;
用ktor发送请求,中间经历耗时的异步非阻塞NIO,之后获取ktorHttp响应;
把ktorHttp响应体反序列化成传入的类型,并返回方法:getJob。
获取到通用请求封装返回的对象,并返回。到此一个Http远程调用完成,新建方法(getJob)是异步非阻塞的,和阻塞式的Sdk表现一致,完成了相同的功能。
在对一个Sdk的非阻塞化封装过程中,除了新建方法,其他步骤流程只需要一次即可。而新建的方法也是非常简单的做下通用封装、Sdk的调用,相当于是这一整套工具的入口。
在所述的步骤中,ktor可以替换为其他任意非阻塞Http客户端,JenkinsSdk可以替换成任意三方阻塞式HttpSdk,getJob方法可以替换成该Sdk下的其他任意方法。
过程中逻辑的通用化封装,以及易变操作的便捷化封装;Http请求对象从一个客户端转为另外一种客户的对象实例,需要考虑方方面面,以JenkinsJavaClientApacheHttpClient为例,伪装的Http客户端类名为FakeApacheHttpClient。FakeApacheHttpClient继承Apache基础客户端抽象类CloseableHttpClient,覆盖所有请求必经的实现最终功能必然调用到的方法。在本实施例中所述实现最终功能必然调用到的方法为doExecute方法。如果覆盖的执行方法中不包括doExecute方法,则伪装的Http客户端建立失败。此时需要重新建立伪装的Http客户端。doExecute方法的整个调用过程如下:1.封装请求头和body;2.发起请求;3.提取响应结果。
这里需要注意的是:本实施例中采用的doExecute仅仅是Apache Http客户端的通用请求方法名。如果采用不同的客户端,其方法名会变,除了Apache Http client采用的doExecute外,在OkHttp中采用的是execute,在Docker-Java api:中采用的是execute。虽然名称有变化,但是所有Http请求经处理后都走的这个方法逻辑是一致的。
覆盖方法内部能接收到HttpHost、HttpRequest对象参数,将这两个对象放在线程变量ThreadLocal里面,然后直接抛自定义异常FakeRequestException退出执行,不走实际发生阻塞IO的逻辑。创建JenkinsSdk客户端对象JenkinsHttpClient时,传入FakeApacheHttpClient。调用诸如getJob方法时,即可按上述说明,获取到ApacheHttpRequest对象。
Http对象转化实现:
如图4、图5所示:以ApacheHttpclient请求对象ApacheRequest转ktor请求对象为例。
新建ktor请求对象KtorRequest;
获取ApacheRequest的链接uri、地址host、端口port、请求方法method,设置到KtorRequest;
遍历ApacheRequest的请求头,逐个设置到KtorRequest的请求头中;
判断ApacheRequest是否有请求体,如果有的话,以字节数组的形式获取到请求体内容,字符串的形式获取请求体类型,以这二者以ktorByteArrayContent对象设置为KtorRequest请求体。
Http响应结果解析以JenkinsSdk为例。
前面获取到了KtorRequest请求体,这里使用ktor发送请求,然后获取到ktor响应HttpResponse。直接调用body<T>方法,传入T泛型,如Job类型,ktor内部会使用提前设置好的jackson反序列化器,从响应体获取到T类型的实例。
压力测试控制逻辑:开启1000个并发,每个并发内部循环执行,每10秒调用一次JenkinsSdk,访问两次Jenkins,获取任务文件夹列表。如图7所示为采用现有技术中的方案一时每个阻塞式api新开启线程的线程资源消耗情况;图8所示为本实施例中封装阻塞式api后线程资源消耗情况。从图7和图8中可见采用本发明的技术方案后,线程资源消耗从上千减少到40多,消耗显著减少。图中的线程包括了活跃线程和守护线程,所谓守护线程,是指在程序运行的时候在后台提供一种通用服务的线程,并且这种线程并不属于程序中不可或缺的部分。因此,当所有的非守护线程结束时,程序也就终止了,同时会杀死进程中的所有守护线程。反过来说,只要任何非守护线程还在运行,程序就不会终止。
本实施例中记载的方案,在没有公开接口的情况下甚至可以用动态代理、字节码来拦截。动态代理是利用代理模式的软件设计模式的一种具体应用,通过字节码的模式自动生成代理类。例如采用cglib库的动态代理技术,生成最终执行Http请求的类的代理类,在代理类覆盖重写Http请求方法,方法内部写伪装的Http的逻辑。在基于三方组件的Sdk非阻塞封装中生成对应该三方组件Sdk的客户端,为对应该三方组件Sdk新增一个伪装的Http客户端,在通用请求调用组件中新建方法该方法接收和Sdk对应方法相同的参数。除了cglib库,Javassist、Byte Buddy这几个也是常见的是字节码操作库,也都能应用在本发明的实施方式中。
实施例:如图6所示为某企业内部平台为JVM下基于webflux+Kotlincoroutines的非阻塞系统,内部使用本发明所述的封装方式来请求Jenkins、Kubernetes、Docker,达到了快速开发、使阻塞式三方Sdk完美契合非阻塞系统的效果。
上述封装中,除了前端对接各个组件restapiSdk不同,其他逻辑整体上是类似的,通用的部分可以封装成库来复用。这里实现了OkHttp请求转换为ktor请求、ApacheHttpclient请求转化为ktor请求的通用封装,伪装的ApacheHttpclient请求处理实现封装,通用请求线程存储封装;这些封装的类库,其他采用类似方案的对接都可以直接复用,比如下面三个客户端直接使用的这些封装。
封装Jenkins客户端就是上文所述的伪装的ApacheHttp客户端注入JenkinsJavaSdk,然后对接ktor;为内部平台系统提供Jenkins任务创建、修改、删除、运行、流水线自定义编辑等功能,对内部平台中的DevOps体系的构建环节提供基础支持;
封装Kubernetes客户端,由于其JavaSdk可以直接返回OkHttpCall对象,略去注入伪装的客户端步骤,直接转换Call为ktor请求来对接;为内部平台系统提供Kubernetes的操作功能,用来获取容器运行的状态、宿主机的监控指标等;至于部署的api操作内部平台通过另外的helm进行,对内部平台DevOps体系的部署环节提供基础支持。
封装Docker客户端,Docker-JavaSdk里面直接有DockerHttpClient接口,可以自己做实现,就直接注入伪装的DockerHttpClient实现,逻辑同FakeHttpClient,获取到的Request对象转为ktor请求来发送。为内部平台提供操作远程宿主机上面Docker的能力,可以用来管理Kubernetes外的容器,这些容器一般提供内部平台系统所没有做的额外功能的补充。
由于本实施例所在系统较为复杂,因此对三个封装客户端均有涉及,且不仅仅涉及此3个客户端。但是对于其它结构简单的平台系统,可以仅使用其中部分封装的客户端。
如图9所示,在本实施例中每新增一个接口对接,传统方案二需要新增10多行代码,来处理参数逻辑,拼装url地址、url参数、请求参数,本方案只需要调用Sdk即可,新增3行代码,其中两行还只是方法声明的语法结构,实际逻辑只有调用的这一行,非常简单。
本发明还包括一种设备,包括处理器以及与所述处理器相连接的存储器;
所述存储器用于存储计算机程序,所述计算机程序至少用于所述的在JVM非阻塞系统中调用阻塞式客户端库的方法;
所述处理器用于调用并执行所述存储器中的所述计算机程序。
需要说明的是,在本文中,诸如第一和第二等之类的关系术语仅仅用来将一个实体或者操作与另一个实体或操作区分开来,而不一定要求或者暗示这些实体或操作之间存在任何这种实际的关系或者顺序。而且,术语“包括”、“包含”或者其任何其他变体意在涵盖非排他性的包含,从而使得包括一系列要素的过程、方法、物品或者设备不仅包括那些要素,而且还包括没有明确列出的其他要素,或者是还包括为这种过程、方法、物品或者设备所固有的要素。在没有更多限制的情况下,由语句“包括一个……”限定的要素,并不排除在包括所述要素的过程、方法、物品或者设备中还存在另外的相同要素。
以上实施例仅用以说明本公开的技术方案,而非对其限制;尽管参照前述实施例对本公开进行了详细的说明,本领域的普通技术人员应当理解:其依然可以对前述各实施例所记载的技术方案进行修改,或者对其中部分技术特征进行等同替换;而这些修改或者替换,并不使相应技术方案的本质脱离本公开各实施例技术方案的精神和范围。
Claims (8)
1.一种在JVM非阻塞系统中调用阻塞式客户端库的方法,应用于配置有Kotlin语言库的JVM虚拟机中,其特征在于,在非阻塞业务系统中生成基于三方组件的Sdk非阻塞封装,所述基于三方组件的Sdk非阻塞封装设有对应Sdk的非阻塞api接口以及通用请求调用组件;
在基于三方组件的Sdk非阻塞封装中生成对应该三方组件Sdk的客户端,为对应该三方组件Sdk新增一个伪装的Http客户端,在通用请求调用组件中新建方法,该方法接收和Sdk对应方法相同的参数;
在通用请求调用组件中新建一个回调,回调内部直接调用Sdk;把回调、响应对象类型传入通用请求调用组件中;在通用请求调用组件中内执行回调;在回调过程中,Sdk组装访问服务端的Http请求,然后调用之前新增的伪装的Http客户端,在伪装的Http客户端内:利用通用发送请求的方法获取到请求对象,把其中的阻塞式Http库请求对象放到本地线程变量;抛出异常跳出组件库的执行逻辑;此时在通用请求调用组件内执行:捕获异常,忽略捕获到的异常并通过非阻塞Http库继续执行以下步骤:
从本地线程变量中取出请求对象;
把阻塞式Http库请求对象转化为非阻塞Http库请求对象;
用非阻塞Http库发送请求,中间经历耗时的异步非阻塞模型,获取相应的响应;把非阻塞Http库获取的响应结果反序列化成传入的类型,并返回;
最终在通用请求调用组件内获取到通用请求封装返回的对象,并返回,完成调用。
2.根据权利要求1所述的一种在JVM非阻塞系统中调用阻塞式客户端库的方法,其特征在于,所述利用通用发送请求的方法获取到请求对象时依次在Http请求包中的方法、路径、请求头、请求体位置获取请求对象。
3.根据权利要求1所述的一种在JVM非阻塞系统中调用阻塞式客户端库的方法,其特征在于,所述伪装的Http客户端的生成方法为:建立伪装的Http客户端类名,该伪装的Http客户端继承基础客户端对应的抽象类,覆盖所有请求必经的执行方法;覆盖的执行方法内部能接收到Http主机和Http请求的对象参数,将这两个对象参数放在线程变量里面,然后不运行实际发生阻塞io的逻辑而是直接进入自定义异常从而退出执行。
4.根据权利要求3所述的一种在JVM非阻塞系统中调用阻塞式客户端库的方法,其特征在于,该伪装的Http客户端继承对应原有的Http客户端对应的抽象类,实现响应的执行接口,当一个抽象类里面包含有多个执行方法时,只需确定覆盖的执行方法中包括了实现最终功能必然调用到的方法,如果覆盖的执行方法中不包括实现最终功能必然调用到的方法,则伪装的Http客户端建立失败,需要重新建立Http客户端。
5.根据权利要求1所述的一种在JVM非阻塞系统中调用阻塞式客户端库的方法,其特征在于,Http对象转化实现方法为:通过多平台应用框架建立请求对象的非阻塞式Http库;获取阻塞式Http库请求包的链接uri、地址host、端口port、请求方法method,设置到非阻塞式Http库;遍历阻塞式Http库请求的请求头,逐个设置到请求对象非阻塞式Http库请求的请求头中;判断阻塞式Http库的请求中是否有请求体,如有,以字节数组的形式获取到请求体内容,字符串的形式获取请求体类型,以这二者以非阻塞式Http库中字节数组内容对象设置为非阻塞式Http库请求的请求体。
6.根据权利要求1所述的一种在JVM非阻塞系统中调用阻塞式客户端库的方法,其特征在于,Http响应结果解析方法为:获取到了非阻塞式Http库请求的请求体后这里使用非阻塞式Http库发送请求,然后获取到对应的响应,直接调用基于泛型获取Http响应体的方法,自动把响应体转换成想要的类型,非阻塞式Http库内部会使用提前设置好的反序列化器,从响应体获取到该类型的实例。
7.根据权利要求1-6其中任一所述的一种在JVM非阻塞系统中调用阻塞式客户端库的方法,其特征在于,所述三方组件的Sdk包括Jenkins、Kubernetes以及Docker,针对的阻塞式Http库包括Apache HttpClient以及Ok HttpClient,采用的非阻塞式Http库包括ktorClient和WebFlux WebClient。
8.根据权利要求7所述的一种在JVM非阻塞系统中调用阻塞式客户端库的方法,其特征在于,每个基于三方组件的Sdk非阻塞封装内仅有一套对应的三方组件,根据获取的对应Sdk的非阻塞api接口接入到该Sdk的非阻塞封装中。
Priority Applications (1)
Application Number | Priority Date | Filing Date | Title |
---|---|---|---|
CN202310539582.XA CN116257327B (zh) | 2023-05-15 | 2023-05-15 | 一种在jvm非阻塞系统中调用阻塞式客户端库的方法 |
Applications Claiming Priority (1)
Application Number | Priority Date | Filing Date | Title |
---|---|---|---|
CN202310539582.XA CN116257327B (zh) | 2023-05-15 | 2023-05-15 | 一种在jvm非阻塞系统中调用阻塞式客户端库的方法 |
Publications (2)
Publication Number | Publication Date |
---|---|
CN116257327A CN116257327A (zh) | 2023-06-13 |
CN116257327B true CN116257327B (zh) | 2023-09-15 |
Family
ID=86684669
Family Applications (1)
Application Number | Title | Priority Date | Filing Date |
---|---|---|---|
CN202310539582.XA Active CN116257327B (zh) | 2023-05-15 | 2023-05-15 | 一种在jvm非阻塞系统中调用阻塞式客户端库的方法 |
Country Status (1)
Country | Link |
---|---|
CN (1) | CN116257327B (zh) |
Citations (6)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
CN108200177A (zh) * | 2018-01-04 | 2018-06-22 | 郑州云海信息技术有限公司 | 一种非阻塞同步模式数据库中间件网络通信的方法及系统 |
KR102256736B1 (ko) * | 2020-02-13 | 2021-05-27 | 비엠텍시스템 주식회사 | Api 관리 시스템 및 그에 관한 방법 |
CN114756357A (zh) * | 2022-06-14 | 2022-07-15 | 浙江保融科技股份有限公司 | 一种基于jvm的非阻塞分布式计划任务调度方法 |
CN114978663A (zh) * | 2022-05-18 | 2022-08-30 | 王荣鑫 | 基于行为伪装的互联网安全服务系统 |
CN115834660A (zh) * | 2023-02-22 | 2023-03-21 | 江苏为是科技有限公司 | 一种非阻塞rdma连接建立方法及装置 |
CN116088971A (zh) * | 2023-02-17 | 2023-05-09 | 北京奇艺世纪科技有限公司 | 服务提供方法和装置、电子设备、存储介质 |
Family Cites Families (1)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
US10095562B2 (en) * | 2013-02-28 | 2018-10-09 | Oracle International Corporation | System and method for transforming a queue from non-blocking to blocking |
-
2023
- 2023-05-15 CN CN202310539582.XA patent/CN116257327B/zh active Active
Patent Citations (6)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
CN108200177A (zh) * | 2018-01-04 | 2018-06-22 | 郑州云海信息技术有限公司 | 一种非阻塞同步模式数据库中间件网络通信的方法及系统 |
KR102256736B1 (ko) * | 2020-02-13 | 2021-05-27 | 비엠텍시스템 주식회사 | Api 관리 시스템 및 그에 관한 방법 |
CN114978663A (zh) * | 2022-05-18 | 2022-08-30 | 王荣鑫 | 基于行为伪装的互联网安全服务系统 |
CN114756357A (zh) * | 2022-06-14 | 2022-07-15 | 浙江保融科技股份有限公司 | 一种基于jvm的非阻塞分布式计划任务调度方法 |
CN116088971A (zh) * | 2023-02-17 | 2023-05-09 | 北京奇艺世纪科技有限公司 | 服务提供方法和装置、电子设备、存储介质 |
CN115834660A (zh) * | 2023-02-22 | 2023-03-21 | 江苏为是科技有限公司 | 一种非阻塞rdma连接建立方法及装置 |
Non-Patent Citations (2)
Title |
---|
Inter-kernel Reuse-aware Thread Block Scheduling;Muhammad Huzaifa;ACM Transactions on Architecture and Code OptimizationVolume 17Issue 3;1-27 * |
一种安全非阻塞通信的实现方法;张建辉;;网络安全技术与应用(第12期);88-90 * |
Also Published As
Publication number | Publication date |
---|---|
CN116257327A (zh) | 2023-06-13 |
Similar Documents
Publication | Publication Date | Title |
---|---|---|
US8151277B2 (en) | Method and system for dynamic remote injection of in-process agents into virtual machine based applications | |
US7593980B2 (en) | Application server system and method | |
Schmidt et al. | C++ Network Programming, Volume 2: Systematic Reuse with ACE and Frameworks | |
US7904886B2 (en) | Method for executing an application in a virtual container forming a virtualized environment session | |
US8402443B2 (en) | Method and system for automated analysis of the performance of remote method invocations in multi-tier applications using bytecode instrumentation | |
Schmidt | Applying patterns and frameworks to develop object-oriented communication software | |
US20100242031A1 (en) | Systems and Methods for Dynamically Linking Application Software into a Running Operating System Kernel | |
US7130881B2 (en) | Remote execution model for distributed application launch and control | |
US20050086640A1 (en) | Initiating execution of application programs on a data processing arrangement | |
Lin et al. | Tracing function dependencies across clouds | |
US20240143468A1 (en) | System and methods for testing microservices | |
CN104423932B (zh) | Javascript中调用二进制组件的方法 | |
Arad et al. | Message-passing concurrency for scalable, stateful, reconfigurable middleware | |
CN116257327B (zh) | 一种在jvm非阻塞系统中调用阻塞式客户端库的方法 | |
Fortier et al. | Dyninka: a FaaS framework for distributed dataflow applications | |
CN116743833A (zh) | 增强终端与服务通讯能力和网络控制能力的方法和装置 | |
Furlong et al. | The case for determinism on the edge | |
Solayman et al. | Seamless Integration of DevOps Tools for Provisioning Automation of the IoT Application on Multi-Infrastructures | |
CN113312031B (zh) | 一种软件通信体系结构的命名服务接口 | |
Wolf et al. | Supporting component-based failover units in middleware for distributed real-time and embedded systems | |
Valetto et al. | A uniform programming abstraction for effecting autonomic adaptations onto software systems | |
US7774756B1 (en) | Method and system for creating a logical view out of remote method invocations | |
Rakshitha et al. | Software Configuration Using Jenkins and Yocto Project | |
CN118642865A (zh) | 一种多语言多平台算法封装调度系统及方法 | |
Lovas et al. | Debugging of metacomputing applications |
Legal Events
Date | Code | Title | Description |
---|---|---|---|
PB01 | Publication | ||
PB01 | Publication | ||
SE01 | Entry into force of request for substantive examination | ||
SE01 | Entry into force of request for substantive examination | ||
GR01 | Patent grant | ||
GR01 | Patent grant |