需求:及时0-2秒内响应请求,并发送给第三方认证客户端进行认证,返回结果并保存至数据库
1、WebService接口用于接收各地区用户请求(等待1分钟待Windows服务处理完成,通过不断查询数据记录状态【成功失败】判
任务是否处理完成****很不好的方式,不知怎么解决???)
2、Windows服务程序(用于处理各地区的用户请求,并负责与第三方认证客户端通信,将结果【成功失败】保存到数据库中)
3、第三方认证客户端(Socket UDP协议)
问题:
如何及时响应WebService的请求,并支持高并发??
目前这些请求是保存在数据库中,Windows服务程序通过循环查询数据库中的请求,并读取到堆栈中,
并创建50多个线程执行,并发送第三方认证客户端。
但这种方式需要每隔几十毫秒就要查询数据库,效率很低,CPU占用率高。
想请教各位从架构方面有什么好的技术能解决这种高并发的认证请求?
能改成异步调用,处理完成后给回调么?
不可以的,这是三个独立的程序,WebService不好回调吧,wcf回调太麻烦,而且跨平台性不好,android这些系统都不支持
@paaple: 和你用什么rpc框架无关,你现在前提是同步请求,每个请求又需要1分钟拿到结果,这样你性能怎么可能高的起来?
你客户端过来一个请求,服务端响应一个ok就结束掉,等后续服务处理成功了再反向通知客户端不行么?
@Daniel Cai: 业务需求不是这样的,客户端请 求都是在同步请求的,
现在的问题不是异步的问题,必须要同步方法(我们后台是异步的,但提供给客户的接口必须同步)。
我们的响应时间主要是在及时响应webservice请求上,
做数据库轮循太慢了。。
@paaple:
1.如果你这里硬要上同步,并发肯定上不来的。
2.非要上同步,你这里可以避开轮询。比如当后面处理成功后发条消息出来,而消息的消费者会根据消息中的id hash后确定是哪台机器正在等待,然后通知过去告知处理结果。这台接受同步请求的机器不再轮db,而是轮自己内存中的一个表,当通知过来后更新内存中的这个表,前面轮的线程就可以继续同步响应了。
3.db轮询中,你应该轮可以最大粒度过去数据的那端,比如状态为未成功的,并在状态位上加索引。因为在这种情况下,未成功的相对于成功的实际是相当稀少的,虽然状态可选值可能很少,但过滤度相当高因此索引在这块是有效的。
@Daniel Cai: 内存表也想过,但是处理的方式和我现在的其实应该是差不多的,需要不断的隔一定时间去查询,这样效率不会太高,特别是连接请求大的时候,但效率比直接轮db要高多了。。
我是想为每个请求创建一个socket连接,状态信息都存储于每个连接会话中,这样服务端返回信息后就可以立即响应。这样webservice也不需要不断轮循,请求完成销毁socket
另外要说明的是请求不是一次的,因为服务端要返回一个特殊值返回给客户端,并且客户端经过计算后又要重新发给服务器再进行其它运算。
不知道这样做是否合适。
@paaple: 内存表中效率已经相当高了,就算是用concurrentdictionary每秒都在百万次级别。换成外接的cache,如redis,根据数据大小也在万到十万级。
你直接走tcp和走webservice在这里没多大区别,走tcp好的地方你可以对连接做更细致的控制,比如连接池,不用每次打开关闭,但看你前面的描述你现在的瓶颈根本不在这。
你所谓的请求不是一次性的,实际这个看法是错的,这个还是正常的请求响应方式。
除了我前面说的那种方案,你看看能不能在中间加一道缓存,比如某些认证请求的响应(成功的情况下)短时间内是否可以cache到本地。
还有你问题说的请求保存在数据库中(非日志需求),这里是否可以改成用队列,这样就可以避免轮询过程了。
@Daniel Cai: 非常感谢!我现在的方式是利用WebServer的session,其实tcp也是这样的原理,把客户端请请先缓存起来,待所有请求数据完整后再做统一的提交。tcp请求还要封装连接,还要处理粘包拆包也是头疼..现在用Webservice本身功能,但可能请求量大后不知道会有什么后果,做集群,负裁均衡?
这两天这个功能实现了,至少比放在数据库稳定多了,就像你说的可以精细控制,还有就是响应及时性提高了。
还是没用内存表方式,使用直接连接精 准控制,使用WebService的Session管理客户端连接请求。