linux 下 java 消息队列 lajp,Linux下消息队列和socket绝对速度比拼[转].docx

Linux下消息队列和socket绝对速度比拼[转].docx

在当今的网络时代, 我们常常见到的进程间通信方式都是 socket, 比如 Java 的 EJB 调用, Java 和 C 通信,Web Service 服务等。socket 是最常用的通讯技术,几乎所有的系统、语言都支 持,socket 也是面向网络的,通信的两方可以跨越 IP 网络进行传输。 在本地通信中同一台机器上的进程间通讯,socket 的网络特性却成了累赘,组装解析网络 报头、报文确认、CRC 校验等都是针对网络的,本地通信没有必要,反而会影响传输效率。 本地通信的一些传统技术,如管道、FIFO、消息队列等,没有网络功能的负担,传输速度应 该高于 socket, 那到底高多少以至于值得在应用中替换 socket 技术呢, 今天就来一场小测试, 就 System V 消息队列和 socket 之间,做一次全面的速度比拼。 比拼场地 本人的笔记本赛扬 1.5G 内存 1.5G 系统Ubuntu8.04 Desktop Linux 2.6.24-24-generic JDK1.6 第一回合 Java 测试 先说明一下,Java 并不支持 System V 消息队列,因此特为 Java 提供了 JNI 接口,我们使用 lajp_9.09 提 供C 源 码 编 译 的 so 动 态 连 接 库 , lajp 的 下 载 地 址 和 文 档 首先上场的是 System V 消息队列。 发送端程序 package test; import lajp.MsgQ; public class TestSend / 消息队列 KEY */ static final int IPC_KEY 020021230; static JNI System.loadLibrary“lajpmsgq“; public static void mainString args 创建或获得现有的消息队列 int msqid MsgQ.msggetIPC_KEY; 发送字节数组 byte msg new byte1024; for int i 0; i h_addr-s_addr; /* 服务端 地址 */ client_addr.sin_port htonsport; /* 端口 */ /* 建立 socket */ int sockfd socketAF_INET, SOCK_STREAM, 0; /* 连接 */ connectsockfd, struct sockaddr * int i; for i 0; i 1024 * 5000; i /* 发送 */ sendsockfd, msg, 1024, 0; printf“发送结束,共发送d 次 n“, i; return 0; 接收端程序 include include include char msg1024; /* 接收缓冲区 */ int main int listen_port 9527; /* 侦听端口 */ int listenfd socketAF_INET, SOCK_STREAM, 0; /* 建立侦听 socket */ /* 服务端填充 sockaddr 结构 */ struct sockaddr_in server_addr; /* 服务端地址结构 */ bzero server_addr.sin_family AF_INET; /* AF_INETIPV4 协议 */ server_addr.sin_addr.s_addr htonlINADDR_ANY; /* INADDR_ANY通配地址,表示内 核选择 IP 地址 */ server_addr.sin_port htonslisten_port; /* 端口 */ /* 绑定端口 */ bindlistenfd, struct sockaddr * /* 侦听 */ listenlistenfd, 5; int sockfd acceptlistenfd, NULL, NULL; int i; for i 0; i 1024 * 5000; i /* 接收 */ recvsockfd, msg, 1024, 0; printf“接收结束,共接收d 次 n“, i; return 0; C 语言中,socket 程序复杂了不少。测试标准和 Java 相同,发送接收了1024 * 5000次,5G 数据,先启动接收端程序,然后以 time 方式启动发送端,测试结果如下 用户 系统 时钟 第一次 0.524s 9.765s 20.666s 第二次 0.492s 9.825s 20.530s 第三次 0.468s 9.493s 21.831s 第四次 0.512s 9.205s 20.059s 第五次 0.440s 9.605s 21.888s 用 top 命令监控测试期间的 CPU、内存的使用 C 语言的 socket 程序系统用时多一些,消息队列程序用户用时多一些,这和他们的实现方式 相关,从时钟比较看,消息队列比 socket 快 10左右,和 Java 测试结果相似。比较 Java 和 C,C 只领先了三分之一,看来当前的 Java 效率已经相当高了。 还不能忙于下结论,socket 的通信方式一般有两种长连接和短连接。长连接指发送端和接 收端建立连接后, 可以保持 socket 通道进行多次消息传输, 在这种场景基本不用计算 socket 建立和关闭的时间,前面的测试都是基于长连接方式;短连接一般在建立 socket 通道后, 只进行一次通信,然后就关闭 socket 通道,这种场景必须考虑 socket 建立和关闭的时间 (socket 建立连接需要三次握手,关闭连接要四次通信) 。 第三回合 Java 测试短连接 将第一回合中的 Java 程序稍作修改,先看 socket 的 发送端程序 import java.io.IOException; import java.io.OutputStream; import .Socket; public class SocketSend2 public static void mainString args throws IOException long start System.currentTimeMillis; 开始时间 发送字节数组 byte msg new byte1024; for int i 0; i 1024 * 1000; i 建立 Socket 连接 Socket socket new Socket“127.0.0.1“, 9527; 输出流 OutputStream out socket.getOutputStream; 发送 out.writemsg; 关闭输出流 out.close; 关闭 socket 连接 socket.close; long end System.currentTimeMillis; 结束时间 System.out.println“用时“ end start “毫秒“; 建立 socket 的语句放在了循环内部,这样每次发送都是新建的连接,025 行的关闭语句是必 须的,因为 socket 是系统的有限资源,支持不了这么大规模的申请。 接收端程序 import java.io.IOException; import java.io.Stream; import .ServerSocket; import .Socket; public class SocketRecv2 public static void mainString args throws IOException 侦听 9527 端口 ServerSocket serverSocket new ServerSocket9527; 接收缓冲区 byte msg new byte1024; for int i 0; i 1024 * 1000; i 接到客户端 Socket 连接请求 Socket socket serverSocket.accept; 输入流 Stream in socket.getStream; 每次接收 1204 字节 in.readmsg; 关闭输入流 in.close; 关闭 socket 连接 socket.close; System.out.println“接受结束.“; 接收端也做了相应的改动, 发送和接收次数降低到1024 * 1000次, 测试结果 431280 毫秒, 不要吃惊,没错是 431.280 秒,这也是书本上为什么总在强调使用数据库连接池的原因。 消息队列没有像 socket 那样的连接概念,为了做个参考,将第一回合中的消息队列程序也 修改一下 发送端程序 package test; import lajp.MsgQ; public class TestSend2 / 消息队列 KEY */ static final int IPC_KEY 020021230; static JNI System.loadLibrary“lajpmsgq“; public static void mainString args 发送字节数组 byte msg new byte1024; for int i 0; i 1024 * 1000; i 创建或获得现有的消息队列 int msqid MsgQ.msggetIPC_KEY; 每次发送 1204 字节 MsgQ.msgsndmsqid, 9527, msg, msg.length; System.out.println“发送结束.“; 将 024 行的 msgget方法放在循环内部,作为和 socket 比较的“连接”。 接收段程序 package test; import lajp.MsgQ; public class TestRcv2 / 消息队列 KEY */ static final int IPC_KEY 020021230; static JNI System.loadLibrary“lajpmsgq“; public static void mainString args long start System.currentTimeMillis; 开始时间 接收缓冲区 byte msg new byte1024; for int i 0; i 1024 * 1000; i 创建或获得现有的消息队列 int msqid MsgQ.msggetIPC_KEY; 每次接收 1204 字节 MsgQ.msgrcvmsqid, msg, msg.length, 9527; long end System.currentTimeMillis; 结束时间 System.out.println“用时“ end start “毫秒“; 测试结果6617 毫秒。 总结 在能够使用 socket 长连接的应用中,建议使用 socket 技术,毕竟很通用熟悉的人也多,而 消息队列能够提高的效率有限;在只能使用 socket 短连接的应用中,特别是并发量大的场 景,强烈建议使用消息队列,因为能够极大的提高通信速率。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值