美文网首页程序员
高性能服务器线程模型演进 Tomcat Netty Vert.x

高性能服务器线程模型演进 Tomcat Netty Vert.x

作者: 黄大海 | 来源:发表于2020-06-16 20:20 被阅读0次

    Hello World

    • 让我们从最简单的单线程阻塞模型开始
    ServerSocket server = new ServerSocket(8080);
        
    Socket socket = server.accept();
    
    InputStream inputStream = socket.getInputStream();
    
    byte[] bytes = new byte[1024];
    int len;
    StringBuilder sb = new StringBuilder();
    while ((len = inputStream.read(bytes)) != -1) {
        sb.append(new String(bytes, 0, len,"UTF-8"));
    }
    
    System.out.println("get message from client: " + sb);
    
    OutputStream outputStream = socket.getOutputStream();
    outputStream.write("Hello World".getBytes("UTF-8"));
    
    
    outputStream.close();
    inputStream.close();
    socket.close();
    server.close();
    
    • 这个初始版本只能单线程处理,其中的IO会堵塞,性能很差


      单线程.jpg

    tomcat

    • tomcat是我们比较熟悉的传统web容器。提供了多线程的线程模型和NIO多路复用
      • 用一个Acceptor线程统一处理连接
      • 连上后交给Poller处理底层协议和一般性的IO,Poller线程数为CPU个数
      • Poller线程处理完底层的协议之后把servlet相关的请求交给worker处理, worker线程数默认是200个
    tomcat2.jpg
    • 但是tomcat的异步处理只是占一部分, 并不彻底
      tomcat io 对比
      tomcat_io.jpg

    netty

    • netty提供了更高效率的线程模型。当然他也使用了DirectBuffer, JCTools的高性能无锁队列。这里只介绍线程模型:
    netty.jpg
    • EventLoop类似于tomcat中的Poller,主要处理连接之外的全部IO。线程数是CPU*2
    • 另外Eventloop也会处理协议和业务回调。参考源码:NIOEventLoop#run
            final long ioStartTime = System.nanoTime();
            try {
                   processSelectedKeys(); // 处理IO
            } finally {
                   // Ensure we always run tasks.
                   final long ioTime = System.nanoTime() - ioStartTime;
                   // 用相同的时间处理回调业务
                   ranTasks = runAllTasks(ioTime * (100 - ioRatio) / ioRatio);                         
            }
    
    • IO处理和任务处理的默认比例是1:1
    • Netty这样做有几个好处
      • 使用较少的线程意味着减少上下文切换
      • 使用较少内存,java每个线程栈默认1M开销
      • 一个EventLoop绑定多个Channel和对应的业务处理。从channel的角度看是单线程的,不存在线程切换,不需要处理并发问题。
    • 当然Netty的线程处理有个大前提。不能block Eventloop!!!
    • 但是传统的业务处理都是阻塞型的,必须开另外的线程池处理,这就和tomcat比优势不明显了

    vert.x

    • vert.x是对netty的高级别封装,其核心还是EventLoop
    • 他通过全异步的方式使得IO全异步处理而通过少量线程性能最大化
    vertx.jpg
    • 这个例子里通过Vert.x的EventLoop接管http/redis的IO和回调
    • 理论上所有的代码都可以异步,vert.x提供了大量的常用框架的异步IO适配。
    • 对于不能或不方便的阻塞代码, 通过worker线程池处理,幷提供异步回调接口(例子中的mysql调用)

    为什么netty/nginx之类的高性能服务器不用AIO呢?

    相关文章

      网友评论

        本文标题:高性能服务器线程模型演进 Tomcat Netty Vert.x

        本文链接:https://www.haomeiwen.com/subject/eitdxktx.html