网站技术与Java中间件培训方案
2022-10-13 10:03:19 0 举报
AI智能生成
网站技术与Java中间件培训方案
作者其他创作
大纲/内容
1、分布式系统介绍
定义:由多个互相连接的计算机节点组成的系统
优点
1、升级单机处理能力的性价比越来越低(摩尔定律)
摩尔定律:当价格必变,每隔18个月,集成电路可容纳的晶体管数目会增加一倍,性能也提升一倍。
2、单机处理能力存在瓶颈
3、提高系统的稳定性和可用性
分布式系统基础知识
计算机的5个要素
外存
内存
CPU
运算器
控制器
输入设备
输出设备
这5个部分组成了整个计算机系统
分布式系统从外部看就像是超级计算机,也可以抽象为5个部分
多线程
单线程只需要控制程序的顺序,分支和循环执行;多线程需要处理线程间的通讯,线程间的协调工作
多线程的模式
互不通讯的线程模式,线程间没有共享数据,线程间没有交集
基于共享容器协同的多线程模式;例如:生产者和消费者
通过事件协同的多线程模式;A、B两个线程,线程B的需要等待线程A改变某个数据状态或者触发某个事件
网络通讯
OSI的七层模型和TCP/IP的4层模型
网络IO实现方式
BIO:阻塞IO;使用一个线程处理连接、读数据和写数据
NIO:非阻塞IO;采用Reactor的模式,基于事件驱动,将客户端的请求派发到不同的线程中进行处理
AIO:异步IO;采用Proactor模式。AIO接收到客户端请求,会调用对应的线程的读/写操作进行处理,
 并且会传入CompletionHandler,CompletionHandler用户接受处理的结果通知
NIO和AIO最大的区别:NIO在有通知时可以进行相关操作,AIO在有通知时表示相关操作已经完成
单机系统到分布式
输入设备
其他节点发送的输入数据
人机交互的输入设备
输出设备
其他节点发送的输出数据
人机交互的输出设备
CPU
控制器
控制器的作用是协调和控制节点之间的动作和行为
实现
硬件负载均衡
LVS负载均衡
问题1:增加网络流量开销
如果请求数据小响应数据大,可以使用LVS的TUN或者DR模式,将响应结果不经过中间LVS代理直接输出给客户端
问题2:网络延迟
网络延迟影响很小
问题3:LVS代理出现故障
LVS代理服务器热备份
服务的注册中心
请求提供方将服务地址和名称注册到注册中心,请求的发起方在注册中心根据名称获得请求地址,从而发起请求
规则服务器
请求的发起方请求规则服务器,规则服务器根据请求规则返回给客户端请求提供方的地址,请求发起方进行调用
规则服务器与注册中心服务器的区别在于:前者不和请求处理方式连接,后者和请求处理方连接。
mater-worker模式
mater负责接受任务,将任务分配给不同的worker处理
运算器
1.通过DNS服务器进行调度和控制
2.负载均衡
3.Master-Worker
存储器(外存和内存)
1.使用Key-Value(redis)统一存储
2.增加代理服务器,统一管理KV存储
3.增加名称服务器,管理在线的KV存储服务器,并且把地址传到应用服务器
4.Master-Worker模式
分布式系统的问题
1、缺乏全局时钟,如何控制多个系统程序间的执行顺序
2、面对故障的独立性,整个系统的一部分有问题,其他部分是正常的。
3、处理单点故障
冗余备份
数据分片存储
4、事务挑战
2、大型网站演进过程
大型网站的标准
访问量
数据量
大型网站的演进主要围绕者计算和运算
演进过程
1、单机网站
2、单机负载告警,数据库和应用程序分离
3、应用程序负载告警,应用程序搭建集群
问题1:应用服务器请求选择的问题
引用负载均衡设备解决
问题2:session共享问题
1、粘滞session
2、session复制
3、session集中存储
4、cookie存储会话数据
4、数据库读压力大
4.1 读写分离
问题1:数据复制问题
数据库自身的主从复制
问题2:应用数据源选择问题
使用数据库中间件,例如Mycat
4.2 搜索引擎,减少数据库like查询的压力
4.3 缓存
数据缓存
页面缓存
5、弥补关系型数据库的不足,引入分布式存储系统
分布式文件系统:解决海量文件存储的问题
分布式Key——Value系统:提供高性能的半结构化的支持,例如:MongoDB
分布式数据库:提供大数据,高并发的数据库系统
6、读写分离后,单机数据库存储的问题
垂直切分,专库专用
水平切分,一个表的数据拆分到不同数据库中存储
7、应用程序的瓶颈
按照业务拆分应用程序
问题:不同应用程序间会存储相同的代码
面向服务架构
特点
1. 应用系统间远程调用
2. 共享代码被做成服务化提供给外部调用
3. 数据库的访问集中在服务中心
4. 服务化的架构让不同的团队分工更加明确,团队内部更加稳定
8、消息中间件
消息中间件能够实现系统之间结构,让系统的调用由同步变为异步
3、Java中间件
定义:介于应用于底层系统之间,“不上不下”的位置,是应用与应用之间的桥梁,是应用与服务之间的桥梁
分布式系统中中间件主要包括3个方面
1. 远程过程调用和对象访问中间件
2. 消息中间件
3. 数据访问中间件
Java中间件基础
1、JVM:Java字节码运行的环境,JVM实现了Java语言“一次编写,到处运行”的效果
2、垃圾回收机制和Java内存布局
Java的垃圾回收机制可以让开发者不用关注内存处理的问题
3、并发编程的类、接口和方法
1. 线程池:降低线程创建的开销
无限线程池:ExecutorService threadpool = Executors.newCachedThreadPool();
固定线程池:ExecutorService threadpool = Executors.newFixedThreadPool(3);
单线程池:ExecutorService threadpool = Executors.newSingleThreadExecutor();
周期线程池:ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);
2. Synchronized:锁可以实现线程间的互斥
3. ReentrantLock:类似于Synchronized的锁机制,但是比Synchronized更加灵活
tryLock方法,不会造成线程阻塞,返回true即获得锁,返回false没有获得锁
其构造方法接受一个Boolean类型参数,描述锁是否是公平锁
ReetrantReadWriteLock,提供了读写锁,使用与读多写少的情况
4. volatile
volatile保证了共享变量在线程间的可见性
volatile相比Synchronized,前者是保证了可见性,后者具备可见性和操作互斥性。
操作互斥性和可见性是两回事,操作互斥性保证了操作的原子性。可见性是共享变量的变化在多个线程间是可见的
5、Atomics
JDK提供的原子类,其提供的变量的写操作是线程安全的。内部使用了CAS进行实现
6、等待唤醒机制
Synchronized
线程等待:锁对象.wait();
随机唤醒一个线程:锁对象.notify();
唤醒所有线程:锁对象.notifyAll()
Lock
Condition pro = lock.newCondition();
线程等待:condition.await();
随机唤醒一个线程:condition.signal();
唤醒全部线程:condition.signalAll();
7、CountDownLatch
描述:CountDownLatch是java.util.concurrent并发包下的类
作用:提供的机制是当多个线程到达预期状态或者完成预期工作时触发事件,其他线程等待这个事件来触发自己后续的工作。
构造方法:CountDownLatch latch = CountDownLatch(int count); //count是调用countDown线程的数量
触发事件:countDown()
线程等待:await()方法
注意:等待的线程可以是多个,也就是说countDown()可以唤醒多个在等待的线程
8、CyclicBarrier
描述:循环屏障
作用:可以协作多个线程,让多个线程在这个屏障前等待,知道所有线程都到达这个屏障时,才一起继续执行后续的代码
构造方法:CyclicBarrier barrier = CyclicBarrier(int count); //count是等待线程的数量
等待方法:barrier.awat();
9、Semaphore
描述:适用于管理信号量,构造参数传递的是可供管理的信号量的数值。
作用:控制并发的代码,执行前先获得信号(acquire方法),执行后归还信号(release方法),每次获得信号后,总信号量就会-1,如果没有可用的信号,acquire就会阻塞,知道有线程执行release方法释放信号量。
构造方法:Semaphore semaphore = new Semaphore(count); //count是信号的总数
获得信号
acquire()
释放信号
release()
注意
如果信号量为1,就是互斥锁了
如果信号量多于1,主要用来控制并发数
相比控制线程数来控制并发数,Semaphore更加的细粒度。
10、Exchanger
描述:交换。
作用:用于在两个线程之间进行数据的交换。线程会阻塞在exchange方法上,直到另外一个线程也达到exchange方法时,两者交换数据,然后各自线程再继续执行自身的代码。
注意:无论是谁先达到exchange方法,都会等待另外一个线程也达到
11、Future&FutureTask
FutureTask可用于异步获取执行结果或取消执行任务的场景。通过传入Runnable或者Callable的任务给FutureTask,直接调用其run方法或者放入线程池执行,之后可以在外部通过FutureTask的get方法异步获取执行结果,因此,FutureTask非常适合用于耗时的计算,主线程可以在完成自己的任务后,再去获取结果。另外,FutureTask还可以确保即使调用了多次run方法,它都只会执行一次Runnable或者Callable任务,或者通过cancel取消FutureTask的执行等。
FutureTask是Future的实现类,帮助实现了具体的任务以及与Future接口的get等方法的关联。
get方法:异步获得线程返回的结果
12、并发容器
并发容器主要指的是在JDK并发包中以CopyOnWrite和Concurrent开头的几个容器
优势:相比加锁互斥保证线程安全,并发容器的思路是尽量不使用锁实现线程安全,性能上比直接使用锁要好很多。
CopyOnWrite思路
更改容器元素时,把容器拷贝一份进行写操作,保证正在读的线程不收影响。这种方式用在读多写少的情况
Concurrent思路
尽量保证不加锁,修改时不影响读,所以比使用读写锁有更高的并发性能。
4、动态代理
静态代理
装饰着设计模式
动态代理
JDK动态代理
CGlib动态代理
Javassist
5、反射
在运行状态中操作类和对象
作用
1. 在运行时,判断一个对象所属的类
2. 在运行时,构造任意类的对象
3. 在运行时,判断一个类的成员变量和方法
4. 在运行时,调用任意一个对象的方法
5. 生成动态代理
6、网络通讯
BIO
NIO
AIO
Java中间件
网站的演进过程
1. 应用的拆分
2. 服务的拆分
3. 数据的拆分
4. 应用的解耦
Java中间件
1. 服务框架:解决应用拆分和服务拆分
2. 数据层中间件:解决数据的拆分和数据的管理、扩容和迁移等工作
3. 消息中间件:应用的解耦以及分布式事务
4、服务框架
4.1 应用的拆分
随着应用程序越来越大,维护和开发的成本也越来越高,这时就需要进行应用的拆分
大->小
大的应用拆分成多个小的应用程序,各个应用程序之间通过URL进行跳转
特点:拆分简单,各个应用程序业务独立
不足:各个应用程序都去操作底层数据库资源,造成数据层压力很大
服务化
将各个应用程序的公共部分抽取成服务,通过服务框架进行远程RPC调用
特点:提供服务的应用负责和数据层交互,服务层的代码可以被上层应用复用。
需要依赖服务化框架才能实现
4.2 服务框架的设计与实现
4.2.1 服务框架模型
服务调用方
接口调用
寻址路由:让调用方确定哪个实例被调用
编码
通讯
服务提供方
通讯
解码
实例定位:被调用的机器上找到对应的实例进行方法调用
服务调用
4.2.2 实例
本地调用的接口实现只关心业务的处理,而远程服务的调用会比较复杂
服务调用方
1. 根据服务名称,获得可用服务列表
2. 确定要调用服务的目标机器
3. 建立连接
4. 请求序列化
5. 发送请求
6. 接受结果
7. 解析结果
服务提供方
1. 设置死循环,监听服务端口号
2. 接受请求
3. 发序列化数据
4. 获得服务对象
5. 通过反射执行服务对象方法
6. 序列化结果数据
7. 响应数据
4.2.3 服务调用端设计与实现
分支主题
服务框架的使用
代码角度看如何使用服务框架
分支主题
ConsumerBean是一个通用对象,是完成本地和远程服务的桥梁
interfaceName:接口名称。ConsumerBean通过接口知道调用的服务是哪个,然后生成这个接口的代理,以供本地调用
version:版本号。接口的变动不可避免,如果需求变更需要修改接口定义,通过版本号进行分区隔离。
group:分组。对同一个接口的远程服务又很多机器,可以将这些远程服务的机器进行分组,调用者根据不同的分组来调用,这样可以实现调用者对统一服务的调用进行隔离
服务框架与应用和容器的关系
服务框架的部署
服务框架作为应用的扩展
分支主题
服务框架是Web容器的一部分
分支主题
服务框架本身作为容器
分支主题
服务框架的jar包与应用jar包冲突
使用自定义classLoader实现jar包的隔离
分支主题
服务调用者和服务提供者之间的通讯方式
分支主题
1. 服务提供者注册服务地址到注册中心
2. 服务调用者从注册中心根据服务名称查找服务地址列表
3. 服务调用者从服务列表中选择一个服务进行调用
随机
轮询
权重
4. 服务地址变更后,注册中心主动通知服务调用者
基于接口、方法、参数的路由
在服务寻址完成后,就要进行实际的远程调用,如果接口中有些方法非常耗时,势必会影响远程调用的性能,导致所有线程会等待在耗时的方法上。
分支主题
例如:接口A的方法1非常耗时,测试服务器中所有的线程都会被接口A的方法1的执行所占用。服务没有更多的线程处理其他方法的请求。
解决方案
一、增加线程数和增加机器数,但是此方案不经济
二、按照接口或者方法、参数进行隔离,让耗时的方法与其他方法互不影响
分支主题
服务定位提供服务地址与路由规则中的地址一起取交集,得到的地址列表再进行负载均衡的算法,最终得到一个可用的地址去调用。
跨机房的服务调用
分支主题
基本思路是甄别服务调用者的地址,尽量返回同机房的服务提供者的地址,以提高服务调用的效率
服务调用端的流控处理
流量控制是为了保证系统的稳定性
控制方式
0-1开关,例如0就是不进行流控,1进行流控
固定值,流量达到某个固定值才进行流控
控制维度
1. 针对不同接口、方法设定流控阈值
2. 针对同样的接口、方法根据来源设定阈值
序列化和反序列处理
序列化就是讲内存对象变为二进制数据
反序列化就是将二进制数据变为内存对象
服务调用方将方法参数进行序列化后,通过网络传输到远程的服务提供端,服务提供端进行反序列化数据后进行相关调用
网络通讯选择
BIO
分支主题
服务调用端有3个线程进来,分别创建3个线程处理,每个线程有独立的连接,远端的服务提供方有对应的3个线程来执行相关服务。这种方式会导致调用者和提供者之间建立大量的连接,而且是阻塞方式,连接不能充分利用。
NIO
分支主题
使用IO线程专门负责调用方和提供方的通讯,IO线程是非阻塞的。使用工作线程进行服务的调用。此种方式需要将异步转同步。
调用端采用NIO示意图
分支主题
组成部分
IO线程:专门负责和Socket连接交互
数据队列:请求方每个线程将需要发送的数据入队,由IO线程从数据队列取出数据调用远端服务。
通讯对象队列:请求线程将数据放入数据队列后,会生成一个通讯对象,通讯对象会入队列,线程在通讯线程上阻塞等待。如果远端有返回,那么IO线程会通知通讯对象,通讯对象会结束请求线程的等待。
定时任务:定时任务负责检查通讯队列中那些通讯对象已经超时,然后超时的通讯对象会通知请求线程已经超时的事实。
AIO
多种方式的异步调用
Oneway
分支主题
不考虑服务调用返回结果
Callback
分支主题
被动等待服务调用返回结果
Future
分支主题
主动获得服务调用的返回结果
消息中间件
Future优化对远程服务的调用
优化前
分支主题
耗时:15+25+40+20=100ms
优化后
分支主题
耗时:40+20=60ms
4.2.4 服务提供方设计与实现
分支主题
服务端的配置
服务端的处理流程
网络通信用BIO
IO线程进行通讯
反序列可以在IO线程也可以在工作线程
调用服务在工作线程
分支主题
调用不同服务的线程池隔离
根据服务的名称、方法、参数来确定要执行服务的线程池是哪个
分支主题
服务提供端的流量控制
0-1开关控制服务是否可用
阈值控制限流
针对调用者提供差异化的服务访问,确保优先级高的调用者优先提供服务。
通讯、序列化、协议等功能对服务提供者和调用者来讲应该是公共的
服务框架应该是模块化的
4.2.5 服务升级
服务接口和方法没有变
直接修改服务提供者接口实现的代码,使用灰度发布方式验证后全部发布。
服务接口或者方法变化
增加方法
直接新增方法即可
方法参数变化
使用版本号区分新旧方法
4.3 实战中的优化
1 服务的拆分
2 服务的粒度
3 优雅和实用的平衡
如果服务调用者读取数据频率非常高,让服务调用者直接读缓存会比较好
分支主题
4 请求合并
将调用相同服务的请求进行合并,减少服务的请求次数
4.4 服务治理
管理服务
写操作
查看服务
读操作
4.5 服务化与ESB的对比
ESB(企业服务总线)是同面向服务发展而来的,也是用于分布式系统的解耦
分支主题
ESB与服务化的差异
1. 服务框架是点对点,而ESB是一个总线式的模型
2. 服务化框架面向同构的系统,而ESB面向不同厂商和系统提供服务
5、数据访问层
5.1 数据库从单机到分布式的挑战和应对
5.1.1 单机数据库下,应用程序使用JDBC连接一个数据库,随着业务发展、数据量的增多,需要进行分库分表
5.1.2 拆分方式
垂直拆分
将不同业务的数据拆分到不同的数据库
影响
单机的ACID被打破,需要引入分布式事务
Join操作比较困难
外键约束受到影响
水平拆分
将同一业务的数据拆分到不同数据库
影响
单机的ACID被打破,需要引入分布式事务
Join操作比较困难
外键约束收到影响
ID的唯一性和连续性
单个逻辑意义的表查询需要跨库
5.1.3 事务处理
XA事务规范
Application Program:应用程序,定义了事务的边界
Resource Manager:资源管理器,可以理解为DBMS,管理应用程序的数据资源
Transaction Manager:事务管理器,负责协调和管理实务
分布式事务的理论
CAP
C:Consistency。一致性
A:Availibility。可用性。每个请求都会收到一个反馈,不管是成功还是失败。重点在于响应
P:Parition-Tolerance:分区容忍性。系统中有一部分节点出现问题,整个系统也是可用的。
CAP不可能同时都满足,但可以同时满足2项
CA:放弃分区容忍性。其实就是单机环境
AP:放弃一致性。例如NoSQL数据库就是如此。
CP:放弃可用性。准求一致性。
以上3中组合,使用较多的是AP,但是也不代表不关心一致性,只要保证最终一致性即可
BASE
Basic Available:基本可用
Soft state:软状态,接受一段时间的状态不同步
Eventually Consistency:最终一致性。
Paxos
分布式系统下节点之间的通信方式
共享内存
发送消息
Paxos可以保证分布式系统中状态一致性
Paxos的前提是不存在拜占庭将军问题,也就是说节点之间传递的消息是可靠的
Paxos的角色
领导者
负责管理所有节点
跟随者
负责参与投票
观察者
负责提供数据访问
实现方式
二阶段提交
第一阶段是准备阶段
第二阶段是执行第一阶段资源提交或者回滚
TCC
try-confirm-cancel,事务补偿性
消息中间件
使用消息中间件保证2个应用程序操作的一致性
5.1.4 ID的唯一性和连续性
使用专门的程序负责生成ID
zookeeper
redis
使用专门的ID生成算法
雪花算法
5.1.5 应对多机的查询
跨库Join
1. 将Join操作分多次在不同数据库执行
2. 数据冗余,将原来需要Join的操作进行单表查询
3. 借助第三方系统(MyCat)实现
外键约束
分库库的表尽量内聚,否则只能靠应用判断了。
跨库查询
查询合并
函数处理
每个数据源分别梳理,然后在应用程序中在合并处理
分页查询
从每个数据库取出PageSize大小的数据,然后在归并分页
5.2 数据访问层设计与实现
对应用提供对外访问的接口
专用API
通用API
类ORM框架
数据访问层接口的设计
分支主题
SQL解析
获得SQL中的关键信息,例如表名、字段、where条件等
规则处理
规则处理的目的是执行SQL的目标库
固定哈希算法
id值取模
时间取模
一致性哈希算法
分支主题
将节点对应的哈希值变为了一个范围,而不再试离散的值
将整个哈希值的范围定义非常大,然后把这个范围分配给现有的节点
问题
新增一个节点时,除了新增的节点,只有一个节点收到影响,这个新增节点和受影响节点的负载明显比其他节点低
减去一个节点时,处理减去的节点外,只有一个节点收到影响,它要承受的原来和减去节点的工作,负载压力比其他节点明显高
虚拟节点对一致性哈希的改进
一个物理节点对应多个虚拟节点
同一个物理节点对应的虚拟机节点尽量均匀的分布
自定义规则
以上的规则使用哪一个没有明确的答案,目标是尽量避免跨库的查询
改写SQL
针对分库后的表,为了避免误操作,通常会将表名重命名
选择数据库源
规则处理决定的是一组相同的数据库源,这样做是为了实现实现一写多度,提高数据库的访问速度。
选择数据库源就是选择某一个具体的数据库
执行SQL和结果处理
需要注意的是对异常的处理判断,要能辨别出来是哪一个库的异常信息
实战使用图
分支主题
DataSource:数据访问层对外提供透明的DataSource
groupDataSource:管理同一组数据源的对象
AtomDataSource:连接具体数据库的数据源对象,这里不使用第三方的数据源c3p0等,是为了配置和实现更加的灵活
数据访问层实现方式
分支主题
采用数据库协议,将Proxy看做数据库,Proxy使用JDBC连接数据库。实现方式复杂
采用私有协议,Proxy对外提供的通讯协议是自己设计的,并且需要一个数据层客户端。实现相对简单一些
读写分离的挑战和应对
分支主题
主从复制
MySQL Replication
消息中间件
分支主题
应用程序在主库进行写操作后
应用程序给MQ发送消息
数据同步服务器接收MQ消息从主库查询数据写入到从库
采用数据库的日志实现主从备份
数据平滑迁移
在不完全宕机的情况下平滑的移动数据
1. 开始扩容时记录数据变更的日志,用id表示记录,用v表示版本
分支主题
2. 开始复制记录,此时可能会有新的记录更新进来,此时复制完成后,新库中的表不是最新的
分支主题
3. 当全量数据迁移完毕后,将增量数据进行迁移,在移动增量数据时,可能还会有新的数据更新
分支主题
4. 比较新库和旧库之间的不同的数据记录下来
5. 停止旧库数据的写操作,将新增量的数据迁移到新库
6. 最后根据路由规则,所有的读和写操作都在新库进行
6、消息中间件
6.1 消息中间件的价值
解耦
异步
6.2 保证消息一致性
目标:保证业务操作和消息发送的一致性
6.2.1 一致性方案
JMS针对Session、Connection、ConnectionFactory提供了支持分布式事务的接口
分支主题
此种方式有局限性,数据库必须支持分布式事务
其他方式
分支主题
步骤分析
1. 应用将消息发送给消息中间件,标记消息的状态为未处理
2. 消息中间件将消息进行存储,并不投递
3. 消息中间件返回消息处理结果(入口未投递),成功或者失败
4. 应用程序接收到消息中间件返回的结果进行业务处理
返回成功,处理自身业务
返回失败,就放弃业务处理,结束
5. 业务操作完成,应用程序将业务操作结果发送给消息中间件
6. 消息中间件接收到结果,进行消息处理
业务成功,更新消息的状态为可发送,投递消息
业务失败,删除存储中的消息,结束
问题分析
问题1:业务操作未进行,消息未存储
问题2:业务未进行,消息存入存储,状态为待处理
问题3:业务操作成功,消息存入存储,状态为待处理
解决方式
问题1不需要处理,本身就是一致状态
问题2和问题3要根据业务结果来处理存储中的待处理的消息
方案
分支主题
消息中间件主动查询业务处理的结果
业务处理成功,投递消息
业务处理失败,删除消息
6.2.2 降低消息中间件和应用的耦合度
以上的方式就加大了消息中间件与应用的依赖关系
方式一
分支主题
应用程序自己的业务数据库存储消息数据
消息中间件访问业务数据库
方式二
分支主题
消息中间件不需要与业务数据库打交道
方式三
分支主题
消息存储到本地文件中
6.2.3 消息模型
点对点
一个消息只能被一个消费者消费
发布订阅
消息消息可以被所有消费者消费
多线程下的消息消费
点对点
分支主题
发布订阅
分支主题
实战中的消息模型
分支主题
需求
1.消息发送方和接收方都是集群
2. 同一个消息的接收方可能有多个集群进行消息的处理
3. 不同集群对同一个消息的处理不能重复消费
问题
点对点
分支主题
集群A和集群B收到的消息都不完整
两个集群的消息加起来才是完整的消息
发布订阅
分支主题
集群A和集群B内部存在重复消费
解决方案
分支主题
集群间对消息的处理使用发布订阅,集群内对消息的处理使用点对点
6.2.4 订阅消息方式
非持久订阅
接收方启动订阅关系有效,接收方宕机订阅关系失效
持久订阅
接收方启动订阅关系有效,接收方宕机在激动后任然可以接受之前消息
6.3 消息的可靠性
分支主题
目标:保证消息不丢失
三个阶段
发送端发送消息到消息中间件可靠性
消息中间件及时、明确地返回成功,表示消息可靠达到消息中间件
消息中间件返回错误、出现异常、超时等情况,都表示消息未到达消息中间件
需要注意的是处理异常情况,不要吞掉异常
消息中间件存储消息可靠性
将消息存储在关系型数据库中
消息表
消息头
消息体
消息的投递对象
为了提高消息存储和调度的效率,采用宽表和冗余数据方式存储数据
宽表
将消息相关的信息都存储在一个表中,便于查询和插入
冗余
如果某条消息需要尽快处理,可以增加额外的投递表,提高调度消息
双机内存备份
分支主题
发送端将消息发给机器1
机器2备份机器1的消息
正常情况下消息的本地存储不会工作
分支主题
如果机器1发生故障,机器2将消息进行本地持久化
消息存储的扩容
消息中间件投递消息可靠性
消息中间件需要收到接受者确认消息处理的信号才能删除消息
消息接受者不能在接收到消息后就发送确认消息,而是在处理完业务后再发送确认消息
消息投递优化
多线程优化
使用多线程异步进行处理
步骤
1. 投递线程只负责将消息发送给接受端
2. 将需要等待处理结果的消息放置在内存中,不占用线程资源
3. 如果消息有结果,再将消息放入另外的线程池中处理
4. 处理完消息结果,通过批量的方式更新数据库的状态
多个接收端重复消费相同消息
方式一:不同的消费端共享同一个连接
分支主题
方式二:消息中间件只向应用发送一次消息,应用内部进行转发
分支主题
6.4 重复消息的发生和应对
发生原因
问题:消息发送方没有收到中间件返回成功的结果,消息重复发送
解决:消息发送方发送相同消息时消息ID都是相同
问题:消息中间件没有收到接受者返回处理成功的结果,消息重复投递
解决:消息接收端进行幂等性处理
JMS消息确认机制
AUTO_ACKNOWLEDGE
JMS接收到消息后自动确认,此时业务还没来得及处理就确认消息,不可靠
CLIENT_ACKNOWLEDGE
客户端调用message.acknowledge()方法进行确认消息
DUPS_OK_ACKNOWLEDGE
消息接收方的消息处理函数执行完毕后进行确认
6.5 其他消息属性
消息优先级
保证某些消息比其他消息优先处理
消息的顺序
分支主题
自定义属性
类似与Http的头信息,一般是对对消息的抽象描述,方便消息发送方和处理方快速获得消息的重要信息
局部顺序
分支主题
交易A或交易B内部的消息处理是有严格顺序(交易创建-》付款-》发货-》确认收货)
分支主题
6.6 消息的有序消费
消息中间件内部维护队列结构,存储消息
每个消息队列的消息严格顺序被接受和消费
同一个队列中,不同消费者分别维护自身指针,并且可以通过指针回溯,可以把消息消费回溯到之前的某一个位置
性能优化
分支主题
数据队列上存储物理队列的索引信息
每个队列的索引是独立的
好处
队列轻量化,单个队列数据非常少
对磁盘的访问串行化
6.7 消息中间件扩容
Master和Slave异步复制
类似于MySQL的Replication,Slave订阅到的消息总比Master少一点
Master和Slave同步复制
Master接受到消息后,主动发送给Slave,并且受到Slave响应后才给消息发送者返回“成功”结果
7、软负载中心
分支主题
分支主题
7.1 作用
聚合地址信息
分支主题
生命周期感知
分支主题
7.2 内部结构
服务端
感知提供服务的机器是否在线
聚合提供者的信息
将数据传给使用数据的应用
客户端
服务提供者
把服务提供者的信息主动传输给服务端
提供者的信息变更后负责更新服务端的数据
服务使用者
向服务端告知自己需要的数据
将数据缓存到本地,如果服务信息变更,负责更新本地数据
分支主题
聚合数据
数据结构:key-value
dataId是数据的唯一标识
同样额dataId内部支持分组(group)
通过dataId和group可以定位到具体的数据
订阅关系
服务使用者将自己需要的信息告知给软负载中心
订阅的粒度和聚合数据的粒度是一直的,也是通过dataId和Group
如果聚合数据有变化时,通过订阅关系找到使用者,通知使用者更新数据
连接数据
连接数据也是key-value结构,groupId作为Key,物理连接作为Value
当订阅数据发生变更时,通过订阅关系找到需要通知的groupId,通过groupId找到连接,通过连接发送最新数据
7.3 内容聚合
目标
1. 在异常或者复杂情况下,保证数据的正确性
2. 高效聚合数据
设计
1. 高并发保证数据的正确性。主要针对同一个数据的不同发布者,高并发下同时插入或者更新、删除数据
分支主题
使用锁或者并发容器保证线程安全
2. 数据更新、删除的顺序保证
3. 大量数据同时插入时的性能问题
分支主题
根据dataId和groupId分线程处理数据的新增、删除和更新操作,这样就不要锁保证线程安全。
7.4 服务上下线的通知
服务的提供者和使用者都与软负载中心保持长连接,软负载中心通过心跳检测感知服务的上线和下线
问题:由于软负载中心的高负载,可能导致心跳检测的响应超时,导致误判发生,这是需要服务的调用者在进行时需要确认下服务的状态
7.5 数据的分发
特点
分支主题
对比消息中间件的数据分发,消息中间件要保证每条消息的可靠到达,而软负载中心不需要确保每条消息的准确达到,而保证最新的消息到达即可。另外消息中间件的集群中每个节点不会消费同一条数据,而软负载的集群中的节点都需要接受分发的所有数据。
提高数据分发性能设计
数据压缩
全量和增量的选择
7.6 针对服务化的特性支持
软负载数据分组
根据开发/生产进行分组,保证不同环境的隔离
区分优先级的隔离,重要的服务使用者有专门的组来提供服务
提供自动感知上下线外人工控制
通过指令优雅的控制服务的开关
路由规则属于非持久化数据,单独维护管理
7.7 集群
数据管理问题
数据统一管理
分支主题
软负载中心不管理数据,无状态,这样数据发布者和订阅者连接任何软负载中心都可以
分支主题
软负载中心写数据和读数据分开,分工明确
数据对等方案
分支主题
软负载中心保存数据,集群中的各个节点互相通讯,任意节点数据发生变化,其他节点从该节点同步最新数据
这种方式的问题是节点间进行数据同步的成本高
优化
分支主题
数据分组且软负载分工后的方案
连接管理问题
8、集中配置管理
数据的维度
是否持久
持久性数据指的是数据本身与发布者的生命周期无关,
 相反,非持久性数据指的是与发布者的生命周期有关
持久性:订阅关系、路由规则、分库分表规则、数据库配置
非持久性:服务地址列表
是否聚合
聚合:服务地址列表、订阅关系
非聚合:路由规则
数据的组合
持久且聚合
持久非聚合
非持久且聚合
非持久非聚合
软负载中心管理非持久数据
集合配置关系中心管理持久数据
作用
1. 集中配置中心主要管理各个应用集合和中间件的配置信息
2. 通过集中配置中心对应用的行为进行修改
结构
分支主题
WebApp:负责操作数据等应用逻辑处理
Nginx:Nginx提供数据访问并返回给客户端
Local File:为了容灾和提升读写性能
客户端:提供对数据的访问
管理SDK:负责管理配置中心的数据
客户端实现和容灾策略
实现:客户端采用长轮询方式获得集中配置管理的数据
分支主题
容灾
数据本地缓存,缓存服务端数据,提高系统性能
数据本地快照,保存最近几次数据,为了方便数据回退
数据本地配置,本地配置是为了解决服务端不可用时有备用配置
文件格式采用文本格式,方便手动修改
服务端实现和容灾策略
实现:Web应用+Nginx+本地文件
Web应用从数据库获取数据
Nginx:负责处理Http请求和响应
本地文本:缓存数据的数据和进行容灾备份
业务
1、提供客户端数据的访问和数据更新
2、更细数据库的持久化数据
3、定时检查数据库的数据与本地数据的一致性
9、大型网站的其他要素
9.1 CDN
概念: 内容分发网络,是一种网络缓存技术,将一些相对静态的的文件(图片、视频、JS脚本)等内容分发到离用户最近的地方,加速用户的访问速度
组成
分支主题
CDN源
CDN节点
网络访问过程
传统
分支主题
加入CDN
分支主题
关键技术
1. 全局调度
2. 缓存技术,提高CND缓存命中率,再通过内存+SSD+机械硬盘方式提高缓存容量
3. 内容分发
4. 带宽优化
9.2 存储支持
1、分布式文件系统
2、NoSQL
3、缓存系统
数据缓存
页面缓存ESI
9.3 搜索系统
正排索引表
分支主题
倒排索引表
分支主题
9.4 数据计算
离线计算
MapReduce
在线计算
Storm
9.5 发布系统
1. 分发应用
2. 应用监测
3. 灰度发布
4. 产品改版Beta
9.6 应用监测系统
数据监控维度
系统数据
CPU、内存使用情况、IO情况等
应用数据
调用次数、成功率、响应时间等
数据记录方式
1. 记录在本地
2. 通过网络记录在远端
一般消息每隔一段时间记录,异常信息每条都记录
数据采集方式
服务器主动推送
监控中心轮询拉取
展现与警告
通过Web页面展示监控数据,设置告警条件和接收人
9.7 依赖管理系统
管理应用的依赖关系
依赖类型
强依赖:必须依赖
弱依赖:有了更好,没有也不影响功能
通过标识信息追踪请求的调用情况来研究系统的依赖关系
9.8 多机房问题
同城机房,主要价值在容灾
异地机房,CDN加速
9.9 系统容量规划
0 条评论
下一页