Posts for: #Java

构建健壮系统

背景

在现代软件工程中,我们构建的系统规模越来越庞大,架构也从简单的单体演变为复杂的分布式系统。然而许多系统并没有因为架构升级而变得更加健壮,反而陷入了维护成本变高、故障定位困难、代码质量恶化的泥潭。

要真正打造具有高健壮性与可扩展性的系统,我们需要仔细审视那些让系统变得不稳定或性能下降的根因,而不是急于用防御代码或更细的服务拆分临时性地解决(掩盖)问题,只有找到病因才能对症下药。以下几点是笔者工作中的一些总结和思考,力求抛砖引玉。

锁是原罪

并发编程的核心难题在于共享状态的管理。为了解决多线程或多进程在并发场景下的资源竞争,绝大多数开发者第一反应就是加锁,但笔者的观点恰恰是:锁,是复杂度的原罪。

以 Java 为例,在语言层面和 SDK 层面均提供了极其庞杂的锁机制:synchronizedReentrantLockReentrantReadWriteLockStampedLock 等等不同的锁实现,每种锁不仅用法迥异同时即便是同一种锁还可进一步区分公平和非公平模式、可重入性、乐观、悲观策略等概念。

更多 →

从 HTTP 客户端封装看软件架构与编程范式的演进

背景

在日常的业务开发中,HTTP 客户端的封装可以说是最为常见的基础模块,无论是调用第三方 API 服务、对接内部微服务还是抓取外部数据,几乎每一个项目中都能看到类似于 HttpUtilsHttpClientWrapper 的身影。然而看似简单的网络请求,在不同的经验层级与架构范式下,写出来的代码质量与设计哲学却有着天壤之别。很多初级的封装仅仅停留在‘把功能调通’的阶段,忽略了底层 TCP 连接池、资源生命周期管理以及超时控制,为线上高并发场景埋下了严重的性能与稳定性隐患。

本文将以一个普通的 HTTP 客户端封装为例一步步演进重构,探讨如何写出完善严谨的代码,并借此梳理软件架构设计与编程范式的变迁。

第一次封装

在一些祖传项目或是更早的基于 JDK 1.7 以及后来的 JDK 8 项目中经常可以看到 Apache HttpClient 类库的身影,以下参考的 HttpUtils 可能是某个项目上默默工作的最为平凡的封装。

更多 →

Spring Boot 项目下载文件接口问题

背景

今天组内研发同学报告说项目中有一个模块提供了文件下载的接口, 在实际使用中遇到有客户使用 迅雷 进行离线下载的情况, 同时模块中针对文件下载的接口做了 AOP 切面进行计费统计. 而 迅雷 会针对该接口进行多线程并发下载, 同时即使退出 迅雷, 迅雷 还会继续发起对文件下载接口的调用. 于是便抽空大致看了下项目内的代码, 出问题的接口功能也比较简单, 并没有很复杂的逻辑. 其大致实现如下:

更多 →