房产基于Swoole的PHP RPC框架设计

2020年5月20日 367点热度 0人点赞 0条评论

图片


导语

本文基于业务的实际场景出发,重构异步驱动的PHP微服务框架,实现了对接跨平台跨语言的微服务管理能力,保证了PHP在开发效率和运行效率的兼容,希望能够对PHP开发同学实现高并发的服务有所帮助。


背景

58内部常用的微服务框架(SCF)是基于Java技术栈的,而房产租房业务开发通常采用的是PHP技术栈,在运行机制和模式与Java有着诸多的差异。在接口不多,系统与系统交互较少的情况下,用Http接口能够快速实现跨系统/服务的调用,但是随着租房业务的蓬勃发展,内部的子系统/项目越来越多,系统架构也由集中式架构向分布式架构转变,Http的接口调用无论是代码层面,还是在性能层面已经不能满足日渐复杂的应用系统发展能力,开发的同学会经常面临如下的情况:

  • Http接口需要配置Nginx负载均衡,一旦故障/重启则会影响下游的调用方,直接影响服务的可用性。

  • 大部分是基于Json的格式传输,字节大小和序列化相比二进制传输更消耗性能。

  • 调用纷繁复杂的上游域名,路由眼花缭乱,令后续的维护成本骤升。

  • 服务的耗时,响应,扩容以及安全性都有待弥补。

由于PHP作为解释型语言,在请求结束即释放所有资源的特性,在持久化服务注册发现和心跳检测的实现上有一定的难度,针对PHP此特性业内通用有两种做法:服务代理扩展和长驻内存能力实现,代表分别为微博的Agent和腾讯的Tars-php。
鉴于公司内部已有成熟的微服务管理平台(SCF)可供对接,PHP的技术栈只需要实现服务层处理能力&&接入服务管理平台即可快速提供服务,也因此,为了提升服务的可用性和调用效率,提升应用系统的稳定性,房产租房业务部门内部孵化了基于Swoole的常驻内存RPC框架。

图片

SCF RPC架构图

技术目标

1、高发并支持

PHP作为解析型语言的代表,每次执行都需要将PHP代码转为Opcode数组(PHP7增加了抽象语法树,分析阶段生成AST),然后由Zend引擎来执行,并释放响应资源,鉴于Fpm的传统同步模式都需要开启大量进程保证并发,造成CPU上下文切换频繁和资源的相对浪费。因此新的服务框架需要具备以下特点:
  • 支持事件驱动的异步编程模式,支持多线程Reactor模式处理网络请求,能够应对大量链接的情况。

  • 具备同步/异步/协程实现能力。

  • 避免每次请求都重新解析,创建,销毁的空转流程。

  • 支持IPC通信。

图片
图片
Swoole Reactor说明图

2、快速部署
  • 能够兼容房产现有框架的开发测试监控流程。

  • 支持集团云服务管理平台&&代码发布平台。


3、监控&统计上报能力
  • 支持函数的自动化注册能力,鉴于PHP并无Maven pom配置文件,也无注解(Annotation),为保证系统开发的便捷性需要能够实现函数的映射&注册能力。
  • 服务调用异步统计&上报,支持识别服务的访问,访问耗时,执行耗时,异常,抛弃等状态的捕捉和上报。
  • 支持对服务管理平台的长连接心跳检测,保证服务侧可用状态维护及对应熔断能力。


4、序列化&反序列化服务

  • 通用性,能够支持丰富的数据结构类型并实现跨语言跨平台的序列化和反序列化能力,保证序列化性能的同时也要保证服务的可用性。
  • 鲁棒性,一旦出现内部结构扰动,可以有效避免序列化/反序列化的带来的不确定性。
  • 可扩展性&可读性。

由于系统升级的不可避免性,序列化协议应该具备良好的可扩展性,支持自动增加新的能力而不影响老服务。简化序列化流程,保证开发同学能够通过较低的学习和接入成本来共同接入。

5、通用组件支持

对开发同学常用的组件如redis服务(Wredis),个性化监控打点服务(Wmonitor),分布式KV,KList系统(Wtable)等工具和服务有着友好的接入能力,能够由同步编程驱动快速切成换异步编程驱动处理业务逻辑。

图片

Swoole RPC 进程解析图


6、服务治理

为了系统能够在并发量峰值场景下提供稳定可靠的服务,服务需要有效实现如下内容:

  • 服务的注册和发现:服务启动时通过独立进程,上报ip,端口,服务详情等信息至服务管理中心,由服务管理中心实时更新。

  • 服务的限流,熔断,降级:避免对挂起服务的请求造成服务的不可用蔓延至整个集群,熔断器和限流器的令牌算法保障服务的可用性。

  • 服务的配置中心能力。


技术难点

1、如何实现服务层的序列化/反序列化

架构平台部提供的RPC客户端(SCF-client)是基于Fpm同步进程的架构体系的,为了提升序列化的性能会将实体序列化至Apcu中,但是锁的粒度较粗,高并发的情况下会存在锁的竞争,一方面性能较差,另一方面会造成异步处理进程阻塞乃至异常退出。针对这种情况我们重构了服务层的序列化框架,舍弃对Apcu的依赖,降低资源的线程式读取,避免无效类的抽象,精简反序列化和序列化流程,精简80%代码,聚焦核心流程。
图片
SCF Client重构流程图


2、服务层如何实现高效的心跳检测&统计&上报

持久化服务层需要保持长连接和服务管理平台实现心跳检测和调用上报,在这方面架构平台提供了相应的扩展初始化了独立的进程支持来实现心跳检测和服务调用上报协议,服务层实现函数的调用即可统计。但是由于服务层的运行机制,众多Worker之间是内存隔离的,如果将心跳检测进程依赖于任何一个worker进程,那么在处理一定的Tcp请求后Worker会自动关闭,造成上报进程也会随之关闭,因此我们将心跳上报进程在Manager进程启动时Fork出来,然后通过持久化的task进程来实现上报,worker处理完Tcp请求后,将任务投递到task中实现异步收集和上报。

3、 怎么从同步编程切换为异步非阻塞的模式

众所周知,PHP常用Fpm运行模式是同步处理请求的,如果我们调用4-5个微服务应用(SCF)服务时,耗时是串行累加的,而在服务层通过协程(用户态的线程)在网络IO处理的时候是可以跳过去执行其他的业务逻辑,也就是可以并行的发起后端的请求,一旦请求完毕则会将结果放在一个Channel中去供下游逻辑使用。假设一个服务中调用其所依赖的其他服务共N个请求&每个请求耗时相等,那么总耗时仅为同步的1/N(如果N个服务耗时不等,总耗时=max(子请求耗时)),极大提升了服务吞吐能力。

系统架构

图片
PHP 微服务架构图
  • 务侧动态化配置能力,在启动时依据服务层配置文件和业务层配置文件分别启动不同的能力,灵活定制服务侧能力,同时通用框架文件,配置信息常驻内存,避免每次请求处理都需要编译执行通用信息。
  • 启动过程中基于业务类的反射配置,获取业务模块的函数信息,参数等,自动注册至服务管理平台,并监听指定的Tcp端口。
  • Tcp请求通过框架级的序列化/反序列化通用能力(WSCF)将二进制流转化成可供PHP识别的变量和参数,调用路由映射类将请求分发至指定的类实现业务逻辑需求。
  • 通过协程并行请求后端的资源能力,通过池化设计能力,降低链接资源的重复开销,有效复用链接资源。
  • 函数的访问,耗时,执行等统计类信息,基于IPC交付至异步的task进程,避免同步阻塞任务,由异步任务统计至上报扩展,再由上报扩展通信至服务管理平台。

功能设计&实践

1、服务进程启动

服务启动时监听配置文件指定端口,在启动Manager进程时开启上报进程,并将通过反射Map获取的服务名称,函数名称等信息注册至服务管理平台,通过长连接保持心跳检测服务的可用性。

2、序列化&路由映射

Tcp EOF收到完整的二进制字节流后,根据PHP的数据序列化/反序列组件(WSCF)对字节流定义的字段类型开始序列化/反序列化,获取路由信息以及对应参数信息,转换至PHP可识别的类和函数,然后使用钩子调用对应的路由能力,由对应的业务逻辑处理。

3、协程异步处理
在业务处理阶段,对于依赖的后端服务能力,如微服务框架(SCF),Mysql,Redis服务(Wredis),分布式KV,Klist系统(Wtable)等能力,通过协程实现并行能力请求,如遇到接口请求自动挂起协程,将CPU让给其他协程执行,提升单线程的CPU资源利用率,提高性能。同时持久化后端资源池,降低Tcp资源连接开销,减少本地端口调用并提升系统吞吐能力。

图片

协程流程图

展望&总结

目前已和云平台共同定制了服务侧的开发标准,并推广至公司级平台,面向广大的开发同学,在租房业务线已有连接组和租房组等业务线平稳接入使用,安居客业务线在调研接入阶段,同步的连接模式变更至异步的驱动模式,有效降低对后端资源的开销,充分挖掘了系统的潜力。
图片
图片

作者简介

陈艺天,房产租房技术部。专注于PHP的生态建设和性能提升。先后负责PHP技术栈的WSCF重构,Wfmanager扩展,PHP微服务能力孵化等工作。

END

阅读推荐

应用AST技术实现自动化升级React 15至React 16的解决方案
深度文本表征与深度文本聚类在小样本场景中的探索与实践
前端爬虫攻防之接口签名方案
58商家通Android端WebView加载优化方案
并发在58二手车列表的应用
58App-Android端的动态化框架实践与思考

图片

35630房产基于Swoole的PHP RPC框架设计

这个人很懒,什么都没留下

文章评论