返回顶部
首页 > 资讯 > 精选 >Java NIO怎么处理慢速的连接
  • 839
分享到

Java NIO怎么处理慢速的连接

2023-06-17 11:06:08 839人浏览 八月长安
摘要

本篇内容主要讲解“Java NIO怎么处理慢速的连接”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Java Nio怎么处理慢速的连接”吧!对企业级的服务器软件,高性能和可扩展性是基本的要求。除此

本篇内容主要讲解“Java NIO怎么处理慢速的连接”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Java Nio怎么处理慢速的连接”吧!

对企业级的服务器软件,高性能和可扩展性是基本的要求。除此之外,还应该有应对各种不同环境的能力。例如,一个好的服务器软件不应该假设所有的客户端都有很快的处理能力和很好的网络环境。如果一个客户端的运行速度很慢,或者网络速度很慢,这就意味着整个请求的时间变长。而对于服务器来说,这就意味着这个客户端的请求将占用更长的时间。这个时间的延迟不是由服务器造成的,因此CPU的占用不会增加什么,但是网络连接的时间会增加,处理线程的占用时间也会增加。这就造成了当前处理线程和其他资源得不到很快的释放,无法被其他客户端的请求来重用。例如Tomcat,当存在大量慢速连接的客户端时,线程资源被这些慢速的连接消耗掉,使得服务器不能响应其他的请求了。

前面介绍过,NIO的异步非阻塞的形式,使得很少的线程就能服务于大量的请求。通过Selector的注册功能,可以有选择性地返回已经准备好的频道,这样就不需要为每一个请求分配单独的线程来服务。

在一些流行的NIO的框架中,都能看到对OP_ACCEPT和OP_READ的处理。很少有对OP_WRITE的处理。我们经常看到的代码就是在请求处理完成后,直接通过下面的代码将结果返回给客户端:

不对OP_WRITE进行处理的样例:

while (bb.hasRemaining()) {      int len = SocketChannel.write(bb);      if (len < 0) {          throw new EOFException();      }  }

这样写在大多数的情况下都没有什么问题。但是在客户端的网络环境很糟糕的情况下,服务器会遭到很沉重的打击。

因为如果客户端的网络或者是中间交换机的问题,使得网络传输的效率很低,这时候会出现服务器已经准备好的返回结果无法通过tcp/IP层传输到客户端。这时候在执行上面这段程序的时候就会出现以下情况。

(1) bb.hasRemaining()一直为“true”,因为服务器的返回结果已经准备好了。

(2) socketChannel.write(bb)的结果一直为0,因为由于网络原因数据一直传不过去。

(3) 因为是异步非阻塞的方式,socketChannel.write(bb)不会被阻塞,立刻被返回。

(4) 在一段时间内,这段代码会被无休止地快速执行着,消耗着大量的CPU的资源。事实上什么具体的任务也没有做,一直到网络允许当前的数据传送出去为止。

这样的结果显然不是我们想要的。因此,我们对OP_WRITE也应该加以处理。在NIO中最常用的方法如下。

一般NIO框架中对OP_WRITE的处理:

while (bb.hasRemaining()) {      int len = socketChannel.write(bb);      if (len < 0){          throw new EOFException();      }      if (len == 0) {          selectionKey.interestOps(                          selectionKey.interestOps() | SelectionKey.OP_WRITE);          mainSelector.wakeup();          break;      }  }

上面的程序在网络不好的时候,将此频道的OP_WRITE操作注册到Selector上,这样,当网络恢复,频道可以继续将结果数据返回客户端的时候,Selector会通过SelectionKey来通知应用程序,再去执行写的操作。这样就能节约大量的CPU资源,使得服务器能适应各种恶劣的网络环境。

可是,Grizzly中对OP_WRITE的处理并不是这样的。我们先看看Grizzly的源码吧。在Grizzly中,对请求结果的返回是在ProcessTask中处理的,经过SocketChannelOutputBuffer的类,最终通过OutputWriter类来完成返回结果的动作。在OutputWriter中处理OP_WRITE的代码如下:

Grizzly中对OP_WRITE的处理:

public static long flushChannel(SocketChannel socketChannel,          ByteBuffer bb, long writeTimeout) throws IOException  {      SelectionKey key = null;      Selector writeSelector = null;      int attempts = 0;      int bytesProduced = 0;      try {          while (bb.hasRemaining()) {              int len = socketChannel.write(bb);              attempts++;              if (len < 0){                  throw new EOFException();              }              bytesProduced += len;              if (len == 0) {                  if (writeSelector == null){                      writeSelector = SelectorFactory.getSelector();                      if (writeSelector == null){                          // Continue using the main one                          continue;                      }                  }                  key = socketChannel.reGISter(writeSelector, key.OP_WRITE);                  if (writeSelector.select(writeTimeout) == 0) {                      if (attempts > 2)                          throw new IOException("Client disconnected");                  } else {                      attempts--;                  }              } else {                  attempts = 0;              }          }      } finally {          if (key != null) {              key.cancel();              key = null;          }          if (writeSelector != null) {              // Cancel the key.              writeSelector.selectNow();              SelectorFactory.returnSelector(writeSelector);          }      }      return bytesProduced;  }

上面的程序例17.9与例17.8的区别之处在于:当发现由于网络情况而导致的发送数据受阻(len==0)时,例17.8的处理是将当前的频道注册到当前的Selector中;而在例17.9中,程序从SelectorFactory中获得了一个临时的Selector。在获得这个临时的Selector之后,程序做了一个阻塞的操作:writeSelector.select(writeTimeout)。这个阻塞操作会在一定时间内(writeTimeout)等待这个频道的发送状态。如果等待时间过长,便认为当前的客户端的连接异常中断了。

这种实现方式颇受争议。有很多开发者置疑Grizzly的作者为什么不使用例17.8的模式。另外在实际处理中,Grizzly的处理方式事实上放弃了NIO中的非阻塞的优势,使用writeSelector.select(writeTimeout)做了个阻塞操作。虽然CPU的资源没有浪费,可是线程资源在阻塞的时间内,被这个请求所占有,不能释放给其他请求来使用。

Grizzly的作者对此的回应如下。

(1) 使用临时的Selector的目的是减少线程间的切换。当前的Selector一般用来处理OP_ACCEPT,和OP_READ的操作。使用临时的Selector可减轻主Selector的负担;而在注册的时候则需要进行线程切换,会引起不必要的系统调用。这种方式避免了线程之间的频繁切换,有利于系统的性能提高。

(2) 虽然writeSelector.select(writeTimeout)做了阻塞操作,但是这种情况只是少数极端的环境下才会发生。大多数的客户端是不会频繁出现这种现象的,因此在同一时刻被阻塞的线程不会很多。

(3) 利用这个阻塞操作来判断异常中断的客户连接。

(4) 经过压力实验证明这种实现的性能是非常好的。

到此,相信大家对“Java NIO怎么处理慢速的连接”有了更深的了解,不妨来实际操作一番吧!这里是编程网网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

--结束END--

本文标题: Java NIO怎么处理慢速的连接

本文链接: https://lsjlt.com/news/288785.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • Java NIO怎么处理慢速的连接
    本篇内容主要讲解“Java NIO怎么处理慢速的连接”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Java NIO怎么处理慢速的连接”吧!对企业级的服务器软件,高性能和可扩展性是基本的要求。除此...
    99+
    2023-06-17
  • mysql中远程连接mysql很慢,本地连接mysql很快怎么处理
    这篇文章主要介绍mysql中远程连接mysql很慢,本地连接mysql很快怎么处理,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完! 症状:远程连接 mysql 很慢,但是 本地连接 ...
    99+
    2024-04-02
  • 电脑开机速度慢怎么处理
    电脑开机速度慢的原因可能有很多,下面是一些常见的处理方法:1. 清理开机启动项:打开任务管理器,点击“启动”选项卡,禁用不必要的启动...
    99+
    2023-08-08
    电脑
  • vsftpd连接变慢怎么解决
    本篇内容主要讲解“vsftpd连接变慢怎么解决”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“vsftpd连接变慢怎么解决”吧!vsftpd 是“very secure FTP daemon”的缩...
    99+
    2023-06-27
  • 解决java连接zookeeper很慢的问题
    目录java连接zookeeper很慢记一次惨痛的zookeeper连接教训java连接zookeeper很慢 最近在学习zookeeper,但是在连接zookeeper服务端时很慢...
    99+
    2024-04-02
  • springboot怎么处理多个连接
    Spring Boot可以使用多个连接的方式来处理,可以通过多线程、连接池等方式来实现。一种常见的方式是使用线程池来处理多个连接。可...
    99+
    2023-10-11
    springboot
  • oracle sqlplus连接很慢怎么解决
    如果Oracle SQL*Plus连接很慢,可以尝试以下方法来解决问题: 检查网络连接:确保网络连接稳定,没有丢包或延迟问题。可...
    99+
    2024-04-09
    oracle sqlplus
  • 怎么解决mysql连接过慢的问题
    这篇文章主要讲解了“怎么解决mysql连接过慢的问题”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“怎么解决mysql连接过慢的问题”吧! 3种解决方法(前...
    99+
    2024-04-02
  • 怎么解决Linux服务器端SSH远程连接速度慢的问题
    这篇文章主要介绍“怎么解决Linux服务器端SSH远程连接速度慢的问题”,在日常操作中,相信很多人在怎么解决Linux服务器端SSH远程连接速度慢的问题问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”怎么解决L...
    99+
    2023-06-13
  • navicat连接mysql失败怎么处理
    这篇文章将为大家详细讲解有关navicat连接mysql失败怎么处理,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。1、本地连接本地数据库无法连接,报错1251错误代码。第...
    99+
    2024-04-02
  • mysql连接池满了怎么处理
    mysql连接池满了的处理方法在命令行中,使用命令进入mysql数据库;mysql -u root -p进入mysql数据库后,查看mysql数据的最大连接数;show variables like 'max_connections';修改...
    99+
    2024-04-02
  • sqlserver连接池满了怎么处理
    当SQL Server连接池满了时,可以采取以下几种处理方法: 增加连接池大小:可以通过修改连接池的最大连接数来增加连接池的大小...
    99+
    2024-04-09
    sqlserver
  • mysql连接数过多怎么处理
    当MySQL连接数过多时,可以考虑以下几种处理方式: 调整MySQL的最大连接数设置:可以通过修改MySQL配置文件中的max_...
    99+
    2024-04-09
    mysql
  • redis连接数过高怎么处理
    当Redis连接数过高时,可以采取以下几种方法来处理: 优化应用程序:检查应用程序的代码,确保在连接Redis时,使用连接池管理连...
    99+
    2024-04-09
    redis
  • Java NIO的ByteBuffer工作原理是什么
    这篇文章给大家介绍Java NIO的ByteBuffer工作原理是什么,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。1 APINetty 的数据处理 API 通过两个组件暴露——抽象类ByteBuf 和 接口 Byte...
    99+
    2023-06-15
  • 如何解决java连接zookeeper很慢的问题
    这篇文章主要为大家展示了“如何解决java连接zookeeper很慢的问题”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“如何解决java连接zookeeper很慢的问题”这篇文章吧。java连接...
    99+
    2023-06-25
  • java怎么连接mysql
    java连接mysql的方法:1.下载mysql的jar驱动文件;2.配置好jdbc,新建类,写入连接代码;3.运行代码,当连接成功后,控制台会打印成功连接的信息。java连接mysql的方法:下载mysql的jar驱动文件,下载地址htt...
    99+
    2024-04-02
  • PostgreSQL怎么连接JAVA接口
    本篇文章为大家展示了PostgreSQL怎么连接JAVA接口,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。安装在我们开始之前,我们需要在Java程序中使用PostgreSQL,确保PostgreSQ...
    99+
    2023-06-17
  • dreamweaver怎么快速批处理图片链接
    本篇内容主要讲解“dreamweaver怎么快速批处理图片链接”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“dreamweaver怎么快速批处理图片链接”吧!对于网页制作者来说,最烦琐的事情可能...
    99+
    2023-06-08
  • 代理服务器拒绝连接怎么处理
    如果您遇到代理服务器拒绝连接的问题,可以尝试以下步骤:1. 检查代理服务器设置是否正确,确保代理服务器地址和端口号正确。2. 检查防...
    99+
    2023-06-14
    代理服务器 服务器
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作