9月
20
2014
7

因为理想,所以改变世界

我记得很早以前,在我还是个学生的年代里,有人善意地提醒我们:「等你踏入社会,你要学会在这个世界生存的规则,并去遵守这个游戏规则。」而其实所谓的规则是什么?规则是有了人以后,人去定义的,它总是代表了一些东西,象征着一些制定规则的人所在意的东西。

于是我问道:「假如我明知道这个规则是错误的,我还要去遵守吗?」

「当然,这都是为了生存。」——一个「善意」的回答。

但我始终都没有办法去相信这一点,我所相信的是,人总是希望活在一个更好的世界,而这个集体意识的投影会引导世界朝着更美好的方向前进,所谓当下的那些丑恶的、灰色的、虽被人们唾弃但又不得不去适应甚至遵守的「规则」,只是一个短暂的剪影,历史的车轮总是在前进,时代的浪潮一旦向前掀起就无法被停滞,更不用说后退。

所以今天我们看到,很多过去我们以为这辈子都不会变化的事情,很多我们的长辈口中的「没办法,就是这样」的事情,在不知不觉中,从那坚不可摧的顽石里已经开始迸发出变革的萌芽。

摧毁顽石的力量,是科技不可阻挡的浪潮,是理想主义者坚持的信念。 (more…)

Written by Hesey Wang in: 思考 |
5月
25
2014
29

「我只是认真」——聊聊工匠情怀

老罗的Smartisan T1手机发布会很多人应该都看了,发布会的最后老罗凝视着自己的工匠自画像,半晌没说话,随后转过身,慢慢离开舞台,屏幕下方只留下一句话:

我不是为了输赢,我就是认真。

这一瞬间让我想起93年「狮城舌战」的主角蒋昌建,在「人性本善还是人性本恶」的总结陈词最后,以顾城的名句,「黑夜给了我黑色的眼睛,我却用它寻找光明」,把整个辩论赛的氛围推向高潮。

而老罗的这句话,和这句话背后的工匠背景,却以另外一种无声的却震人心魄的力量,敲打着每一个在场的,或是观看着整个发布会的观众的心绪。

「工匠情怀」,我深有体会,就像我在 面向GC的Java编程 一文中所提到的:

优秀程序员的价值,不在于其所掌握的几招屠龙之术,而是在细节中见真著。

如果我们可以一次把事情做对,并且做好,在允许的范围内尽可能追求卓越,为什么不去做呢?

追求卓越,追求完美,追求细节的极致。小时候看到那些修表匠,握着一个小螺丝刀,或是看着电工,用烙铁沾着锡和松香,在那一小寸的世界里,把坏了的地方修好,那种专注的眼神,觉得很厉害。

现在再去回想那些工匠工作的场景,越发觉得钦佩。在我老家有一家刻章的店,在我上幼儿园的时候就已经在那开了很多年了。前段时间需要刻一个章,发现那家店还在,于是走进去,门口坐着一个老人,我确实记不得当年是不是他,不过看这岁数八九不离十。我以前在别的地方刻的章,都是在电脑里设计完图案后,激光刻蚀。但那次老人却是用的手刻,我着实惊呆了。只看他拿出一块红色的印底,右手持着刻刀,开始一下一下地刻着。虽然老人连话都不怎么说得清了,但是工作时那专注的神情,和精湛的手艺,以及最后成品那比机器更完美的效果,着实让我心里非常动容。 (more…)

Written by Hesey Wang in: 思考 |
5月
12
2014
1

Swap对响应时间敏感应用的影响

最近排查的一个线上应用load高的问题,和GC以及Swap有关系。

现象是机器load突然升高,查看占用CPU的线程发现是JVM自己的线程。

jstat发现一个奇怪的现象,Eden Gen到了100%之后会持续好几秒,但Old Gen没有明显增大,说明并不是Eden Gen不够用promote到Old Gen了,感觉似乎是Young GC出了问题。

进一步查看GC Log,发现一次Young GC要1秒多,正常情况下20~30ms都应该结束了。

然而仔细去看那条log会发现CPU消耗并不高:

[Times: user=0.23 sys=0.00, real=1.31 secs]

多出来的时间如果不在CPU上,那就是耗在了I/O上了,GC的I/O不会在网络上,只能是磁盘了。

free -m看了下,果然Swap的空间快被用满了都。

在排查到最终的内存原因前,先把Swap关掉:

sudo swapoff -a

对于Web应用等对响应时间(rt)非常敏感的系统来说,关闭Swap通常都是一个好的实践。

因为一般来说宁愿应用OOM挂掉也不愿意导致rt飙高,使得应用hang在那里的。

另外建议开启这两个参数:

-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=path

帮助你在发生OOM时dump heap,一般这时候的heap dump质量都比较高:)

Written by Hesey Wang in: Java,Linux,技术 |
5月
06
2014
13

面向GC的Java编程

Java程序员在编码过程中通常不需要考虑内存问题,JVM经过高度优化的GC机制大部分情况下都能够很好地处理堆(Heap)的清理问题。以至于许多Java程序员认为,我只需要关心何时创建对象,而回收对象,就交给GC来做吧!甚至有人说,如果在编程过程中频繁考虑内存问题,是一种退化,这些事情应该交给编译器,交给虚拟机来解决。

这话其实也没有太大问题,的确,大部分场景下关心内存、GC的问题,显得有点“杞人忧天”了,高老爷说过:

过早优化是万恶之源。

但另一方面,什么才是“过早优化”?

If we could do things right for the first time, why not?

事实上JVM的内存模型( JMM )理应是Java程序员的基础知识,处理过几次JVM线上内存问题之后就会很明显感受到,很多系统问题,都是内存问题。

对JVM内存结构感兴趣的同学可以看下 浅析Java虚拟机结构与机制 这篇文章,本文就不再赘述了,本文也并不关注具体的GC算法,相关的文章汗牛充栋,随时可查。

另外,不要指望GC优化的这些技巧,可以对应用性能有成倍的提高,特别是对I/O密集型的应用,或是实际落在YoungGC上的优化,可能效果只是帮你减少那么一点YoungGC的频率。

但我认为,优秀程序员的价值,不在于其所掌握的几招屠龙之术,而是在细节中见真著,就像前面说的,如果我们可以一次把事情做对,并且做好,在允许的范围内尽可能追求卓越,为什么不去做呢(more…)

Written by Hesey Wang in: Java,技术 |
11月
26
2013
6

一次CMS GC的调优工作

某台机器的内存比较大,之前的JVM参数是4G的堆,在压测过程中发现当QPS上来以后,Full GC会开始抬头,YoungGC的频率就不用说了,比较高。

观察GC日志和jstat -gcutil,感觉是QPS在峰值的时候对象创建比较多,也有大对象产生。于是打算加大堆的大小来延缓GC的时机,并且有一些GC参数的优化,反复调整后找到了一个适合我们的参数(没有一个best的参数,还是得按照应用的的情况去测量,最好是一遍压测一遍调整,最终找到一个best fit的参数组)。

在把堆调大的过程中比较担心下面几个问题:

1、GC的压力会不会增大?

2、一次GC的耗时会不会增加?

3、如果在GC stop-the-world的时间里,rt飙高怎么办? (more…)

Written by Hesey Wang in: Java,技术 |
11月
18
2013
10

消除Java应用中的Exception开销

抛异常最大的消耗在于构造整个异常栈的过程,如果你的栈很深,特别是用了一些框架的话,这个开销基本是不可忽视的,之前做的一个优化显示当时应用中的一个异常使得整个应用的性能下降至少30%。 (more…)

Written by Hesey Wang in: Java,技术 |
11月
16
2013
2

如何真实压测一个Web浏览型应用的性能

对于应用压测大家应该都有一些自己的方式,通常都是构造一些请求,不过构造请求学问就大了。

构造什么样的请求?构造的请求是否真实?构造的请求各种业务场景的配比?读写比例?

对于一个Web浏览型应用来说,相比对纯DB的压测,会更复杂一些,主要因为涉及缓存。 (more…)

Written by Hesey Wang in: 分布式,技术,架构 |
9月
03
2013
2

Java应用线上问题排查的常用工具和方法

在长期排查线上问题的过程中,总结了一些工具的用法和排查问题的思路,这里跟大家分享一下,在遇到类似的问题时,希望能给予一些帮助。 (more…)

Written by Hesey Wang in: Java,Linux,技术 |
4月
13
2013
3

支持生产阻塞的线程池

在各种并发编程模型中,生产者-消费者模式大概是最常用的了。在实际工作中,对于生产消费的速度,通常需要做一下权衡。通常来说,生产任务的速度要大于消费的速度。一个细节问题是,队列长度,以及如何匹配生产和消费的速度。 (more…)

Written by Hesey Wang in: Java,并发,技术 |
4月
05
2013
3

何时对null值做Cache

前几天发现某个系统对某个远程调用接口的调用量大幅上升,涨幅不可思议。根据接口调用上升的时间点和发布记录,查看SVN提交记录,发现是在系统主路径中添加了这个接口的调用,难道这个接口没有做Cache吗?仔细一看,倒是也做了Cache,并且这个RPC对应的DB表的数据量非常小,按理说是能全部被缓存起来的。那么为什么会反复调用,看起来仿佛没有Cache一样呢?

直觉是缓存被不存在的数据击穿了,马上验证。

通过对系统方法的追踪,发现每次调用传入的参数都是0,再去DB里面查,0对应的结果确实为空。

所以这是一个典型的因为空记录导致的缓存被击穿的案例。

解决方法很简单,对不存在的记录做一个null的Cache,下次就不会落到远端了。不过这里结合业务的特定场景,我只是加了一个判断,当值大于0才会去查询,这样连一次查询Cache的开销也省掉了。

这个简单的问题可以衍生出一些思考。 (more…)

Written by Hesey Wang in: Java,分布式,技术 |

©2006 - 2016 Hesey (舒)