440 likes | 741 Views
实现轻型服务器的 Java TM 方法. 议题. < 在此处插入图片 >. 背景 Java NIO 和 NIO.2 JSSE 和 SSLEngine 结论. 背景. C10K 问题 轻型 Web 服务器 (Nginx 、 Lighttpd) NIO 架构 (Netty 、 Apache MINA) Grizzly. 目标. 改善延迟 提高可伸缩性 最大限度提高吞吐量 最大限度提高性能 可重用性. 议题. < 在此处插入图片 >. 背景 Java NIO 和 NIO.2 JSSE 和 SSLEngine 结论.
E N D
议题 <在此处插入图片> • 背景 • Java NIO 和 NIO.2 • JSSE 和 SSLEngine • 结论
背景 • C10K 问题 • 轻型 Web 服务器 (Nginx、Lighttpd) • NIO 架构(Netty、Apache MINA) • Grizzly
目标 • 改善延迟 • 提高可伸缩性 • 最大限度提高吞吐量 • 最大限度提高性能 • 可重用性
议题 <在此处插入图片> • 背景 • Java NIO 和 NIO.2 • JSSE 和 SSLEngine • 结论
Java I/O • 阻塞 I/O (Java SE 1.4 之前) • 调用者被阻塞 • 非阻塞 I/O (NIO) (Java SE 1.4) • 调用者即时获得数据或错误代码 • 异步 I/O (NIO.2) (Java SE 1.7) • 调用者获得通知
传统服务模式 • ServerSocket/Socket • InputStream/OutputStream • 线程 (1:1) 服务器
传统服务模式 • ServerSocket/Socket • InputStream/OutputStream • ExecutorService (JDK 1.5) • 线程池 (M:N) 线程池 服务器 线程池
传统服务模式 • 操作系统的线程数限制 • 线程上下文切换是一种“高负载”操作 • 工作线程是 I/O 绑定的 线程 Pool 服务器 线程池
读取 | 写入 读取 | 写入 读取 | 写入 反应器 NIO 反应器模式 • Selector/SelectionKey • Channel/Buffer • 线程 (1:N) 服务器 . 线程 分派器 接收器
读取 | 写入 读取 | 写入 读取 | 写入 反应器 NIO 反应器模式 • Selector/SelectionKey • Channel/Buffer • 工作线程池 • 线程 (1:X:N) 线程池 服务器 . 线程 分派器 接收器
读取 | 写入 读取 | 写入 读取 | 写入 反应器 NIO 反应器模式 • Selector/SelectionKey • Channel/Buffer • 工作线程池/多个反应器 • 线程 (K:X:N) 线程池 线程池 服务器 分派器 接收器
NIO.2 前摄器模式 不要联系我们,我们会联系您!
NIO.2 前摄器模式 不要联系我们,我们会联系您!
前摄器 NIO.2 前摄器模式 • AsynchronousChannel/Buffer • AsynchronousChannelGroup • CompletionHandler • 线程 (M:N) 线程池 不要联系我们,我们会联系您! 服务器 处理器 分派器 接受 读取|写入
前摄器 NIO.2 前摄器模式 • 充分利用操作系统 I/O 功能 线程池 不要联系我们,我们会联系您! 服务器 处理器 分派器 接受 读取|写入
NIO.2 概念 • 发起非阻塞 I/O 操作 • 在 I/O 完成时发出通知
CompletionHandler • interface CompletionHandler<V,A> { • void completed(V result, A attachment); • void failed(Throwable exc, A attachment); • } • V = 结果值的类型 • A = 附加到 I/O 操作中的对象的类型 • 用于传递上下文 • 通常封装连接上下文 • 若成功则会调用 completed 方法 • 若 I/O 操作失败则会调用 failed 方法
CompletionHandler class Connection { … } class Handler implements CompletionHandler<Integer, Connection> { public void completed(Integer result, Connection conn) { // handle result } public void failed(Throwable exc, Connection conn) { // error handling } } AsynchronousSocketChannel ch = ... ByteBuffer buf = ... Connection conn = ... Handler handler = ... ch.read(buf, conn, handler);
AsynchronousSocketChannel • 异步连接 • 异步读取/写入 • 异步分散/集中(多个缓冲区) • 读取/写入操作支持超时设置 • 出现超时异常时调用 failed 方法 • 实现 NetworkChannel • 用于绑定、设置套接字选项等
ChannelGroup • 哪些线程调用 completion 处理器? • 面向网络的通道与一个组绑定 • AsynchronousChannelGroup • 组封装线程池和其他共享资源 • 创建含线程池的组 • 较为简单的应用程序的默认组 • 由池线程调用 Completion 处理器 • AsynchronousFileChannel 可以使用自己的线程池(单一组)来创建
创建一个组 // custom thread pool ExecutorService pool = ... AsynchronousChannelGroup group = AsynchronousChannelGroup .withThreadPool(pool); AsynchronousSocketChannel channel = AsynchronousSocketChannel.open(group);
Buffer 和 ByteBuffer • 直接和非直接 Buffer • ByteBuffer.allocateDirect() • MappedByteBuffer
ByteBuffer 的问题 • 问题: • 假设接受了 10000 个连接 • 因此会创建 10000 个 ByteBuffer 并调用读取操作 • 现在,我们等待、等待、再等待,等待远程客户端向我们发送字节(客户端/网络非常慢) • 这时接收到另外 10000 个请求,我们再一次创建 10000 个 ByteBuffer 并调用 read() operations.ByteBuffer.allocateDirect() MappedByteBuffer • 系统不堪重负!
使用 ByteBuffer 池和限制 • 我们不必过于消极。目前为止,我们对超过 20000 个客户端进行了测试,均未出现任何问题 • 但您仍然需要谨记上面的问题!! • 您可能希望对 read() 操作进行限制,以避免创建过多的 ByteBuffer • 我们强烈建议使用 ByteBuffer 池,特别是在使用堆时。在调用 read() 方法之前获取一个 ByteBuffer,并在读取操作完成后立即将其返回给池。
议题 <在此处插入图片> • 背景 • Java NIO and NIO.2 • JSSE 和 SSLEngine • 结论
SSL/TLS 和 JSSE • TLS/SSL 协议 • HTTPS 协议 • JavaTM安全套接字扩展 • SSLEngine与非阻塞 I/O
NIO 和 NIO.2 的 SSLEngine ByteBuffer
SSLEngine 操作 • SSLEngine.wrap(ByteBuffer src, ByteBuffer dst) • SSLEngine.unwrap(ByteBuffer src, ByteBuffer dst) • SSLEngine.getDelegatedTask()
SSLEngineResult.HandshakeStatus • NEED_UNWRAP • SSLEngine 需要先从远端接收数据,然后才能继续握手。 • NEED_WRAP • SSLEngine 必须先将数据发送给远端,然后才能继续握手,因此应调用 SSLEngine.wrap()。
SSLEngineResult.HandshakeStatus • FINISHED • SSLEngine 刚完成握手。 • NEED_TASK • SSLEngine 需要一个(或多个)委托任务的结果,然后才能继续握手。 • NOT_HANDSHAKING • SSLEngine 当前未进行握手。
SSLEngineResult.Status • OK • SSLEngine 已完成该操作。
SSLEngineResult.Status • BUFFER_OVERFLOW • SSLEngine 无法处理操作,因为目标缓冲区中没有足够的空间来保存结果。 • BUFFER_UNDERFLOW • SSLEngine 无法解包传入数据,因为源空间没有足够的可用数据来建立完整有效的协议包。 • CLOSED • SSLEngine 已经关闭,操作无法完成。
前摄器 NIO.2 前摄器模式中的 SSLEngine 服务器 线程池 处理器 分派器 接受 读取|写入 不要联系我们,我们会联系您! SSLENGINE 状态 分派器
议题 <在此处插入图片> • 背景 • Java NIO and NIO.2 • JSSE 和 SSL 引擎 • 结论
总结 • NIO.2 和 SSLEngine 非常适于构建安全轻型服务器。 • NIO.2 已在 JDK7 试用版中提供,赶快体验它吧!
更多信息 — NIO.2 • OpenJDK NIO.2 页面: • http://openjdk.java.net/projects/nio/ • NIO.2 文档 • http://openjdk.java.net/projects/nio/javadoc/ • NIO.2 邮件列表 • nio-dev@openjdk.java.net • Alan 的博客 • http://blogs.sun.com/alanb/
更多信息 — JSSE • JSSE 参考指南: • http://download.oracle.com/javase/7/docs/technotes/guides/security/jsse/JSSERefGuide.html • 安全开发邮件列表 • security-dev@openjdk.java.net
更多信息 — Grizzly • Grizzly 项目: • http://grizzly.dev.java.net • Grizzly 的 Twitter • http://twitter.com/project_grizzly