网络中大量数据流动涉及 I/O 问题,大多web应用系统的瓶颈都是 I/O 瓶颈。本章分析I/O内在工作机制,介绍java I/O 类库、磁盘I/O 和 网络 I/O 的工作机制,还有同步异步、阻塞非阻塞的区别,以及一些I/O优化技巧。
java 的 I/O 操作类主要在 java.io 包下的 ,可以分为 4 组:
基于字节操作的 I/O 接口:InputStream OutputStream
基于字符操作的 I/O 接口:Reader Writer
基于磁盘操作的 I/O 接口:File
基于网络操作的 I/O 接口:Socket
数据格式(前两组) 传输方式(后两组)
注意:在使用流的时候,必须要指定流最终写到什么地方,要么写到磁盘,要么写到网络中。
a. InputStream
This abstract class is the superclass of all classes representing an input stream of bytes.
b. OuputStream
This abstract class is the superclass of all classes representing an output stream of bytes. An output stream accepts output bytes and sends them to some sink.
注意:不管是Writer还是Reader,它们都只定义了读取或写入的数据字符的方式,并没有规定数据要写到哪里。
a. Reader
Abstract class for reading character streams. The only methods that a subclass must implement are read(char[], int, int) and close(). Most subclasses, however, will override some of the methods defined here in order to provide higher efficiency, additional functionality, or both.
b. Writer
Abstract class for writing to character streams. The only methods that a subclass must implement are write(char[], int, int), flush(), and close(). Most subclasses, however, will override some of the methods defined here in order to provide higher efficiency, additional functionality, or both.
a. InputStreamReader
An InputStreamReader is a bridge from byte streams to character streams: It reads bytes and decodes them into characters using a specified {@link java.nio.charset.Charset charset}. The charset that it uses may be specified by name or may be given explicitly, or the platform’s default charset may be accepted.
b. OuputStreamWriter
An OutputStreamWriter is a bridge from character streams to byte streams: Characters written to it are encoded into bytes using a specified {@link java.nio.charset.Charset charset}. The charset that it uses may be specified by name or may be given explicitly, or the platform’s default charset may be accepted.
Java序列化就是将一个对象转化成一串二进制表示的字节数组,通过保存或转移这些字节数据来达到持久化的目的。
反序列化时,必须有原始类作为模板,才能将这个对象还原。
注意:
序列化的属性是对象,则这个对象必须实现Serializable接口,否则会报错;
反序列化时,如果对象的属性有修改或删减,则修改的部分属性会丢失,但不会报错;
在多语言环境下,用Java序列化存储后,很难用其他语言还原出结果。在这种情况下,尽量存储通用的数据结构,如JSON或者XML结构数据。
a. 网络带宽
b. 传输距离
c. TCP拥塞控制
socket是在应用层和传输层之间的一个抽象层,是对TCP/IP协议的封装和应用,它把TCP/IP层复杂的操作抽象为几个简单的接口供应用层调用已实现进程在网络中通信。
建立连接后,客户端和服务端都有一个Socket实例,每个实例都会有一个InputStream和一个OutputStream, 并通过这两个对象交换数据。
读写阻塞;
不同客户端的给不同的优先级;
访问竞争资源;
数据流图:
数据发送端 –>发送端Buffer缓冲区 –> 发送端Channel —> 网络 –> 接收端Channel –>接收端Buffer缓冲区 –>数据接收端
Selector检测信道中有数据传输时,将数据 读/写 到buffer。
原始
写入5字节
Transfer——数据直接在内核空间移动–减少内核到用户空间的复制
Map——将文件映射为内存区域
性能指标
系统 I/O wait
磁盘 IOPS
提升性能
加缓存,减少IO
优化磁盘管理系统
设计合理的磁盘 存储/访问 数据块的策略
应用合理的 RAID 策略。
可分配端口数
大量TIME_WAIT——调小tcp_fin_timeout, 快速释放请求
调优参数。。。
查看 tcp 统计信息
处理原则:
减少交互次数——合并请求,打包发送
减小传输数据量——数据压缩
尽量减少编码——以字节发送,减少字符到字节的转化
交互场景:
a. 同步与异步:【调用】在发出之后,是否直接返回
b. 阻塞与非阻塞:【调用结果】返回之前,该调用会不会阻塞当前线程
Target: 目标接口, 期待的接口
Adaptee : 源角色,需要适配的接口
Adapter: 适配器,继承源接口,实现目标接口
适配器: InputStreamReader ,实现了 Reader 接口,(间接)持有 InputStream 的引用,实现 byte 到 char 转换。
Component: 抽象组件角色,定义一组抽象接口。
ConcreteComponent: 实现抽象组建的所有功能。
Decorator: 装饰器角色,持有一个Component对象实例的引用,定义一个与抽象组件一致的接口。
ConcreteDecorator: 具体的装饰器实现者,负责实现装饰器角色定义的功能。
抽象组件:InputStream
具体组件:FileInputStream,实现抽象组件的所有接口,
装饰角色:FilterInputStream,实现了 InputStream 的所有接口,并且持有 InputStream 的对象实例的引用。
具体的装饰器实现者:BufferedInputStream,他给 InputStream 附加了功能,提高读性能。
类似的类还有 LineNumberInputStream
适配器————转换接口,保持功能
装饰器————保持接口,增强功能