多节点定时任务的同步

背景现在有两个或以上的web节点,启动时,会查询数据库,根据数据库中配置的数据(cron表达式等)创建定时任务。由于期望一个任务定时只有一个节点执行,所以需要多个web节点间做master竞选,这个已经实现了,身为master的web节点会将定时任务发送给实际执行的worker节点执行,非master节点的web节点会跳过此定时任务。 然而,由于系统有个功能,用户可以在web页面对定时任务进...

发布于 technology

使用同一个线程调用本容器的其他服务,不经过网络传输

dapeng容器目前的模式,每个请求都需要以调用远程服务的方式请求服务,即使它请求的服务运行在本地同一个容器内。打个比方,客户端调用A服务,A服务内需要调用B服务,这时候,对于A服务来说,它是B服务的客户端,它请求B服务的方式与标准的前端没有任何区别,都需要经过各种过滤链,走网络传输,然后调用到本地(或其他节点)的服务。 这样做的优点是,对于所有请求,模式是统一的,每一个请求都是完整的服务调用。缺点在于: 如果一个节点有很多服务,一个请求链的互相调用过程中,即使每次都是调用本节点,也依然有大量的网络传输过程开销; 对一个完整的服务调用来说,每个请求处理需要占用一个新的线程,如果一个请求中调用了十次本节点的服务,那么就至少占用了本节点10个线程,并且大多数都处于等待状态; 在分布式服务的调用过程中,如果后面某个服务调用异常,前面成功的服务调用无法自动回滚,但如果都是在同一个线程同一个事务,后面的异常可以使前面的数据库操作回滚。 因此,提出了这么一种需求:“如果本节点存在即将调用的服务,那么,不经过网络传输,直接用当前线程调用本地服务”,以此来解决上述的3个问题。

发布于 technology

pinpoint 插件开发实战

资源文件pinpoint agent在启动的时候,会加载plugin文件夹下所有的插件。它会扫描插件jar包中META-INF/services目录下的两个配置文件来确认ProfilerPlugin和TraceMetadataProvider的实现类。META-INF/services/com.naercorp.pinpoint.bootstrap.plugin.ProfilerPlugin: 1com.isuwang.dapeng.pinpoint.plugin.DapengPinpintPlugin META-INF/services/com.navercorp.pinpoint.common.trace.TraceMetadataProvider: 1com.isuwang.dapeng.pinpoint.plugin.DapengTraceMetadataProvider TraceMetadataProvider只需要实现setup方法,添加ServiceType和AnnotationKey, 主要用于服务类型和记录的数据的标识,agent上送给collector, collector和web通过它们区分不同的服务节点类型。 12345678910111213141516public class DapengTraceMetadataProvider implements TraceMetadataProvider { public static ServiceType DAPENG_PROVIDER_SERVICE_TYPE = ServiceTypeFactory.of(1999, "DAPENG_PROVIDER", RECORD_STATISTICS); public static ServiceType DAPENG_CONSUMER_SERVICE_TYPE = ServiceTypeFactory.of(9999, "DAPENG_CONSUMER", RECORD_STATISTICS); public static AnnotationKey DAPENG_ARGS_ANNOTATION_KEY = AnnotationKeyFactory.of(900, "dapeng.args", VIEW_IN_RECORD_SET); public static AnnotationKey DAPENG_RESULT_ANNOTATION_KEY = AnnotationKeyFactory.of(999, "dapeng.result", VIEW_IN_RECORD_SET); @Override public void setup(TraceMetadataSetupContext context) { context.addServiceType(DAPENG_PROVIDER_SERVICE_TYPE); context.addServiceType(DAPENG_CONSUMER_SERVICE_TYPE); context.addAnnotationKey(DAPENG_ARGS_ANNOTATION_KEY); context.addAnnotationKey(DAPENG_RESULT_ANNOTATION_KEY); }} 注意这里的ServiceType和AnnotationKey的code是有范围的.RECORD_STATICSTICS类型的ServiceType, agent会统计它的耗时。VIEW_IN_RECORD_SET属性的AnnotationKey将会在调用树状图中行显示。

发布于 technology

pinpoint插件原理学习

主要节选翻译自官方文档 Pinpoint Plugin Developer Guide 在pinpoint里面,一个“事务”(或者说请求?)是由一组spans构成的。每个span代表了请求经历的一个单独的逻辑节点。 一个span记录了重要方法的信息和它们的相关数据,请求,返回值等,概括它们为spanEvents. 一个span和它包含的所有spanEvents代表了一个方法调用。 PinPoint插件结构pinpoint插件是由TraceMetadataProvider和ProfilerPlugin的实现组成。TraceMetadataProvider的实现提供了ServiceType和AnnotationKey给PinPoint agent/web/collector. ProfilerPlugin的实现被agent使用,用来修改目标类,记录跟踪数据。 插件放在agent的plugin目录,web和collector的WEB-INF/lib目录。插件需要在资源文件夹的META-INF/services目录中,声明自己实现的TraceMetadataProvider和ProfilerPlugin。 TraceMetadataProviderServiceType每个Span和SpanEvent都包含了ServiceType, 代表了正在追踪的方法属于谁。web也需要通过serviceType来展示。 需要注意的是,每个ServiceType由name,code,description,properties组成。其中,code是不能乱用的,每个serviceType的code唯一。因此,pinpoint预留了一部分code范围供我们自己开发使用。 AnnotationKey同样的,AnnotationKey也有自己的唯一code, 900-999是pinpoint团队为我们预留的。 ProfilerPluginprofilerPlugin修改目标类以收集跟踪数据。 它工作的步骤是: jvm 启动时启动pinpoint agent agent加载插件目录下所有的插件 agent调用每个插件的ProfilerPlugin.setup(ProfilerPluginsetupContext)方法 在setup方法里面,插件决定是否要转换类,并且注册一个transformerCallerBack 应用启动 每次类加载的时候,agent会寻找注册在该类上的TransformerCallback 如果找到了,agent会调用callback里面的doInTransform方法 TransformerCallerBack会修改目标类的字节码,添加拦截,添加字段等等 修改后的字节码被返回给jvm,然后类被加载 应用继续 当一个修改后的方法被调用时,注入的拦截器before和after方法会被调用 拦截器纪录追踪数据

发布于 technology

pinpoint 安装配置

本文记录了pinpoint的安装、配置和使用过程。

发布于 technology