转载

openfire服务器2种性能测试方法

XMPP Server(IM Server)不像Web Server有十分标准的性能评测工具, 一个新的IM服务器拿到之后,通常并没有十分方便的方式来进行测试性能。 通常我们只能依赖网上的数据来衡量某个服务器产品的性能。但是网上的数据通常并不准确,因为测试的环境, 测试的指标不同,测试的方法有差异,得到的结果并没有直接的可比性。我们去验证某些测试结果,得出的数据有2~3倍的差异并不奇怪。 因此最好通过自己的环境去验证这些产品的性能指标,所以构建一套简单的性能测试工具十分重要。目前想到的测试一个XMPP Server的几种方案。
  • 使用 Smack API, 它是一个 Java 的XMPP Client Library,也是由Jive Software开发。
  • 使用 Java Socket异步NIO select方式, 模拟XMPP登录。XML可直接用string构建,可直接根据XML返回结果的特征字符判断调用是否成功。如使用XML library来解析可能会造成部分自身瓶颈。
    • 优点:可以模拟更多的客户连接。1台客户机可以模拟数万个用户同时操作。
    • 编程稍复杂,需要熟悉Java NIO async socket,或相关框架,如Mina
    • 代码示例,使用MINA模拟客户端连接到服务器
/** * Use mina client to connect xmpp server * @author Tim * */ public class XmppClient { public static void main(String[] args) { String hostname = "server"; int port = 5222; SocketConnectorConfig cfg = new SocketConnectorConfig(); cfg.getFilterChain().addLast("codec", new ProtocolCodecFilter(new TextLineCodecFactory())); for (int i = 1; i <= 2; i++) { SocketConnector connector = new SocketConnector(); connector.connect(new InetSocketAddress(hostname, port), new XmppProtocolHandler("tim" + i, "tim", "mina"), cfg); } } } class XmppProtocolHandler extends IoHandlerAdapter { String username = "tim"; String password = "tim"; String server = "server"; String bareJid = username + "@" + server; String resource = "mina"; public XmppProtocolHandler(String username, String password, String resource) { this.username = username; this.password = password; this.resource = resource; this.bareJid = username + "@" + server; } @Override public void sessionClosed(IoSession session) throws Exception { System.err.println("Closed. Total " + session.getReadBytes() + " byte(s)"); } @Override public void messageReceived(IoSession session, Object message) throws Exception { ByteBuffer buf = (ByteBuffer) message; while (buf.hasRemaining()) { System.out.print((char) buf.get()); } System.out.flush(); } @Override public void sessionOpened(IoSession session) throws Exception { sendPacket(session, sendStream(true)); Thread.sleep(50); sendPacket(session, sendAuth(username, bareJid, password)); Thread.sleep(200); sendPacket(session, sendStream(false)); Thread.sleep(50); sendPacket(session, sendResource(username, resource)); Thread.sleep(50); sendPacket(session, sendPresence(username)); } private String genPassword(String bareJid, String username, String password) { String str = bareJid + "\0" + username + "\0" + password; BASE64Encoder base64 = new BASE64Encoder(); return base64.encode(str.getBytes()); } private StringBuilder sendStream(boolean addHeader) throws IOException { StringBuilder sb = new StringBuilder(); if (addHeader) sb.append("<?xml version='1.0' encoding='UTF-8'?>"); sb.append("<stream:stream to=\"").append(server) .append("\" xmlns=\"jabber:client\" xmlns:stream=\"http://etherx.jabber.org/streams\" version=\"1.0\">"); return sb; } private StringBuilder sendAuth(String username, String bareJid, String password) throws IOException { String pwd = genPassword(bareJid, username, password); StringBuilder sb = new StringBuilder(); sb.append("<auth mechanism=\"PLAIN\" xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\">") .append(pwd).append("</auth>"); return sb; } private StringBuilder sendResource(String username, String resource) throws IOException { StringBuilder sb = new StringBuilder(); sb.append("<iq id=\"").append(username) .append("-0\" type=\"set\"><bind xmlns=\"urn:ietf:params:xml:ns:xmpp-bind\"><resource>") .append(resource).append("</resource></bind></iq>"); return sb; } private StringBuilder sendPresence(String username) throws IOException { StringBuilder sb = new StringBuilder("<presence id=\"") .append(username).append("-2\" />"); return sb; } private void sendPacket(IoSession session, StringBuilder sb) throws Exception { sb.append("\r\n"); System.out.println(sb.toString()); session.write(sb.toString()); } }
  • 使用 tsung, tsung使用erlang开发,利用了erlang并发编程的优势,可以从一到多个客户机向发起xmpp请求。
    • 优点:利用现成的工具,无需开发。测试过程使用XML来配置,不需要改动源代码。
    • 缺点:配置和扩展复杂,学习成本,适应成本及扩展成本大。
  • 使用 Python 等动态语言开发,如PyXMPP
    • 优点:开发及重构效率比Java稍快,可以更多关注测试模型及指标本身。而不是测试程序怎么实现。
    • 缺点:需要开发人员熟悉相关语言及特性。另外同样有 one thread per client 的问题,占用客户端资源过高。可能要几台客户机才能搞定一台服务器。
    • 代码示例,下面例子可以对实现一个Python的client有个基本了解,详细可参考 PyXMPP examples 下面的例子。
class MyClient(Client): def session_started(self): self.stream.send(Presence()) def idle(self): print "idle" Client.idle(self) if self.session_established: target=JID("tim2",s.jid.domain) self.stream.send(Message(to_jid=target,body=unicode("测试","utf-8"))) def post_disconnect(self): print "Disconnected" raise Disconnected logger=logging.getLogger() logger.addHandler(logging.StreamHandler()) logger.setLevel(logging.DEBUG) libxml2.debugMemory(1) print "creating stream..." s=MyClient(jid=JID("tim@server/Test"),password=u"tim",auth_methods=["sasl:DIGEST-MD5","digest"]) print "connecting..." s.connect() print "processing..." try: try: s.loop(1) finally: s.disconnect() except KeyboardInterrupt: traceback.print_exc(file=sys.stderr) except (StreamError,Disconnected),e: raise libxml2.cleanupParser() if libxml2.debugMemory(1) == 0: print "OK" else: print "Memory leak %d bytes" % (libxml2.debugMemory(1)) libxml2.dumpMemory()
 
正文到此结束
Loading...