近一个月遇到的坑

Netty FixedChannelPool 导致启动慢

fixedchannel 就是一个 netty 提供的原生的线程池, 支持异步获取。

那么要有异步的话,就要用到 ioThread, 结果,整个channelpool 其实只是由 ioGroup 里面的 一个 ioThread 处理。

那么,必定会造成, 刚启动的时候, io事件较多, 导致影响了获取链接。

解决方案

不用它, 自己造轮子,搞一个不靠 iothread 的连接池。

Netty watermark 泄漏

这个还要从异步说起,因为要异步,所以肯定需要一个缓存, 于是 netty 里面 每一个 IOThread 其实都有一个 queue。

那么, netty 的queue 默认多大, Integer.MAX

看源码的时候,看到这里吓一跳, 直接的反应就是限制一下大小,免得大并发下,直接oom。

结果,这导致了 watermark 泄漏 = =

解决方案

不限长度, 纯靠 watermark 限流。 此 issue 估计下下版本会修复

Log4j 锁

日常以为线上打印一下日志没啥问题。

但是 log4j1 有多坑, 日志量一大的话, 竟然不是操作系统 io 堵,而是 java 自己锁住了 = =

有多严重?

log4j 内部 有synchronize, 线程越多, 竞争越厉害,越严重。

业务线程也就算了, 如果 netty 的iothread 内部也打日志, 就崩溃了。

大流量下, 启动的时候 不锁个5,6秒 回不来。

解决方案

  1. 升级 log4j2

  2. 对于框架代码没主动权, 只能减少日志量, ioThread 尽量少打日志, 即使要打,也得采样打日志。

java UUID 导致启动慢

uuid 也坑, 自带的实现锁很多。

高并发下会很慢。

主要原因

  1. 有好几个 全局 synchronize
  2. synchronize 默认底层依赖操作系统的 /dev/random (速度不可控)
  3. java6/7 的早期版本实现性能不够好
  4. 我们 iothread 里面 也获取了 uuid, 加剧了 iothread 的慢 - -

解决方案

  1. 究极方案: 自己实现伪随机 的uuid
  2. 临时方案: 启动参数添加 -Djava.security=file:/dev/./urandom 使其内部使用 SHA1PRNG 减少锁。

不同版本 jdk map.values() 顺序不一致

这个问题很坑, 我们都知道 map 底层就是数组, 也知道 jdk7 的map 和jdk8 的map 改了许多,

但怎么就没有联想到, 改了很多的话, 底层 hash 方式 肯定也变了 = =

明知道是坑, 但必须踩一下。

avatar

lelouchcr's blog