【目录】
1.Java Socket编程*:如何基于Socket 实现 Server
2.深入讨论IO*: Server 处理时到底发生了什么
3.IO模型与相关概念*:怎么理解 NIO
4.Netty框架简介:什么是Netty
5.Netty使用示例*:如何使用Netty实现NIO
6.总结
1.Java Socket编程
IP:标识主机唯一性
端口:标识主机上对应的不同进程 or 服务
Java实现一个最简单的HTTP服务器(三种方式)
// 单线程处理socket
public class SocketHttpDemo {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(8081);
while (true) {
Socket socket = serverSocket.accept();
service(socket);
}
}
private static void service(Socket socket) {
try {
Thread.sleep(20);
PrintWriter printWriter = new PrintWriter(socket.getOutputStream(), true);
printWriter.println("HTTP/1.0 200 ok");
printWriter.println("Content-type:text/html;charset=utf-8");
printWriter.println();
printWriter.println("hello nio");
printWriter.close();
socket.close();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
// 每个请求一个线程
public class SocketHttpDemo {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(8081);
while (true) {
Socket socket = serverSocket.accept();
new Thread(() -> {
service(socket);
}).start();
}
}
private static void service(Socket socket) {
try {
Thread.sleep(20);
PrintWriter printWriter = new PrintWriter(socket.getOutputStream(), true);
printWriter.println("HTTP/1.0 200 ok");
printWriter.println("Content-type:text/html;charset=utf-8");
printWriter.println();
printWriter.println("hello nio");
printWriter.close();
socket.close();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
// 固定大小的线程池处理
public class SocketHttpDemo {
public static void main(String[] args) throws IOException {
ExecutorService executorService = Executors.newFixedThreadPool(40);
ServerSocket serverSocket = new ServerSocket(8081);
while (true) {
Socket socket = serverSocket.accept();
executorService.execute(()->{
service(socket);
});
}
}
private static void service(Socket socket) {
try {
Thread.sleep(20);
PrintWriter printWriter = new PrintWriter(socket.getOutputStream(), true);
printWriter.println("HTTP/1.0 200 ok");
printWriter.println("Content-type:text/html;charset=utf-8");
printWriter.println();
printWriter.println("hello nio");
printWriter.close();
socket.close();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
压测环境可观察三种情况下执行效率
2.深入讨论IO*: Server 处理时到底发生了什么
服务分类有CPU密集型(计算/业务操作)和IO密集型(IO操作与等待/网络,磁盘,数据库等)
使用多线程可以提升CPU执行效率,过多则会导致频繁上下文切换花销变大,得不偿失,要合理分配线程大小
3.IO模型与相关概念
同步 / 异步(回调函数) 是通信模式
阻塞 / 非阻塞 是线程处理模式
①阻塞式IO - BIO
最常见,按顺序执行同时等待程序按步骤执行的过程
②非阻塞IO
与阻塞IO类比,内核会立即返回做其他事;
用户进程第一阶段并不阻塞,会不断主动询问kernel数据是否准备好;第二个阶段依旧是阻塞的,要等数据执行;
③IO多路复用 - 事件驱动IO
思想:先全部接收请求,内部再进行服务的执行(将接收请求和服务分离)
单线程中同时监控多个套接字,通过select或poll轮询所负责的所有socket,当某个socket有数据到达,通知用户进程
select - 数组
poll - 链表
epoll - 红黑树
④epoll Reactor模型
⑤信号驱动IO
消息队列的最早的原型
线程池 -> EDA(事件驱动架构) -> SEDA(分阶段事件驱动架构)
⑥异步IO
IO全流程的非阻塞;用户进程发出系统调用后立即返回,内核等待数据准备完成,之后将数据拷贝至用户进程缓冲区,之后发送信号告诉用户进程IO操作执行完毕(回调过程)
各个环境支持异步IO时间:
4.Netty
特点:
- 异步
- 事件驱动
- 基于NIO
适用于 服务端、客户端、TCP/UDP
高性能的协议服务器:
- 高吞吐
- 低延迟
- 低开销
- 零拷贝
- 可扩容
- 松耦合:网络和业务逻辑分离
- 使用方便,可维护性好
基本概念:
Event & Handler
入站事件:
- 通道激活和停用
- 读操作事件
- 异常事件
- 用户事件
出站事件:
- 打开连接
- 关闭连接
- 写入连接
- 刷新数据
Netty 应用组成:
- 网络事件
- 应用程序逻辑事件
- 事件处理程序
5.NIO程序
管道 + 过滤器 实现网关demo