这是一篇憋了很久的文章,一直想写,却又一直忘记了写。整篇文章可能会有点流水账,相对详细地介绍怎么写一个小型的"框架"。这个精悍的胶水层已经在生产环境服役超过半年,这里尝试把耦合业务的代码去掉,提炼出一个相对简洁的版本。
之前写的几篇文章里面其中一篇曾经提到过Canal
解析MySQL
的binlog
事件后的对象如下(来源于Canal
源码com.alibaba.otter.canal.protocol.FlatMessage
):
如果直接对此原始对象进行解析,那么会出现很多解析模板代码,一旦有改动就会牵一发动全身,这是我们不希望发生的一件事。于是花了一点点时间写了一个Canal
胶水层,让接收到的FlatMessage
根据表名称直接转换为对应的DTO
实例,这样能在一定程度上提升开发效率并且减少模板化代码,这个胶水层的数据流示意图如下:
要编写这样的胶水层主要用到:
IOC
容器(可选)。项目的模块如下:
canal-glue-core
:核心功能。spring-boot-starter-canal-glue
:适配Spring
的IOC
容器,添加自动配置。canal-glue-example
:使用例子和基准测试。下文会详细分析此胶水层如何实现。
笔者做小数据和零号提数工具人已经有一段时间,服务的对象是运营和商务的大佬,一般要求导出的数据是Excel
文件,考虑到初创团队机器资源十分有限的前提下,选用了阿里出品的Excel
工具EasyExcel
。这里简单分享一下EasyExcel
的使用心得。EasyExcel
从其依赖树来看是对apache-poi
的封装,笔者从开始接触Excel
处理就选用了EasyExcel
,避免了广泛流传的apache-poi
导致的内存泄漏问题。
下面的简介摘抄自docsify的官网 https://docsify.js.org 中的简介
docsify是一个神奇的文档网站生成器。他可以快速帮你生成文档网站。不同于GitBook
、Hexo
的地方是它不会生成静态的.html
文件,所有转换工作都是在运行时。如果你想要开始使用他,只需要创建一个index.html
就可以开始编写文档并直接部署在GitHub Pages
(码云Pages
、阿某云OSS
或者鹅云COS
等等)。它的主要特性如下:
markdown
文档转换)markdown
文档的大小)API
Emoji
,可以在文中添加表情IE11
SSR
docsify的最大优势是可以让使用者感受到用写博客的姿势去编写文档,反过来说也行:用写文档的姿势去写博客。docsify
的学习成本很低,部署简单,官方文档十分完善,原则上只需要理解markdown
的语法和Node.js
的安装即可,对于非IT
技术从业者也十分友好。知名的技术公众号号主JavaGuide的站点就是采用docsify
构建的。下文简单介绍docsify
的使用姿势。
之前已经花了大量时间分析同步器框架AQS
的源码实现,这篇文章分析一下CountDownLatch
的源码实现,本文参看的JDK
源码为JDK11
,其他版本不一定适合。
CountDownLatch其实是复合名词,由单词countdown和latch复合而来。countdown是倒数的意思,而latch则是闩锁、闭锁的意思,复合词容易让人联想到预先设定一个计数值,并且"锁住(阻塞)“一些东西(线程),然后进行倒数,当数值减少到0的时候进行"放行(解除阻塞)”。
CountDownLatch
是AQS共享模式下的典型实现。本文会先简单介绍CountDownLatch
的基本API
、类比监视器方式的实现以及深入分析其源码实现。
Canal
上一个正式版是于2019-9-2
发布的v1.1.4
,笔者几个月前把这个版本的Canal
推上了生产环境,部署了HA
集群。过程中虽然遇到不少的坑,但是在不出问题的前提下,Canal
的作用还是非常明显的。上周的一次改造上线之后,去掉了原来对业务系统订单数据通过RabbitMQ
实时推送的依赖,下游的统计服务完全通过上游业务主库的binlog
事件进行聚合,从而实现了核心业务和实时统计两个不同的模块解耦。
这篇文章简单分析一下如何搭建生产环境下可靠的Canal
高可用集群。
很早之前就打算看一次JUC线程池ThreadPoolExecutor
的源码实现,由于近段时间比较忙,一直没有时间整理出源码分析的文章。之前在分析扩展线程池实现可回调的Future
时候曾经提到并发大师Doug Lea
在设计线程池ThreadPoolExecutor
的提交任务的顶层接口Executor
只有一个无状态的执行方法:
public interface Executor {
void execute(Runnable command);
}
而ExecutorService
提供了很多扩展方法底层基本上是基于Executor#execute()
方法进行扩展。本文着重分析ThreadPoolExecutor#execute()
的实现,笔者会从实现原理、源码实现等角度结合简化例子进行详细的分析。ThreadPoolExecutor
的源码从JDK8
到JDK11
基本没有变化,本文编写的时候使用的是JDK11
。
并发编程大师Doug Lea在编写JUC
(java.util.concurrent
)包的时候引入了java.util.concurrent.locks.AbstractQueuedSynchronizer
,其实是Abstract Queued Synchronizer
,也就是"基于队列实现的抽象同步器",一般我们称之为AQS
。其实Doug Lea
大神编写AQS
是有严谨的理论基础的,他的个人博客上有一篇论文《The java.util.concurrent Synchronizer Framewor》,可以在互联网找到相应的译文《JUC同步器框架》,如果想要深入研究AQS
必须要理解一下该论文的内容,然后结合论文内容详细分析一下AQS
的源码实现。本文在阅读AQS
源码的时候选用的JDK
版本是JDK11
。
出于写作习惯,下文会把AbstractQueuedSynchronizer称为AQS、JUC同步器框或者同步器框架。
这篇文章不是标题党,下文会通过一个仿真例子分析如何优化百万级别数据Excel
导出。
笔者负责维护的一个数据查询和数据导出服务是一个相对远古的单点应用,在上一次云迁移之后扩展为双节点部署,但是发现了服务经常因为大数据量的数据导出频繁Full GC
,导致应用假死无法响应外部的请求。因为某些原因,该服务只能够分配2GB
的最大堆内存,下面的优化都是以这个堆内存极限为前提。通过查看服务配置、日志和APM
定位到两个问题:
CMS
参数,采用了CMS
收集器,该收集算法对内存的敏感度比较高,大批量数据导出容易瞬间打满老年代导致Full GC
频繁发生。对于问题1咨询过身边的大牛朋友,直接把所有CMS
相关的所有参数去掉,由于生产环境使用了JDK1.8
,相当于直接使用默认的GC
收集器参数-XX:+UseParallelGC
,也就是Parallel Scavenge + Parallel Old
的组合然后重启服务。观察APM
工具发现Full GC
的频率是有所下降,但是一旦某个时刻导出的数据量十分巨大(例如查询的结果超过一百万个对象,超越可用的最大堆内存),还是会陷入无尽的Full GC
,也就是修改了JVM
参数只起到了治标不治本的作用。所以下文会针对这个问题(也就是问题2),通过一个仿真案例来分析一下如何进行优化。
为了给个人博客提速,全部静态资源放到云上的对象存储中,并且加了CDN
,耗费了不少RMB
。新申请的域名也备案通过了,但是SSL
证书一般需要按年付款,看了下鹅云上最便宜的泛域名证书也裤头一紧:
毕竟至少是一年一付,金额也不算少(4块钱一天),感觉钱包压力有点大。于是通过多种搜索方式,找到了一种可行的白piao泛域名SSL
证书的方案,并且应用于已经备案好的个人博客域名上。最终子域名可以通过HTTPS
协议访问,效果如左下的图:
那么开始发车!
本文只适用于在鹅云上备案、解析的域名,已经把成功把
HTTPS
应用于鹅云的CDN
,其他云厂商没有进行试验,有兴趣的伙伴可以自行按照下文的思路重演。
2019年末到2020年年中,算是活了20多年来,境况最差的一段时间了,这里的差是指大环境(经济、实业,就业等等)。广州珠江新城花城汇恰饭和逛街的人少了很多,不少区的餐馆倒闭了,甚至找不到下一个接盘的商家,就闲置在那里。所以大概明白了为什么面试或者贩卖焦虑类型的文章会在很多知识分享平台火起来,因为大家都很焦虑,大家都想突围,我也是焦虑众人之一。
2019年底我离开了自2016年以实习生加入的某广州某科技金融公司,去了一家小的创业公司担任架构和打杂工程师。如果是同一个领域的伙伴就知道,当时圈内很多巨头都暴雷了,考虑到风险、可持续发展性以及刚好遇到赏识我的前Boss
出来创业,我很短时间内做完了交接工作就到另一个全新的领域上岗。没想到的是刚入职不久,新冠肺炎就爆发了,接下来遭遇到业务收缩、远程办公(一个月)等等。回想起来,这半年时间过得比较快,大概是因为远程办公和996
占比比较高。