性能探讨

我们的项目,我简单描述一下业务。
系统负责缓存用户信息,定时任务将用户取出,到人人网获取用户相关信息。
要求是5分钟可以处理40万个用户,也就说我要去人人网做40W个HTTP请求,服务器用pc-server,8G内存,8核cpu。这样的需求可行么,切合实际么。
现在的实现采用jms+ejb mdb。
还要问一下,mdb最大可以设置多少线程数。今天设置mdb的线程池800个,系统崩溃了,cpu占用率800%。
我个人觉得5分钟轮询40W用户是不可能的。

首先对方要能承受,自己靠一台估计不太可能,你要把抓取和更新两个过程分开,需要一个分布式架构,ejb 没必要用,用普通jms 就可以了。最终结果要测试

楼主的意思是爬取别人网站的信息是吧?挺无耻的应用,不过我感兴趣的是你如何访问网页的?用htmlutil还是httpclient?或者别的什么?我觉得你最好搞一个搜索引擎去他网站上没日没夜的爬。。。。。

首先,40w用户是我们单台机器要求的负载数量,不可改变。
mdb消耗cpu么,要用jms api去监听队列么,会节省cpu么?

2009年11月06日 10:51 "newthinker"的内容
楼主的意思是爬取别人网站的信息是吧?挺无耻的应用,不过我感兴趣的是你如何访问网页的?用htmlutil还是httpclient?或者别的什么?我觉得你最好搞一个搜索引擎去他网站上没日没夜的爬。。。。。


这个不是偷取信息,我们是跟人人网有合同的,他们提供api供我们调用,获取信息。用的是httpclient

在说一下需求
每个用户可以绑定好友,每个好友去人人网请求一次
要求每台节点机器能承受2W用户,初步估计每个用户绑定20个好友,这样请求量是40W,要求每5分钟轮询一次。在不好的情况下,可能会比40W更多。我认为这个需求纯属扯淡。每5分钟40W+不可能。
希望有此方面经验的朋友,做一下预测。
[该贴被wjkiss000于2009-11-06 10:56修改过]

2009年11月06日 08:34 "banq"的内容
首先对方要能承受,自己靠一台估计不太可能,你要把抓取和更新两个过程分开,需要一个分布式架构,ejb 没必要用,用普通jms 就可以了。最终结果要测试

你的意思是,抓取信息后交由另一个系统去做下一步业务。也是采用jms通信是吧

2009年11月06日 11:00 "wjkiss000"的内容

你的意思是,抓取信息后交由另一个系统去做下一步业务。也是采用jms通信是吧

如果你只能单台,JMS还会降低性能,单台就用并发模式,将访问和处理使用两种线程来实现,并行处理。不要有JMS那种Queue类型,单台反而限制性能。

首先,通过httpclient访问网站,似乎做不到5分钟40w+的访问次数。这跟你是否使用jms构建业务逻辑无关。既然人人网跟你们有合作,那你们应该让他们提供更直接的api啊,而不是通过什么httpclient访问他们的网站!用httpclient访问肯定会受到性能影响这是无疑的。。他们人人网或许可以提供webservice给你们,那样的话,应该说5分钟40w用户数据有戏。因为你调用一次webservice或许就是可以获取1w或更多用户数据。一次访问就可以完成很多用户数据操作。这是可能的。

现在人人网不可能再为我们做任何东西,高层跟他们谈合同的时候,也没考虑到这一点,致使一个用户要请求多次。另外servlet式的api跟webservice性能差距应该不大,差不多。
banq说的有道理,在一台机器上不应该用jms。当时是怕写多线程麻烦,而采用jms+mdb方案。
今天测试结果,8核cpu,jboss服务器。设置mdb连接池50-200个,另外这台机器还部署了服务端。1W用户,查看控制台,最大线程数不超过208个,而我配置的是最大1000。查看mdb currentcount是不到100个,cpu高居800%不下。导致线程死在那,执行缓慢。
是我的程序问题?还是mdb不能启动那么多线程。
很多疑问,望高手解答

我在自己的机器上,单核的cpu。跑1000个用户,13秒完成,每秒153个,很快的啊,是20个mbd。如果8核pc-server能启动10倍的mdb数量,每秒就有1530个,那问题不大啊。
可是怎么就不行呢?配置的问题么?
现在脑子里一堆问号,苦于无人帮忙

JMS有事务,容易死锁。并发和死锁是一对矛盾,你如果还是隔着JMS这个靴子搔痒,很难找到问题根结,直接面对多线程,java6的并发线程还是简单的,你开发一个线程或futrue,然后放到Executor中执行就可以,这个Executor可以设定最大线程数,这样便于你微调。很简单。几条语句。


的确发生死锁,如何避免呢。现在如果人人网足够快的话,我初始化50个mdb,处理速度是2600条/秒。cpu占用率200%左右。但是会出现个别死锁,但不影响性能,查看jboss控制台,当前消息数2个,正在交付的消息数2个,这2个就死那了。此时cpu占用率1%。
还有,谁用过jboss messaging。jboss重启后,客户端连接发送队列发不过去,但不报错。
看一下我的客户端代码:


private QueueConnectionFactory connectionFactory = null;
private QueueConnection connection = null;
private QueueSession queueSession = null;
public final static String JNDI_FACTORY = "ConnectionFactory";
protected String queueName;
public WebJmsManager() {}

@SuppressWarnings(
"unchecked")
public WebJmsManager(String providerUrl ) throws NamingException, JMSException {
Hashtable props=new Hashtable();
props.put(Context.INITIAL_CONTEXT_FACTORY,
"org.jnp.interfaces.NamingContextFactory");
props.put(Context.PROVIDER_URL, providerUrl);
props.put(
"java.naming.rmi.security.manager", "yes");
props.put(Context.URL_PKG_PREFIXES,
"org.jboss.naming");
//
ctx = new InitialContext(props);
connectionFactory = (QueueConnectionFactory) ctx.lookup(JNDI_FACTORY);
connection = connectionFactory.createQueueConnection();
queueSession = connection.createQueueSession(false,Session.AUTO_ACKNOWLEDGE);
}




public void queue(String queueName, ServiceMessage message) throws JMSException, NamingException{
Destination destination = (Queue) ctx.lookup(queueName);
MessageProducer messageProducer = queueSession.createProducer(destination);
messageProducer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
ObjectMessage objectMessage = queueSession.createObjectMessage(message);
messageProducer.send(objectMessage);
}

这个客户端类,我是给缓存起来的。
[该贴被wjkiss000于2009-11-13 11:22修改过]
[该贴被wjkiss000于2009-11-13 11:23修改过]

三个办法:
1. tunning微调JBoss的Queue性能,需要深入内部。
2. 选择另外更快的JMS 如法国电信的Fiorano MQ 9.0.1,根据他们自己测试,是其他好几倍,测试结果:
http://www.fiorano.com/whitepapers/fmq/jms_performance_comparison.php
3.我前面说过,不要JMS,抛弃Queue概念,有Queue一般肯定有死锁可能存在,使用Java并发包。

下周,公司会测其他模块性能,他们用的是线程方式。如果真的比我的快很多,我就改架构了。队列的方式肯定还是会用的,但不是jms,用java api里的queue,启动多个线程重queue里取出用户。
忘了说了,前几天说的cpu占用过高是因为jms死锁造成的。
而造成大范围死锁的其中一个原因是,我使用了两个队列,一个mdb里包含往另一个队列发送消息的程序。暂时先合到一个队列完成,大范围死锁算是解决了,偶尔会出现1,2个死锁的现象现在,但不消耗cpu。