书籍作者:庞永华 | ISBN:9787121360350 |
书籍语言:简体中文 | 连载状态:全集 |
电子书格式:pdf,txt,epub,mobi,azw3 | 下载次数:6562 |
创建日期:2021-02-14 | 发布日期:2021-02-14 |
运行环境:PC/Windows/Linux/Mac/IOS/iPhone/iPad/Kindle/Android/安卓/平板 |
本书从实战角度出发,首先介绍Java多线程、Socket、Spring、动态代理、动态字节码、序列化等技术在构建分布式微服务框架中的应用。然后介绍一种微服务框架的架构设计与编程实践,并将这一微服务框架分解为底层Socket通信、服务注册与发现、服务暴露与引用、远程方法调用等层面,逐一深入讲解。这里重点介绍作者如何活用相关技术一步步地构建微服务框架的基础RPC框架并分享了相应的性能调优经验。最后介绍微服务架构中配套的服务治理系统的设计与实现方案,包括服务的设计、配置、管理与监控。
IBM高级咨询架构师,拥有16年以上各种类型软件系统的开发经验。擅长分布式与微服务架构的设计和开发。
本书从实战角度出发,介绍了一种综合运用Java多线程、Socket、动态代理等技术来构建微服务框架的方法。先从开发微服务框架所要用到的基础知识的开始讲解,再通过剖析现有的微服务框架的办法来讲解作者是如何综合的运用这些技术的,一步一步构建起这样一套完整的微服务框架。通过这一学习过程,读者可以深刻掌握Java多线程、Socket、动态代理等相关的技术,并能举一反三,灵活地运用它们,从而提升自身的Java编程水平,并为进一学习和研究Java分布式技术与微服务框架打下基础。
前言
本书适合有一定Java基础且有志成为架构师的开发人员阅读。一个优秀的架构师必须要有扎实的编程功底和丰富的理论知识,不光要能完成架构设计,更要有能力将设计转换为实际的产品。不会写代码、纸上谈兵的“架构师”设计出来的“架构”是靠不住的。因此,本书将从相关的基础知识讲起,通过剖析一个小巧精练的微服务框架的核心,介绍这些基础知识是如何在实践中被灵活、适当地运用的。
本书不是关于微服务的理论书籍,也不是某个微服务框架的使用手册。微服务涉及的范围很广,我们很难在一本书里讲清楚微服务的方方面面。
目前相关的主流框架是Spring Cloud和Dubbo。虽然Spring Cloud和Dubbo都很强大,但这个世界上从来没有最好,只有更好,因此我们永远不要停下自己创新的脚步。我们依然可以有自己的想法,并勇于尝试、付诸实践。事实上Spring Cloud和Dubbo都存在各自的问题和不足。我们通过对它们的学习和研究,站在巨人的肩膀上,吸取它们的优点再加以创新,是完全有可能做到青出于蓝而胜于蓝的。
在正式开始之前,让我们先了解一下微服务的发展背景。
面向服务的架构
1996年,Gartner公司首次提出了面向服务的架构(Service-Oriented Architecture,SOA)这一软件设计思想。其核心理念是将一个个的业务功能包装成一个个的标准服务,为这些服务定义良好的接口和服务契约,以便在需要的时候可以重用和水平伸缩。通过将这些服务进行组合和编排,可以创建新的业务流程,或者灵活地修改现有流程,以适应不断变化的业务需求,让我们的系统功能更丰富、结构更灵活、更易于扩展。同时,让系统规模能够根据需要弹性伸缩,最大限度地利用现有资产,提高效率,降低成本。总之,要使我们的系统能更灵活、更快地响应不断变化的需求。
不过,受到当时计算机水平的限制,面向服务的架构思想在诞生之初,并没有得到广泛的关注和发展。随着软件系统的规模越来越大、越来越复杂,软件系统的架构也在不断地演进,面向服务的架构开始受到人们的关注和认可。目前,大型软件系统的服务端架构多数都是面向服务的架构,或者正在朝这一架构迁移。
要明确的是,面向服务的架构中的“服务”虽然也包括系统对外提供的服务,但更多的是指系统内部的各个“模块”或“组件”的“服务化”,以及模块(服务)之间的相互调用与协同。它是“分布式”与“服务化”两个技术发展趋势合流的产物。
分布式系统
所谓的“分布式”是相对于“集中式”的一种应用系统内部组织结构。相对于传统的集中式系统(单机应用系统和集群式应用系统都属于集中式系统),分布式系统将原本集中在一个服务端应用中的功能模块拆分出来,分为多个系统组件或应用,分散部署在多个服务器上,并通过网络将它们连接起来协同工作。而客户端系统感觉不到服务端系统内部的这种变化,仍然和原来调用集中式系统一样。
分布式设计使得原本集中在单个服务器上进行的计算或存储需求被分散到了多个服务器上,从而降低了我们对单一服务器的性能要求。这样就让我们能用相对廉价的PC服务器代替昂贵的传统服务器,并通过水平扩容的方式继续提升系统的处理能力。
分布式系统并没有约定其内部的各个组件或应用之间应采用什么样的形式来实现彼此通信。早期人们使用DCOM、CORBA等技术实现组件的暴露和远程访问。这便是分布式系统的早期形态。但是这些技术比较复杂且十分笨重,只在大型系统和企业级应用中被使用。尽管之后又出现了COM+、RMI、EJB等技术,但仍然比较笨重和难用。
服务化
早期的系统都是相互独立的。受限于计算机的处理能力,其规模都比较小。比如,财务系统和人力资源管理系统分别是两个不同的系统。它们可能由不同的软件厂商,采用不同的开发语言和技术开发,并运行在各式各样的操作系统和硬件设备上。随着企业发展的需要,人们试着在两个系统间建立通信,尝试让它们彼此协同。双方的通信方式和协议由厂商之间彼此协商来制定,开发起来成本很高。各个厂商都试图制定自己的通信技术标准和协议,并力争成为业内标准。显然,如果所有厂商都遵循同一套技术标准和通信协议,就能大大地降低开发成本,让各个系统彼此更容易地互联互通。
随着基于Web的应用的普及,以及XML技术的出现和成熟,出现了基于HTTP、XML的服务暴露与远程访问方式,这就是Web Services。但Web Services的协议和实现方式很多,技术标准也多种多样。企业内部各系统之间的互联互通仍然比较麻烦。于是,企业服务总线(Enterprise Service Bus,ESB)系统被设计来实现各系统之间的服务接口适配和管理,以便各系统能够用自己熟悉的技术、标准和规范来相互调用彼此的服务。随着时间的推移,简单对象访问协议(Simple Object Access Protocol,SOAP)、Web服务描述语言(Web Services Description Language,WSDL),以及通用描述、发现与集成服务(Universal Description,Discovery and Integration,UDDI)协议逐渐成为主流的Web Services标准和规范。
后来,随着互联网技术的发展,基于HTTP RESTful的轻量级Web Services逐渐取代了基于SOAP的传统Web Services技术成为主流。由于HTTP RESTful服务暴露和调用开销比SOAP小很多,且速度更快,这就使得我们可在大型系统内部也大量使用,以作为各子系统之间,尤其是异构子系统之间最佳的通信形式。
面向服务
当我们将系统中的模块或组件服务化,代替COM+、RMI、EJB等分布式领域的组件通信技术后,系统架构就转变为面向服务的架构。当然,分布式系统中的很多组件是难以服务化的。不是所有的模块和组件都适合服务化。比如,有些模块的调用频率很高,接口复杂,转变成服务后,访问性能可能无法满足设计要求。又比如,有些模块与模块之间的耦合度较高,如果不进行重构来解耦,那么是无法单独作为服务暴露的。还有些模块的重用度不高或调用频率过低,没有服务化的必要。在对系统进行SOA改造时,一定要分析清楚。
综上所述,面向服务的架构是分布式架构中的一种。面向服务的架构一定是分布式架构,但分布式架构不一定面向服务。能够对外提供服务的系统并不一定是面向服务的架构,面向服务架构的系统也不一定对外暴露服务。
什么是微服务
顾名思义,微服务就是指粒度较小的服务。这意味着我们要对现有的分布式系统进行进一步的拆分,将其划分为更多、更小的服务来进行设计或重构。“微服务”的概念源于2014年3月Martin Fowler所写的一篇文章Microservices。它扩大了面向服务架构中“服务”的概念。不再局限于系统与系统之间的接口调用,也不局限于某种具体的服务形式。系统中凡是可被复用的功能模块都可以被“服务化”,转变为“服务”。这些服务可以对外暴露,也可能仅限于在系统内部使用。这对面向服务架构提出了更高的设计要求。由于服务数量更多、粒度更小,因此管控难度会更大,对性能的要求也更高。
那么,我们为什么要将系统拆分成一个个的微服务呢?
微服务的好处
微服务有如下好处。
1. 方便编排和重用
当我们在开发新功能时,可能需要复用现有的模块。以往我们需要将可复用的代码放到jar包中,并在工程中引用。这容易导致依赖关系的复杂和混乱,而且每次都需要重新编译和打包,也很不方便,更不要说对现有的模块进行编排和组合了。将这些模块转变为服务后,我们只需要调用这些服务,而不需要关心服务的具体实现、依赖和提供者。同时还能够使用服务编排工具将现有服务编排到新的流程中,组合成为新的服务,或者修改现有的服务流程。
2. 方便开发和调试
每一个微服务专注于单一功能,并通过定义良好的接口来清晰表述它的边界。服务越小,复杂度越低,开发起来也就越简单、越快,调试和维护也更方便。这就缩短了服务开发和修改的周期,使程序能更快地迭代。
3. 方便部署与更新
微服务一般随应用部署。一个系统中有若干可独立运行的应用,每个应用通常提供了一个或多个微服务。当某个微服务发生变更时,只需编译和部署相应的应用,而不用重新编译和部署整个系统。这使得部署发布更加高效,同时也缩小了每次变更和部署的影响范围,降低了风险。
4. 系统集成更方便
使用不同语言、不同技术栈开发的服务,只要按照统一的协议暴露,比如统一使用HTTP RESTful形式暴露为服务,就可以方便地相互调用和协同。这使得我们能够将各类系统轻松集成在一起。
5. 提高容错能力
某一模块或组件发生故障时,容易导致整个系统变得不可用。比如,某个模块的内存泄漏可能导致整个应用因内存不足而崩溃。由于微服务架构中的服务粒度很小,且相互隔离,因此即使某个服务出现问题,处理起来也相对容易,影响范围有限。微服务系统可以通过失败重试、失败转移、服务降级等机制实现容错处理,避免问题扩大,微服务系统甚至能自动从故障中恢复(自愈)。
6. 方便横向扩展
当某个服务出现性能瓶颈时,我们只需要增加此服务所属应用的部署数量,而不用增加整个系统的部署。而且,由于不同的服务对资源的要求不同,我们可以根据实际情况灵活地对服务进行混合部署,以便更合理地分配服务器资源。
RPC与微服务
微服务环境下服务的粒度更细,调用频率也更高,一般用于系统内部的面向服务架构,而不是直接对外提供服务。在这种场景下,Web Services的跨语言、跨平台优势不再那么重要,Web Services的易用性问题和性能问题反而变得突出起来。
随着Socket、多线程、序列化等技术的发展,涌现出了很多优秀的RPC框架,以代替传统的RMI等技术。与Web Services偏向对外暴露服务与远程调用不同,RPC框架专注于细粒度(方法级别)的、系统内部模块或组件之间的相互调用与协同。由于多数RPC框架采用Socket长连接和二
第1章 多线程基础
1.1 多线程的概念
1.1.1 进程与线程
1.1.2 并发与并行
1.1.3 线程状态
1.2 Thread线程类
1.2.1 基本用法与思考
1.2.2 常用方法介绍
1.2.3 wait和sleep的区别
1.2.4 sleep和yield的区别
1.3 Runnable接口
1.4 线程池
1.4.1 Executors
1.4.2 ExecutorService
1.4.3 ThreadPoolExecutor
1.4.4 基本用法与思考
1.5 Callable与Future
1.6 线程安全与效率
1.6.1 什么是线程安全
1.6.2 线程同步
1.6.3 饥饿与公平
1.6.4 锁与死锁
1.6.5 线程中断
1.7 编程进阶
1.7.1 volatile关键字
1.7.2 synchronized关键字
1.7.3 wait/notify/notifyAll
1.7.4 CAS操作
1.7.5 atomic包
1.7.6 Lock自旋锁
1.7.7 Condition条件变量
1.7.8 线程安全容器
1.7.9 ThreadLocal类
1.7.10 CountDownLatch计数器
1.7.11 CyclicBarrier栅栏
1.7.12 Semaphore信号量
1.7.13 fork/join框架
第2章 Socket基础
2.1 TCP与Socket
2.2 TCP的通信过程
2.2.1 基本过程
2.2.2 建立连接
2.2.3 全双工异步通信
2.2.4 断开连接
2.2.5 优雅地断开
2.2.6 半……连接
2.3 通信方式
2.3.1 长连接与短连接
2.3.2 线程模型
2.3.3 拆包与组包
2.3.4 断包与粘包
2.3.5 数据包的结构
2.4 BIO
2.4.1 典型编程模型
2.4.2 关键API概述
2.4.3 字符流传输
2.4.4 字节流传输
2.4.5 传输多笔数据
2.5 NIO
2.5.1 NIO简介
2.5.2 Buffer
2.5.3 Channel
2.5.4 Selector
2.5.5 Scatter/Gather
2.5.6 Pipe
2.5.7 内存映像文件
2.5.8 文件传输示例
2.5.9 “聊天室”示例
2.6 AIO
2.6.1 AIO简介
2.6.2 关键API概述
2.6.3 示例代码
第3章 Spring与Spring Cloud
3.1 Spring简介
3.2 IoC容器
3.2.1 IoC的概念
3.2.2 Spring中的bean
3.2.3 XML配置方式
3.2.4 注解配置方式
3.2.5 用Java类来配置
3.2.6 BeanFactory与FactoryBean
3.2.7 ApplicationContext与ApplicationContextAware
3.2.8 动态注册bean配置
3.2.9 ApplicationListener与容器事件
3.3 bean的基本配置
3.3.1 scope属性
3.3.2 parent与abstract
3.3.3 factory-bean与factory-method
3.3.4 bean的初始化与释放
3.4 依赖注入
3.4.1 setter注入
3.4.2 工厂方式注入
3.4.3 构造器注入
3.4.4 注解注入
3.5 Spring Boot
3.5.1 快速创建工程
3.5.2 编码与测试
3.5.3 打包部署
3.5.4 辅助开发工具
3.5.5 监控功能
3.6 Spring Cloud
3.6.1 Spring Cloud简介
3.6.2 架构设计
3.6.3 创建应用
3.6.4 服务的注册与发现
3.6.5 服务配置
3.6.6 Ribbon负载均衡
3.6.7 Feign服务调用
3.6.8 Hystrix
3.6.9 Zuul服务路由
3.6.10 服务监控
第4章 动态代理
4.1 代理模式
4.2 静态代理
4.3 类的装载
4.4 Java反射
4.5 JDK动态代理
4.6 CGLIB动态代理
4.7 Java Compiler API
4.8 Javassist动态代理
第5章 对象序列化
5.1 什么是序列化
5.2 Java序列化
5.2.1 基本用法
5.2.2 关于serialVersionUID
5.2.3 自定义序列化
5.2.4 封装实现代码
5.3 Hessian序列化
5.4 Kryo序列化
5.5 FST序列化
5.6 其他序列化组件
5.7 集成与扩展
5.7.1 优雅地集成
5.7.2 使用Java SPI
5.7.3 使用Spring
第6章 框架设计
6.1 总体结构
6.1.1 逻辑架构
6.1.2 框架设计概述
6.1.3 RPC原理
6.1.4 工程结构
6.1.5 依赖的jar包
6.1.6 主要的类
6.2 初始化过程
6.2.1 Spring配置
6.2.2 应用节点的启动
6.2.3 Web容器的启动
6.2.4 RpcCore的初始化
6.2.5 RpcContext的初始化
6.3 服务的暴露
6.3.1 服务暴露配置
6.3.2 方法配置与ID
6.3.3 内置的服务方法
6.3.4 服务提供方本地调用器
6.3.5 服务提供方代理生成器
6.3.6 注册要暴露的服务
6.4 服务的引用
6.4.1 服务引用配置
6.4.2 本地引用工厂类
6.4.3 注册本地引用工厂
6.4.4 本地引用与方法ID
6.5 服务的注册与发现
6.5.1 注册表集合
6.5.2 注册表的同步
6.5.3 注册表的解析
6.5.4 提交注册表
6.5.5 注册表推送
6.5.6 注册表检查
6.6 优雅地停机
6.6.1 停机的过程
6.6.2 停机钩子
6.6.3 监听Web容器的关闭
6.6.4 RpcCore的关闭
6.6.5 停机通知的处理
第7章 方法调用
7.1 方法调用类型
7.2 同步调用
7.2.1 同步调用的时序
7.2.2 同步调用的发起
7.2.3 负载均衡
7.2.4 指定服务提供者
7.2.5 失败转移
7.2.6 发送调用请求
7.2.7 处理调用请求
7.2.8 处理调用响应
7.3 异步调用
7.3.1 异步调用的时序
7.3.2 异步调用的发起
7.3.3 异步调用的执行
7.3.4 方法调用对象
7.4 同步/异步通知
7.5 异步回调
7.6 广播调用与广播通知
7.6.1 广播示例
7.6.2 广播代码
第8章 通信层实现
8.1 Socket通信框架
8.1.1 Netty与Mina
8.1.2 为什么要自己写
8.1.3 是NIO还是AIO
8.1.4 设计思路
8.1.5 实际结构
8.2 通信协议
8.2.1 传输对象
8.2.2 数据包结构
8.2.3 拆包与发送
8.2.4 接收并组包
8.3 连接的建立
8.3.1 工作模型
8.3.2 开始监听
8.3.3 发起连接
8.3.4 绑定连接
8.3.5 断线检测
第9章 性能测试与调优
9.1 性能调优概述
9.1.1 性能指标
9.1.2 性能瓶颈
9.1.3 环境因素
9.2 压力测试
9.2.1 测试方法
9.2.2 场景设计
9.2.3 测试环境
9.2.4 Dubbo配置
9.2.5 测试程序
9.3 线程池调优
9.3.1 调整线程池的大小
9.3.2 选择合适的队列
9.3.3 线程的管理逻辑
9.3.4 选择拒绝策略
9.4 优化线程同步
9.4.1 减少上下文切换
9.4.2 避免线程滥用
9.4.3 避免过多的锁
9.4.4 synchronized VS Lock
9.4.5 缩小锁的范围和粒度
9.4.6 线程分析工具
9.5 JVM调优
9.5.1 堆与栈
9.5.2 JVM内存的分代
9.5.3 GC分类
9.5.4 GC算法
9.5.5 分代GC
9.5.6 对象的引用
9.5.7 内存大小设置
9.5.8 内存调优工具
9.6 其他优化内容
9.6.1 避免使用反射
9.6.2 对象池
9.6.3 缓冲区队列
9.6.4 使用直接内存
9.6.5 缓存其他对象
9.6.6 协调与平衡
第10章 服务治理
10.1 服务治理概述
10.1.1 什么是服务治理
10.1.2 服务治理架构
10.1.3 服务治理接口
10.2 服务的定义
10.2.1 服务识别
10.2.2 接口定义
10.2.3 版本管理
10.2.4 协议适配
10.2.5 服务设计
10.2.6 服务的实现
10.2.7 依赖关系管理
10.3 服务的部署
10.3.1 服务的部署方式
10.3.2 自动化部署
10.3.3 服务的热部署
10.4 注册与发现
10.4.1 WSDL与UDDI
10.4.2 ZooKeeper的方案
10.4.3 Eureka的方案
10.4.4 Consul的方案
10.4.5 etcd的方案
10.4.6 注册中心集成方案
10.5 服务的控制
10.5.1 服务状态
10.5.2 服务控制
10.5.3 服务开关
10.5.4 服务模拟
10.5.5 黑白名单
10.5.6 “踢除”服务提供者
10.6 监控与限流
10.6.1 TPS监控与限流
10.6.2 响应时间的监控
10.6.3 调用链的监控
10.6.4 资源监控