Upload
kaipo
View
140
Download
0
Embed Size (px)
DESCRIPTION
实现轻型服务器的 Java TM 方法. 议题. < 在此处插入图片 >. 背景 Java NIO 和 NIO.2 JSSE 和 SSLEngine 结论. 背景. C10K 问题 轻型 Web 服务器 (Nginx 、 Lighttpd) NIO 架构 (Netty 、 Apache MINA) Grizzly. 目标. 改善延迟 提高可伸缩性 最大限度提高吞吐量 最大限度提高性能 可重用性. 议题. < 在此处插入图片 >. 背景 Java NIO 和 NIO.2 JSSE 和 SSLEngine 结论. - PowerPoint PPT Presentation
Citation preview
‹#›
< 在此处插入图片 >
实现轻型服务器的 JavaTM 方法
‹#›
< 在此处插入图片 >
议题
• 背景• 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 绑定的
传统服务模式
服务器
线程池
‹#›
• Selector/SelectionKey• Channel/Buffer• 线程 (1:N)
NIO 反应器模式
服务器
. 线程反应器
接收器
分派器
读取 | 写入
读取 | 写入
读取 | 写入
‹#›
• Selector/SelectionKey• Channel/Buffer• 工作线程池• 线程 (1:X:N)
NIO 反应器模式
服务器
. 线程反应器
接收器
分派器
读取 | 写入
读取 | 写入
读取 | 写入
‹#›
• Selector/SelectionKey• Channel/Buffer• 工作线程池 /多个反应器• 线程 (K:X:N)
NIO 反应器模式
服务器
反应器
接收器
分派器
读取 | 写入
读取 | 写入
读取 | 写入
‹#›
NIO.2 前摄器模式
‹#›
NIO.2 前摄器模式
‹#›
• AsynchronousChannel/Buffer• AsynchronousChannelGroup• CompletionHandler• 线程 (M:N)
NIO.2 前摄器模式
服务器
前摄器
处理器
分派器
读取 | 写入
接受
‹#›
• 充分利用操作系统 I/O 功能
NIO.2 前摄器模式
服务器
前摄器
处理器
分派器
读取 | 写入
接受
‹#›
• 发起非阻塞 I/O 操作• 在 I/O 完成时发出通知
NIO.2 概念
‹#›
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);
CompletionHandler
‹#›
• 异步连接• 异步读取 / 写入• 异步分散 / 集中(多个缓冲区)• 读取 / 写入操作支持超时设置– 出现超时异常时调用 failed 方法
• 实现 NetworkChannel– 用于绑定、设置套接字选项等
AsynchronousSocketChannel
‹#›
• 哪些线程调用 completion 处理器?• 面向网络的通道与一个组绑定– AsynchronousChannelGroup
• 组封装线程池和其他共享资源• 创建含线程池的组• 较为简单的应用程序的默认组• 由池线程调用 Completion 处理器• AsynchronousFileChannel 可以使用自己的线程池
(单一组)来创建
ChannelGroup
‹#›
// custom thread poolExecutorService pool = ...
AsynchronousChannelGroup group = AsynchronousChannelGroup .withThreadPool(pool);
AsynchronousSocketChannel channel = AsynchronousSocketChannel.open(group);
创建一个组
‹#›
Buffer 和 ByteBuffer
‹#›
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
‹#›
SSLEngine
‹#›
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
服务器
线程池
前摄器
处理器
分派器
读取 | 写入
接受
SS
LE
NG
INE
状态
分派器
‹#›
< 在此处插入图片 >
议题
• 背景• 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 邮件列表– [email protected]
• Alan 的博客– http://blogs.sun.com/alanb/
‹#›
更多信息 — JSSE
• JSSE 参考指南:– http://download.oracle.com/javase/7/docs/technotes/guides/
security/jsse/JSSERefGuide.html
• 安全开发邮件列表– [email protected]
‹#›
更多信息 — Grizzly
• Grizzly 项目:– http://grizzly.dev.java.net
• Grizzly 的 Twitter– http://twitter.com/project_grizzly
‹#›
问答
‹#›