akka监控框架设计
本博客介绍一种AOP、无侵入的akka监控方案,方便大家在生产使用akka的过程中对akka进行监控。
对于自身javaer来说,AOP三个字母基本就解释清楚了akka监控框架的原理。哈哈哈,不过我这里还是啰嗦一点,把相关的方案和框架介绍一下。
无侵入监控方案,不管是对akka还是其他java应用来说,经常听到动态代理、静态代理、AOP这些词汇。AOP为Aspect Oriented Programming的缩写,意为:面向切面编程。使用Spring的童鞋一定听过这个词。虽然AOP一般用在spring上,但用在我们的akka监控来说也是非常合适的。静态代理、动态代理只不过是AOP的一种实现方式,就是用统一的代理类来拦截特定对象的执行过程,并加以监控。但这有一个比较严重的缺陷,至少在akka的监控中是这样的,那就是代理类会影响目标类的类型,比如通过classOf获取到的是代理类的类型。字节码注入是另一种AOP的实现方式,它是通过编译期或加载期修改目标类的字节码,来进行监控的。简单来说就是修改了Java的class文件,从而在不修改源码的情况下,修改编译结果。字节码注入有很多框架,但我们这里选择了ASPECTJ,这个工具可以通过注解的形式定义注入点,非常方便。
好了,基本的知识点就讲解清楚了,下面直接上代码及其框架。
监控框架工程命名为akkamon,意为akka的监控,哈哈。分为四个模块:
- akkamon-core。核心模块,定义基本类型,主要用来定义注入点函数,就是aspectJ中的pointCut。
- akkamon-injector。注入器。定义并实现ActorSystem的一个AkkaInjectorExtension,将注入点拦截到的信息以消息的形式发送给特定的actor
- akkamon-java-shell。pointCut实现模块。因为aspectj-maven-plugin对scala支持不太友好,此处用Java实现对pointCut的具体实现。
- akkamon-target。测试模块
下面我们分模块详细讲解各个类的定义及其意义。首先是akkamon-core
trait Instrumentation
Instrumentation意为仪器、仪表,代表一组注入函数集合。
trait ActorCellInstrumentation extends Instrumentation {
def beforeActorCellCreation(system: ActorSystem, ref: ActorRef, props: Props, parent: ActorRef ):Unit
def beforeActorTerminate(cell:ActorCell):Unit
}
比如ActorCellInstrumentation代表ActorCell的监控仪表,它定义了两个函数,分别是ActorCell创建前和销毁前。
trait ActorSystemInjectPoint extends ListenerInstrumentation
with ActorCellInstrumentation
with ActorSystemInstrumentation
with MessageInstrumentation
ActorSystemInjectPoint代表ActorSystem的所有注入点,它主要是所有Instrumentation的一个汇总。
class ActorSystemInjectPointImpl extends ActorSystemInjectPoint
ActorSystemInjectPoint有一个实现类,它来实现ActorSystemInjectPoint,主要是把拦截到的消息通知给listener,我们来看看其中一个函数的实现。
override def beforeActorCellCreation(system: ActorSystem, ref: ActorRef, props: Props, parent: ActorRef): Unit = {
val message = notifyMessage(ActorCellCreation(system.name,ref,props,parent))
log.debug(s"beforeActorCellCreation $message")
}
很明显在拦截到ActorCell创建的时候,会构建ActorCellCreation这个case class,然后通过notifyMessage函数把消息通知给listener。
notifyMessage是ActorSystemInstrumentationListeners的一个方法,ActorSystemInstrumentationListeners维护了ActorSystemInstrumentationListener列表,在notifyMessae内部,依次调用所有listener的onMessage函数。
abstract class ActorSystemInstrumentationListener{
def onMessage(message:InjectMessage):Unit
def close():Unit
}
那么到这里,可能会有读者问,ActorSystemInstrumentationListener是什么时候注册到ActorSystemInstrumentationListeners里面的呢?答案就是监控ActorSystemInstrumentationListener构造函数的调用,然后把它register到listeners列表的。那Instrumentation定义的那些函数又是啥时候调用的呢?答案就在akkamon-java-shell模块。
@Aspect
public class InstrumentationJavaShell implements ActorSystemInjectPoint
这个模块只有一个InstrumentationJavaShell类,它继承了ActorSystemInjectPoint,所以它会实现你所有定义的注入点,并把相应的函数调用转发给ActorSystemInjectPointImpl
private static ActorSystemInjectPointImpl actorSystemInstrumentation = new ActorSystemInjectPointImpl();
ActorSystemInjectPointImpl是InstrumentationJavaShell里面的一个静态类。
@Pointcut("execution(akka.actor.ActorCell.new(..)) && args(system, ref, props, *, parent)")
public void actorCellCreation(ActorSystem system , ActorRef ref,Props props , ActorRef parent){} @Override
@Before("actorCellCreation(system,ref,props,parent)")
public void beforeActorCellCreation(ActorSystem system , ActorRef ref, Props props , ActorRef parent) {
actorSystemInstrumentation.beforeActorCellCreation(system,ref,props,parent);
}
上面两个函数分别定义了一个Pointcut和一个advice,Pointcut是对akka.actor.ActorCell.new的注入,Before这个advice是在akka.actor.ActorCell.new执行之前调用,可以看到beforeActorCellCreation就是简单的把相关的参数传给actorSystemInstrumentation.beforeActorCellCreation,而beforeActorCellCreation里面是通知各个listener。
下面是listener的注册过程。
@Pointcut("execution(com.gabry.akkamon.listener.ActorSystemInstrumentationListener.new(..)) && this(listener)")
public void listenerCreation(ActorSystemInstrumentationListener listener) { } @Override
@After("listenerCreation(listener)")
public void afterListenerCreation(ActorSystemInstrumentationListener listener) {
actorSystemInstrumentation.afterListenerCreation(listener);
}
listener的注册过程其实也是通过AOP来实现的。
class ActorListener(actorRef:ActorRef) extends ActorSystemInstrumentationListener{
override def onMessage(message: InjectMessage): Unit = {
actorRef ! message
} override def close(): Unit = { }
}
上面是一个listener的实现,其实就是简单的把消息通知给了相关的actor。
至此,一个akka的监控框架就实现了,是不是很简单呢?框架很简单,麻烦的是Instrumentation的定义和实现啊。
读者问怎么执行?那就是java命令行的-javaagent参数啊。
akka监控框架设计的更多相关文章
- 前端MVVM框架设计及实现(二)
在前端MVVM框架设计及实现(一)中有一个博友提出一个看法: “html中使用mvvm徒增开发成本” 我想这位朋友要表达的意思应该是HTML定义了大量的语法标记,HTML中放入了太多的逻辑,从而增加了 ...
- GPS部标平台的架构设计(九)-GPS监控客户端设计
交通部的部标过检,所有的测试都是从客户端发起的,也是在客户端体现的,在客户端承载了部标标准所要求的所有的功能,是整个部标平台当中工作量最大的部分,也是最繁琐的部分. 客户端设计面临两个问题: 1.基于 ...
- 偶的《javascript框架设计》终于出版
#cnblogs_post_body p{ text-indent:2em!important; } 历时两年多,我的书终于付梓出版了.应各方面的要求,写软文一篇,隆重介绍一下此书对各位程序员的钱途有 ...
- Socket开发框架之框架设计及分析
虽然在APP应用.Web应用.Winform应用等大趋势下,越来越多的企业趋向于这些应用系统开发,但是Socket的应用在某些场合是很必要的,如一些停车场终端设备的接入,农业或者水利.压力监测方面的设 ...
- 【niubi-job——一个分布式的任务调度框架】----框架设计原理以及实现
引言 niubi-job的框架设计是非常简单实用的一套设计,去掉了很多其它调度框架中,锦上添花但并非必须的组件,例如MQ消息通讯组件(kafka等).它的框架设计核心思想是,让每一个jar包可以相对之 ...
- 基于cocos2d-x的游戏框架设计——李成
视频:http://v.youku.com/v_show/id_XMzc5ODUyMTI4.html?f=17330006 网易科技讯 3月31日,第四届CocoaChina开发者大会暨Cocos2d ...
- js架构设计模式——前端MVVM框架设计及实现(二)
前端MVVM框架设计及实现(二) 在前端MVVM框架设计及实现(一)中有一个博友提出一个看法: “html中使用mvvm徒增开发成本” 我想这位朋友要表达的意思应该是HTML定义了大量的语法标记,HT ...
- js架构设计模式——前端MVVM框架设计及实现(一)
前端MVVM框架设计及实现(一) 最近抽出点时间想弄个dom模块化的模板引擎,不过现在这种都是MVVM自带的,索性就想自己造轮子写一个简单的MVVM框架了 借鉴的自然还是从正美的avalon开始了,我 ...
- niubi-job:一个分布式的任务调度框架设计原理以及实现
niubi-job的框架设计是非常简单实用的一套设计,去掉了很多其它调度框架中,锦上添花但并非必须的组件,例如MQ消息通讯组件(kafka等).它的框架设计核心思想是,让每一个jar包可以相对之间独立 ...
随机推荐
- Leetcode 220.存在重复元素III
存在重复元素III 给定一个整数数组,判断数组中是否有两个不同的索引 i 和 j,使得 nums [i] 和 nums [j] 的差的绝对值最大为 t,并且 i 和 j 之间的差的绝对值最大为 ķ. ...
- LOJ#539. 「LibreOJ NOIP Round #1」旅游路线
n<=100,m<=1000的图,在此图上用油箱容量C<=1e5的车来旅行,旅行时,走一条边会耗一单伟油,在点i时,若油量<ci,则可以把油以pi的价格补到ci,pi<= ...
- nyoj_10_skiing_201405181748
skiing 时间限制:3000 ms | 内存限制:65535 KB 难度:5 描述 Michael喜欢滑雪百这并不奇怪, 因为滑雪的确很刺激.可是为了获得速度,滑的区域必须向下倾斜,而且当 ...
- [bzoj4698][Sdoi2008]Sandy的卡片_后缀数组_二分/单调队列_双指针
Sandy的卡片 bzoj-4698 Sdoi-2008 题目大意:题目链接. 注释:略. 想法: 这个题跟一个Usaco的题特别像.我们把这些串差分 现在我们要求的就是公共子串且出现次数不少于$k$ ...
- 谈谈hibernate的缓存
一,hibernate是什么技术? 1 hibernate是一个orm 就是对象关系映射框架. 及我们创建的实体类对象与数据库表中的数据是一一对应的关系. 我们可以改变对象信息从而改变数据库中的 ...
- 洛谷 P4136 谁能赢呢?
P4136 谁能赢呢? 题目描述 小明和小红经常玩一个博弈游戏.给定一个n×n的棋盘,一个石头被放在棋盘的左上角.他们轮流移动石头.每一回合,选手只能把石头向上,下,左,右四个方向移动一格,并且要求移 ...
- 所有的异常都要使用try catch 语句捕获?
在开发应用程序过程中必须检测代码可能发生的错误并进行正确的处理,这个在理想的情况下,应用程序中的每行 代码都按照预想的执行,要用到的每种资源总是可以利用,但是在实际的开发过程中,写代码难免会出错,或是 ...
- SaltStack及Multi-Master介绍
1.先说下SaltStack是啥? SaltStack是基于Python开发的一套C/S架构配置管理工具(功能不仅仅是配置管理,如使用salt-cloud配置AWS EC2实例),它的底层使用Zero ...
- uva 439 Knight Moves 骑士移动
这道题曾经写过,bfs.用队列,不多说了,上代码: #include<stdio.h> #include<stdlib.h> #include<string.h> ...
- Start Xamarin——与Microsoft 的sales development manager的闲谈
由于在Xamarin属于微软之前,就已经有Xamarin的账号,试用过破解版的.所以4月1号微软set Xamarin free之后.就收到了Xamarin的邀请试用邮件. 试用完了之后第二天.收到邮 ...