分布式学习
2019-07-17 14:54:55 1 举报
AI智能生成
分布式学习总结
作者其他创作
大纲/内容
分布式服务框架底层通信
I/O模型
阻塞
调用方发起调用请求,在没有返回结果之前,调用方线程被挂起,处于一直等待状态
非阻塞
非阻塞和阻塞的概念相对应,调用方发起请求,当线程不会等待挂起,而会立刻返回。后续可以通过轮询等手段来获取调用结果状态
同步
在发出一个功能调用时,在没有得到结果之前,该调用就会返回
异步
异步和同步的概率相对。当一个异步过程调用发出后,调用者不会立刻得到结果,通过回调等措施来处理这个调用
java I/O
Streams字节流
ByteArrayOutputStream/ByteArrayInputStream
ByteArrayOutputStream可以将数据写入字节数组,随着数据的写入能够自动扩容。无须调用close()方法进行关闭。ByteArrayInputStream可以将字节数组转换成输入流
FileOutputStream/FileInputStream
FileOutputStream用于将数据写入文件。一般用来写入二进制字节流。如图像文件的数据。FileInputStream用来从文件读取字节流数据
专门用于文件的I/O操作。适合于图片等二进制文件操作
FilterOutputStream/FilterInputStream
是所有过滤输入/输出流实现的超类。
BufferedOutputStream/BufferedInputStream
先将字节数据写入该缓冲类,再一次性输出。将单字节操作转变为批量操作字节数组,避免了做个字节处理操作,提高了I/O处理性能
DataOutputStream/DataInputStream
DataOutputStream提供了直接写入原生Java数据类型数据的能力,后续可以使用DataInputStream将数据读取到程序中并转换成对应Java数据类型
常用于网络数据传输过程中的写入与读取
PrintStream
字节打印流,功能很强大的一个装饰流,作为FilterInputStream的一个子类,在OutputStream基础上做了增强,可以方便地打印各种类型的数据。它可以自动刷新,当我们在构造PrintStream时指定它自动刷新,则每次调用它的print或println方法之后都会及时得地将数据写入底层字节输出流中,而不用手动调用flush去刷新。还有一个特性就是它从不抛出IOException
常用于日志输出组件的实现
ObjectOutputStream/ObjectInputStream
Java对象字节输入/输出流,一般用来实现java的序列化功能
常用于Java对象的反序列化/序列化或者网络数据的写入与读取
PipedOutputStream/PipedInputStream
通过管道读写字节流
Writer/Reader字符流
BufferedWriter/BufferedReader
先将字符数据写入或者读取到缓冲区,再一次性处理,相对于逐个字符处理,提高了I/O处理性能
使用了装饰模式,增加了对字符流操作缓存能力,使其能够批量读写字符流,提高了I/O操作的效率与性能
CharArrayWriter/CharArrayReader
CharArrayWriter提供了一个字符类型数据缓存,当写入数据的时候,缓冲区自动增长。CharArrayReader提供了字符输入流的缓存数组
能够将字符串或者字符数组转换为字符流
应用
某个第三方API使用字符流对外输出数据,writer可以将获得的字节流展示保存在内存,不必存到磁盘
OutputStreamWriter/InputStreamReader
InputStreamReader是字节输入流通想字符流的桥梁。OutputStreamWriter是字符输出流通向字节流的桥梁
FileWriter/FileReader
提供一字符为单位读写文件的能力。但是没有stream的性能好
一般用来操作文本文件
第三方接口返回的数据时字节流形式的文本,为了提高操作性能及操作便捷性,可以用这个将字节流转换为字符流
StringWriter/StringReader
将字符串String类型的数据适配到Writer与Reader操作
PipedWriter/PipedReader
通过管道读写字符流
PrintWriter
除了提供PrintStream中的所有print方法,还提供了格式化输出字符串的能力。其方法不会抛出I/O异常
字节流/字符流对比
因为一个字节8bit,而一个字符是16bit,字符串由字符组成,字符串类型天然处理的是字符而不是字节。更重要的是,字节流无法知道字符集及其字符编码
NIO
缓冲区(Buffer)
缓冲区实质上是一个数组。抽象类是Buffer
所有缓冲区的属性
容量
缓冲区能够容纳的数据元素的最大数量。这一容量在缓冲区创建时被设定,并且永远不能被修改
上界
缓冲区的第一个不能被读或写的元素。或者说是缓冲区中现存元素的计数
位置
下一个要被读或写的元素的索引。回执会自动由相应的get()和put()函数更新
标记
一个备忘位置。调用mark()来设定mark=postion。调用reset()设定position=mark。标记在设定前是未定义的
属性之间总是遵循的关系
0 <= mark <= position <= limit <= capacity
通道(Channel)
Stream VS Channel
Stream 是单向的,通过OutputStream实现输出流,InputStream实现输入流
Channel是全双工通道,可以通过Channel实现同时读取和写入
Selector选择器
Channel在Selector上注册,Selector通过不断轮询注册在骑上的Channel,能够感知到Channel可读或者可写事件。通过这种机制,可以使用一个或者少数几个线程管理大量的网络连接。用较少的线程处理大量的网络连接有很大的好处,可以减少线程之间的切换开销,而且线程本身也需要占用系统资源。
Netty
分布式服务架构负载实现
软负载的实现原理
目的
将请求按照某种策略分布到多台机器上,使得系统能够实现横向扩展,是应用实现可伸缩性的关键技术
定义
分布式服务架构中实现负载均衡是通过软件算法来实现的,有别于基于硬件设备实现负载均衡
原理
服务消费端在应用启动之初从服务注册中心获取服务提供者列表,缓存到服务调用端本地缓存
服务消费端发起服务调用之前,先通过某种策略或者短发从服务提供者列表本地缓存中选择本地调用的目标机器,再发起服务调用,从而完成负载均衡的功能
负载均衡算法
随机
获取服务列表大小范围内的随机数,将该随机数作为列表索引,从服务提供列表中获取服务提供者
加权随机
在随机算法的基础上针对权重做了处理。首先根据加权数放大服务提供者列表,比如服务提供者A加权数为3,放大之后变为A,A,A,存放在新的服务提供者列表,然后对新的服务提供者列表应用随机算法
轮询
将服务调用请求按顺序轮流分配到服务提供者后端服务器上,均衡对待每一台服务提供者机器
依次按顺序获取服务提供者列表中的数据,并使用计数器记录使用过得数据索引,若数据索引到最后一个数据,则计数器归零,重新开始新的循环
加权轮询
首先根据加权数放大服务提供者列表,再在放大后的服务提供者基础上使用轮询算法获取服务提供者
源地址hash
利用请求来源的IP的hashcode对服务提供者列表大小取模,得到服务提供者列表索引,从而获取服务提供者
使用调用方ip地址的hash值,将服务列表大小取模后的值作为服务列表索引,根据该索引取值
分布式服务架构服务治理
服务治理内容
服务注册与发现
软负载
服务质量监控与服务指标数据采集
服务分组路由
服务依赖关系分析
服务降级
服务权重调整
服务调用链路跟踪
记录负责人
实现
服务分组路由实现原理
由于注册中心都是保存的路径,所以在路劲中加入分组名。注册中心加入服务分组名路径之后,指定消费摸个服务组的消费端将该服务组下的服务提供者列表获取到本地缓存,消费端服务调用的时候,将按照指定的软负载算法从本地缓存中选取一个服务调用者发起调用
简单服务依赖关系分析实现
服务提供者信息与对应的服务消费者信息在注册中心已经存在了,所需要做的,不过是提供获取服务提供者信息与消费者信息列表的接口方法,从注册中心查找对应的信息
服务调用链路跟踪实现原理
在服务调用发起方生成标识本次调用的唯一ID,传递到服务提供方,然后将该ID使用ThreadLocal保存起来,在应用的业务代码里面使用拦截器统一从ThreadLocal中获取出来。
分布式
一般用来实现部署在不同机器上的系统之间的方法调用,使得程序能够像访问本地系统资源一样,通过网络传输去访问远端系统资源
组成部分
Client Code
客户端调用方代码实现,负责发起RPC调用,为调用方用户提供使用API
Serialization/Deserialization
负责RPC调用通过网络传输的内容进行序列化与反序列化,不同的RPC框架有不同的实现机制
Stub Proxy
屏蔽RPC调用过程中复杂的网络处理逻辑,使得RPC调用透明化,能够保持与本地调用一样的代码风格
Transport
作为RPC框架底层的通信传输模块,一般通过Socket在客户端与服务器端之间传递请求与应答消息
Server Code
服务端服务业务逻辑具体的实现
Java RMI
是一种基于Java的远程方法调用技术,是java特有的一种RPC实现
特性
支持真正的面向对象的多态性
Java独有,不支持其他语言
使用java原生的序列化机制,所有序列化对象必须实现java.io.Serializable接口
底层通信基于BIO(同步阻塞I/O)实现Socket完成
缺点
由于使用了java原生序列化机制与BIO通信机制(因为存在新能问题),所以导致RMI的性能较差
WebService
是一种跨平台的RPC技术协议
CXF
是一个开源的WebService RPC框架,它包含一个范围广泛、功能齐全的集合
特点
支持Web Service标准,包括SOAP规范,WSI Basic Profile、WSDL、WS-Addressing等
支持JSR相关规范和标准,包括JAX-WS、JAX-RS、SAAJ
支持多种传输洗衣和协议绑定、数据绑定
Axis2
是Axis的后续版本,是新一代的SOAP引擎,是CXF之外另外一个非常流行的Web Service/SOAP/WSDL实现
高性能,Axis2具有自己的轻量级对象模型AXIOM,并且采用stAx技术,具有更加优秀的性能表现,比前一代的内存消耗更低
热部署,Axis2配备了再系统启动和运行时部署Web服务和处理程序的功能
异步服务支持,支持使用非阻塞客户端的传输的异步,以及Web服务和异步Web服务调用
WSDL支持,支持Web服务描述语言版本1.1和2.0,它允许轻松构建存根以访问远程服务,还可以自动导出来自Axis2的已部署服务的机器可读描述
Thrift
是跨越不同的平台和语言,协助构建可伸缩的分布式系统的一种RPC实现,开源,具备广泛的语言支持以及高性能
Trrifts有着明显的性能优势,在于它是采用二进制编码协议、使用TCP/IP传输协议的一种RPC实现,而XML-RPC/JSON/-RPC/SOAP与WSDL协议栈采用文本协议,WSDL的实现WebService采用HTTP作为传输协议。对于网络数据传输,TCP/IP协议的性能要高于HTTP协议
gRPC
是Google的一个高性能、开源和通用的RPC框架,面向移动和HTTP/2设计
在个RPC里客户端应用可以像调用本地对象一样直接调用另一台不同机器上服务端应用的方法,能够更容易地创建分布式应用和服务
HTTP Client
序列化实现
序列化
是将对象的状态信息转换成为可存储或传输的形势过程
反序列化
是序列化的逆过程,将字节数组反序列化为对象,把字节序列恢复为对象的过程
作用
通过将对象序列化为字节数组,使得不共享内存通过网络连接的系统之间能够进行对象的传输
通过将对象序列化为字节数组,能够将对象永久存储到存储设备
解决远程接口调用JVM之间内存无法共享的问题
衡量指标
序列化后码流的大小
序列化本身的速度及系统资源开销大小
java默认的序列化(Serializable)
优点
java语言自带,无须额外引入第三方依赖
与java语言有天然的最好的易用性与亲和性
只支持java语言,不支持跨语言
java默认序列化性能欠佳,序列化后产生的码流过大,对于引用过深的对象序列化易发生内存溢出异常
XML序列化框架
可读性好,利于调试
由于XML具有语言无关性,可用于异构系统之间的数据交换协议(WebService)
由于使用标签对来表示数据,导致序列化后码流大,而且效率不高。(适用于对性能要求不高,且QPS较低的企业级内部系统之间的数据交换的场景)
JSON序列化框架
是一种轻量级的数据交换格式
相比XML,它的码流更小,而且保留了XML可读性好的优势
开源工具
Jackson
fastjson
GSON
总结
jackson与fastjson比GSON性能好,但是Jackson与GSON相对fastjson稳定性更好
Hessian序列化框架
支持跨语言传输的二进制序列化协议
相对于java默认的序列化机制,Hessian具有更好的性能与易用性
protobuf序列化框架
是一个纯粹的展示层协议,可以和各种传输层协议一起使用
文档非常完善
空间开销小及高解析性能,序列化后数据量相对少,也适合应用层对象的持久化场景
非常适合公司内部对性能要求高德RPC调用
由于需要编写.proto IDL文件,使用起来工作量稍大
需要额外学习proto IDL特有的语法,增加了额外的学习成本
protostuff序列化架构
实现了在代码执行时实现编译功能,而不必像protobuf那样通过它提供的编译器生成对应于各种语言的代码
protostuff-runtime实现了无须预编译对java bean进行protobuf序列化/反序列化的能力
具有高性能,同时免去了编写.proto文件的麻烦
thrift序列化框架
支持多种序列化协议,常用的有TBinaryProtocol、TCompactProtocol和TJSONProtocol。其中TBinaryProtocol为二进制序列化协议,TCompactProtocol可以看做是TBinaryProtocol的升级版,采用了字节压缩算法,进一步减少了序列化后的码流,TJSONProtocol是一种JSON数据格式序列化协议
需要编写以.thrift结尾的IDL文件,再使用thrift提供的编译器编译生成对应的代码
Avro序列化框架
动态类型
Avro无须生成代码。数据总是伴以模式定义,这样就可以在不生成代码、静态数据类型的情况下对数据进行所有处理,有利于构建通用的数据处理系统和语言
无标记数据
由于在读取数据时有模式定义,这就大大减少了数据编辑所需的类型信息,从而减少序列化空间开销
不用手动分配的字段ID
当数据模式发生变化,处理数据时总是同时提供新旧模式,差异就可以用字段名来做符号化的分析
性能高、基本代码少和产出数据量精简
丰富的数据结构类型
快速可压缩得二进制数据形式
存储持久数据的文件容器
远程过程调用RPC
简单的动态语言结合功能,Avro和动态语言结合后,读取数据文件和使用RPC协议都不需要生成代码,而代码生成作为一种可选的优化只值得在静态类型语言中实现
两种序列化编码方式
二进制
性能更高,序列化后产生的码流更小
JSON编码
编码后的可读性好,适合在开发调试阶段使用
JBoss Marshalling序列化框架
是一个java对象序列化包,兼容java原生的序列化机制,对其做了优化,在性能上有很大的提升
保持跟java.io.Serializable接口兼容的同时增加了一些可调的参数和附加特性,这些参数和附加的特性可通过工厂类进行配置,对原生java序列化是一个很好的替代
子主题
序列化框架的选型
技术层面
序列化空间开销,即序列化结果产生的码流大小,码流过大会对带宽、存储空间造成较大的压力
序列化时间开销,即徐丽华过程消耗的时长,序列化消耗时间过长会拖慢整个服务的响应时间
序列化协议是否支持跨平台、跨语言,公司内部存在异构系统通信需求时,往往要求RPC架构采用的序列化协议支持跨平台、跨语言
可扩展性/兼容性
成熟度及支持的数据结构的丰富性也是一个需要重点考量的方面
其他层面
技术的流行程度,背后是否有大公司技术支撑,是否是一个长期发展的持续进化的技术,是否已经得到业界的充分验证
学习难度和易用性
选型建议
对于公司间的系统调用,性能要求在100ms以上的服务,基于XML的SOAP洗衣是一个值得考虑的方案
基于Web Browser的Ajax,以及Mobile APP与服务器之间的通信,JSON协议是首选。对于性能要求不太高,或者动态类型语言为主,或者传输数据载荷很小的运用场景,JSON也是一个非常不错的选择
对于调试环境比较恶劣的场景,采用JSON或XML能够极大的提高调试效率,降低系统开发成本
对于性能和简洁性有极高要求的场景,Hessian,protobuf,Thrift,Avro之间具有一定的竞争关系。其中Hessian是在性能和稳定性同时考虑下最优的序列化协议
对于T级别的数据持久化应用场景,protobuf和Avro是首要选择。如果持久化后的数据存在Hadoop子项目里,Avro会是更好的选择
由于Avro的设计理念偏向于动态类型语言,对于以动态语言为主的应用场景,Avro是更好的选择
对于持久层非Hadoop项目,以静态类型语言为主的应用场景,protobuf会更符合静态类型语言工程师的开发习惯
对需要提供一个完成的RPC解决方案,Thrift是一个好的选择
对于序列化后需要支持不同的传输层协议,或者需要跨防火墙访问的高性能场景,Protobuf可以优先考虑
分布式服务框架注册中心
服务注册中心
分布式服务框架部署在多台不同的机器上,集群就是一个典型的例子,不同的集群之间要进行通信
实时存储更新服务提供者信息及该服务的实时调用信息。所有的服务调用者和服务提供者都得让服务注册中心知道
流程
服务启动的时候,将服务提供者信息主动上报到服务注册中心进行服务注册
服务调用者启动的时候,将服务提供者信息从注册中心下拉到读物调用者机器本地缓存,服务调用者从本地缓存的服务提供者地址列表中,基于某种服务负载均衡策略选择一台服务提供者发起远程调用
服务注册中心能够感知服务提供者集群中某一台机器下线,将该机器服务提供者信息从服务注册中心删除,并主动通知服务调用者集群中的每一台机器,使得服务调用者不在调用该机器
软负载及透明化服务路由:服务提供者和服务调用者之间相互解耦,服务调用者不需要硬编码服务提供者地址
服务动态发现及可伸缩能力:服务提供者机器增减能被服务调用者通过注册中心动态感知,而且通过增减机器可以实现服务的弹性伸缩
通过注册中心可以动态地监控服务运行质量及服务依赖,为服务提供服务治理能力
Zookeeper
提供了统一命名服务、配置管理、分布式锁等分布式基础服务,基于这些服务,可以实现集群管理、软负载、发布/订阅、分布式锁,分布式队列、命名服务等
实现服务注册中心
实现流程
服务注册中心还可以用来收集服务消费者信息,以达到实现部分服务治理功能的目的。在服务消费端,通过将服务消费者信息写入ZooKeeper临时节点,一旦消费者机器下线,断开与ZooKeeper的连接,该临时节点将被自动删除,达到通过ZooKeeper自动收集消息者信息的目的
作用及应用
收藏
收藏
0 条评论
下一页