一次生产中使用list。parallelStream()血的教训
项目背景最近在完成一项历史数据的清洗工作,主要就是把以前的 垃圾数据调用第三方渠道来完成一次认证,迫于监管的淫威吧。 但是第三方的qps又没有多高,政府机关的接口你懂得。 于是,代码随心的写了起来。项目上线由于项目紧急,也没有压测,自觉也不会有什么问题,项目部署上线,部署了四个实例,对方 qps 实测 1s内完成 3~4次请求。 最后TPS 在20 上下,即使增加实例,起色不大。排查原因为什么呢这是?难道要堆机器嘛?不应该啊,单台实例 也不止这个 TPS 啊, 何况我是并发处理? list.parallelStream().forEach(...) 明明已经并发了啊?怎么回事了? 再次review 代码发现:该api 其实开启的线程数 根据操作系统内核。 并且现在微服务部署都是 docker 部署。所以你懂得导致其实系统一直是单线程在跑,难怪 TPS 上不去。解决方案之一
采用了一种解决方案就是,自己构造线程池来解决。 private ThreadFactory namedThreadFactory = new ThreadFactoryBuilder() .setNameFormat("user-pool-%d") .build(); private ThreadPoolExecutor pool = new ThreadPoolExecutor(10, 10, 10L, TimeUnit.SECONDS, new LinkedBlockingQueue<>(1024), namedThreadFactory, new ThreadPoolExecutor.CallerRunsPolicy()); 这个 参数也是生产上跑数据用到的,其中尤其注意 队列满时的处理策略。 刚开始用的 直接丢弃肯定不行,后来换成CallerRunsPolicy,提交任务的线程来执行,这提交任务的线程就阻塞住,不会继续往线程池提交任务了。