oh-my-zsh

https://github.com/robbyrussell/oh-my-zsh/wiki/Plugins-Overview

https://github.com/robbyrussell/oh-my-zsh/wiki/Themes

zsh才是王道啊,各种插件,很爽.

我用

1
colored-man colorize sublime mvn terminalapp
插件.theme用
1
avit
,再装上Solarized Dark,prefect!!!

Portia, the open source visual web scraper!

http://blog.scrapinghub.com/2014/04/01/announcing-portia/

https://github.com/scrapinghub/portia

可视化的网页抓取工具,多么牛掰啊.

java8,javadoc对格式要求更严格了.

http://docs.oracle.com/javase/8/docs/technotes/guides/javadoc/whatsnew-8.html

The javadoc tool now has support for checking the content of javadoc comments for issues that could lead to various problems, such as invalid HTML or accessibility issues, in the files that are generated by javadoc. The feature is enabled by default, and can also be controlled by the new -Xdoclint option. For more details, see the output from running “javadoc -X”. This feature is also available in javac, although it is not enabled by default there.

所以以前能成功生成文档的现在变为:

1
2
3
4
5
6
/Users/bohr/code/yjf/maven-plugin/target/generated-sources/plugin/com/yiji/maven/HelpMojo.java:26: warning: no description for @author
 	* @author
   	^
/Users/bohr/code/yjf/maven-plugin/target/generated-sources/plugin/com/yiji/maven/	HelpMojo.java:27: warning: no description for @version
 	* @version
 	  ^

修改maven doc插件如下,忽略异常先:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-javadoc-plugin</artifactId>
            <version>2.9.1</version>
            <configuration>
                <failOnError>false</failOnError>
            </configuration>
            <executions>
                <execution>
                    <id>attach-javadocs</id>
                    <goals>
                        <goal>jar</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>

##Performance Considerations in Distributed Applications

http://apmblog.compuware.com/2009/09/28/performance-considerations-in-distributed-applications/

一篇老文,主要谈到了分布式应用中一些性能关注点.文章部分内容加上自己总结如下:

###The devil in disguise

  1. 序列化

    序列化的重要性体现在,序列化本身需要消耗的cpu时间,而且序列化后的内容的大小也会影响传输时间.一般来说用二进制协议效率更高.soap协议最好还是不要在内部使用了:第一,序列化和反序列化效率不高(FI应该会快,没亲测);第二,里面无意义的信息太多了.

    除了性能,还要考虑易用性,也就是说序列化后数据的兼容性问题.这个处理不好就会引起非常严重的事故.so,我们现在的dubbo序列化选hessian,分布式缓存/消息中间件中用到序列化的地方用的是兼容性的kryo(带有字段信息).等以后性能问题凸显的时候,会考虑用dubbo自带的序列化或者kryo.在数据量较大的交互时,还需要考虑提供阀值压缩数据.

    虽然分布式服务框架一般会提供多版本功能,理论上是不要考虑兼容性的.每次升级接口时,升级版本就搞定.但是在服务器不是足够多的情况下,还是不考虑了,增加了运维成本.

  2. CONNECTIONS

    这个不多说,长连接+连接池.这里需要注意的是,长连接一定要有心跳机制来保活.

  3. 线程模型

    原文只是谈到了同步和异步处理,现在比较好的做法是有专门的io线程来io请求.不过最好不要在io线程上做序列化和反序列的操作.让io线程单纯点,io处理能力更强.

  4. 网络

    这点确实容易忽掉,而且很多开发人员对网络都不是很熟悉(include me!),万兆(40G?)交换机+千兆网卡应该是必须的吧.

The beauty of remoting technologies is …

这部分作者说了不少,我的观点是:java自带的序列化比较慢,最好不要用;distributed garbage collector 最好不要碰;内部系统不要玩

1
WS-*
;消息中间件是个好东东,一般企业到后期还是会需要到消息总线,不过神马都往总线里面丢,最终ESB implementor自己就是瓶颈,合理的规划业务很重要.

What can go wrong

  1. Anti Pattern: Wrong Protocol

    选择合适的协议,内部通信就不要用webservice了.涉及到互操性的场景,可以考虑hessian提供的二进制协议.

  2. Anti Pattern: Chatty Application

    总的来说就是,

    1
    分布式对象设计第一定律:不要分布式使用对象
    
    ,尽量减少远程调用+粗粒度的接口+读缓存.

  3. Anti Pattern: Big Messages

    接口不要携带多余的,不相关的信息.这条和上条需要仔细权衡了.

  4. Anti Pattern: Distributed Deployment

    还是分布式对象设计第一定律.

Don‘t Trust Your Log Files: How and Why to Monitor ALL Exceptions

http://apmblog.compuware.com/2014/04/01/dont-trust-your-log-files-how-and-why-to-monitor-all-exceptions/

异常开销比较大,所以,业务异常尽量不要去收集栈信息,还要去属性第三方api,减少异常被吞掉的情况.可以参考下这篇blog.

Heartbleed test

http://filippo.io/Heartbleed/

c语言没处理好是多么的恐怖啊.

tomcat关闭时出现NoClassDefFoundError

某dubbo应用,在tomcat在关闭时,报了下面的异常,

1
java.lang.NoClassDefFoundError: org/jboss/netty/util/internal/ExecutorUtil

so,顺便分析下tomcat容器关闭时的内存泄漏检测机制.

首先有个三个东东:

  1. 1
    org.apache.catalina.core.JreMemoryLeakPreventionListener
    

    普通的java程序的类加载顺序是由父到子(先在父classloader中找,找不到在到子classloader中加载),这样做是为了安全和节省内存.web容器类加载器为了做到隔离,一般先是在子classloader中找,找不到在委托给父classloader.

    此listener主要是通过使用java classloader或者tomcat 系统classloader来加载类,避免

    1
    WebappClassLoader
    
    加载类后reload释放不了,同时也避免了内存浪费.还对一些东东进行了调整.

    源代码中段话说的很形象:

    1
     Use the system classloader as the victim for all this ClassLoader pinning we're about to do.
    

  2. 1
    org.apache.catalina.loader.WebappClassLoader
    

    相关逻辑主要在

    1
    stop
    
    方法中:

    • 调用
      1
      org.apache.catalina.loader.JdbcLeakPrevention
      
      来deregister Driver
    • 找出所有应用线程,如果线程还在执行,则打印警告信息.如果启用了
      1
      clearReferencesStopThreads
      
      ,使用反射来关闭线程池或者线程.
    • 清理ThreadLocal
    • 清理各种cache…
    • 清理资源路径

    加载类步骤:

    1. 判断WebappClassLoader是否关闭,如果已关闭,报异常,打印日志
    2. 检查resourceEntries缓存
    3. 使用当前类加载器加载
    4. 使用SystemClassLoader加载
    5. 如果启用delegate,从父加载器加载
    6. 1
      WEB-INFO/classes
      
      1
      WEB-INFO/lib
      
      目录加载
    7. 用父类加载器来加载
    8. 加载不到抛出
      1
      ClassNotFoundException
      
  3. 1
    org.apache.catalina.core.ThreadLocalLeakPreventionListener
    

    清理线程池.

再分析下dubbo怎么关闭的:

  1. dubbo中的每个provide都是
    1
    ServiceBean
    
    对象,此对象实现
    1
    DisposableBean
    
    .在容器关闭时,
    1
    ServiceBean
    
    取消注册.
  2. 1
    com.alibaba.dubbo.config.AbstractConfig
    
    中注册了一个
    1
    ShutdownHook
    
    ,调用
    1
    ProtocolConfig.destroyAll()
    
    ,清理资源(比如关闭和注册中心的连接和关闭netty)

这里需要注意下,调用

1
org.apache.catalina.loader.WebappClassLoader#stop
和调用
1
ProtocolConfig.destroyAll()
的不是同一个线程.而且
1
org.apache.catalina.loader.WebappClassLoader#started
字段并不是
1
volatile
的,有可能出现并发状态下的的不一致.这个时候,
1
WebappClassLoader
已经
1
started=true
了,然而
1
ShutdownHook
线程读到的值为false,继续去加载类,由于各种缓存也清空了,最终会抛出
1
ClassNotFoundException
(参考加载步骤)

参考:

1
http://wiki.apache.org/tomcat/MemoryLeakProtection

实战 Groovy: 使用闭包、ExpandoMetaClass 和类别进行元编程

http://www.ibm.com/developerworks/cn/java/j-pg06239.html

1
println "ifconfig en0".execute().text
,这行代码使用fluent api+元编程,执行linux命令,打印结果.

这个特性对于测试同学来说就非常重要,就这么直接mock原类的行为,很方便.

Venkat Subramaniam 讨论多语言编程、JVM 和多核处理

这篇文章很精彩,看了这篇文章有学习scala和groovy的冲动.摘录一些原文比较精彩的内容:

1.关于多语言编程

Ola Bini 曾在他的语言金字塔中很好地阐述关于语言。在语言金字塔中,Scala 或 Java 可以非常有效地编写基础架构代码。在此基础之上,他谈到了一个更具动态性的分层。在这一层中,利用元编程功能。可以说,元编程带来的最大优势就是能够减少您需要编写的代码量。最直观的体验就是代码数量的减少,您可以在代码中编写非常灵活的内容。在此基础之上,金字塔的塔尖是更为特定于领域的语言层,即 DSL 层。

使用动态语言编程时,最重要的是设定更出色的准则,以便指导单元测试的编写,确保代码不会偏离原意,准确执行您希望的操作

2.关于多核并行:

一种方法是推行不可变性,也就是说:我不会更改任何东西。您处理的所有数据都是不可变,由于不可变,因此也不需 要同步。这解决了冲突问题,但我要如何在线程间通信?如何交换数据?为此,我们可以使用 Erlang 和 Scala 奉行的基于 Actor 的模型。使用 Actor,然后通过来回传递数据在 Actor 之间通信,但数据仍然保持不可变,整个过程极为安全。

软件事务处理内存模型所做的是将您的数据访问绑定到事务边界内,就像数据库为您提供 ACID(原子性、一致性、隔离和持久性)时一样。它为您提供了这种功能,但您无法在内存中实现数据持久性,因此它会处理原子性、一致性和隔离。 您可以通过三种方法处理并行性。在解决并行性时,最糟糕的方法就是共享的可变性,这就是同步模型。更好的方法是采用基于 Actor 的模型,在线程间传输不可变数据。如果存在不频繁的写入操作和极其频繁的读取操作,那么第三个选择就是事务软件内存。

Baby’s First Garbage Collector

http://journal.stuffwithstuff.com/2013/12/08/babys-first-garbage-collector/

https://github.com/munificent/mark-sweep/blob/master/main.c

用c实现的一个简单的gc,采用Marking and sweeping的方式,大致能明白gc如何工作了.

Volatile Vs Static in JAVA

http://malalanayake.wordpress.com/2013/09/12/volatile-vs-static-in-java/

volatile能保证原子性和可见性.对static field的内存模型认识不足导致有些概念模糊了.内存结构见图:

101 个 MySQL 的调优贴士

http://www.oschina.net/translate/101-tips-to-mysql-tuning-and-optimization?print

看数据库相关的文章看到”双缓存”“问题.数据库服务把OS cache打开会导致无意义的”预读取”(操作系统层面的随机或者顺序读取文件)和”后写入”(批处理),而且会导致”双缓冲”和昂贵的内存拷贝.”双缓冲”浪费了系统内存,并且浪费了额外的资源处理时间(读:从磁盘到os cache到DBMS cache;写:从DBMS cache 到OS cache 到磁盘).

搜索双缓存相关的东东,把这篇文章搜索出来了.有几点可以说说(数据库管理层面的I DONT CARE!).

1
2
3
4
74.为了 避免在更新前SELECT,使用INSERT ON DUPLICATE KEY或者INSERT IGNORE ,不要用UPDATE去实现。 (这深有体会,以前处于二逼阶段写的存储过程由17行变成了7行,简单依赖啊,减少了查询,减少了并发时的异常处理)
81.使用DROP TABLE,CREATE TABLE DELETE FROM从表中删除所有数据。 (为毛不用truncate?)
95. 为了更快的进行导入,在导入时临时禁用外键约束。 
96. 为了更快的进行导入,在导入时临时禁用唯一性检测。

zookeeper 分布式锁的实现

http://bohr.me/zookeeper-dev-ops/

给自己写的zookeeper相关的分析添加一个链接地址.

Spring Data Repositories - A Deep Dive

https://github.com/olivergierke/repositories-deepdive

http://spring.io/blog/2011/04/26/advanced-spring-data-jpa-specifications-and-querydsl/

最近在看jpa,spring对jpa的支持确实比较犀利.Querydsl结合APT可以写出类型安全,易读的查询语句.不知道性能如何?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Test
public void testQuerydsl() throws Exception {
	QTask $ = QTask.task;
	BooleanExpression titleStartWith = $.title.startsWith("Study");
	BooleanExpression descEndWith = $.description.endsWith("org/");
	
	Iterable<Task> result = taskDao.findAll(titleStartWith.and(descEndWith));
	for (Task task : result) {
		System.out.println(task);
	}
} 上面这段代码最后生成的sql如下:

select
    id,raw_add_time,raw_update_time,description,title,user_id 
from
    t_task  
where
    (title like ? escape '!') 
    and (description like ? escape '!')	

ROCA Resource-oriented Client Architecture

A collection of simple recommendations for decent Web application frontends. 可以参考下,

加盐密码哈希:如何正确使用

http://blog.jobbole.com/61872/

The Enemy Knows The System.看了这篇文章,感觉我们做的东西太少了,对于密码的重视程度还不够,简单总结下:

  1. 永远不要告诉用户到底是用户名错了,还是密码错了
  2. 不要使用短盐值和盐值重复(明白了某开源项目为什么用户表里有个salt字段)
  3. 盐值应该使用基于加密的伪随机数生成器来生成,java里面用
    1
    java.security.SecureRandom
    
  4. 使用慢哈希函数,java里面用
    1
    PBKDF2WithHmacSHA1
    
    (需要权衡,太慢了会把登录做成DDOS攻击)
  5. 不要使用过时的hash算法,比如MD5或SHA1
  6. 密码重置时令牌应该要有有效期,并且重置时需要生成新的盐值.
  7. 不要过于频繁地强制你的用户修改密码,最多6个月1次(呵呵,bops)

这些用上基本上就够了.附带赠送一个能够破解任何8位及以下长度MD5值的彩虹表

Java中的CopyOnWrite容器

http://coolshell.cn/articles/11175.html

以前只是把CopyOnWrite用于拦截器这些场景,看来用于黑/白名单也挺适合的.特别是

1
CopyOnWriteMap
,很适合读写比例很大的场景.

不过原文中提到的

1
内存占用问题
,我不赞同此问题,map本身的数据结构是Entry,这个Entry会上百M?
1
Arrays.copyOf
1
java.util.HashMap#HashMap(java.util.Map<? extends K,? extends V>)
都不是深拷贝.

5 Techniques to Improve Your Server Logging

http://www.takipiblog.com/2014/02/27/5-techniques-to-improve-your-server-logging/

文章提到5个处理服务器端日志的细节.值得分享下:

  1. Hello my (Thread) name is

    给线程取一个合理的名字.在开发云消息中间件时,考虑到便于跟踪业务执行轨迹,统一用msgid来作为线程的名字.

    现在想起来还是比较土,当时不知道有MDC这个概念(2012年看到这个概念还很兴奋).现在我写的系统中,基本上都引入了MDC这个东东,方便自己定位问题.

  2. Distributed identifiers

    每个业务请求需要一个唯一的业务标识.这个必须有,写了

    1
    ID
    
    就是来干这事的.我很赞同作者的观点,
    1
     every inbound operation going into your system should have a unique ID which will travel with it until it’s completed. 
    
    ,我们的gid改造还没有结束,哈哈.

  3. Dont text + drive. Don’t log + loop

    在循环里面处理日志要小心,作者举的例子是加了一个打印日志次数的限制.在

    1
    while
    
    循环里处理东东都要小心,最近给某项目分析定时任务没有执行的问题,发现循环中插入数据库,结果悲剧了,死循环一直插,数据库表示好伤啊.

  4. Uncaught handlers

    给线程加上未捕获的异常处理器.

    在和peigen讨论摘要日志时,提到了要加这个东东,结果真的给忘了.哎,真的老了么?忘事太容易了.真得注意下防御性编程了.openapi使用摘要日志api有问题,导致空指针异常,我在代码中加了一行error日志

    1
    由于api使用不当导致线程本地变量DL被清空,请仔细检查您的代码.本次操作会重新生成DL对象
    
    .但是还有个洞没有塞住.万一使用
    1
    SDL
    
    时,没有在
    1
    final block
    
    中调用
    1
    SDL.end()
    
    ,最终会导致OOM.在
    1
    Thread.setDefaultUncaughtExceptionHandler
    
    时,来清除
    1
    SDL
    
    ,也算是一个不错的方式.

    摘要日志API的设计过程中主要想着能给大家提供方便使用的api.现在易用性已经达到了,但是感觉用得不当太危险了.特别是

    1
    SDL
    
    ,
    1
    ThreadLocal
    
    中有个
    1
    ArrayDeque
    
    ,万一没有调用
    1
    SDL.end()
    
    ,迟早会有OOM.

    线程变量真可怕!!!

  5. Catch external calls

    外部调用都要catch异常并记录日志.最好也别把异常吞了,重新抛出一个程序内部定义的运行时异常吧.分布式应用外部调用都很多,建议还是统一来处理日志和异常转换,AOP派上用场了.

评论更精彩,有童鞋建议外部调用记录处理时长,用csv来记录日志便于后期处理.摘要日志中有记录时长的,我们用的json来记录日志,更方便处理,只是业务线程需要承担序列化的开销.

The Logging Olympics – A Race Between Today’s Top 5 Java Logging Frameworks

http://www.takipiblog.com/2013/12/18/the-logging-olympics-a-race-between-todays-top-5-logging-frameworks/

比较了几种日志框架,以前在写日志优化时,注意到了log4j2异常牛掰,特别是采用了disruptor的异步日志,在多线程下的表现非常夸张.不过我们已经被绑架到logback了,只是看看而已.

First-class functions in Java 8

http://www.youtube.com/watch?v=Rd-sqHjmfB0

这动画做的挺有意思,只是Java8还离我们比较远啊.

HTTP/1.1 Upgrade header

http://en.wikipedia.org/wiki/HTTP/1.1_Upgrade_header

通过http upgrade header来实现协议转换,比如把http协议转换为websocket协议.wildfly走得更远,8080端口支持HTTP (Servlet, JAX-RS, JAX-WS), Web Sockets, HTTP Upgraded Remoting (EJB Invocation, Remote JNDI).这篇文章讲述了一些细节.

When should I not kill -9 a process?

http://unix.stackexchange.com/questions/8916/when-should-i-not-kill-9-a-process

Generally, you should use kill -15 before kill -9 to give the target process a chance to clean up after itself.

Java里快如闪电的线程间通讯

http://www.infoq.com/cn/articles/High-Performance-Java-Inter-Thread-Communications

多线程中,锁是一个很大的性能开销.如果采用无锁实现,会发现原来世界可以更美好.

elasticsearch中文学习文档

https://github.com/medcl/elasticsearch-rtf

http://tanjianna.diandian.com/post/2013-07-27/elasticsearch-study

elasticsearch中文发行版,针对中文集成了相关插件,并带有Demo,方便新手学习,或者在生产环境中直接使用

elasticsearch中文学习文档

http://webappchecklist.com/ Web开发者必备:Web应用检查清单

Cache coherence

http://en.wikipedia.org/wiki/Cache_coherence

In a shared memory multiprocessor system with a separate cache memory for each processor, it is possible to have many copies of any one instruction operand: one copy in the main memory and one in each cache memory. When one copy of an operand is changed, the other copies of the operand must be changed also.

Cache coherence is the discipline that ensures that changes in the values of shared operands are propagated throughout the system in a timely fashion.

高性能、高流量Java Web站点打造的22条建议

http://www.csdn.net/article/2013-12-20/2817861-22-recommendations-for-building-effective-high-traffic-web-application

  • 通过使用类似Lucene的索引器做表的索引,使用一个允许在结果集上做基于其他字段的查询.

    对于复杂的查询,在数据库中直接做是很影响性能的,通过使用搜索引擎,能减轻数据库的压力.

  • 考虑使用Oracle或者MySQL分片

    数据量大时,做分片能获得不错的性能提升.

  • 不要使用session stickiness

    会话粘滞会带来一系列的问题.我们的分布式session方案中,默认要求LB启用会话粘滞,这样做的目的是能让本地缓存生效.当需要failover时,才去后端memcached中取数据.能同时兼顾性能和高可用.

  • 终止反向代理商的SSL

    在反向代理或者LB上卸载ssl,能够减轻web应用服务器的压力.

  • 拥抱一切“reactor”