之前在分享微智能的话题中提到了应用服务监控,本文将会着重介绍Java环境下如何实现无侵入的监控,以及无侵入模式对实现各种技术架构统一服务治理的意义,还会破解“监控系统如何监控自己”的悖论。此次分享包含宜信众多关键技术实践和落地办法,内容提纲如下:
1. 服务治理监控,机房监控,APM的区别与联系
2. “无侵入”的应用服务监控
3. 无侵入引领统一服务治理
4. 打破悖论:监控系统如何监控自己
在开始之前,先解释一下几个概念。首先,APM(Application Performance Management)即应用性能管理,按照Gartner提出的抽象模式,它应该涵盖以下内容:
-
End User Experience:关注终端用户对性能的真实体验
-
Runtime Application Architecture:应该反映应用的架构
-
Business Transactions:能够支持分析应用与用户交互的操作事务
-
Deep Dive Component Monitoring:深度应用诊断,特别是代码级的性能追踪
-
Analytics / Reporting:按照业务模型对大量性能数据进行(实时)精确分析
下图是Gartner对APM的抽象模型。APM领域目前已经有不少商用系统,比如国外的Dynatrace, IBM APM,国内的OneAPM,听云APM等等。
接下来说说机房监控。机房监控又被称为IT监控,这是咱们最常见的监控系统类别,它一般涵盖以下内容:
-
操作系统级监控:例如CPU、内存、网络流量、磁盘IO、连接数、系统日志等等。
-
基础设施监控:例如交换机、路由器负载、存储设备IO等等。
-
基础设施环境监控:例如UPS电源、动力监控、环境温度、电力负荷监控等等。
以操作系统级监控为主的机房监控,目前有不少的实现,例如Nagios、Zabbix、Open-Falcon;针对基础设施的监控以及环境的监控通常需要借助额外的硬件采集设备来完成。
最后说说服务治理监控。先简单解释一下什么是服务治理。服务治理是针对面向服务架构的系统进行监控和管理的过程。面向服务的架构包括传统SOA,分布式服务,微服务等。
服务治理的核心内容涵盖四个层面:
-
服务注册与发现:服务接口信息被注册到服务配置中心的过程;服务调用方可以通过服务唯一标识从服务配置中心查找服务接口信息。
-
应用/服务监控:针对应用以及服务接口进行监控,包括性能监控,业务指标监控,安全监控等。
-
服务SLA协调:评估并量化各个层面的服务等级指标,这些层面包括应用,应用实例,服务实例,服务接口等。
-
服务运行时控制:是服务之间调用过程的干预,包括路由规则,负载均衡,Failover切换,服务安全,保护降级,弹性伸缩。
服务治理的四个核心内容实际上也是一个层级关系(Layers Topology),上层的实现需要依赖下层的实现。
服务治理的监控主要涉及服务注册与发现和应用服务监控两个层级。在实践中,我们又将这两个层级扩展了辅助层级:
-
服务画像:对服务接口特征信息(技术协议、入参出参、方法、类等)进行描述。
-
应用画像:对应用的架构、组成、技术栈、部署信息进行描述。
-
应用上下文画像:应用的运行是受上下文环境的影响,包括应用所处的容器(物理机OS、虚拟机、Docker等),同一个容器内的兄弟服务进程的状态描述。
-
应用上下文监控:针对上下文环境的容器,同一容器内的兄弟服务进程的性能监控。
下图展示服务治理的层级关系和服务治理监控包含的内容:
这三者由于关注点不同,所以在各自领域会有差异,但也有交集的地方。根据需要也可扩展各自的外延。
下图展示了APM,服务治理监控,机房监控的区别与联系:
“无侵入”的应用服务监控
这个部分主要介绍如何实现JAVA环境下的“无侵入”应用服务监控。如前文提到,要实现应用服务监控,就要先实现服务注册。
经典的服务注册方法有两种:
-
显式配置:通过人工将服务的接口信息(服务名,服务URI等)通过配置的方式存储到服务注册中心。经典的WebService UDDI就是这种模式。这种方式的问题在于服务接口信息都是由人工收集的,出现滞后或者谬误可能性高,较高的运维代价,无法适应快速迭代的节奏。
-
代码实现:通过代码调用服务注册中心客户端,将服务的接口信息发送到服务注册中心。使用ZooKeeper客户端实现服务注册就是这种模式。这种方式的进步之处在于服务接口的URI可能是通过代码收集出来的,例如获得IP,context路径,接口相对地址从而拼接成服务接口的URI。
我们在早期服务化实现中,采用的是这种模式,但它的问题是需要代码埋点,也就是“侵入”,这引发了如下问题:
-
与服务注册中心客户端的紧耦合:如果使用ZooKeeper,需要依赖它的jar包。
-
服务注册代码与服务接口代码上下文紧耦合:必须在特定位置去使用服务注册的代码,而且可能还会包含特定服务的信息,这些信息可能是人工编排进去的。
-
由于不同系统是由不同团队开发的,需要行政制度,“TopDown”规定服务注册的编程,一旦有“不按套路出牌”的情况就会出现各种运维问题。
无侵入的服务注册思路也用到了”微智能”的思想。
-
全自动的收集应用实例,服务实例,服务接口的信息。这些信息包括应用唯一标识(AppID),服务名(Service ID),服务实例的URI,服务接口的URI,服务接口的元数据(类,方法,入参出参,注解,部署描述符),即自动发现。
-
收集过程对应用透明,不可有任何直接依赖(API依赖,jar包依赖),对系统的研发团队同样透明,即无侵入。
-
收集过程能够自动适应应用,服务,服务接口的变化,即自我维护。
接下来分析一下JEE应用的特点:
-
以应用服务器(Tomcat,Jetty,IBM WAS,JBoss)为容器,JEE应用的启动或停止都被其应用容器感知。
-
遵守JEE规范,服务以servlet,JAXWS,JAXRS等落地;或遵守“事实”规范,比如Spring,服务以Spring MVC落地。
-
servlet是HTTP的唯一入口(当然还有RMI,RPC等,其实类似,这里不做详细展开)。
于是解决方案如下:
从应用服务器的层面来对应用进行画像,即应用画像,服务画像。这个过程发生在每次应用启动的时候,因为这样就能自然捕获应用的变化。就好比电影《星际穿越》里,从四维空间能够更容易,更直接解决三维空间的问题,且更具通用性。
这里用到两种技术:
-
中间件劫持
-
应用画像技术
中间件劫持就是将我们自己的代码行为植入到中间件的各种行为中。实现画像和监控主要依靠四种关键行为:应用启动,停止,接收请求,响应回复。
-
应用启动:用于应用画像,服务画像
-
应用停止:失效服务摘除
-
接收请求,响应回复:用于应用,服务监控(稍后会介绍)
对JEE应用服务器的劫持核心是掌控classloader tree,获得优先加载权,从而可以改变这些行为。尽管各家实现不同,但其classloader tree结构基本类似。
下面以Tomcat为例进行说明,下图是Tomcat的classloader tree:
值得注意的是,每个JEE应用都会被分配一个WebAppClassloader来加载其所有class。那么如果我们能够感知应用启动的行为,通过WebAppClassloader就可以收集到前文提到的各种画像信息。
那么我们需要植入一个自己的classloader来获取优先加载权。通过加载改写后的class,来改变行为。我们把这个classloader成为UAVClassLoader(无人机类加载器)。
UAVClassLoader算法基本原理
-
UAVClassLoader创建时,将能够读取到的Class文件对应的Class名存储到ClassMap中
-
将TomcatLoader设置为UAVClassLoader的Parent
-
将UAVClassLoader设置为TomcatLoader的一个属性
-
重写TomcatLoader的loadClass方法
1、如果UseUAVClassLoaderFlag为true,则使用UAVClassLoader.loadClass
2、加载成功则返回Class
3、失败则使用TomcatLoader自己的loadClass
-
UAVClassLoader的LoadClass方法
1、如果ClassMap中含有要加载的Class,则使用自己的findClass加载Class
2、否则,将UseUAVClassLoaderFlag设置为false
3、使用TomcatLoader.loadClass(注:这时TomcatLoader会直接用自己的loadClass)
-
将UsePlusLoader Flag设置为true
具备中间件劫持能力之后,就可以进行应用画像和服务画像了。
JEE应用服务器的应用启动实际是Web容器的创建过程。在Tomcat中的StandardContext就是Web容器的根类,在其加载的时候,UAVClassLoader会感知,通过改写或bytecode weave手段在其start方法的最后植入代码,完成两个步骤:
-
收集将Web容器的上文信息:包括WebAppClassLoader实例、Context Path、应用名、ServletContext、BasePath(应用实际路径)、WorkDir(应用工作目录)等。
-
植入应用、服务画像的代码。
应用画像包含了应用相关信息的收集,下面列举几个关键画像信息:
-
应用标识(AppID):先取部署的应用名(由应用服务器配置决定),如果应用名为空则取Context Path(通常可能就是war包的名字),应用标识对于应用实例自动归类有妙用,就是实现应用实例自动归类。
-
应用名称:使用WebAppClassLoader可以获得web.xml的路径,通过解析web.xml提取display-name(这个也是servlet规范),如果为空,则使用应用标识作为名称。
-
应用的URI:应用URI=http(s)://<本地IP>:<端口>/。本地IP的获取方式很多,这里不做说明;端口的获取是通过劫持CoyoteAdapter(启动监听的入口)来获得;Context Path已经获得。
-
应用的类库信息:通过WebAppClassLoader可以获取所有类库信息,通过类库信息可以掌握应用的技术栈,可以扩展做很多有趣的事情。
服务画像是按照技术规范(参见JEE应用的特点2),常见的技术规范:
-
Servlet规范
-
JAXWS规范
-
JAXRS规范
-
Spring规范
-
RMI规范
-
RPC规范(Netty,Thrift,Hessian等)
针对每种技术规范从3个方面进行收集:
-
Class和Method:通过Java的反射方式提取信息,如服务类名,方法名,入参出参。
-
Annotation:通过注解扫描工具提取具有相关注解的类,然后通过注解API提取注解信息。
-
部署描述符:通过WebAppClassLoader获取web.xml, spring-config.xml, log4j.xml等部署描述符文件路径,然后使用DOM解析提取关注的tag信息。
下面以Servlet为例对服务画像过程进行说明:
-
使用FastClasspathScanner(轻量的开源类扫描工具)将带有javax.servlet.annotation.WebServlet( Servlet 3.0的注解类)的Class扫描,这个过程需要WebAppClassLoader支持。并提取注解的信息(比如urlPatterns,loadOnStartup)。
-
通过WebAppClassLoader获取应用的实际路径(BasePath),而web.xml就在/WEB-INF下,加载web.xml提取所有的元素值(就是servlet class),同时也提取,等元素值。
-
对通过注解获得的Servlet与通过web.xml获得的Servlet进行合并。
3.1 只有注解有或只有web.xml有的,直接保留。
3.2 web.xml与注解重叠的servlet,保留web.xml的信息(Servlet规范,部署描述符替换注解)
-
对Servlet画像数据进行整理
4.1 ServiceID:由Servlet Class定义,保证唯一性
4.2 Service URI:ServiceURI=<应用URI>+
JAXWS,JAXRS,SpringMVC等的画像过程基本一致,主要区别在第1步时,需要通过注解提取“服务接口的相对路径”信息。例如:
JAXWS需要服务名
ServiceURI=<应用URI>+<Servlet Url Pattern>+<JAXWS Service Name>
JAXRS或SpringMVC的每个服务接口路径都是到方法级的
ServiceURI=<应用URI>+<Servlet Url Pattern>+<Class的Path信息>+<Method的Path信息>
有同学可能会问:“讲了半天,虽然我们已经拿到了应用,服务的画像数据,哪服务注册是怎么发生的呢?”这个问题会在第三部分揭秘。
接下来,看看如何实现“无侵入”的应用服务监控。应用服务监控实际上是对应用实例,服务实例,服务接口的性能指标进行捕获的过程,常用的性能指标:响应时间,请求计数,错误计数,响应代码计数等等。这些值的捕获是发生在请求进入和出去的地方。
下图是JEE应用服务器的Http CallFlow展示了HTTP的请求响应过程:
应用服务监控的落地方法:
-
运用中间件劫持技术改写CoyoteAdaptor.service()方法, 它负责整个Tomcat的请求处理,在方法开头拦截请求,方法结尾拦截响应。这里可以监控应用服务器,应用,所有的URL的性能指标。
-
运用中间件劫持技术改写StandardWrapper.service()方法,它负责Servlet的请求处理,同上如法炮制。这里可以监控所有Http服务的性能指标(参见JEE应用特点3)。
总结起来,通过中间件劫持和应用画像技术,可以轻松的实现对应用/服务的画像以及监控。由于Tomcat的服务器架构比较古老,所以我们采用了改写或bytecode weave的方式,但是也仅仅只是改写了Tomcat的3个方法。如果是Jetty,可以通过实现它的InterceptChain来实现,完全没有代码改写,只是增加了植入代码。而Jboss可以通过扩展它的listener来实现,也没有代码改写。
那么捕获到这些数据之后如何监控呢?这也会在第三部分解答。
无侵入模式引领统一服务治理
无侵入模式除了解决前面提到的诸多技术问题以外,还与我们自身的实际需要相关。
-
面临“微服务”的转型关口,但十年沉淀下来上百的系统也需要时间来逐步重构,这个过程可能很长。
-
各个系统虽然基本都是JAVA的,但是使用的JEE技术还是各有不同的,比如JAXWS,JAXRS,纯Servlet,SpringMVC,Thrift,SpringBoot等等。
-
系统架构差异大,包含单体架构,分布式服务架构,半SOA化架构,微服务架构。
-
系统的迭代很快,几乎每天都有更新,新型技术栈引入的可能不断增加。
从服务治理的角度,非统一的技术栈意味着像Dubbo之类统一技术栈的玩法不可行。所以“反转”这个思路,把从以服务调用技术栈为中心的治理方式转向以服务自动画像与注册为基础,逐步接管调用链路的治理方式。
而对JEE应用完全无侵入的模式恰好适应了这一需求。
我们的服务治理系统的代号叫无人机(UAV),寓意是无人机能够7*24的不间断巡航,随时随地收集地理,建筑,物品,人的变化,随时随地监控他们的行为,甚至精确的打击或操控。
我们把UAV定位为统一服务治理的模式,一种与“服务调用”技术栈基本无关的治理方法。
下图是UAV的架构图:
接下来解答第二部分遗留的两个问题:
-
收集了应用和服务画像之后,如何实现服务注册
-
捕获到监控数据之后如何监控呢
先来看看UAV的捕获流图:
数据捕获步骤:
-
无论是画像数据,还是性能数据(实时数据)暂存在内存中。JEE应用服务器中可以暂存到MBean中
-
监控代理程序每隔5秒(可调节),采集Mbean中的画像和性能数据
-
监控代理程序将收集的数据发送给消息系统
-
健康管理程序负责各种数据落地
-
同时健康管理程序会提取服务实例以及接口的信息注册到缓存中,这个缓存作为服务注册的存储中心。由于每个一定周期(5秒)都有画像数据推送,也意味着维持了服务心跳
下面的图展示了实现细节:
通过UAV的捕获流图,可以发现在数据传输格式上采用了统一的Schema,实现对画像数据,性能数据,日志数据的统一。这样不仅仅统一了三种数据的传输,也对实现后期数据的各种转换和处理提供了统一的处理模板,具有更好的扩展性。
下图是性能监控数据的Sample:
下图是画像数据的Sample:
打破悖论:监控系统如何监控自己
监控系统通常都面临一个问题:如何监控自己。监控系统不能监控自己的原因也很明显,因为不能处理来自自身的异常。
其实破解之法也很直接,就是“冗余”。不过这里“冗余”不是简单的冗余资源,而是在处理机制上实现“冗余”。
破解之法:双通道+双心跳
UAV采用双通道+双心跳的方式:
-
双通道就是一条Http传输通道,用来传输容器/节点画像数据和监控数据;一条MQ传输通道,用来传输实时数据,画像数据,日志数据。
-
双心跳是指不管来自Http通道还是MQ通道的数据实际上即可以看成业务数据,也可以看成心跳数据(远端的节点还活着并且在工作)。
-
来自每个通道数据都会通过健康管理程序“签到”。因此UAV的任何节点(监控代理程序,健康管理程序)出现宕机,都能够被发现;并且它们的进程状态,应用状态也被自己监控。
这样的做法并不是为了冗余而冗余,而是有以下考虑:
-
从分布式系统的考虑,UAV实现了心跳服务,并且允许多活,也允许多级心跳上行,那么Http通信方式更加适合这样的场景;同时,Http通信意味着每次携带的数据payload不能太大,所以更适合容器,节点的画像和监控数据,这些数据以及指标比较固定。
-
应用,服务的个数是未知的,且无论是画像还是指标(性能,业务等)也可能很多,意味着数据payload可能较大,而MQ适合payload较大的场景;MQ可以一定程度保证数据有序,且队列可以暂时持久化数据,防止了由于接收端宕机导致的数据丢失;同时“多活”的消费者,可以动态扩展,也能在某些消费者宕机后,快速接替继续消费。
-
两种通信方式意味着更高的可靠性,即便当某些服务不可用时,监控系统的另一部分依然可以继续工作。例如如果UAV的实时数据服务都挂了,那么应用的性能数据就看不了,但是应用的进程(比如Tomcat)的性能数据还是能看的。
下面是一部分UAV实际监控的效果图。
应用容器监控:包含UAV节点,所有服务进程,JAVA进程的监控
容器画像,UAV节点画像,进程画像
进程监控:Tomcat为例
应用监控:应用,应用实例
应用画像,服务画像
应用监控
JEE应用服务器监控:
Tomcat为例
服务监控
应用日志监控
最后总结一下:
-
APM,服务治理监控,机房监控由于关注点不同,所以监控内容有差异,但也有交集。服务治理监控可以根据实际需要扩展外延到APM或机房监控的范畴。
-
“无侵入”应用服务监控的关键是实现中间件劫持和应用画像技术。
-
无侵入模式的玩法颠覆了传统以服务调用技术栈为中心的服务治理模式,可以容纳更多技术栈,具有更好的可扩展性,适合混合架构下的服务治理需要。
-
监控系统如何监控自己的破解之法就是实现双通道+双心跳,从容器、进程的角度,或从应用,服务的角度来两个维度来落地心跳和性能监控。
嘉宾介绍
张真,目前就职宜信技术研发中心,高级架构师。主要负责基础系统架构演进与优化,服务治理,监控平台,微服务建设,DevOps平台,自动化测试框架以及电子签约,短信,邮件等应用系统。
一直都从事分布式系统的研发,早年就职于IBM中国研发中心,负责IBM WebSphere应用服务器包括传统WAS,下一代轻量级JEE应用服务器Liberty等的设计与开发,及应用服务器对云计算,移动平台的支持,并为银行、电商客户提供技术咨询和服务。
个人也比较喜欢参与开源社区贡献,如Cloud Foundry、Apache CXF、Apache Wink等。目前主要关注微服务架构实施,微智能设计思想应用,虚拟化技术应用,共识计算研究,十分欢迎和大家广泛的,深入的交流。
相关推荐
通过以上详细解析,我们可以看出Dubbo不仅仅是一个简单的RPC框架,它还提供了丰富的服务治理功能,包括服务注册与发现、负载均衡、监控等,这些功能使得Dubbo能够在复杂的分布式环境中发挥重要作用。无论是对于初学...
书中详细阐述了服务治理的演进历程,从无到有,从服务框架提供的SDK,到轻量级隔离容器Pandora,再到无侵入式的Java Agent以及Service Mesh,这些技术的发展反映了服务治理能力的不断提升,涵盖了开发、测试、线上...
书中详细阐述了微服务治理的演进历程,从最初的SDK治理,到轻量级隔离容器Pandora,再到无侵入式的Java Agent和Service Mesh,揭示了服务治理在开发、测试、运维、高可用等多个层面的关键能力。 书中提到,微服务...
IT运维从传统走向智慧,首先要经历数字化运维阶段,搭建数字运维中台既是实现运维数据有效治理的前提和基础,也是推进运维数智化转型的第一步。针对上述需求,擎创科技自主研发的擎创夏洛克AIOps智慧运营平台(如下图...
4. 调用跟踪:通过Java Agent和AspectJ技术实现无侵入式的调用埋点,记录每个请求的完整调用链路,便于问题排查和性能优化。 5. 服务治理:建立了防止循环依赖的服务依赖关系计算机制,控制调用深度,实现了业务...
- **非侵入式微服务接入**:利用ServiceMesh技术,使现有服务能够无侵入地集成到微服务体系中。 - **统一配置中心**:支持配置项的发布、变更和通知,便于集中管理和更新。 - **微服务仪表盘**:实时监控微服务实例...
3. **SDK和Mesher**:Java应用使用ServiceComb SDK,PHP应用通过Mesher接入,实现统一服务治理。 4. **监控运维**:ServiceComb提供了丰富的监控和运维工具,对业务层面进行细化监控。 总结,基于ServiceComb的...
- Pinpoint:适用于Java环境,采用JavaAgent技术实现零侵入式监控,包含Collector(数据收集)、Agent(应用探针)和Web(数据展示)三个主要部分,数据存储在HBase中。 - SkyWalking:其架构包括Collector(数据...
此外,华为云微服务引擎支持Java和Go两种语言的微服务SDK,提供了非侵入式的Mesher和其他微服务工具,以及微服务管理平台,包括OpenAPI、注册中心、配置中心、治理中心等。演示Demo展示了如何基于ServiceStage的流水...
然而,这种架构存在服务可见性无隔离、接口级服务发现等问题,以及Java技术栈之外的微服务治理能力不足。 Service Mesh落地时面临的挑战包括新技术的平滑演进、技术与业务发展的协调、处理历史包袱,以及克服大规模...
3. **面向接口代理**:Dubbo支持基于Java的动态代理,实现了服务的无侵入性。 4. **服务自动注册与发现**:服务提供者启动时自动向注册中心注册,服务消费者通过注册中心获取服务提供者的地址。 5. **负载均衡**:...
Dubbo是一个高性能、轻量级的Java分布式服务框架,它主要解决了分布式环境下的服务调用问题。Dubbo的核心功能包括服务治理、远程调用、负载均衡、容错机制等,使得开发者可以方便地实现服务的发布、发现和调用。 ...
本文将深入探讨阿里巴巴(B2B)服务框架的演进历程及其在面对业务快速增长、应用规模日益庞大时的技术策略与实践。 #### 应用开发技术的变迁 自阿里巴巴B2B平台成立以来,其应用开发技术经历了多次迭代升级。从1999/...
2. **Apache Dubbo**:Apache Dubbo是一个高性能、轻量级的Java RPC框架,它提供了服务治理、监控等高级功能,是阿里巴巴开源并贡献给社区的重要组件,广泛应用于分布式系统中。 3. **基于注释的文档生成**:这种...
它支持Spring、Hibernate等常见的Java框架,同时具备低侵入性,只需简单配置即可实现对应用程序的全面监控。 2. 主要功能: - **调用链追踪**:Pinpoint-Agent能够生成完整的请求调用链路,清晰展示服务间的依赖...
通过pinpoint-collector收集应用数据,pinpoint-web展示监控结果,pinpoint-agent无侵入式地监控应用,再借助HBase存储和管理大量监控信息,为企业提供了强大的微服务监控工具。对于大型分布式系统来说,Pinpoint是...
- **Agent/Probe**:安装在应用程序服务器上,无侵入性地监控应用的运行情况。 3. **Apache-skywalking-apm-bin** 这个文件是SkyWalking的二进制发行版,包含了SkyWalking后端服务、UI和必要的配置文件。安装时,...
8.4.0 版本的 SkyWalking Agent 是该系统的重要组成部分,它允许用户无侵入地监控应用程序的性能,包括服务调用链路、系统指标以及故障排查等。下面将详细介绍 SkyWalking Agent 在8.4.0版本中的关键特性和功能。 1...
Nacos是阿里巴巴开源的一款分布式服务治理和配置中心的框架,主要应用于微服务架构中的服务发现、配置管理和控制台管理。Nacos 2.0.1是该框架的一个稳定版本,提供了许多新特性和性能优化。 1. **服务发现**: - ...
- **无侵入性**:通过Sidecar模式部署,对应用程序几乎无侵入。 - **流量管理**:支持精细的流量控制策略,如路由规则、熔断机制等。 - **安全性**:提供了全面的安全功能,包括认证、授权和加密等。 综上所述,...