2.5.1 磁盘I/O优化
1. 性能检测ios
2. 提高I/O性能缓存
2.5.2 TCP网络参数调优网络
要可以创建一个TCP链接,必须知道对方的IP和一个未被使用的端口号,因为32位操做系统的端口号一般由两个字节表示,也就是只有2^16=65535个,因此一台主机可以同时创建的链接数是有限的,固然操做系统还有一些端口0~1024是受保护的,如80端口、22端口,这些端口都不能被随意占用。并发
在Linux中能够经过查看/proc/sys/net/ipv4/ip_local_port_range文件来知道当前这个主机可使用的端口范围,如图2-22所示。
异步
图2-22表示可使用的端口为61000-42768=18232。若是能够分配的端口号偏少,在遇到大量并发请求时就会成为瓶颈,因为端口有限致使大量请求等待创建链接,这样性能就会压不上去。另外若是发现有大量的TIME_WAIT的话,能够设置/proc/sys/net/ipv4/tcp_fin_timeout为更小的值来快速释放请求。咱们经过另一个主机ab -c 30 -n 1000000 10.232.101.208.8080/来压测这台机器,看看网络的链接状况,如图2-23所示。
tcp
能够看出TIME_WAIT的链接有26364个,咱们设置sudo sh -c "echo 3 > /proc/sys/net/ipv4/tcp_fin_timeout"后再进行测试,如图2-24所示。
函数
调整后TIME_WAIT的数量明显减小。除了增大端口范围以外,还可让TCP链接复用等,这些调优参数如表2-4所示。
工具
注意,以上设置都是临时性的,系统从新启动后就会丢失。另外iain,Linux还提供了一些工具可用于查看当前的TCP统计信息,以下所示。性能
2.5.3 网络I/O优化测试
网络I/O优化一般有以下一些基本处理原则。
减小网络交互的次数。
减小网络传输数据量的大小。
尽可能减小编码。
根据应用场景设计合适的交互方式。所谓的交互场景主要包括同步与异步、阻塞与非阻塞方式,下面进行详细介绍。
1. 同步与异步
2. 阻塞与非阻塞
3. 两种方式的组合
组合的方式有4钟,分别是同步阻塞、同步非阻塞、异步阻塞、异步非阻塞,如表2-5所示。
虽然异步和非阻塞可以提高I/O的性能,可是也会带来一些额外的性能成本,例如,会增长线程数量从而增长CPU的消耗,同时也会致使程序设计复杂度的上升。
下面举一些异步和阻塞的操做实例。
在Cassandra中要查询数据一般会向多个数据节点发送查询命令,可是要检查每一个节点返回数据的完整性,就须要一个异步查询同步结果的应用场景,部分代码以下:
class AsyncResult implements IAsyncResult { private byte[] result_; private AtomicBoolean done = new AtomicBoolean(false); private Lock lock_ = new ReentrentLock(); private Condition condition_; private long startTime_; public AsyncResult() { condition_ = lock_.newCondition();//建立一个锁 startTime_ = System.currentTimeMillis(); } //检查须要的数据是否已经返回,若是没有返回阻塞 public byte[] get() { lock_.lock(); try { if (!done_.get()) { condition_.await(); } } catch (InterruptedException ex) { throw new AssertionError(ex); } finally { lock_.unlock(); } return result_; } //检查须要的数据是否已经返回 public boolean isDone() { return done_.get();} //检查在指定的时间内须要的数据是否已经返回,若是没有返回,抛出超时异常 public byte[] get (long timeout, TimeUnit tu) throws TimeoutException { lock_.lock(); try { boolean bVal = true; try { if ( !done_.get() ) { long overall_timeout = timeout - (System.currentTimeMillis() - startTime_); if (overall_timeout > 0) //设置等待超时的时间 bVal = condition_.await(overall_timeout, TimeUnit.MILLISECONDS); else bVal = false; } } catch (InterruptedException ex) { throw new AssertionError(ex); } if (!bVal && !done_.get()) { //抛出超时异常 throw new TimeoutException("Operation timed out."); } } finally { lock_.unlock(); } return result_; } //该函数供另一个线程设置要返回的数据,并唤醒在阻塞的线程 public void result(Message response) { try { lock_.lock(); if (!done_.get()) { result_ = response.getMessageBody();//设置返回的数据 done_.set(true); condition_.signal(); //唤醒阻塞的线程 } } finally { lock_.unlock(); } } }