大家好,今天来为大家分享php外卖网站源码分享下载的一些知识点,和php外卖平台源码的问题解析,大家要是都明白,那么可以忽略,如果不太清楚的话可以看看本篇文章,相信很大概率可以解决您的问题,接下来我们就一起来看看吧!
序言
时间回到2008年,还在上海交通大学上学的张旭豪、康嘉等人在上海创办了饿了么,从校园外卖场景出发,饿了么一步一步发展壮大,成为外卖行业的领头羊。2017年8月饿了么并购百度外卖,强强合并,继续开疆扩土。2018年饿了么加入阿里巴巴大家庭,与口碑融合成立阿里巴巴本地生活公司。“爱什么,来什么”,是饿了么对用户不变的承诺。
饿了么的技术也伴随着业务的飞速增长也不断突飞猛进。据公开报道,2014年5月的日订单量只有10万,但短短几个月之后就冲到了日订单百万,到当今日订单上千万单。在短短几年的技术发展历程上,饿了么的技术体系、稳定性建设、技术文化建设等都有长足的发展。各位可查看往期文章一探其中发展历程,在此不再赘述:
《饿了么技术往事(上)》《饿了么技术往事(中)》《饿了么技术往事(下)》
而可观测性作为技术体系的核心环节之一,也跟随饿了么技术的飞速发展,不断自我革新,从“全链路可观测性ETrace”扩展到“多活下的可观测性体系ETrace”,发展成目前“一站式可观测性平台EMonitor”。
EMonitor经过5年的多次迭代,现在已经建成了集指标数据、链路追踪、可视化面板、报警与分析等多个可观测性领域的平台化产品。EMonitor每日处理约1200T的原始可观测性数据,覆盖饿了么绝大多数中间件,可观测超5万台机器实例,可观测性数据时延在10秒左右。面向饿了么上千研发人员,EMonitor提供精准的报警服务和多样化的触达手段,同时运行约2万的报警规则。本文就细数饿了么可观测性的建设历程,回顾下“饿了么可观测性建设的那些年”。
1.0:混沌初开,万物兴起
翻看代码提交记录,ETrace项目的第一次提交在2015年10月24日。而2015年,正是饿了么发展的第七个年头,也是饿了么业务、技术、人员开始蓬勃发展的年头。彼时,饿了么的可观测性系统依赖Zabbix、Statsd、Grafana等传统的“轻量级”系统。而“全链路可观测性”正是当时的微服务化技术改造、后端服务Java化等技术发展趋势下的必行之势。
我们可观测性团队,在调研业界主流的全链路可观测性产品–包括著名的开源全链路可观测性产品“CAT”后,吸取众家之所长,在两个多月的爆肝开发后,推出了初代ETrace。我们提供的Java版本ETrace-Agent随着新版的饿了么SOA框架“Pylon”在饿了么研发团队中的推广和普及开来。ETrace-Agent能自动收集应用的SOA调用信息、API调用信息、慢请求、慢SQL、异常信息、机器信息、依赖信息等。下图为1.0版本的ETrace页面截图。
在经历了半年的爆肝开发和各中间件兄弟团队的鼎力支持,我们又开发了Python版本的Agent,更能适应饿了么当时各语言百花齐放的技术体系。并且,通过和饿了么DAL组件、缓存组件、消息组件的密切配合与埋点,用户的应用增加了多层次的访问信息,链路更加完整,故障排查过程更加清晰。
整体架构体系
ETrace整体架构如下图。通过SDK集成在用户应用中的Agent定期将Trace数据经Thrift协议发送到Collector(Agent本地不落日志),Collector经初步过滤后将数据打包压缩发往Kafka。Kafka下游的Consumer消费这些Trace数据,一方面将数据写入HBase+HDFS,一方面根据与各中间件约定好的埋点规则,将链路数据计算成指标存储到时间序列数据库–LinDB中。在用户端,Console服务提供UI及查询指标与链路数据的API,供用户使用。
全链路可观测性的实现
所谓全链路可观测性,即每次业务请求中都有唯一的能够标记这次业务完整的调用链路,我们称这个ID为RequestId。而每次链路上的调用关系,类似于树形结构,我们将每个树节点上用唯一的RpcId标记。
如图,在入口应用App1上会新建一个随机RequestId(一个类似UUID的32位字符串,再加上生成时的时间戳)。因它为根节点,故RpcId为“1”。在后续的RPC调用中,RequestId通过SOA框架的Context传递到下一节点中,且下一节点的层级加1,变为形如“1.1”、“1.2”。如此反复,同一个RequestId的调用链就通过RpcId还原成一个调用树。
也可以看到,“全链路可观测性的实现”不仅依赖与ETrace系统自身的实现,更依托与公司整体中间件层面的支持。如在请求入口的Gateway层,能对每个请求生成“自动”新的RequestId(或根据请求中特定的Header信息,复用RequestId与RpcId);RPC框架、Http框架、Dal层、Queue层等都要支持在Context中传递RequestId与RpcId。
ETraceApi示例
在Java或Python中提供链路埋点的API:
/*\n记录一个调用链路\n/\nTransactiontrasaction=Trace.newTransaction(Stringtype,Stringname);\n//businesscodes\ntransaction.complete();\n\n/*\n记录调用中的一个事件\n/\nTrace.logEvent(Stringtype,Stringname,Map<String,String>tags,Stringstatus,Stringdata)\n\n/*\n记录调用中的一个异常\n/\nTrace.logError(Stringmsg,Exceptione)
Consumer的设计细节
Consumer组件的核心任务就是将链路数据写入存储。主要思路是以RequestId+RpcId作为主键,对应的Data数据写入存储的Payload。再考虑到可观测性场景是写多读少,并且多为文本类型的Data数据可批量压缩打包存储,因此我们设计了基于HDFS+HBase的两层索引机制。
如图,Consumer将Collector已压缩好的Trace数据先写入HDFS,并记录写入的文件Path与写入的Offset,第二步将这些“索引信息”再写入HBase。特别的,构建HBase的Rowkey时,基于ReqeustId的Hashcode和HBaseTable的Region数量配置,来生成两个Byte长度的ShardId字段作为Rowkey前缀,避免了某些固定RequestId格式可能造成的写入热点问题。(因RequestId在各调用源头生成,如应用自身、Nginx、饿了么网关层等。可能某应用错误设置成以其AppId为前缀RequestId,若没有ShardId来打散,则它所有RequestId都将落到同一个HBaseRegionServer上。)
在查询时,根据RequestId+RpcId作为查询条件,依次去HBase、HDFS查询原始数据,便能找到某次具体的调用链路数据。但有的需求场景是,只知道源头的RequestId需要查看整条链路的信息,希望只排查链路中状态异常的或某些指定RPC调用的数据。因此,我们在HBbase的ColumnValue上还额外写了RPCInfo的信息,来记录单次调用的简要信息。如:调用状态、耗时、上下游应用名等。
此外,饿了么的场景下,研发团队多以订单号、运单号作为排障的输入,因此我们和业务相关团队约定特殊的埋点规则–在Transaction上记录一个特殊的&34;的Tag–便会在HBase中新写一条“订单表”的记录。该表的设计也不复杂,Rowkey由ShardId与订单号组成,ColumneValue部分由对应的RequestId+RpcId及订单基本信息(类似上文的RPCInfo)三部分组成。
如此,从业务链路到全链路信息到详细单个链路,形成了一个完整的全链路排查体系。
Consumer组件的另一个任务则是将链路数据计算成指标。实现方式是在写入链路数据的同时,在内存中将Transaction、Event等数据按照既定的计算逻辑,计算成SOA、DAL、Queue等中间件的指标,内存稍加聚合后再写入时序数据库LinDB。
指标存储:LinDB1.0
应用指标的存储是一个典型的时间序列数据库的使用场景。根据我们以前的经验,市面上主流的时间序列数据库–OpenTSDB、InfluxDB、Graphite–在扩展能力、集群化、读写效率等方面各有缺憾,所以我们选型使用RocksDB作为底层存储引擎,借鉴Kafka的集群模式,开发了饿了么的时间序列数据库–LinDB。
指标采用类似Prometheus的“指标名+键值对的Tags”的数据模型,每个指标只有一个支持Long或Double的Field。某个典型的指标如:
COUNTER:eleme_makeorder{city=&34;,channel=&34;,status=&34;}45
我们主要做了一些设计实现:
指标写入时根据“指标名+Tags”进行Hash写入到LinDB的Leader上,由Leader负责同步给他的Follower。借鉴OpenTSDB的存储设计,将“指标名”、TagKey、TagValue都转化为Integer,放入映射表中以节省存储资源。RocksDB的存储设计为:以&39;transaction&39;{appId}.transaction&39;type&39;name&39;status&39;ezone&39;hostName&39;timerCount&39;timerSum&39;timerMin&39;timerMax&39;sampling&39;Timer&34;tag1&34;tag2&34;报警规则+一个规则多个订阅标签+一个用户订阅多个标签”的方式,完美迁移了几乎其他系统所有的报警规则与订阅关系。其他各系统在报警触达与触达内容上也略有不同。我们统一整合成“邮件+短信+钉钉+语音外呼”四种通知方式,并且提供可参数化的自定义Markdown模板,让用户可自己定时报警信息。
经过一番艰苦的报警配置与逻辑整合后,我们为用户“自动”迁移了上千个报警规则,并最终为他们提供了一个统一的报警平台。
报警,更精准的报警
外卖行业的业务特性是业务的午高峰与晚高峰,在业务曲线上便是两个波峰的形状。这样的可观测数据,自然难以简单使用阈值或比率来做判断。即使是根据历史同环比、3-Sigma、移动平均等规则,也难以适应饿了么的可观测性场景。因为,饿了么的业务曲线并非一成不变,它受促销、天气因素、区域、压测等因素影响。开发出一个自适应业务曲线变化的报警算法,势在必行。
我们经过调研既有规则,与饿了么的业务场景,推出了全新的“趋势”报警。简要算法如下:
计算历史10天的指标数据中值作为基线。其中这10天都取工作日或非工作日。不取10天的均值而取中值是为了减少压测或机房流量切换造成的影响。根据二阶滑动平均算法,得到滑动平均值与当前实际值的差值。将基线与差值相加作为预测值。根据预测值的数量级,计算出波动的幅度(如上界与下界的数值)。若当前值不在预测值与波动幅度确定的上下界之中,则触发报警。
如上图所示,22点01分的实际值因不在上下界所限定的区域之中,会触发报警。但从后续趋势来看,该下降趋势符合预期,因此实际中还会辅以“偏离持续X分钟”来修正误报。(如该例中,可增加“持续3分钟才报警”的规则,该点的数据便不会报警)算法中部分参数为经验值,而其中波动的阈值参数用户可按照自己业务调整。用户针对具备业务特征的曲线,再也不用费心的去调整参数,配置上默认的“趋势”规则就可以覆盖大多数的可观测性场景,目前“趋势”报警在饿了么广泛运用。
智能可观测性:根因分析,大显神威
作为AIOPS中重要的一环,根因分析能帮助用户快速定位故障,缩短故障响应时间,减少故障造成的损失。2020年初,我们结合饿了么场景,攻坚克难,攻破“指标下钻”、“根因分析”两大难关,在EMonitor上成功落地。
根因分析最大的难点在于:包含复杂维度的指标数据难以找到真正影响数据波动的具体维度;孤立的指标数据也难以分析出应用上下游依赖引起的故障根因。例如,某个应用的异常指标突增,当前我们只能知道突增的异常名、机房维度的异常分布、机器维度的异常分布等,只有用户手工去点击异常指标看来链路之后,才能大致判断是哪个SOA方法/DB请求中的异常。继而用户根据异常链路的环节,去追溯上游或下游的应用,重复类似的排查过程,最后以人工经验判断出故障点。
因此,在“指标下钻”上,我们针对目标指标的曲线,细分成最精细的每个维度数据(指标groupby待分析的tag维度),使用KMeans聚类找出故障数据的各维度的最大公共特征,依次计算找到最优的公共特征,如此便能找到曲线波动对应的维度信息。
其次,在链路数据计算时,我们就能将额外的上下游附加信息附加到对应的指标之中。如,可在异常指标中追加一个维度来记录产生异常的SOA方法名。这样在根据异常指标分析时,能直接定位到是这个应用的那个SOA方法抛出的异常,接下来“自动”分析是SOA下游故障还是自身故障(DB、Cache、GC等)。
在2020.3月在饿了么落地以来,在分析的上百例故障中,根因分析的准确率达到90%以上,显著缩短的故障排查的时间,帮助各业务向稳定性建设目标向前跨进了一大步。
4.0:继往开来,乘势而上
经过4、5年的发展,风云变幻但团队初心不改,为了让用户用好可观测性系统,EMonitor没有停下脚步,自我革新,希望让“天下没有难用的可观测性系统”。我们向集团的可观测性团队请教学习,结合本地生活自己的技术体系建设,力争百尺竿头更进一步,规划了以下的EMonitor4.0的设计目标。
一、进行多租户化改造,保障核心数据的时延和可靠性
在本地生活的技术体系与阿里巴巴集团技术体系的不断深入的融合之中,单元化的部署环境以及对可观测性数据不同程度的可靠性要求,催生了“多租户化”的设计理念。我们可以根据应用类型、数据类型、来源等,将可观测性数据分流到不同的租户中,再针对性配置数据处理流程及分配处理能力,实现差异化的可靠性保障能力。
初步我们可以划分为两个集群–核心应用集群与非核心应用集合,根据在应用上标记的“应用等级”将其数据自动发送到对应集群中。两套集群在资源配置上优先侧重核心集群,并且完全物理隔离。此外通过配置开关可动态控制某个应用归属的租户,实现业务的柔性降级,避免当下偶尔因个别应用的不正确埋点方式会影响整体可观测可用性的问题。
未来可根据业务发展进一步发展出业务相关的租户,如到家业务集群、到店业务集群等。或者按照区域的划分,如弹内集群、弹外集群等。
二、打通集团弹内、弹外的可观测性数据,成为本地生活的一站式可观测性平台
目前本地生活很多业务领域已经迁入集团,在Trace链路可观测方面,虽然在本地生活上云的项目中,EMonitor已经通过中间件改造实现鹰眼TraceId在链路上的传递,并记录了EMonitorRequestId与鹰眼TraceId的映射关系。但EMonitor与鹰眼在协议上的天然隔阂仍使得用户需要在两个平台间跳转查看同一条Trace链路。因此,我们接下来的目标是与鹰眼团队合作,将鹰眼的Trace数据集成到EMonitor上,让用户能一站式的排查问题。
其次,本地生活上云后,众多中间件已迁移到云上中间件,如云Redis、云Kafka、云Zookeeper等。对应的可观测性数据也需要额外登陆到阿里云控制台去查看。云上中间的可观测性数据大多已存储到Prometheus之中,因此我们计划在完成Prometheus协议兼容后,就与云上中间件团队合作,将本地生活的云上可观测性数据集成到EMonitor上。
三、拥抱云原生,兼容Prometheus、OpenTelemetry等开源协议。
云原生带来的技术革新势不可挡,本地生活的绝大多数应用已迁移到集团的容器化平台–ASI上,对应带来的新的可观测环节也亟需补全。如,ASI上Prometheus协议的容器可观测性数据、Envoy等本地生活PaaS平台透出的可观测性数据与Trace数据等。
因此,我们计划在原先仅支持LinDB数据源的基础上,增加对Prometheus数据源的支持;扩展OpenTelemetry的otel-collectorexporter实现,将OpenTelemetry协议的Trace数据转换成EMonitor的Trace格式。如此便可补全云原生技术升级引起的可观测性数据缺失,并提供高度的适配性,满足本地生活的可观测性建设。
结语
纵观各大互联网公司的产品演进,技术产品的走向与命运都离不开公司业务的发展轨迹。我们饿了么的技术人是幸运的,能赶上这一波技术变革的大潮,能够发挥聪明才智,打磨出一些为用户津津乐道的技术产品。我们EMonitor可观测性团队也为能参与到这次技术变更中深感自豪,EMonitor能被大家认可,离不开每位参与到饿了么可观测性体系建设的同伴,也感谢各位对可观测性系统提供帮助、支持、建议的伙伴!
作者简介:柯圣,花名“炸天”,饿了么监控技术组负责人。自2016年加入饿了么,长期深耕于可观测性领域,全程参与了ETrace到EMonitor的饿了么可观测性系统的发展历程。
本文为阿里云原创内容,未经允许不得转载。
好了,本文到此结束,如果可以帮助到大家,还望关注本站哦!