实现PHP内核可重入的方法、装置、服务器和存储介质与流程

文档序号:15636263发布日期:2018-10-12 21:30阅读:242来源:国知局
本发明涉及计算机
技术领域
:,特别涉及一种实现php内核可重入的方法、装置、服务器和存储介质。
背景技术
::在多线程环境中,一般是使用php-fpm(fastcgiprocessmanager,fastcgi进程管理器)对处理请求进行处理。当php-fpm接收到处理请求时,会为该处理请求分配一个服务进程,该服务进程使用同步阻塞io(input/output,输入/输出)的处理模式进行处理,然而同步阻塞io的处理模式严重限制了php-fpm处理高并发请求的处理能力。而提升并发能力最有效的方法就是将io处理异步化。而传统的将io处理异步化的方法往往是基于事件异步回调处理的方式进行实现。但传统的基于事件异步回调处理的编程模式在处理复杂业务逻辑的场景中开发效率十分低下;并且无法重用原有的业务代码。而使用基于协程的服务器架构可以很好的解决这一点,其同步编码异步执行的特性方便业务开发的同时兼备了高性能。由于php(hypertextpreprocessor,超文本预处理器)语言本身并没有对应用透明的协程特性。因此为了解决这个问题,需要将php内核嵌入到协程架构中,使得php开发也能充分享用到协程的特性,将php服务的性能提升到一个新的高度。而将php内核嵌入到协程架构中,就需要实现php内核的可重入问题。技术实现要素:本发明提供了一种实现php内核可重入的方法、装置、服务器和存储介质,可以解决相关技术中存在的问题。技术方案如下:一方面,本发明实施例提供了一种实现php内核可重入的方法,所述方法包括:当服务器接收到处理请求时,为待重入的超文本预处理器php内核分配协程;通过所述协程运行所述php内核,得到所述php内核的运行实例;根据所述php内核的全局实例表,选择一个空闲实例的实例标识,所述全局实例表中存储至少一个实例标识和实例状态的对应关系;根据所述实例标识,将所述php内核的运行实例切换到选择的空闲实例中,以及根据所述实例标识,将对所述php内核中的结构体指针资源的访问,切换到所述空闲实例对应的资源上。一方面,本发明实施例提供了一种实现php内核可重入的装置,所述装置包括:分配模块,用于当服务器接收到处理请求时,为待重入的超文本预处理器php内核分配协程;运行模块,用于通过所述协程运行所述php内核,得到所述php内核的运行实例;选择模块,用于根据所述php内核的全局实例表,选择一个空闲实例的实例标识,所述全局实例表中存储至少一个实例标识和实例状态的对应关系;切换模块,用于根据所述实例标识,将所述php内核的运行实例切换到选择的空闲实例中,以及根据所述实例标识,将对所述php内核中的结构体指针资源的访问,切换到所述空闲实例对应的资源上。一方面,本发明实施例提供了一种服务器,所述服务器包括:处理器和存储器,所述存储器中存储有至少一条指令、至少一段程序、代码集或指令集,所述指令、所述程序、所述代码集或所述指令集由所述处理器加载并执行以实现如第一方面所述的实现php内核可重入的方法中所执行的操作。一方面,本发明实施例提供了一种计算机可读存储介质,所述计算机可读存储介质中存储有至少一条指令、至少一段程序、代码集或指令集,所述指令、所述程序、所述代码集或所述指令集由处理器加载并执行以实现如第一方面所述的实现php内核可重入的方法中所执行的操作。本发明实施例提供的技术方案带来的有益效果至少包括:在本发明实施例中,当服务器接收到处理请求时,将该php内核的运行实例切换到协程中,将该php内核的结构体指针资源的访问切换到空闲实例上,从而实现了php内核的可重入,从而使得php内核具备了协程特性,提高了php内核的并发处理能力。附图说明图1是本发明实施例提供的一种php内核的架构的示意图;图2是本发明实施例提供的一种tsrm的处理机制的示意图;图3是本发明实施例提供的一种实现php内核可重入的方法流程图;图4是本发明实施例提供的一种结构体指针资源和资源表的对应关系的示意图;图5是本发明实施例提供的一种协程和结构体指针资源的对应关系的示意图;图6是本发明实施例提供的一种实现php内核可重入的装置的结构示意图;图7是本发明实施例提供的一种服务器的结构示意图。具体实施方式为使本发明的目的、技术方案和优点更加清楚,下面将结合附图对本发明实施方式作进一步地详细描述。本发明实施例提供了一种php内核的框架。该php内核可以为zendengine(php官方引擎)。参见图1,该php内核包括:zendapi(applicationprogramminginterface,应用程序编程接口)、executor(执行器)、garbagecollector(垃圾回收器)、compiler(编码器)、languageparser(语言分析器)、languagelexer(语言词典)、memmanager(内存管理器)和tsrm(threadsaferesourcemanager,线程安全资源管理器)。其中,memmanager,用于实现整个php内核的内存管理;languagelexer,用于实现对php脚本的词法分析;languageparser,用于实现对php脚本的语法解析;compiler,用于实现对php的代码编译,生成opcode。garagecollector,用于释放php内核运行过程中未及时回收的内存。executor,用于执行编译器输出的opcode;且该executor可以为物理机,可以为vm(virtualmachine,虚拟机)。zendapi为php内核对外的接口,提供php扩展开发必要的api。tsrm是zts(zendthreadsafety,zend线程安全)机制的具体实现。tsrm实现php内核线程安全的机制为:在多线程环境下,tsrm为处理请求申请全局变量不再是简单的声明一个变量,而是整个进程在进程堆上分配一个内存空间,将该内存空间用作线程全局变量池。在进程启动时,tsrp初始化该线程全局变量池。当tsrp接收到线程申请全局变量时,tsrp调用获取该线程的参数,基于该参数在全局变量池中分配该参数对应的内存区块,并将该内存区块的标识返回给该线程。当该线程需要读写数据时,将该内存区块的标识传递给tsrm。tsrm根据该内存区块的标识,进行读写操作,从而实现线程安全的全局变量。参见图2,多线程环境中包括两个线程,分别为thread1和thread2;当thread1申请全局变量时,thread1向tsrm发送第一申请请求,该第一申请请求携带该thread1的线程标识。tsrm接收第一申请请求,为该thread1分配内存区块globalvar1,向thread1发送globalvar1的标识。thread1接收globalvar1的标识,存储该globalvar1的标识。当thread1进行读写操作时,thread1向tsrm发送第一读写请求,该第一读写请求携带待读出的数据标识或者待写入的数据,该第一读写请求还携带该globalvar1的标识。tsrm接收thread1发送的第一读写请求,基于该globalvar1的标识,在该globalvar1上进行读写操作。同样,当thread2申请全局变量时,thread2向tsrm发送第二申请请求,该第二申请请求携带该thread2的线程标识。tsrm接收第二申请请求,为该thread2分配内存区块globalvar2,向thread2发送globalvar2的标识。thread2接收globalvar2的标识,存储该globalvar2的标识。当thread2进行读写操作时,thread2向tsrm发送第二读写请求,该第二读写请求携带待读出的数据标识或者待写入的数据,该第二读写请求还携带该globalvar2的标识。tsrm接收thread2发送的第二读写请求,基于该globalvar2的标识,在该globalvar2上进行读写操作。在本发明实施例中,将php内核嵌入到协程架构中,要解决的核心问题就是使用协程替换线程,每支协程可以独立访问自己对应的全局变量池。由于tsrm对于线程间全局资源的隔离访问完全是被动式的,即在资源获取函数的实现中是通过获取执行线程私有变量的方式得到资源访问入口的。因此,在协程环境下,通过tsrm访问全局资源将总是获取到相同的资源入口。因为协程都是运行在同一支线程中的。因此,必须对tsrm进行改造,改造的目的是能够提供api对全局资源入口进行主动式切换,结合协程本身的调度切换,实现zend在协程环境下的可重入。本发明实施例提供了一种实现php内核可重入的方法,该方法的执行主体可以为服务器。参见图3,该方法包括:步骤201:服务器接收处理请求。当终端需要执行某个操作时,终端向服务器发送处理请求;服务器接收终端发送的该处理请求。该处理请求可以为任一用于指示服务器执行操作的处理请求;例如,该处理请求可以为用于指示服务器读数据的读请求、用于指示服务器写数据的写请求或者用于与服务器之间传输数据的数据传输请求等。在本发明实施例中,对处理请求的具体操作不作具体限定。并且,该处理请求的网络协议可以为现有的任一网络协议;例如,udp(userdatagramprotocol,用户数据报协议)或者tcp(transmissioncontrolprotocol,传输控制协议),在本发明实施例中,对该处理请求的网络协议不作具体限定。需要说明的是,该服务器中包括协程架构,在本步骤中是服务器中的协程架构接收该处理请求。该协程架构可以为spp(simplifiedparallelprocess,简并行过程),并且spp由c++编写,具有高效的协程能力。在本发明实施例中,实现php内核可重入时,需要将php内核嵌入到协程架构中,因此接收到处理请求后,通过步骤202为php内核分配协程。步骤202:服务器为待重入的php内核分配协程。在一个可能的实现方式中,服务器中包括多个协程,并且服务器中存储每个协程的状态信息,该状态信息可以为忙碌或者空闲。相应的,本步骤可以为:服务器根据每个协程的状态信息,从多个协程中选择一个状态信息为空闲的协程,将选择的协程分配给php内核。在另一个可能的实现方式中,服务器中包括多个协程,并且服务器事先从多个协程中指定一个专门用于运行php内核的协程。相应的,本步骤可以为:服务器从该多个协程中选择指定协程,该指定协程用于运行php内核;服务器将选择的协程分配给php内核。在另一个可能的实现方式中,服务器中包括多个协程,不同的协程的处理性能不同;服务器中存储每个协程的处理性能,服务器可以为该php分配一个处理性能较好的协程。相应的,本步骤可以为:服务器根据每个协程的性能,选择性能最好的协程,将选择的协程分配给php内核。在另一个可能的实现方式中,服务器中包括多个协程,不同类型的协程可以处理不同的请求;例如,某个类型的协程用于运行php内核,某个类型的协程用于处理读请求等。服务器基于协程的类型为php内核分配协程。相应的,本步骤可以为:服务器基于每个协程的类型,从多个协程中选择指定类型的协程,将指定类型的协程分配给php内核。其中,指定类型的协程能够运行php内核。步骤203:服务器通过该协程运行该php内核,得到该php内核的运行实例。服务器在该协程中运行该php内核,从而得到该php内核的运行实例。另外,为了使得php内核实现协程特性,服务器在协程架构中接收处理请求,并指示php内核处理该处理请求。而服务器指示php内核处理该处理请求之前,服务器通过以下步骤204对该php内核的运行实例进行切换。步骤204:服务器根据该php内核的全局实例表,从该全局实例表中选择一个空闲实例的实例标识。该全局实例表用于存储至少一个实例标识和状态信息的对应关系。该状态信息包括忙碌和空闲。服务器根据该全局实例表中的每个实例标识对应的状态信息,从该全局实例表中选择一个状态信息为空闲的实例标识。实例标识可以为运行实例的名称、编号等。步骤205:服务器根据该实例标识,将该php内核的运行实例切换到选择的空闲实例中。服务器根据该实例标识,确定该实例标识对应的空闲实例。服务器将该php内核的运行实例切换到该空闲实例中,从而实现在协程环境下运行该php内核。服务器将该php内核的运行实例切换到选择的空闲实例中,协程的切换对php内核完全透明,协程切换的代码实现如下所示:publicstaticfunctionsend($host,$port,$data,$timeout=0){client=zendco_udpsndrcv($host,$port,$data,$timeout*1000);reture$client;}在本发明实施例中,php内核对于协程的使用完全透明,对已有业务代码的移植也十分容易。在一个可能的实现方式中,服务器将该php内核的运行实例切换到选择的空闲实例中之后,服务器在该全局实例表中将该空闲实例的状态修改为忙碌,以便于后续接收到处理请求时,能够准确为该处理请求分配空闲的实例。步骤206:服务器根据该实例标识,将对该php内核中的结构体指针资源的访问,切换到该空闲实例对应的资源表。本步骤可以通过以下步骤(1)至(3)实现,包括:(1):服务器根据该实例标识,确定该实例标识对应的资源表。本步骤可以通过以下步骤(1-1)和(1-2)实现,包括:(1-1):服务器根据该实例标识,从实例标识和结构体指针资源的对应关系中获取该空闲实例对应的结构体指针资源。一个线程对应一个tsrm_tls_entry结构体指针资源,一个线程对应一个实例标识。因此,在本步骤之前,服务器根据线程与实例标识的对应关系,以及线程与结构体指针资源的对应关系,确定实例标识与结构体指针资源的对应关系。(1-2):服务器根据该结构体指针资源,从结构体指针资源和资源表的对应关系中获取该空闲实例对应的资源表。资源表中包括多个资源标识。在本步骤之前,服务器中存储结构体指针资源和资源表的对应关系。例如,参见图4,服务器中存储n个结构体指针资源,分别为tsrm_tls_entry_1*、tsrm_tls_entry_2*、tsrm_tls_entry_3*,……,tsrm_tls_entry_n*;n为大于或者等于1的整数。(2):服务器确定该php内核的结构体指针资源的资源标识。服务器确定运行该php内核的协程标识,根据该协程标识,从协程标识和结构体指针资源的对应关系中获取该php内核的结构体指针资源的资源标识。在本步骤之前,服务器建立协程标识映射表,关联每个协程标识和结构体指针资源的对应关系。例如,参见图5,服务器中存储n个协程,分别为协程1、协程2、协程3,……,协程n。协程1对应的结构体指针资源为tsrm_tls_entry_1*,协程2对应的结构体指针资源为tsrm_tls_entry_2*,协程3对应的结构体指针资源为tsrm_tls_entry_3*,……,协程n对应的结构体指针资源为为tsrm_tls_entry_n*。需要说明的是,协程标识和结构体指针资源的对应关系为全局资源变量。因此,在本步骤之前,服务器将该资源切换入口的存储地址由线程私有变量修改为全局资源变量。全局资源入口存储在线程私有变量,修改为存储在全局资源table数组,修改前为:/*threadlocalstorage*/staticpthreadkey_ttls_key#definetsrmtlsset(what)pthread_setspecific(tls_key,(void*)(what))#definetsrm_tls_get()pthread_getspecific(tls_key)修改后//romanvoid*g_aptls[100000]={0};#definetsrm_tls_set(what)g_aptls[g_curcoid]=(void*)(what)#definetsrmtls_get()g_aptls[g_curcoid](3):服务器根据该资源标识和该资源表,通过资源切换入口,获取该php内核访问的资源数据。资源表中包括资源标识和资源数据的对应关系;服务器根据该资源标识,通过该资源切换入口,从该资源表中获取该资源标识对应的资源数据。需要说明的一点是,在本步骤之前,服务器需要增加资源切换入口。服务器增加资源切换入口的实现代码如下://romantsrmls_cache_extern()tsrm_apivoidtsrm_switchco(thread_tcurcoid){g_curcoid=curcoidtsrmls_cache_update();}步骤207:服务器通过该php内核执行该处理请求。服务器对资源进行切换后,服务器将该处理请求发送至php内核,由php内核执行该处理请求。该php内核接收服务器发送的该处理请求,执行该处理请求。步骤208:当该php执行该处理请求的执行逻辑中存在网络io操作时,服务器调用扩展封装的io接口。在本步骤之前,服务器在扩展封装io接口,在本步骤中,服务器调用扩展封装的io接口。本发明实施例中,php扩展的开发也可以使用协程环境,对于后端io的处理十分便捷。并且,php内核具备了嵌入式c/c++网络框架的能力,丰富了服务器的选型,进一步提升了php的整体可靠性。步骤209:服务器在扩展封装的io接口中,通过该协程包裹的接口函数进行该io操作。在扩展封装的io接口中,服务器通过c++协程包裹的接口函数进行io操作,从而php内核具备了协程特性。需要说明的一点是,在调用io接口之前,服务器使用栈空间局部变量保存当前的空闲实例。当php内核执行完该处理请求,得到处理结果,将该处理请求返回给服务器。php内核在io返回处理结果后,由于已完成协程的切回,当前栈保存空闲实例的局部变量已可继续访问,将其值赋给全局资源变量,实现了协程切回后对应的全局资源表访问入口的切换。需要说明的另一点是,该php内核的版本可以为php5、php6、php7或者php7.1。优选地,该php内核的版本可以为php7.1。由于php7.1在php5的基础上进行了全面的升级,无论是性能还是新特性均有了大幅提升,同时php7.1较php7修复了大量的bug(漏洞),更加稳定成熟,是php官方重点推荐的版本。因此,将php7.1作为待重入的php内核版本。另外,由于因为本发明是针对php内核zendengine的,并不依赖于某个特定的框架或者场景,所以改造后的zendengine可以嵌入至任何具有协程特性的c++框架中,形成一个具有原生协程能力的高性能php服务器框架,适用于任何对php服务有高性能要求的业务。在本发明实施例中,当服务器接收到处理请求时,将该php内核的运行实例切换到协程中,将该php内核的结构体指针资源的访问切换到空闲实例上,从而实现了php内核的可重入,从而使得php内核具备了协程特性,提高了php内核的并发处理能力。本发明实施例提供了一种实现php内核可重入的装置,该装置应用在服务器中,用于执行实现php内核可重入的方法。参见图6,该装置包括:分配模块601,用于当服务器接收到处理请求时,为待重入的超文本预处理器php内核分配协程;运行模块602,用于通过该协程运行该php内核,得到该php内核的运行实例;选择模块603,用于根据该php内核的全局实例表,选择一个空闲实例的实例标识,该全局实例表中存储至少一个实例标识和实例状态的对应关系;切换模块604,用于根据该实例标识,将该php内核的运行实例切换到选择的空闲实例中,以及根据该实例标识,将对该php内核中的结构体指针资源的访问,切换到该空闲实例对应的资源上。在一个可能的实现方式中,该装置还包括:执行模块,用于通过该php内核执行该处理请求;调用模块,用于当该php内核执行该处理请求的执行逻辑中存在网络输入输出io操作时,调用扩展封装的io接口;操作模块,用于在该扩展封装的io接口中,通过该协程包裹的接口函数进行该io操作。在另一个可能的实现方式中,该装置还包括:保存模块,用于使用栈空间局部变量保存该实例标识;修改模块,用于当接收到该php内核返回的处理结果时,从该栈空间局部变量中获取该实例标识,将该处理请求的全局资源的资源标识修改为该实例标识。在另一个可能的实现方式中,该切换模块504,还用于根据该实例标识,确定该空闲实例对应的资源表,该资源表包括资源标识和资源数据;确定该php内核的结构体指针资源的资源标识;根据该资源标识和该资源表,通过资源切换入口,获取该php内核访问的资源数据。在另一个可能的实现方式中,该切换模块504,还用于根据该实例标识,从实例标识和结构体指针资源的对应关系中获取该空闲实例对应的结构体指针资源;根据该结构体指针资源,从结构体指针资源和资源表的对应关系中获取该空闲实例对应的资源表。在另一个可能的实现方式中,该切换模块504,还用于确定该协程的协程标识;根据该协程标识,从协程标识和结构体指针资源的对应关系中获取该php内核的结构体指针资源的资源标识。在本发明实施例中,当服务器接收到处理请求时,将该php内核的运行实例切换到协程中,将该php内核的结构体指针资源的访问切换到空闲实例上,从而实现了php内核的可重入,从而使得php内核具备了协程特性,提高了php内核的并发处理能力。需要说明的是:上述实施例提供的实现php内核可重入的装置在实现php内核可重入时,仅以上述各功能模块的划分进行举例说明,实际应用中,可以根据需要而将上述功能分配由不同的功能模块完成,即将装置的内部结构划分成不同的功能模块,以完成以上描述的全部或者部分功能。另外,上述实施例提供的实现php内核可重入的装置与实现php内核可重入的方法实施例属于同一构思,其具体实现过程详见方法实施例,这里不再赘述。图7是本发明实施例提供的一种服务器的结构示意图,该服务器700可因配置或性能不同而产生比较大的差异,可以包括一个或一个以上处理器(centralprocessingunits,cpu)701和一个或一个以上的存储器702,其中,该存储器702中存储有至少一条指令,该至少一条指令由该处理器701加载并执行以实现上述各个方法实施例提供的实现php内核可重入的方法。当然,该服务器还可以具有有线或无线网络接口、键盘以及输入输出接口等部件,以便进行输入输出,该服务器还可以包括其他用于实现设备功能的部件,在此不做赘述。本发明实施例还提供了一种计算机可读存储介质,该计算机可读存储介质应用于服务器,该计算机可读存储介质中存储有至少一条指令、至少一段程序、代码集或指令集,该指令、该程序、该代码集或该指令集由处理器加载并执行以实现上述实施例的实现php内核可重入的方法中服务器所执行的操作。本领域普通技术人员可以理解实现上述实施例的全部或部分步骤可以通过硬件来完成,也可以通过程序来指令相关的硬件完成,所述的程序可以存储于一种计算机可读存储介质中,上述提到的存储介质可以是只读存储器,磁盘或光盘等。以上所述仅为本发明的较佳实施例,并不用以限制本发明,凡在本发明的精神和原则之内,所作的任何修改、等同替换、改进等,均应包含在本发明的保护范围之内。当前第1页12当前第1页12
当前第1页1 2 
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1