77百科网
当前位置: 首页 生活百科

如何查系统日志组件(日志系统开发总结之Guava)

时间:2023-08-15 作者: 小编 阅读量: 2 栏目名: 生活百科

已经连续有10天没有更新头条号了,原因是最近比较忙。即使服务宕机,MQ可以靠其集群特性保证日志不丢失。优点是方案比较成熟,缺点是增加了维护成本。综上考虑,我们最后决定使用eventbus这个组件,暂时也不引入MQ,因为业务量没有那么大。而是创建一个message的表,用以保存日志或者其他消息记录。guava-eventbus为我们提供了同步和异步的事件解决方案,即我们在进程中希望我们这个事件可以同步完成然后返回,或者可以异步完成不影响主线程。

已经连续有10天没有更新头条号了,原因是最近比较忙。最近和同事一起搞日志系统的开发,涉及到基础架构和具体的业务日志记录,难倒不难,但量比较大,而且这期间还有其他需求和BUG需要我们来维护,所以我也就没有了时间去更新头条号,明天我要请一天假有点事处理,今天下午就写写我们这个日志系统怎么做的吧。

有人会问我,你的日志为什么不用AOP来做呢,对一些方法例如save,update方法做方法级别的拦截,在执行完成后像数据库插入一条记录不就可以了。这种方案我们考虑过,也许是我对AOP的理解不到位吧,我们并没有采用这个方案,原因是因为我们要记录的日志并不是固定的、模版式的,而是具有很强的业务属性,要记录每个操作的人、以及具体做了那些操作,操作的对象都是什么属性等,而AOP适合一些公共的,统一的,业务性弱但行为性强的操作。所以我们就没有考虑使用spring的切面。

首先说一下我们这个日志记录的技术要求有哪些:

(1)日志的保存要求在本次事务提交之后的另外一个新事务异步提交;当然也要支持在同一个事务里同步提交。

(2)支持日志的持久化,即若系统宕机后要记录的日志不能丢并保证日志可以在某个时间点统一保存到日志库(表)中。

针对第一个问题,在以前我记录日志的设计中,通常我会在service层(事务层)执行完后成,将日志信息返回到前一层也就是controller(控制层),在控制层中提交日志。优点是可以保证事务已经提交,不过缺点是改造比较大,我需要改造每一个接口,修改返回值等内容,还要在控制层判断业务是否成功。其次,假设日志保存比较慢,日志的保存应当不能影响主线程的进度,所以要开启一个新的线程完成这项工作。

针对第二个问题,我想可以引入MQ,将日志先保存到MQ中,通过监听来读取mq消息,然后逐一保存到日志库中。即使服务宕机,MQ可以靠其集群特性保证日志不丢失。优点是方案比较成熟,缺点是增加了维护成本。

综上考虑,我们最后决定使用eventbus这个组件,暂时也不引入MQ,因为业务量没有那么大。而是创建一个message的表,用以保存日志或者其他消息记录。那首先我们解释下什么是eventbus.

我们在百度搜索eventbus,竟然没有百度百科,很多人都不知道这是什么,如果让我为其总结一个概念我可能也说不好,根据我个人的理解,eventbus汉语意思就是事件服务总线,事件代表着我们系统中各种各样可能被触发的事件、任务。由于服务中的这些事件可能会越来越多,所以我们需要一套机制去管理这些事件,提供订阅、发布等模式,最终形成一整套的事件调度和执行,适应于多系统集成的方案。当然这都是我自己的体会不一定对。简单来说,eventbus的一个比较好的实现就如mq,mq可以作为事件中心,我们将所有的事件全部注册到mq,mq帮助我们来分发消化我们的消息。这里,我们使用的eventbus的实现方案是google的guava的eventbus库。MQ就是传统的事件订阅与发布的模式,eventbus是进程内的模式,下面我们先来看一下具体的术语概念:

那我们如何将日志抽象成事件呢?

(1)当我们保存日志的时候其实就是要注册一个事件,我们可以称之为LogEvent。

(2)而这个事件我们的目的是要保存它,我们肯定会有一个事件监听者我们称之为LogEventListener。

(3)将来我们系统中还会有其他的事件,不同的事件监听器针对不同的事件进行订阅,会走各自的实现类,但接口应该都是一样的,即IEventListener,提供一个listener方法,LogEventListener实现该接口,重写listener方法。将来比如有发短信的事件处理,我们就在定义一个MsgEventListener即可。

(4)IEventListener的listener方法就是统一的事件处理方法

(5)最后我们要做的就是将该事件注册到总线中,让各位监听者可以监听到。

发现讲了很多,可能大家都不会理解,因为文章涉及的内容比较多,我觉得还是应该拆看来讲,我们今天就主要将guava的eventbus库,让大家理解什么是eventbus,如何使用eventbus。

guava-eventbus为我们提供了同步和异步的事件解决方案,即我们在进程中希望我们这个事件可以同步完成然后返回,或者可以异步完成不影响主线程。各自的实现方式如下图:

为了让大家更清晰的了解EventBus所提供的同步和异步机制,下面我们来做一个DEMO,假设我们现在系统内有A事件与B事件分别发送给事件中心EventBus处理,AB事件分别有各自的事件处理者,首先看事件处理接口定义:

实现类如下:

在主线程中,将这些事件处理者在服务启动的时候注册到eventBus中心来管理,如图:

其中eventBus实例为同步实例,而asyncEventBus为异步实例。

假设主线程可以生存5000毫秒,主线程启动后,启动一个新的线程(这个线程1000毫秒就结束了)发送A事件和B事件,在A事件由于业务简单,基本不需要耗时;B事件需要耗时2000毫秒才能执行完成,如果上述场景存在,那结论应该是当我们分别想eventBus提交我们的事件后,A事件会被处理,但B事件不会别处理,因为在同步情况下,B事件所在的子线程1000毫秒已经死亡,B事件由于耗时太长2000毫秒被终止。我们看结论是否正确:

执行main方法,我们看下输出:

1、子线程处理业务开始

2、子线程发送消息给EventBus

3、AEventListener.listener:A事件执行完成

5、子线程终止

6、主线程....

7、主线程结束....

我们发现(4)也就是B事件压根没有输出,也就是说在同步模式下,由于子线程死亡,B事件没有处理成功。

如果同样的问题,我们使用异步的方式结果是什么呢?只需要将eventBus修改为asyncEventBus实例调用post方法即可。

运行main方法,看下输出:

1、子线程处理业务开始

2、子线程发送消息给EventBus

3、AEventListener.listener:A事件执行完成

5、子线程终止

6、主线程....

4、BEventListener.listener:B事件执行完成

7、主线程结束....

结论是(3)(4)事件都会执行了,由于我们使用的是异步方式,即任务已经在其他子线程中执行了,即使其所在的子线程已经死亡,也不会影响任务的执行。

在这里有同学可能会疑问,你是通过什么让AEventListener监听到A任务的?只调用了一个post方法就可以吗? 因为guava已经帮助我们将这个机制给封装了,我们会在之后的续篇讲解其源代码,这里我们可以看一下源代码,当我们调用eventbus.post(T)方法的时候,实际上guava会在底层解析T对象的类型,将其作为key去找map中的value,而这个map是其维护在内部的,key是参数class,而value就是处理类,我们在定义AEventListener的时候它重写listener方法所接受的参数就是AEvent,同理,BEventListener的参数是BEvent,在服务启动时,eventbus中心根据这些类型将listener放在map中,在运行时,根据post的参数类型找到对应的listener。源码如下:

getAnnotatedMethods是找哪些被注解@Subscribe修饰的方法。即如果你想让这个listener监听到你的事件,就要在其方法上加上注解@Subscribe,这样在服务启动时,它就可以以此监听到你的事件了。

其实有了这个机制,不管是做日志还是做其他的什么,只要涉及到异步执行的例如发短信,发邮件等我们都可以基于这个机制来做,如果说性能肯定不如mq,如果从易用性维护性来讲,对于中小型系统足够了。在我们的日志系统中,我们要选择的就是这种异步的处理方式,当主线程的业务处理完成后,构造的日志内容也完成了,此时我们就要将这个日志post到事件中心。而日志的保存就异步执行了,不会阻塞主线程。不过这里还有一个问题我们没有解决就是事务。我们如何保证让主线程的事务提交后,再去post日志数据呢?之前我们说放在controller层,这样显然不好,改动太大,我们要的就是在service层post日志,但需要在service提交事务后做?这里的确可以使用aop做,不过Spring4.3.2给我们提供了更好更简单的方式ApplicationEventPublisher,这个我们将放在下一篇再讲了。

    推荐阅读
  • 支付宝登录如何由图形改成密码登录(具体更改方法教程)

    下面内容希望能帮助到你,我们来一起看看吧!支付宝登录如何由图形改成密码登录首先,下载并打开支付宝APP,先用密码登录自己的账号。跳转到安全设置界面,选择“密码设置”,点击右边的箭头。最后跳转到设置登录密码界面,输入想要更改的登录密码,别忘了点击“保存新密码”,这样就完成更改支付宝登录密码的操作了。

  • 苹果微信双开怎么弄(苹果微信双开如何弄)

    苹果微信双开怎么弄?打开safari浏览器后在顶部输入:应用分身.site,只有手机系统自带的safari浏览器才有权限安装设置;,下面我们就来聊聊关于苹果微信双开怎么弄?接下来我们就一起去了解一下吧!安好了以后打开App输入验证数字登录就可以使用。

  • 多地缴纳社保怎么合并(多地缴纳社保如何合并)

    多地缴纳社保怎么合并准备相关材料:社保卡、离职证明、个人身份证等。到当前所买社保的区社保局的社保服务中心去办理社保转出业务。进入社保局后,不需要拿号排队,可直接在社保自助终端机上根据提示办理。最后需要注意的是,个人的社保缴费记录是很重要的,例如在某些省会城市,会要求外地人员连续缴纳满5年社保,才能申请落户或者在当地买房。所以到了异地工作以后,最好申请社保合并,这样可以享受到部分公共福利政策。

  • 阅微草堂笔记是谁所著的(阅微草堂笔记狼子野心)

    《狼子野心》文言文,我来为大家科普一下关于阅微草堂笔记是谁所著的?阅微草堂笔记是谁所著的《狼子野心》文言文有富室,偶得二小狼,与家犬杂畜,亦与犬相安。稍长,亦颇驯,竞忘其为狼。再就枕,将寐,犬又如前。“狼子野心”,信不诬哉!文言文翻译有个富人偶然得到两只狼崽,将它们和自家的狗混养在一起,倒也和狗平安相处。富人知道后立即把狼杀掉,并把它们的皮扒了。

  • steam绑手机令牌是最安全的吗(steam手机令牌怎么绑定)

    8、将收到的验证码填入到下面指定区域提交就可以了。

  • 预祝考试成功的诗句(祝福考试顺利的诗句)

    预祝考试成功的诗句归志宁无五亩园,读书本意在元元。十年寒窗无人问,一举成名天下知。身既死兮神以灵,魂魄毅兮为鬼雄。三更灯火五更鸡,正是男儿读书时。僵卧孤村不自哀,尚思为国戍轮台。英才齐聚争鳌头,贾生才调更无伦。休对故人思故国,且将新火试新茶。一举夺魁宏名扬,霞光裹身蔽云天。读书三十年,腰间无尺组。献赋今未售,读书凡几秋。历览前贤国与家,成由勤俭破由奢。谤书盈箧不复辩,脱身来看江南山。

  • 手机触摸失灵有什么办法(触摸失灵怎么办)

    故障:6代触摸有时不触故障分析及处理:1、观察主板有没有腐蚀,受压,仔细检查后发现没有进水腐蚀痕迹,也没有严重的变形。

  • 含金量高不限专业的证书(居然是HR最爱考的非专业证书)

    答案是教师资格证。教师,是自古至今备受推崇的一个职业。他们图的是前缀,而不是“教师”两个字。乡村孩子明明是最需要教师的群体。但就近年来的新闻事件看,现在教师群体里有太多败类,不仅不能称之为教师,甚至畜生都不如,没有师德,反而借着师德的幌子牟取利益。这也是大量没有接受过专业培养和筛选的人进入行业的一个弊端,教师资源是丰富了,但是质量堪忧。

  • 长城润滑油排名第几(引领润滑油行业发展)

    3月6日,中国石化长城润滑油在杭州召开“尊龙智变·领创未来”2019年商用车用油新品发布会暨长城润滑油全国经销商大会。从“国二”标准到“国六”标准,氮氧化物排放量下降94%,颗粒物排放下降93%,可以说“国六”要求车辆尾气接近于零排放。中国石化长城润滑油副总经理张春辉发表主题报告2018年,在国际、国内品牌激烈竞争的市场压力下,长城润滑油实现了总体销量的持续增长,蝉联中国润滑油销量第一品牌。