性能探讨

09-11-05 wjkiss000
我们的项目,我简单描述一下业务。

系统负责缓存用户信息,定时任务将用户取出,到人人网获取用户相关信息。

要求是5分钟可以处理40万个用户,也就说我要去人人网做40W个HTTP请求,服务器用pc-server,8G内存,8核cpu。这样的需求可行么,切合实际么。

现在的实现采用jms+ejb mdb。

还要问一下,mdb最大可以设置多少线程数。今天设置mdb的线程池800个,系统崩溃了,cpu占用率800%。

我个人觉得5分钟轮询40W用户是不可能的。

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

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

wjkiss000
2009-11-06 10:51
首先,40w用户是我们单台机器要求的负载数量,不可改变。

mdb消耗cpu么,要用jms api去监听队列么,会节省cpu么?

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

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

wjkiss000
2009-11-06 10:56
在说一下需求

每个用户可以绑定好友,每个好友去人人网请求一次

要求每台节点机器能承受2W用户,初步估计每个用户绑定20个好友,这样请求量是40W,要求每5分钟轮询一次。在不好的情况下,可能会比40W更多。我认为这个需求纯属扯淡。每5分钟40W+不可能。

希望有此方面经验的朋友,做一下预测。

[该贴被wjkiss000于2009-11-06 10:56修改过]

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

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

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

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

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

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

wjkiss000
2009-11-06 23:05
现在人人网不可能再为我们做任何东西,高层跟他们谈合同的时候,也没考虑到这一点,致使一个用户要请求多次。另外servlet式的api跟webservice性能差距应该不大,差不多。

banq说的有道理,在一台机器上不应该用jms。当时是怕写多线程麻烦,而采用jms+mdb方案。

今天测试结果,8核cpu,jboss服务器。设置mdb连接池50-200个,另外这台机器还部署了服务端。1W用户,查看控制台,最大线程数不超过208个,而我配置的是最大1000。查看mdb currentcount是不到100个,cpu高居800%不下。导致线程死在那,执行缓慢。

是我的程序问题?还是mdb不能启动那么多线程。

很多疑问,望高手解答

wjkiss000
2009-11-06 23:17
我在自己的机器上,单核的cpu。跑1000个用户,13秒完成,每秒153个,很快的啊,是20个mbd。如果8核pc-server能启动10倍的mdb数量,每秒就有1530个,那问题不大啊。

可是怎么就不行呢?配置的问题么?

现在脑子里一堆问号,苦于无人帮忙

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

wjkiss000
2009-11-13 11:22
的确发生死锁,如何避免呢。现在如果人人网足够快的话,我初始化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); 
    }
<p>

这个客户端类,我是给缓存起来的。

[该贴被wjkiss000于2009-11-13 11:22修改过]

[该贴被wjkiss000于2009-11-13 11:23修改过]

banq
2009-11-13 13:45
三个办法:

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并发包。

wjkiss000
2009-11-13 14:04
下周,公司会测其他模块性能,他们用的是线程方式。如果真的比我的快很多,我就改架构了。队列的方式肯定还是会用的,但不是jms,用java api里的queue,启动多个线程重queue里取出用户。

忘了说了,前几天说的cpu占用过高是因为jms死锁造成的。

而造成大范围死锁的其中一个原因是,我使用了两个队列,一个mdb里包含往另一个队列发送消息的程序。暂时先合到一个队列完成,大范围死锁算是解决了,偶尔会出现1,2个死锁的现象现在,但不消耗cpu。

猜你喜欢