百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程文章 > 正文

如何打造PHP的Restful API自动化监控系统?58安居客这样做

qiyuwang 2024-10-25 16:37 9 浏览 0 评论

背景

伴随租房业务的不断发展,租房各个子业务系统的集群数量也迎来了一波增长,提供的API接口数量和服务数量也有了井喷式增长,但在业务层自动化监控方面我们却缺失统一的工具平台,随之而来我们开发同学会经常碰到这些问题:

1. 有哪些的接口访问超时/特别慢,往往关注的时候就是服务出现瓶颈的时候。

2. 线上top uri每日的访问量是多少,没有可视化的工具,只能去单机通过awk命令统计。

3. 不知道接口的平均耗时是多少,也就没有优化服务的动力。

但当时我们面对类似问题通常采用下面的方法解决:

1. 采用公司的人工埋点系统Wmonitor手动在代码里埋点,优点是能实现部分可视化和预警,缺点是埋点流程复杂每个接口都需要申请埋点值并在接口中手动埋点,管理复杂效率低下,对开发同学的开发意识要求很高。

2. 通过nginx日志查询访问详细情况如 uri,访问状态,耗时等信息,优点是能得到访问量和访问时长等数据,缺点是每次都需要人工手动查询,缺乏无可视化平台和预警,如某一台机器故障/性能故障则完全无感知 。

由于公司内部已有基于Java Web框架的API监控系统,鉴于这套系统已成熟,PHP侧可以复用其数据存储、数据视图和报警部分,然后自己实现数据采集和上报即可实现PHP可用的API监控系统。那我们的核心重点就是解决在PHP-FPM多进程模型下,如何灵活、高效、稳定的实现数据的采集和上报。


设计理念

1. 灵活定制

面对不同的业务集群,作为服务方需要兼顾灵活和标准, 首先通过从众多的接口访问信息中抽出来标准化的数据信息集,如集群名称,接口uri,http Code,访问量,访问时长,超时量,失败量等具体的数据,标准化的数据保证了传输的顺畅,为后续的分析,统计,展示奠定基础。其次提供灵活的可配置方案,兼容不同集群,不同采集间隔和自动化uri采集模型,去实现业务的灵活变通。

wrm.enable=1
wrm.tick=60
wrm.timeout=2000
wrm.collector_register_url=https://****.**.com/****/****
wrm.collector_port=****
wrm.cluster=***_***_*** 
wrm.total_url_num=500
wrm.enable_sync_uri=1
wrm.sync_uri_url=****.**.com/****/****

2. 低成本接入

利用PHP的底层特性以扩展形式在PHP进程启动的时候加载,避免开发同学因接入监控服务而需要做出额外的开发,实现无感知的数据采集。


3. 资源利用率高

合理选型数据结构和接入方式,依托于PHP-FPM主进程的监控进程,避免对系统额外的cpu和内存资源占用,保证线程安全调用。


系统架构

1. 首先启动PHP Zend引擎后,在注册动态扩展的过程中通过调用MINIT钩子,fork出来监听进程,从而在每次request开始/结束时 执行业务逻辑。

2. 监听根据系统配置,初始化全局变量如上报时长,内存大小,上报地址等信息,以及通过mmap开辟共享内存空间和pthread去实现线程安全上报。

3. 每次request在请求时会初始化php_request_startup,并依次遍历调用扩展中调用Rinit,在这个过程中收集到uri,http code,访问时长等信息存储如对应的结构体。

4. 监听进程根据配置tick收集指定间隔时间的数据后,通过切换数据hash的内存块指针,平滑变更hashtable的角色属性,启动上报线程,开始压缩数据并异步上报至数据中心服务侧。


功能设计&实践

1. 进程启动

PHP引擎启动过程中通过php_module_startup遍历php_extension_list中在php.ini注册的动态扩展,并依次调用对应的Minit钩子函数,在这个过程中我们在Minit中fork出来上报进程,根据配置的url个数初始化共享内存,并依据bkrdhash算法实现uri的hash存储,同时一个hash做输出,一个hash做存储,并通过指针动态切换.该进程同时会监听主进程。


2. 日志收集

在Rinit的钩子中,依赖于sapi_getenv和SG去获取本次请求的参数,如header和Server信息,根据uri路由,收集后存储于trace实体中,在此钩子中不做其他操作,保证最小粒度干扰线上的资源开销,在Rshutdown钩子中,统计响应状态,耗时等日志信息,并存储到对应的hash中。

typedef struct wrm_trace_analyze {
    int mutex; // 互斥量
    struct timeval total_duration;
    int success_times;
    int failed_times;
    int timeout_times;
    int server_port;
    char server_addr[32];
    char uri[256];
} wrm_trace_analyze;


3. 数据上报

依托于配置中的上报周期,上报线程会将数据存储的hash指针做切换,从这一刻起,另外一个空hash结构体开始接受新数据做存储,同时原输出hash开始压缩并上报数据中心服务侧,上报完成后等待下个周期的切换,如此循环往复。


关键问题

1. 如何避免对上报服务端的流量冲击,合理利用资源

鉴于每次的http请求都会产生一条日志数据,如果每次都进行上报则对服务端是个很大的流量冲击,针对这种情况我们通过合理设计本地存储结构,实现时间周期内的日志数据汇总存储,压缩&定期上报汇总数据。

2. 如何设计一个有效的数据采集数据结构

数据实现hash存储,key值采用bkrdhash算法,以质数作为种子,每个字符串的ascii加和,保证每个字符串都参与到运算中,同时hash中只存储有效的日志数据,如http code 200/500次数,时间等信息,以10000个uri举例,只额外占用不到10M内存,并在数据udp上报到服务侧之前通过gz压缩,保证资源的合理优化。


3. 如何去解决hash数据集的并发性写入

我们采用的futex内核级同步锁.在众多php-fpm在同一时间点写入同一个hash的,如果采用自旋锁+等待,在线程较多的时候其他上下文的切换的资源开销不低,但是通过futex内核级锁,在通过双向链表的队列维护竞争的线程,在占用锁资源的线程释放资源后,会按顺序从队列中唤起等待的线程写入。


4. 如何在保证对数据采集和上报流程隔离,实现线程安全的全流程监控

我们采用的方案是通过监听进程的存储层开辟一个共享内存区域,分别为分为存储区A和上报区B,在监控服务收集的过程中所有数据沉淀在A上,等待上报周期时间点一到则会将数据写入的指针指向B,此时B角色切换为存储区,A角色变更为上报区,线程将A上的数据进行上报,上报成功后clean掉数据,等待下一次的角色变更,如此循环往复,实现线程安全的异步上报流程。


5. 如何低成本部署和兼容

我们以php扩展为独立载体,不依赖任何框架,支持公司内部物理机和私有云等集群环境。业务集群需要监控服务则可将此.so文件加载到项目extension/下目录或者 php配置级的extension下,同时在项目中的extension.conf配置采集参数即可方便使用,也因此实现项目级的日志采集能力。

此扩展语法同时支持PHP7.0.0以上的版本集群环境。


总结成果

Restful的自动化日志监控服务,在租房业务线集群以扩展的形式已成功部署至生产环境,各业务线负责人可以方便的通过公司的提供的可视化工具平台(WF manager)直观看到所属的接口访问详情,从而节省各个业务线手动开发,标准不一的开发代价和维护成本。

目前租房业务线累计已有几十个集群先后通过此扩展接入wfmanager系统,覆盖百余台PHP服务器,每分钟采集日志超上百万次,覆盖90%的租房业务线上流量,为服务的平稳运行提供有力保障。

通过可视化的线上接口实时访问数据,对应服务的负责人实现了对所属服务的主动关注/被动报警能力,为服务质量和稳定性提供了有力的支持,具体体现在以下两个方面:

1. 在工程效率方面,过往线上出现接口访问超时现象到问题解决的时间跨度周期往往超过1天,通过此扩展接入日志采集能力后,实现了线上的访问实时监控预警,从问题出现到解决的时间跨度也降低为分钟级别,如 一些APP端的详情页在优化之前接口加载时长达到300ms以上,接入日志监控扩展后清晰看到线上的真实耗时,对应同学收到预警后,经过几轮实时技术优化对比,已成功将耗时降低为100ms以下。

2. 在数据分析维度,过往分析日志从单机awk统计到现在集群整体视角,粒度甚至细分至单机uri的级别,直观监测到实时访问数据,实现了同比,环比的流量波动分析,精准掌握产品的线上的访问流量,为保证服务可用性的增扩容以及优化提供有力决策支持。


作者介绍

陈艺天 / 58房产租房技术部 / 先后负责PHP技术栈的wscf重构,wfmanager扩展,php微服务孵化等;

胡坤 / 58房产租房技术部 / 先后负责租房业务wfmanager扩展项目,房源直播及保障服务在线化能力等;


相关推荐

基于Docker方式安装与部署Camunda流程引擎

1Camunda简介官网:https://docs.camunda.org/manual/7.19/installation/docker/Camunda是一个轻量级、开源且高度灵活的工作流和决策自...

宝塔Linux面板如何部署Java项目?(宝塔面板 linux)

通过宝塔面板部署Java还是很方便的,至少不需要自己输入tomcat之类的安装命令了。在部署java项目前,我还是先说下目前的系统环境,如果和我的系统环境不一样,导致部署不成功,那你可能需要去找其他资...

浪潮服务器如何用IPMI安装Linux系统

【注意事项】此处以浪潮服务器为例进行演示所需使用的软件:Chrome浏览器个人PC中需要预先安装java,推荐使用jdk-8u181-windows-x64.exe【操作步骤】1、在服务器的BIOS中...

Centos7环境Hadoop3集群搭建(hadoop集群环境搭建实验报告)

由于项目需要存储历史业务数据,经过评估数据量会达到100亿以上,在原有mongodb集群和ES集群基础上,需要搭建Hbase集群进行调研,所以首先总结一下Hadoop集群的搭建过程。一、三个节点的集群...

Hadoop高可用集群搭建及API调用(hadoop高可用原理)

NameNodeHA背景在Hadoop1中NameNode存在一个单点故障问题,如果NameNode所在的机器发生故障,整个集群就将不可用(Hadoop1中虽然有个SecorndaryNameNo...

使用Wordpress搭建一个属于自己的网站

现在开源的博客很多,但是考虑到wordpress对网站的seo做的很好,插件也多。并且全世界流量排名前1000万的网站有33.4%是用Wordpress搭建的!所以尝试用Wordpress搭建一个网站...

Centos 安装 Jenkins(centos 安装ssh)

1、Java安装查看系统是否已安装Javayumlistinstalled|grepjava...

Java教程:gitlab-使用入门(java中的git)

1导读本教程主要讲解了GitLab在项目的环境搭建和基本的使用,可以帮助大家在企业中能够自主搭建GitLab服务,并且可以GitLab中的组、权限、项目自主操作...

Dockerfile部署Java项目(docker部署java应用)

1、概述本文主要会简单介绍什么是Docker,什么是Dockerfile,如何安装Docker,Dockerfile如何编写,如何通过Dockerfile安装jar包并外置yaml文件以及如何通过do...

如何在Eclipse中搭建Zabbix源码的调试和开发环境

Zabbix是一款非常优秀的企业级软件,被设计用于对数万台服务器、虚拟机和网络设备的数百万个监控项进行实时监控。Zabbix是开放源码和免费的,这就意味着当出现bug时,我们可以很方便地通过调试源码来...

Java路径-02-Java环境配置(java环境搭建及配置教程)

1Window环境配置1.1下载...

35.Centos中安装python和web.py框架

文章目录前言1.Centos7python:2.Centos8python:3.进行下载web.py框架然后应用:4.安装好之后进行验证:5.总结:前言...

《我的世界》服务器搭建(我的世界服务器如何搭建)

1.CentOS7环境1.1更改YUM源#下载YUM源文件curl-o/etc/yum.repos.d/CentOS-Base.repohttps://mirrors.aliyun.com...

CentOS 7 升级 GCC 版本(centos7.4升级7.5)

1.GCC工具介绍GCC编译器:...

Linux安装Nginx详细教程(linux安装配置nginx)

环境准备1.因为Nginx依赖于gcc的编译环境,所以,需要安装编译环境来使Nginx能够编译起来。命令:yuminstallgcc-c++显示完毕,表示安装完成:2.Nginx的http模块需要...

取消回复欢迎 发表评论: