工作以来,第三次出现内存溢出,第一次是ThreadLocal没有remove造成的问题;第二次是ExecutorService没有正确的shutdown造成的问题;这一次的问题在我出手排查之前,已经知道了是permgen在不断的增长,在permgen中主要有Class和Meta信息,常量。
在开始阶段:排除了ThreadLocal可能导致的问题;排除了Thread可能导致的问题;后面就需要从新的突破点找问题了。
1:基本设置的排查
查找日志中访问量较大的请求的URL:
awk '{print $6}' service-digest.* |awk -F"," '{print $1 ",""1"}'|awk -F"," '{a[$1]+=$2;b[$1]++}END{for(n in a)print a[n] " " n }'|sort -n
查找日志中的调用很多的内容;依然没有发现问题;采用webbench一个个的调用请求来模拟操作,前十名的URL没有发现问题,后面的就没有查看了。
通过线下操作,发现也不是开始怀疑的RMI远程调用的问题;
针对CMS-GC,网上建议开通 -XX:+CMSClassUnloadingEnabled -XX:+CMSPermGenSweepingEnabled ,好吧,我们一开始就是开通的。参考:permgen-out-of-memory-reasons
2:内存使用情况
2.1:查看内存使用情况
jmap -heap pid
2.2:查看permsize的命令
jmap -heap `ps -ef | grep java | grep -v grep` | awk 'NR==44,NR==48'
2.3:触发full gc :
jmap -histo:live pid
2.4:不断的触发full GC 每10分钟观察一下内存的变化情况
PID=`ps -ef | grep java | grep uic | awk '{print $2}'`
for((i=1;i<10000;i++));do
jmap -histo:live ${PID} > /tmp/fullgc.log
jmap -heap ${PID} | awk "NR==42,NR==48" >> heap.log
echo $i
sleep 600
done
2.5:观察一段时间后(5个小时),分析相关的permsize的内存增长情况
awk '{if(NR%7==0) print $0}' heap.log
3:查看perm中的情况
jmap -permstat pid
查询的结果类似一下情况:
0x00000000ce58bb18 1 3200 0x00000000cc02c030 dead sun/reflect/DelegatingClassLoader@0x00000000f4067700
0x00000000cec33d48 1 3088 0x00000000cc02c030 dead sun/reflect/DelegatingClassLoader@0x00000000f4067700
0x00000000ce39c8b0 1 1944 0x00000000cc02c030 dead sun/reflect/DelegatingClassLoader@0x00000000f4067700
0x00000000ce8ab270 1 3104 null dead sun/reflect/DelegatingClassLoader@0x00000000f4067700
0x00000000ceb1d108 1 3104 0x00000000cc02c030 dead sun/reflect/DelegatingClassLoader@0x00000000f4067700
total = 1600 11325 60491768 N/A alive=1, dead=1599 N/A
不是反射的问题。(dead sun/reflect/DelegatingClassLoader)
4:查看JDK的相关垃圾回收情况
我们使用了CMS GC,过程中发现的GC日志看不出任何问题。
PS:未来我们找个时间专门讨论一下CMS GC的过程,方便我们在未来的垃圾处理过程中找到更加合理的方法去处理问题。
5:查看perm中的类加载情况
在启动的脚本中打开-verbose:class来查看运行的过程中到底多少个类被加载了。【verbose和verbose:class意义相同, 还有-verbose:gc, -verbose:jni】
JAVA_OPTS="${JAVA_OPTS} -verbose:class"
启动脚本中把输出内容从 /dev/null 2>&1 & 修改为 >${PWD}/jvm.log
我们通过jvm的日志发现如下奇怪的日志:
[Loaded com.hqb360.uic.dao.point.entity.[bxnxs]PointDetail$$BulkBeanByCGLIB$$5a972456_249 from file:/opt/jetty/work/jetty-0.0.0.0-8080-uic.war-_uic-any-/webapp/WEB-INF/lib/cglib-2.2.2.jar]
[Loaded com.hqb360.uic.dao.point.entity.[bxnxs]PointDetail$$BulkBeanByCGLIB$$5a972456_250 from file:/opt/jetty/work/jetty-0.0.0.0-8080-uic.war-_uic-any-/webapp/WEB-INF/lib/cglib-2.2.2.jar]
[Loaded com.hqb360.uic.dao.point.entity.[bxnxs]PointDetail$$BulkBeanByCGLIB$$5a972456_251 from file:/opt/jetty/work/jetty-0.0.0.0-8080-uic.war-_uic-any-/webapp/WEB-INF/lib/cglib-2.2.2.jar]
[Loaded com.hqb360.uic.dao.point.entity.[bxnxs]PointDetail$$BulkBeanByCGLIB$$5a972456_252 from file:/opt/jetty/work/jetty-0.0.0.0-8080-uic.war-_uic-any-/webapp/WEB-INF/lib/cglib-2.2.2.jar]
[Loaded com.hqb360.uic.dao.point.entity.[bxnxs]PointDetail$$BulkBeanByCGLIB$$5a972456_253 from file:/opt/jetty/work/jetty-0.0.0.0-8080-uic.war-_uic-any-/webapp/WEB-INF/lib/cglib-2.2.2.jar]
[Loaded com.hqb360.uic.dao.point.entity.[bxnxs]PointDetail$$BulkBeanByCGLIB$$5a972456_254 from file:/opt/jetty/work/jetty-0.0.0.0-8080-uic.war-_uic-any-/webapp/WEB-INF/lib/cglib-2.2.2.jar]
[Loaded com.hqb360.uic.dao.point.entity.[bxnxs]PointDetail$$BulkBeanByCGLIB$$5a972456_255 from file:/opt/jetty/work/jetty-0.0.0.0-8080-uic.war-_uic-any-/webapp/WEB-INF/lib/cglib-2.2.2.jar]
uic.dao.point.entity.[bxnxs]PointDetail的类一直在perm中增加,每次都在复制,没有重用,也没有被垃圾回收。问题基本就定位到这个地方。
6:找出问题的具体原因
6.1:去掉类中的反射,发现问题没有解决。空欢喜了一场!!!!
6.2:反复的测试调用的页面,发现在插入操作的过程中,会出现步骤5中perm class日志的情况。针对
INSERT INTO [bxnxs]_point_detail (
<isNotEmpty property="id">
id,
</isNotEmpty>
……
gmt_created,
gmt_modified
)
VALUES (
<isNotEmpty property="id">
#id#,
</isNotEmpty>
……
now(),
now()
)
这样的情况,我们修改为:
INSERT INTO [bxnxs]_point_detail (
id,
……
gmt_created,
gmt_modified
)
VALUES (
#id#,
……
now(),
now()
)
后续测试一下,发现问题解决,permgen不再持续增长;当某个内容写操作比较多的时候,直接导致permgen里面有大量的类消息,从而导致了内存溢出。
待处理:我们将下次讨论为什么不能在insert的时候使用isNotEmpty的问题。
2014-04-09 | 团队的标签
在卓望的入职培训,HR给我们培训说公司的企业文化就是老板的文化。其实我工作的前几年都是质疑这句话的。后来到了阿里巴巴工作,对比了一下,发现的确如此。对照一下各大公司的企业文化,其实就是创始人的文化。某人给我说:你带的团队最终都会和你一样。当我去实践的过程中,无论是有意识还是无意识的感觉,真是逐步会如此。有一句古话说:“上若好之,下必甚焉”或许也是在表达这个意思。
去年在团队中推行“服务意识”,其实是给团队打标签的过程,让产品经理和程序员能够走出去发现问题并解决问题,提高大家的主动性。当走近我们的用户并真正体会他们的感受的时候,团队成员也发现自己需要提升的能力,例如:产品可用性,沟通,反馈,驱动落地等,大家在这个过程中得到了锻炼的同时为企业创造了更多的价值。
我也发现在自己在推行“服务意识”过程中发现的问题,虽然我反复强调,当时依然有人有不一样的回答,比例超过了我的预期。仅仅的强调一个东西是没有用的,需要有监督和探讨对这个内容的理解,否则大家可能对这个问题的理解和行动都可能流于形式。而形式主义是管理的大问题!所以要想出反对形式主义的方式方法来协助更好的推行团队文化的建设。
团队文化给人展现的效果是一样的,当你问不同的人,他们说出来的意思大致是一样的。而我们遇到的问题是:团队内部对团队文化的理解和说法都是不一致的。有三分之一的人知道,有三分之一的人分析不清楚,有三分之一的人不知道团队文化什么。
如何解决这个问题?团队多数成员对团队文化不关心的情况下就需要自上而下的反复强调,探讨,总结该如何针对团队文化开展行动。只有反反复复的去强调,大家才可能对某个东西有一定的感觉,然后形成团队的惯性。一旦惯性形成,团队就不需要去再刻意的强调,做事就会有指导思想。开展探讨和总结的目的是更好的监督大家对团队文化的理解,大家相互学习在团队文化方面的具体行动加深印象,后续能够更好的去影响他人,影响新人。
支援业务发展的工作,能够打造骑兵精神是团队的长期实践的沉淀,需要围绕某个中心来开展团队的建设工作和沟通工作就会逐步形成团队的文化。文化是一种惯性,有了这个惯性,大家开展工作就会更加容易。文化的沉淀需要大家共同努力,管理者在这个过程中需要起到模范带头作用,只有自己做到并从内心接受了这个一致性的文化沉淀,团队才容易在一个方向上前进。从某种程度上,企业文化或者团队文化降低了管理成本,提高了工作效率。
文化的总结是需要根据发展不断的变化的,在开始阶段提出来的内容可能在发展的过程中并不能真的让整个团队适应,在合适的条件下,应该做整合,减法,逐步形成固有的风格。如果你整天在会议中不断的强调一些固有的东西以示重视,我相信团队成员才会逐步重视起来,只有自己不断的实践,团队成员才可能不断的实践。
你是什么样子,你的团队就是什么样子!当自己不知道该怎么办的时候,借鉴和微创新可能是很好的出路,^_^
底线是告诉你不要怎么样,是一种约束;团队文化是一种集体品质,是鼓励。做了不该做的要处罚(我主张越过底线直接开除),做了鼓励去做的事情要奖励。界定清晰,做事就好办了!
作坊式的开发的重点是围绕业务开展工作,系统开发出来之后,优化的工作一般都是针对用户端,出现问题一段时间后,有用户反馈才能够发现系统中的业务问题,而有些业务问题其实看看错误日志就可以解决。开发在没有日志反馈的开发环境中,发现问题是被动的。运维人员在这个过程中,也只能被开发驱动去被动解决问题,可能这个问题只是linux配置的问题。为何运维不能及时发现问题通知开发做出相关的调整呢?
为了更好的反馈问题,我们需要对现有的系统监控做好的同时,做好日志监控。界面化的发布系统目的是降低手动操作错误。

1:硬件监控系统和业务监控
监控分为系统监控(Nagios),网络监控(Cacti)和业务监控(自主开发)。当系统磁盘满了,I/O的过于频繁,CPU使用率过高,我们通过Nagios的监控给运维人员发送短信提醒来迅速的定位并解决问题。Cacti很好的帮助我们查看系统之间的访问流量情况。
由于我们的系统上有2个集群,以前系统出问题老是不能确认是哪个集群出了问题,需要手动切换hosts来发现问题,然后做切换。为了解决这个问题,我们把所有的服务的健康状况通过http访问的方式列到一个界面,很直观的展示了线上服务的可用性,方便我们在某集群故障的时候做切换。
本来以为业务监控做起来比较复杂,后来砍掉相关复杂需求,只要求监控状况的时候,一周开发就搞定了。界面中发现有红色的圈的时候,代表该系统不可用。简单的不能再简单,好用的不能再好用!
2:日志系统
2.1:系统错误日志的整理
错误日志的监控使用了sentry,当系统有错误日志的时候,写一份到sentry方便我们分析查看,把各模块的错误日志的解决落实到人,能够快速的定位线上系统的代码bug。错误日志的记录包括:Java系统错误日志,PHP系统错误日志,Nginx错误日志。
这种错误日志的监控不是实时的,根据系统统计的结果,在2天之内能够解决问题即可。有时候会发现严重的问题,需要及时处理。
2.2:代码执行的慢日志
代码执行效率低的查询问题,我们系统本来是记录相关的代码执行时间,借用的是taobao的profile,以前我们都是手动去查看哪些慢日志,为了更加的高效,我就找同事写了个脚本来分析一下这方面的代码执行率低的记录,然后通过界面集成到运维系统中去。
一期项目执行配合的流程是这样的:研发提供相关的脚本→运维负责用django开发后端→前端人员负责美化界面→研发人员测试。在写的过程中没有什么难度,都是很顺畅的利用了现有的资源,把一个手动的需求整合到界面中去了而已。这样做的目的是提高团队的开发效率,更快的反馈性能问题。
性能的优化是个长期的过程。
2.3:DB的慢日志
DB的慢日志,通过脚本来读取相关的mysql的慢日志,由运维开发人员集成到运维平台上去。DB的慢日志可以找到我们数据库设计和代码联合查询的问题,对我们优化DB起到合理的反馈作用。
2.4:Nginx的503错误预警
通过sentry来查看日志并不能及时的发现Nginx的503错误,在系统503错误出现的5秒内,我们需要有一个预警机制来处理后端系统宕机的情况,开始阶段通过脚本来处理,后续考虑使用Logstash来配合分析解决问题。
3:界面化的发布系统
部署系统分为2个部分,一个是PHP的部署,以前手动的敲命令,部署时间比较长,出错的机率大,回滚起来不方便,为了解决这个问题,我们分析了整个部署流程,通过界面化的操作来执行发布,大大的提高了效率,降低了出错的情况。在整个开发的过程中,我们只是把手动的工作脚本化和界面化了而已。
Java的部署采用的Jenkins来完成,又快捷又好用,点一点鼠标,很多事情都通过脚本来搞定了。脚本使用了rsync来Linux hosts之间文件传输。持续集成方面的探索对运维工作效率的提升大有好处,大家不妨去抽空好好的研究一下。
4:配置管理系统
目前运维工作中,还缺少一个统一配置管理的工具,我们考虑用zookeeper来解决这个问题。只是配置方面现在已经很少变动了,整个系统还没有到达必须没有配置服务就经常出错的程度,所以还没有动力去做。目前还没有找到一个可以动手开始的配置项目,为了让系统足够的轻,我们暂时选择配置手动。
在所有的系统运维的工作中,告警机制需要不断的优化,短信,邮件,或者接通其他接口的通知需要及时通知可以处理问题的工作人员,做到监控的实时性。告警的机制需要倾向硬件系统监控和业务监控。
给同僚分享一下其他企业的企业文化,特别牛逼的企业(例如:苹果)没有说,因为大家都知道,但是又什么都不知道,容易争论太多。谈了一下IBM,Microsoft,Intel等IT公司,算是聊天式的谈谈而已。这个话题本来应该是HR谈论的内容,我看完关于Amzon的 《一网打尽》 这本书后捷足先登一步,因为Amazon的企业文化有一部分是来自于沃尔玛。于是起了一个分享的名字《他山之石可以攻玉》。
问题的关键不是分享的内容,而是事后几个人和我说:“你讲的这些词我都知道”,这就遇到了我做技术的时候碰到的同样的问题,你说的知识点我都知道,但是我就是不能解决我们系统问题。碰到这样的情况,一般我都是想骂人,用一句话形容:“送你浅尝辄止四个字都是褒奖你了!”。装逼的先说一下技术,Thread这个东西大家都知道吧,并发编程方面不好好的研究个半年,我就不信你能不搞出内存泄露的问题。“台上十分钟,台下十年功”,没有一些基础方面的锻炼,你顶多就是会一些名字而已。
关于“客服第一”这个话题,是不是大家都知道。遇到问题的时候,你们的态度怎么样?这不是我们部门管辖的范围;可能你需要找研发处理一下;哦,这个小问题我们过几天就解决了;客户真的太刁蛮了……好吧,外面的用户实在不是你的菜,对内需要做好服务的同仁们,不管是我现在呆的企业还是以前呆的企业,多少人真的存在服务意识其实都是个问号。大公司可能围绕KPI展开工作,小公司可能重人情,所以能够服务好用户就所剩无几了。直到去年最后一个季度,我才发现,“客服第一“是可以要求的,是任何人(至少研发团队是)都可以做到的,而且我发现大家觉得能够服务好他人是一件开心的事情,这简直就是我工作这多年来捞到的宝贝之一。
还有就是CEO反复重复的稻盛和夫的那句“敬天爱人”,关于“爱人”这一块大家应该都知道是关爱人,这个名词算是很好理解了,我一说可能不是傻子的人都懂了。今天也讲到好几个企业做到了“以人为本”,问题的关键是,你有没有把学习到的这些东西落实到行动中,在工作中,多少次把团队成员的利益放到自己利益的前面?所以,知道这个词对工作毫无指导意义,还真的不如不知道,图个心安理得岂不更好?
我是一个非常痛恨官僚主义的人,所以,自己算是以身作则,和大家站到一个线上去奋斗,努力的给大家提供一个公平的环境。好吧,看过很多文章谈论IT公司的文化,这个也算是多有接触吧?行动在什么地方?知道名词有个鸟用,转化为行动才是工作的重点,把行动转发为生产力。
“协作,执行” 这2个词大家都懂吧! 2013年,导师和我说:“你不用对结果负责,所以没有必要在过程中旗帜鲜明的反对,何不支持一下静观其变呢?”。我仔细思量了一番发现,其实自己根本就没有能力为大方向的结果负责,何不去主动配合一下同僚或者是CEO的工作呢?后来我学会了主动合作,这个品质让我感觉自己的工作的阻力越来越小,想推动一些事情的时候反而更加容易的落地。多给别人一些建议,多多的鼓励一下同事们,多美好的事情啊!
把从别人那个地方学习到的东西落地成为一种团队惯性,这种本事其实是可以学习的,我不反复的强调也不推广是因为这类东西只能给有缘人传授。想学习真本事的人,我不用反复灌输,也会请教我,也会和我探讨,也会很好的落实学习到的内容。我做的事情大家都可以拿走据为己有,因为只要有问题存在,我就有各种机会。
我们都面对同样的问题:“知易行难”。所有方式方法来源于做事的心态,我当前的心态只能阐述到这种水平,欢迎大家吐槽!!!
最近制定锻炼身体的计划。然后我一直在考虑如何让我的计划可以接地气,能够让自己更好的执行。在twitter上看到 [@bluedavy](http://twitter.com/bluedavy) 的微博,探讨一些taobao技术上的规划的问题,最后一句“关键是有落地的本事吗”才是关键。 做计划,去执行,或者说去不断调整的执行,达到预期效果。个人的目标的执行和团队的目标的执行方式方法可能有所差别,但是对实施者的品质要求是大同小异的。
有一次部门活动,团队中有人提议在山泉的旁边切西瓜吃,让大家好好的感受一下自然。我问第一个人:“你能保证所有人西瓜皮都不会扔在水中么?如果能保证的话,我就切”,他的回答是否定的,因为本身而言,这个协助的后果不愿意承担,而有人愿意站出来协作的,都是愿意承担责任的人。后来西瓜是在山泉边分享的,而没有西瓜皮扔在水中。有人根本不愿意一起承担,所以,他不会推广自己的想法。更多的时候,他们想到的是:“就这样吧!”
就这样吧!这是一个想法遇到阻力的时候的转移负担。让别人去解决吧,我只想坐享其成,或者如果别人解决的不好,我笑一笑,然后装逼的说:“这个问题我早就看到了,所以我没有推广!”。这样的人,不配在企业中当一个成功者,也不配当一个失败者。
“一些新的方法或者是系统确实能够改进我们的成绩,也得到了大家的认可和满意,当时方法或系统的推广却从来没有发生。”,这几乎是很多团队的通病,大家觉得这样干是对的,觉得能够这样执行是有能力的表现,但是没有意志力去推动自己的方式方法或者系统。这个问题类似于“好酒也怕巷子深”的问题,推广和营销自己需要有良好的沟通,而技术人员多半都是自己想办法写更好的代码或者更加牛逼的功能去了,所以不少好东西也只能内部用一下而已。不少程序界知名的人士不是宣扬了他们的框架,而是宣扬了他们的理论,而这些理论能够更好的指导开发。让其他人或者是团队认可自己的方式方法或者是框架系统,需要有类似的推广行动。面对一些认知到方式方法或者系统优秀的人,我认为能力或眼光是有的,没有去尝试推广,是意志力的问题。
不能不说的是,推广的阻力主要来自于内部。所以,敌人不是来自“外部的”,明显的阻力是你的同事或者合作者。Amazon的云计算其实一开始在公司内部并没有得到认同,当这帮聪明人把系统开放给外部人用,然后赢得口碑的时候,内部才开始用起来。阿里云的虚拟机业务存在同样的问题,淘宝的聚石塔项目是阿里云的虚拟机项目赢得外部口碑的时候,内部的合作才能够顺利推行起来。
团队内部的沟通的顺畅才能够让项目真正的落地。
然后面临的一个问题是:我为什么要协助你?第一个接受方式方法或者系统的人,是存在较大风险的,必然存在各种需要完善的点,需要不断改进来逐步解决现有问题,一开始让人看到的负反馈甚至多于真反馈,合作者会沮丧,失望,有些状况甚至出现抵制状态。这个时候考验的是推广者的意志和决心了,如果坚持不懈的去改进问题,可能就很快扭转了局面。其实很多实践者都能够解决这个问题,因为大多数人第一步的勇气都没有,也没有后续所谓的需要落地一些想法了。
走出第一步的人,有不少人抱着KPI的思想去做事,所以不少项目会只有一期,做完之后修改一下bug就完事了。然后拿出一些数据就去邀功了。缺少持续的改进,是一个系统硬伤,除非你觉得这个项目是一个试错性项目,觉得不符合目标就直接砍掉。“一流的想法,二流的执行,三流的推广”,后果就是可想而知的。对于完成KPI的项目,也就是分地盘了,本身这可能不是解决工作中的问题,或者好听一点,拓展业务。这些事情需要有,拓展公司空间本身也是工作的一部分,这些内容是别人想法的支持而已。如果是想法的提出者实施,大有搞头,如果是上头的任务,我只能表示大家对未来的期待需要放低要求了。
如果不是KPI的问题,是工作中实际存在的问题或者是需求。事情成功的机率就可以大大的提升,因为,不管怎么样,问题都在那里,大家都看得到。落地的本事来源于能力和意志力的结合,能力是说明自己能够接手解决这个问题,意志力是帮助自己在困难面前坚定不移或者是在困难面前想方法。
主动解决问题的人是永远的赢家!!!
日志分析相关的操作,小公司没有实例去开发,当让程序员到线上不断关注日志又太依赖于人,很多问题不能很好的统计,不能反馈核心问题。没有错误日志的反馈,在关键路径的操作上,研发存在不少的盲点,遇到问题只有用户反馈的时候才去被动的修改,这不利于系统的演进。所以我们需要一个日志收集的系统。
Sentry 是一个实时的事件日志和聚合平台,基于 Django 构建。Sentry 可以帮助你将 Python 程序的所有 exception 自动记录下来,然后在一个好用的 UI 上呈现和搜索。处理 exception 是每个程序的必要部分,所以 Sentry 也几乎可以说是所有项目的必备组件。
1:安装sentry
安装sentry最开始没有在virtualenv下面,直接安装在自己的开发配置中,发现django是1.6和sentry6.1.2的版本是不兼容的,各种问题不断出现,“Internal Server Error” 的错误这样的情况下基本无解了,然后配置了N久的日志,打印不出来错误日志。各种纠结,折腾之后,还是不想卸载django1.6(因为有相关开发的内容是基于1.6的),只能在virtualenv环境安装sentry了。
1.1:安装virtualenv:
easy_install -UZ virtualenv
1.2:选择一个本地环境,执行virtualenv命令
virtualenv /opt/sentry/
1.3:激活你的virtualenv:
source /opt/sentry/bin/activate
1.4:安装sentry
easy_install -UZ sentry
注意:安装的过程中,遇到pytz这个包,安装流程会卡在这个地方。我是从pypi.python.org/pypi/pytz/2013b下周的文件,然后通过easy_install pytz_*.egg来安装这个包。在安装的过程中,网络一直timeout,需要不断的执行安装命令,后续会自动安装完毕。
1.5:安装sentry-mysql
easy_install -UZ sentry[mysql]
当然,其他数据库也可以根据配置选择安装,本人直接安装的MySQL-python就可以直接启动了,^_^
1.6:配置sentry.conf.py
--后面的路径配置过程中不是必须的,如果没有路径,将在用户的home的.sentry这个目录中生成sentry.conf.py
sentry init /etc/sentry.conf.py
生成完毕之后,注意到sentry.conf.py中去更改相关的DB配置,mysql的配置是:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'sentry',
#'NAME': os.path.join(CONF_ROOT, 'sentry.db'),
'USER': 'root',
'PASSWORD': '',
'HOST': 'localhost',
'PORT': '3306',
}
}
2:Sentry的相关操作
2.1:启动服务
sentry --config=/etc/sentry.conf.py start
如果你用的是默认目录,则可以直接用sentry start来启动;
启动过程中如果报错,注意在sentry.conf.py中加入:
ALLOWED_HOSTS=['*']
一些其他配置的问题可以到文档中去搜一下,地址:
https://sentry.readthedocs.org/en/latest/quickstart/index.html
2.2:添加用户:

sentry --config=/etc/sentry.conf.py createsuperuser
2.3:添加teams
到右边菜单中,添加不同的团队的分组;

2.4:添加工程

注意:每个团队下属的工程,各自添加,然后每个工程会有自己的API keys,拿着这个key配置不同模块的日志;
3:JAVA环境配置日志到sentry
3.1:pom文件的修改
各项目根目录下面的 pom.xml文件的依赖:
<!-- raven 依赖的maven服务器地址 -->
<repositories>
<repository>
<id>sonatype-nexus-snapshots</id>
<name>Sonatype Nexus Snapshots</name>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
<releases>
<enabled>false</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
dependencyManagement中添加raven的依赖
<dependency>
<groupId>net.kencochrane.raven</groupId>
<artifactId>raven</artifactId>
<version>4.0</version>
</dependency>
<dependency>
<groupId>net.kencochrane.raven</groupId>
<artifactId>raven-log4j</artifactId>
<version>4.0</version>
</dependency>
因为没有相关的应用,所以需要在跟pom.xml中添加dependencies来保证把raven的jar打到我们的发布包中;
<dependencies>
<dependency>
<groupId>net.kencochrane.raven</groupId>
<artifactId>raven</artifactId>
</dependency>
<dependency>
<groupId>net.kencochrane.raven</groupId>
<artifactId>raven-log4j</artifactId>
<exclusions>
<exclusion>
<artifactId>log4j</artifactId>
<groupId>log4j</groupId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
3.2:log4j的配置添加
注意:dsn就是工程的API Keys,每个工程的都不一样。
<appender name="SentryAppender" class="net.kencochrane.raven.log4j.SentryAppender">
<param name="dsn" value="http://e61a0d19d87743bd9e0b7499b720c2a5:df28df39628e4dd5a4986eecf4923851@192.168.100.11:9000/1" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d [%X{realRemoteIp}/%X{memberId} - %X{servletPathInfoWithQueryString}] %-5p %c{2} - %m%n" />
</layout>
</appender>
在相关的error日志配置中添加:
<appender-ref ref="SentryAppender" />
例如:
<logger name="com.okhqb.canvas" additivity="false">
<level value="INFO" />
<appender-ref ref="CANVAS-DEFAULT-APPENDER" />
<appender-ref ref="ERROR-APPENDER" />
<appender-ref ref="SentryAppender" />
</logger>
如果系统有错误日志产生,就会在sentry中看到相关的错误日志的分析结果了。
错误日志的展示结果:

4:nginx的配置
使用sentrylogs来监控nginx的日志,到https://github.com/mdgart/sentrylogs 去了解一下源码,通过 easy_install sentrylog就可以安装,然后设置sentry的dsn 启动的时候注意几个参数的指定。
- --sentrydsn SENTRYDSN, -s SENTRYDSN 指定dsn的路径
- --daemonize, -d 静默启动
- --nginxerrorpath NGINXERRORPATH, -n NGINXERRORPATH Nginx错误日志的目录
5:其他系统的配置
在project的setting中可以找到相关模块的不同语言的example,可以通过案例来配置不同的语言,其他语言后续会不断补充……