Docker 完全指南
第1章:Docker 核心架构 Docker 是一种操作系统级别的虚拟化技术,它通过 Linux 内核的多项特性实现进程间的软隔离,而非传统虚拟机的硬件级虚拟化。理解 Docker 的核心架构,是掌握容器技术的第一步。 Docker 的四根柱子 Docker 的核心技术基于 Linux 内核的三大特性,加上一个标准化的容器格式: 1. Namespace(命名空间)—— 隔离 Namespace 是 Linux 内核提供的资源隔离机制,Docker 利用它为每个容器创建独立的运行环境。Docker 使用的 Namespace 包括: Namespace 隔离内容 说明 PID 进程 ID 容器内的进程有独立的 PID 空间 NET 网络 独立的网络栈、IP 地址、端口 MNT 文件系统挂载点 独立的文件系统视图 UTS 主机名和域名 容器可以有自己的主机名 IPC 进程间通信 独立的信号量、消息队列 USER 用户和用户组 容器内的 root 可以映射为宿主机的普通用户 2. Control Group(cgroup)—— 资源限制 cgr...
Guava 解析
前言 Guava 本身适配不同的环境,Jdk 1.8 以上使用 jre flavor,Jdk 1.7 和 android 使用 android flavor。 类库的作者,不要使用 @Beta 成员,以后它们不会是 source-compatible。但我们可以使用其他成员,它们会是 binary-compatible,Guava 现在不会再因为非安全原因删除成员了,即使是 @Deprecated 的。 可用的功能见这个 User Guide。 common Collect 不可变集合 Guava 提供了强类型的不可变集合,这些集合一旦创建就不能被修改,非常适合用于构建线程安全的应用和防御性编程。 1234567891011121314151617181920212223242526import com.google.common.collect.ImmutableList;import com.google.common.collect.ImmutableSet;import com.google.common.collect.ImmutableMap;// 创建不可变 Lis...
一致性哈希与数据分片
数据分片的动机 随着互联网应用的快速发展,数据量和访问量呈现爆炸式增长。单机存储系统面临着两个根本性的瓶颈:存储容量和访问性能。 存储容量方面,单台服务器的磁盘空间是有限的。当数据量超过单机容量时,必须寻找横向扩展的解决方案。垂直扩展通过升级硬件配置可以在一定程度上缓解问题,但成本高昂且存在物理上限。更重要的是,单机无法无限扩展,当数据量达到TB甚至PB级别时,垂直扩展已经无法满足需求。 访问性能方面,单机的处理能力同样有限。随着用户数量和请求量的增加,CPU计算能力、内存带宽、磁盘I/O和网络带宽都会成为性能瓶颈。即使单机能够处理当前的负载,也无法保证未来业务的持续增长。 数据分片提供了一种水平扩展的解决方案。通过将数据分散到多台服务器上,每台服务器只存储部分数据并处理部分请求,从而实现存储容量和访问性能的线性扩展。这种架构具有更好的可扩展性,可以根据业务增长灵活地增加服务器节点。 朴素哈希分片 朴素哈希分片是最直观的数据分片方案。其核心思想是:对于给定的数据键key,通过哈希函数计算其哈希值,然后对节点数量N取模,确定该数据应该存储在哪个节点。 1node_index = h...
API 兼容性设计
在软件工程中,API 兼容性是一个至关重要但又经常被忽视的问题。良好的兼容性设计能够确保系统的平滑演进,避免因 API 变更导致的客户端崩溃和服务中断。本文将从多个维度探讨 API 兼容性设计的最佳实践。 什么是 API 兼容性 API 兼容性分为两种类型: 向前兼容:旧版本的客户端能够与新版本的服务端正常通信。即服务端升级后,旧客户端仍能正常工作。 向后兼容:新版本的客户端能够与旧版本的服务端正常通信。即客户端升级后,旧服务端仍能提供服务。 在实际项目中,我们通常更关注向前兼容,因为服务端的升级往往不可控,而客户端的更新节奏各异。 破坏性变更的分类 破坏性变更是指会导致现有客户端无法正常工作的 API 变更。主要分为三类: 1. 接口签名变更 123456789// 变更前public interface UserService { User getUser(String userId);}// 变更后 - 破坏性变更public interface UserService { User getUser(String userId,...
重读 Eric Evans 的 DDD 蓝皮书
引言 软件系统的复杂性往往被误解为技术问题。在多年的开发实践中,我们习惯了用各种设计模式、架构框架、技术栈来应对复杂性,却忽略了一个根本事实:软件的核心复杂性在于领域本身,而非技术实现。Eric Evans 在《领域驱动设计》一书中提出了这一深刻见解,并给出了一套系统化的方法论——领域驱动设计。 DDD 不是一套必须严格遵守的规范,也不是一个可以简单套用的框架,它是一种思维方式,一种通过深入理解业务领域来构建高质量软件的方法论。重读这本经典著作,让我们重新审视这些核心理念。 通用语言 通用语言是 DDD 的基石。开发团队与领域专家共享同一套语言,这套语言不仅用于沟通,也体现在代码中。代码即文档,文档即代码。 在传统开发模式中,业务专家使用业务术语,技术人员使用技术术语,两者之间存在天然的语言鸿沟。业务需求被翻译成技术文档,技术文档又被翻译成代码,每个翻译环节都会产生信息丢失和误解。通用语言的提出,就是为了消除这种鸿沟。 通用语言应该由开发和业务专家共同构建,在持续的交流中不断完善。它体现在所有方面:需求讨论、文档、代码、测试。当领域专家能够阅读代码并理解其含义时,当开发人员能够直...
HTTP/1.1 到 HTTP/3 的演进
引言 HTTP 协议作为现代互联网的基石,自 1991 年诞生以来经历了多次重大演进。从最初简单的请求-响应模型,到如今高效、安全的 HTTP/3,每一次版本更新都针对前一版本的局限性进行了针对性的改进。本文将系统性地梳理 HTTP/1.0、HTTP/1.1、HTTP/2 和 HTTP/3 的核心技术特性和演进路径,深入分析每一代协议的设计理念、性能优化以及面临的挑战。 HTTP/1.0 的局限性 HTTP/1.0 于 1996 年发布,奠定了现代 Web 通信的基础框架。然而,随着互联网应用的快速发展,HTTP/1.0 的局限性逐渐显现。 每个 TCP 连接只能处理一个请求 HTTP/1.0 采用最简单的请求-响应模型:客户端发起请求,建立 TCP 连接,服务器返回响应后关闭连接。对于包含多个资源(如 HTML、CSS、JavaScript、图片等)的网页,浏览器需要为每个资源建立独立的 TCP 连接。这种模式带来了严重的性能问题: TCP 连接建立和关闭需要消耗系统资源 三次握手和慢启动机制增加了延迟 无法充分利用网络带宽 缺乏 Host 头字段 HTTP/1.0 最初设...
Java 结构化并发
结构化并发(Structured Concurrency) 结构化并发是 Java 并发编程的重要演进方向,与虚拟线程紧密配合,旨在解决传统并发编程中的线程泄漏、错误处理困难等问题。 1. 历史背景 1.1 结构化并发的起源与核心类比 术语起源 “结构化并发”(Structured Concurrency)这个术语由 Martin Sústrik(ZeroMQ 作者)在 2016 年首次提出。随后,Nathaniel J. Smith 在 2018 年发表了著名的文章《Notes on structured concurrency, or: Go statement considered harmful》,系统性地阐述了结构化并发的理论基础。 timeline title 结构化并发发展历程 2016 : Martin Sústrik 首创术语 : 在 250bpm.com 发表系列文章 2018 : Nathaniel J. Smith 发表核心论文 : "Go statement considered ha...
G1/ZGC/Shenandoah 垃圾收集器对比
垃圾收集的核心挑战 垃圾收集器的设计始终面临三个核心指标的权衡:吞吐量、延迟和内存占用。这三个指标构成了一个不可能三角,优化其中一个指标往往需要牺牲其他指标。 吞吐量指单位时间内完成的工作量,通常用应用程序运行时间占总时间的比例来衡量。对于批处理任务、科学计算等场景,高吞吐量是首要目标。 延迟指垃圾收集造成的应用停顿时间。对于交互式应用、金融交易系统等对响应时间敏感的场景,低延迟至关重要。延迟通常关注最大停顿时间和停顿时间分布。 内存占用指垃圾收集器为了完成收集工作所需的额外内存空间。内存受限的环境下,收集器自身的内存开销成为关键约束。 传统垃圾收集器在三者之间做出明确取舍:Serial 和 Parallel GC 追求高吞吐量,但停顿时间较长;CMS GC 降低停顿时间,但牺牲吞吐量并占用更多内存。现代收集器试图在三者之间找到更优的平衡点。 G1(Garbage First)收集器 G1 收集器在 JDK 7u4 版本正式推出,是 JDK 9 之后的默认垃圾收集器。G1 的核心思想是打破传统分代收集的物理隔离,将堆内存划分为多个大小相等的 Region。 Region 化堆内存...
TLS 握手与加密通信
为什么需要 TLS HTTP 协议最初设计为明文传输协议,所有通信内容都以纯文本形式在网络中传输。这种设计在互联网早期是合理的,但随着网络应用的普及和敏感数据的增多,明文传输带来了严重的安全风险。 窃听风险 在明文传输模式下,任何能够访问网络链路的攻击者都可以轻易读取通信内容。这包括: 同一局域网内的其他用户 网络服务提供商(ISP) 恶意的路由器或交换机 公共 Wi-Fi 网络的运营者 攻击者可以使用诸如 Wireshark、tcpdump 等网络抓包工具捕获数据包,直接查看其中的内容。这意味着用户名、密码、信用卡号、私密消息等敏感信息都会暴露在攻击者面前。 篡改风险 明文传输不仅允许攻击者读取内容,还允许他们修改传输的数据。攻击者可以在数据包经过的任何位置插入、删除或修改内容,而接收方难以察觉。例如: 将银行转账金额从 100 元改为 10000 元 修改电子邮件的内容 在网页中插入恶意脚本 替换下载的软件包 冒充风险 由于缺乏身份验证机制,攻击者可以冒充合法的服务器与客户端通信。客户端无法确认与之通信的服务器是否真实可信。这使得钓鱼攻击成为可能:攻击者搭建一个与真实...
变更日志(Changelog)规范
什么是变更日志 变更日志(Changelog)是一个按时间顺序记录项目所有重要变更的文件。它帮助用户、开发者和利益相关者了解每个版本中发生了什么变化,包括新功能、Bug 修复、破坏性变更等。 为什么需要变更日志 用户友好:让用户快速了解新功能、修复的问题和需要注意的变更 版本追溯:帮助定位问题首次出现或修复的版本 团队协作:统一团队对变更的理解和沟通 发布管理:辅助版本发布流程和发布说明的撰写 与 Git Log 的区别 特性 变更日志 Git Log 目标受众 用户、开发者、利益相关者 开发者 内容粒度 功能级别的高级描述 每次提交的详细记录 可读性 高度结构化、易于阅读 技术性强、包含实现细节 维护方式 手动维护或自动化生成 自动记录所有提交 版本关联 按版本组织 按时间顺序 Git Log 记录所有的代码提交,包括内部重构、测试调整等;而变更日志只记录对用户有意义的变更。 Keep a Changelog 规范 Keep a Changelog 是目前最广泛采用的变更日志规范,由 Olivier Lacan 创建。 变更类型分类 Ke...



