`
san_yun
  • 浏览: 2638612 次
  • 来自: 杭州
文章分类
社区版块
存档分类
最新评论

Java程序员也应该知道的一些网络知识

 
阅读更多

对于需要编写网络通信的Java程序员而言,OS/网卡/网络结构等也需要有一些了解,以确保程序运行符合期望。

Java层面本身可通过Socket API来控制一些系统层面的参数(其他的诸如Netty/Mina/Grizzly这些通信框架也都提供设置这些参数的方法),主要是下面几个:
1. setTcpNoDelay(boolean on)
在不设置的情况下,默认为false,即禁用Nagle’s algorithm,具体这个算法的细节请自行google。
从经验上来说,只有在网络通信非常大时(通常指已经到100k+/秒了),设置为false会有些许优势,因此建议大部分情况下均应设置为true。
2. setSoLinger(boolean on,int linger)
这个的作用仅为socket关闭时如发送缓冲区里还有没发送完的包,等多久后关闭,通常来说不对这个做设置。
3. setSoTimeout(int timeout)
这个的作用是在执行socket read/write等block操作时,超时的时间(单位为ms),默认为0,也就是永不超时,nio是通知机制,因此通常不设置这个参数。
4. setSendBufferSize(int size)
缓冲区的大小决定了网络通信的吞吐量,理想的计算公式为:
Throughput = buffer size / latency
例如latency为1ms,buffer size为64KB,那么Throughput = 64KB / 0.001 = 62.5MB/s = 500Mb/s,理论上跑到了千兆网卡的一半。
通常建议buffer size设置为buffer size = RTT * bandwidth,其中RT为ping的rt,bandwidth为网卡的带宽,例如ping为1ms,bandwidth为1000Mb/s,那么 buffer size = 1 * 0.001 * 1000/8 * 1024 = 128KB

这个的默认值取决于os的net.ipv4.tcp_wmem中的第二个值/2,例如net.ipv4.tcp_wmem为:4096 65536 16777216,那么Java Socket默认的sendbuffersize会为65536/2 = 32768Bytes = 32KB

也可通过调用setSendBufferSize来设置,但这个不确保调用会生效(例如设置的最大值超过了os的最大值,如os同时设置了net.core.wmem_max则以这个为最大值,则会以os的最大值为准),因此最好在调用后再get下确认是否生效。

sendBufferSize如果太小,对于往外发东西的server而言,如果碰到其中某x台client接收慢,可能会很快导致send buffer满,这个时候会写不了,对于像mina/netty等框架而言,通常而言在写不了的情况下会放入队列,但不幸的是通常这都是一个没有限制大小 的队列,所以有些时候在这种情况下可能会导致OOM,因此在写这块代码时要特别注意对内存的保护(宁愿写失败也不能导致OOM)。

5. setReceiveBufferSize(int size)
设置接收缓冲区的大小,和sendBufferSize的行为一致。
6. setReuseAddress(boolean on)
设置为true,即表示在连接还在timewait状态时,就可复用其端口,这个对于大量连接且经常有timewait时适用,例如短连接的http server,默认为false,因此建议显式的设置为true。

除了Socket的这些API外,对于ServerSocket,还有一个参数比较重要,不过这个参数是在构造器中传入的:
ServerSocket(int port,int backlog)
这里的backlog主要是指当ServerSocket还没执行accept时,这个时候的请求会放在os层面的一个队列里,这个队列的大小即为 backlog值,这个参数对于大量连接涌入的场景非常重要,例如服务端重启,所有客户端自动重连,瞬间就会涌入很多连接,如backlog不够大的话, 可能会造成客户端接到连接失败的状况,再次重连,结果就会导致服务端一直处理不过来(当然,客户端重连最好是采用类似tcp的自动退让策 略),backlog的默认值为os对应的net.core.somaxconn,调整backlog队列的大小一定要确认ulimit -n中允许打开的文件数是够的。
os上还提供了net.core.netdev_max_backlog和net.ipv4.tcp_max_syn_backlog来设置全局的backlog队列大小(一个是建立连接的queue总队列的大小,一个是等到客户端ACK的SYN队列的大小)。

除了上面这些Java API层面可设置的参数外,还有一些常见的网络问题需要调整os的参数来控制,例如大量TIME_WAIT,TIME_WAIT是主动关闭连接的一端所处 的状态,TIME_WAIT后需要等到2MSL(Max Segment Lifetime,linux上可通过sysctl net.ipv4.tcp_fin_timeout来查看具体的值,单位为秒)才会被彻底关闭,而处于TIME_WAIT的连接也是要占用打开的文件数 的,因此如果太多的话会导致打开的文件数到达瓶颈,要避免TIME_WAIT太多,通常可以调整以下几个os参数:
net.ipv4.tcp_tw_reuse = 1 #表示可重用time_wait的socket
net.ipv4.tcp_tw_recycle = 1 #表示开启time_wait sockets的快速回收
net.ipv4.tcp_fin_timeout = 30 #表示msl的时间

如果碰到的是大量的CLOSE_WAIT则通常都是代码里的问题,就是服务器端关闭连接了,但客户端一直没关。

除了上面这些参数外,对于长连接,尤其是对于需要在断开后自动重连的长连接场景:
1、最好采用心跳机制确保连接没断开
这里有两个原因,一是有些交换机会对连接有自动断开的机制(通常不会),二是像直接拔网线等这种连接本身是不知道已经断开了的。
2、如长连接是经过了中间的负载均衡设备
那有可能会导致的现象是realserver的连接数不均衡,这种情况是长连接很悲催的场景,通常只能是采用连接每处理多少个请求就自动断开重连来缓解这个问题。

通常服务器是两块网卡或更多,网卡的bonding模式会决定能使用的带宽,因此也最好能有些了解,bonding模式可通过cat /proc/net/bonding/*bond*来查看,通常都可以在输出里看到
Bonding Mode: …
常看到的例如:
fault-tolerance (active-backup),表示的为主备模式,即只有一块网卡是活跃的,因此最大的带宽是单块网卡的带宽;
Bonding Mode: IEEE 802.3ad Dynamic link aggregation,表示的为两块网卡都启用,这种情况下通常可跑到双网卡的带宽。

最后推荐下我自己以前写nfs-rpc框架的时候的一些优化经验的总结的文章:http://bluedavy.me/?p=334

=============================
欢迎关注微信公众号:hellojavacases

关于此微信号:
分享Java问题排查的Case、Java业界的动态和新技术、Java的一些小知识点Test,以及和大家一起讨论一些Java问题或场景,这里只有Java细节的分享,没有大道理、大架构和大框架。

公众号上发布的消息都存放在http://hellojava.info上。

分享到:
评论

相关推荐

    java程序员需要掌握的知识点

    ### Java程序员需要掌握的知识点 在当今竞争激烈的IT行业中,作为一名Java程序员,掌握全面而深入的技术知识至关重要。根据提供的信息,我们将重点分析几个关键的知识领域,这些领域在百度、阿里巴巴和京东等大公司...

    java程序员应该知道的

    对于Java程序员来说,掌握基础知识和面试常考知识点是至关重要的。本文将深入探讨这些关键知识点,帮助你提升技能,顺利通过面试。 1. **Java基础语法**:Java是一种面向对象的语言,学习者应熟悉基本的数据类型...

    Java程序员面试宝典

    详细分析了应聘Java程序员职位的常见考点,主要内容包括面试流程及求职准备、Java语言基础、数据类型、集合框架、图形用户界面、输入与输出、多线程、反射机制、网络编程、JDBC、Web开发基础、SSH框架(Struts、...

    2018年新版Java程序员面试宝典

    网络编程基础,如TCP/IP协议、HTTP协议,以及Socket编程等,都是Java程序员需要掌握的知识。 十、算法与数据结构 最后,书中还可能会包含一些基本的算法和数据结构,如排序、搜索、图论等,这些是解决问题的关键...

    Java程序员应该了解的知识及一些公司的面试题目(供初学者参考以及程序员复习使用)

    本资源集合了Java程序员应该了解的关键知识点,并提供了一些知名公司的面试题目,旨在帮助初学者巩固基础,同时为有经验的程序员提供复习材料。 首先,让我们探讨Java的基础知识。Java是一种面向对象的语言,它的三...

    java程序员的成长历程

    对于想要踏入或正在走在这条道路上的Java程序员来说,理解并经历一个完整的学习和发展过程至关重要。以下就是一篇关于“Java程序员的成长历程”的详细解读。 首先,Java初学者通常会从学习基础语法开始,包括变量、...

    Java 程序员宝典 pdf 电子书

    《Java程序员宝典》是一本全面涵盖Java编程技术的电子书,旨在为初学者和有经验的Java开发者提供深入的指导。这本书详细介绍了Java语言的基础、核心特性以及高级概念,帮助读者掌握成为一名优秀Java程序员所需的技能...

    Java程序员面试笔试宝典-何昊pdf版

    根据提供的文件信息,我们可以推断出这是一本关于Java程序员面试和笔试准备的书籍,作者为何昊。本书可能包含了大量关于Java编程语言的基础知识、高级特性以及与面试相关的技巧和策略等内容。下面将对可能涉及的重要...

    java程序员简历模板

    以下是 Java 程序员简历模板的知识点总结: 一、 HR 如何刷简历 * 定位准确:个性鲜明,一眼看上去就能贴上技术精英、管理岗‘专家的标签 * 内部一致:内容聚焦,不能出现前后不符 * 简明扼要:抓住重点,不相关的...

    200道java程序员面试常问知识点

    根据给定的文件内容,无法提供具体的Java程序员面试常问知识点,因为所提供的“部分内容”是经过OCR扫描后未经修正的乱码文本。这些内容无法翻译成有意义的中文信息,也就无法从中提取出任何有关Java面试的知识点。 ...

    java程序员等级图

    网络知识对于开发分布式系统至关重要;数据库管理是数据存储的关键;设计模式则是解决常见问题的成熟解决方案。 "嵌入式与实时系统人才修炼路线图"和"嵌入式与实时系统人才体系图"关注的是特定领域的软件开发,例如...

    java程序员上班那点事儿

    根据给定的信息,“Java程序员上班那点事儿”这一标题与描述指向了关于Java程序员日常工作的一些常见情况、挑战或趣事等内容。尽管提供的具体内容部分没有直接给出相关知识点,但结合标题和描述,我们可以围绕Java...

    java程序员之路

    Java程序员之路是一个涵盖广泛的主题,它涉及到一个人从零基础学习Java编程语言,逐渐掌握核心技术,直至成为精通JSP(Java Server Pages)的专业编程人员的全过程。在这个过程中,开发者需要掌握一系列的技术栈和...

    JAVA程序员的心得

    此外,深入理解网络协议(如TCP/IP)、数据库原理等也可以帮助JAVA程序员更好地设计高性能的应用系统。 #### 心得四:合理安排时间,避免过度工作 程序员常常面临着紧张的工作压力,长时间加班不仅会影响身体健康...

    Java程序员上班那点事儿.txt

    根据提供的文件信息,我们可以从中提炼出关于Java程序员工作的一些关键知识点。这些知识点涵盖了技术技能、职业发展、工作态度以及在IT行业中可能遇到的各种挑战。以下是详细的解析: ### 技术技能要求 - **掌握...

    挑战java程序员系列教程

    【Java程序员系列教程】 在Java编程领域,"挑战java程序员系列教程"是一个旨在提升和测试开发者技能的资源。本教程涵盖了Java语言的核心概念以及实际应用,帮助初学者和有经验的程序员深入理解Java编程的各个方面。...

    Java程序员需要的电子书

    以下是一些Java程序员可能会感兴趣的电子书主题及知识点: 1. **《Java核心技术卷》**:这本书是Java程序员的必备经典,详细讲解了Java语言的核心概念,包括类、对象、接口、异常处理、多线程、网络编程等。通过...

    Java 程序员眼中的 Linux - v1.0.pdf

    本文档详细介绍了 Linux 操作系统的基础知识和实践经验,涵盖了 Linux 的安装、设置、常用命令、文件系统、网络管理、安全配置等方面的内容,同时也涉及到了 Java 开发相关的工具和技术栈,如 Tomcat、Jenkins、...

    java程序员入门之路

    ### Java程序员入门之路详解 ...综上所述,成为一名优秀的Java程序员并非一日之功,需要不断学习新知识、积累实践经验,并保持对新技术的好奇心和求知欲。希望以上内容能够帮助你在Java编程之路上走得更远、更高。

Global site tag (gtag.js) - Google Analytics