求个,用户用电信息采集系统,购电功能优化解决方案。

目前我对购电功能的实现方式:对远程国网专变采集终端,发送一条报文,终端根据报文内容然后返回一条报文,系统根据终端返回的报文进行判断购电是否成功!

遇到的问题:会有几率出现,终端接收到了我发送过去的指令,可是终端并没有即使返回指令(我观察到的原因是gprs网络问题和用户在页面上等的太久而关闭本次请求页面)
系统中这样的一次购电回响一般在5-20秒左右。

问题出现频率:3个月内已经有2次了

希望大家,多给意见,谢谢!

9个回答

[quote]是这样的,首先我向终端发送请求(比如购电),终端收到请求然后对请求确认,处理,再回响给系统。
我系统现在出现了,终端收到了,我发送的请求,确认处理后,再回响我,可是因为网络原因,我没有收到终端的回响。
实际终端已经购电充值成功,但系统却不知道是否成功。[/quote]
购电流程:
1.系统给终端发送购电请求;
2.终端收到系统购电请求后,回复系统可以购电,要求系统确认;
3.系统确认购电并向终端发送确认购电通知;
4.终端收到系统发送购电确认通知,终端进行后台购电操作,操作完成后向系统发送购电操作结果;
5.系统接受终端购电操作结果知并告之客户。
问题出现在第4第5步之间。
按照电信行业计费方式来说,购电和手机预付费模式是一致的,预付费在终端有2种方案:
第一种方案是心跳方式和前端保持连接,一旦检测到前段无法连接了,前段的所以操作会被挂起直到连接恢复;
第二种方案是端口扫描方式,每次请求都是双向的即一发一收。如果只有发没有收上一步操作即为失败,终端进行自动回退的。

对于第二种方案处理来了比较容易的。
一:在终端设置一个端口用于接收你系统消息的回复。终端可以采用间隔N秒发送一条消息,系统没有即时恢复即回滚或者挂起那条充值请求。
二:系统也需要进行双向设置,对于回复可以设置为自动回复。

[quote]我观察到的原因是gprs网络问题和用户在页面上等的太久而关闭本次请求页面[/quote]
你这里的“终端”系统应该不能更改处理方式吧?如果这样,那只能从你发起购电请求这一方优化,我不知道你具体的实现情况,就我的看法呢,如果是“请求时间过长”,建议采用异步处理的方式,即客户购电后立即返回,只告诉用户“购电请求处理中”,这样用户请求就结束。(我想用户并不需要立即就告诉他购电成功,业务上也能接受)而后再把请求发送到终端,待终端有了相应后再更新用户购电请求的状态,提醒用户购电成功。
如果是“GPRS网络有问题”,一方面要提高网络的稳定性,另一方面,因为采用了异步的方式,所以即使请求没有返回,客户的购电请求也不会成功,业务上没有问题。如果是终端那边购电成功,而没有返回响应,可以要求终端多次发生请求(这个可能需要你们和国电协商),或者你的系统主动发起确认成功请求,这样可以保证稳定性。

这个和电信行业开通差不多,先说说电信行业开通是如何操作的。
首先在服务端设置线程相应时间,比如20s响应时间,如果超时了服务端自动回滚本次操作,并通知前端开通失败;如果出现单点故障如断网了,服务端自动回滚操作;
前端也要做对应的超时时间限制,超过时间限制会作2中动作,一个是重复发送请求,另外一个是发送取消请求。如果出现单点故障如断网,前端自动提示开通失败。

[b]引用[/b]
[u]我观察到的原因是gprs网络问题和用户在页面上等的太久而关闭本次请求页面[/u]
1.网络问题可以参照超时和单点故障进行处理
2.用户在页面上等的太久而关闭本次请求页面:在关闭本页面时如ie页面需要重写window.close()方法

[quote]实际终端已经购电充值成功,但系统却不知道是否成功。[/quote]
这种情况我上面的回答已经说明了,网络问题,不是你的系统和终端系统能控制的,所以唯一的办法就是,要么终端系统那边能够在发回响应时判断是否发生成功,要么你的系统对于发起请求了,但状态没更新的,进行再次确认操作,即再次向终端发起一个请求,询问本次购买是否真的成功。这两种方案都需要和终端系统协调,所以不知道终端系统设计时是否考虑了这样的问题。
实际上,这种问题的出现主要是分布式系统造成的,所以一般分布式系统设计有CAP原则,你这里肯定需要提供C(一致性)的可靠性。这方面需要从设计整个系统时就考虑。

[quote]
如果我这样做是否可以:在本次购电时,检查数据库上次购电记录,如果是失败状态,就进行查询终端上次购电单号与数据库失败记录的单号是否一致。如果一致保存本次用户购电记录,但并不发送购电指令给终端,提示用户购电成功;如果数据库上次购电记录是成功状态再发送本次购电指令! 当然失败状态的购电记录用户不用看到。 这样是否合理,是否有可以改进的地方
[/quote]
1、数据库里的购电记录“失败状态”,这个状态你怎么来的?如果上次购电的状态是由终端返回的,那么就不需要再次向终端查询了,如果不是,那你的“失败”状态怎么来的呢?因为如果上次购电终端因网络问题没有返回,那你最多只能说上次购电记录的状态是“处理中”。
2、两次购电的操作之间有关联吗,为什么要前一次购电成功了才发生本次购电指令呢?用户不能多次购买吗?上次购电不成功,除了网络原因,也可能是业务原因,那用户再次请求购电很正常啊。

我觉得通过再次验证的方式确认购电是否成功,应该是可行的。对于你说“再次确认时也有网络问题”,那这个真的需要优化网络了,这就好比你进行购电操作时,整个服务器的都不可用。因为“网络问题”应该属于小概率事件才是合理的,如果你的网络频繁出现问题,那就不是单单从这里能解决了。

另外,还有一种做法就是,把发起购电请求,终端响应作为一个事物来进行,这样不管因为什么原因本地记录没有更新,都认为购电失败。然后再下次进行操作时发送消息到终端,告知撤销之前的购电(有可能终端购电成功)。但这种方案也不是很好,一方面,如果网络不好,用户认为购电一致不成功,会发起很多这样的请求,这导致终端产生很多购电,而终端上都是成功的,到时撤销会很到;另一方面,如果终端购电成功后,后续其内部系统还有很多其他的关联操作,那么要撤销的就不仅仅是购电记录本身了。

建议异步处理方式,用户购电操作后,将用户购电记录存储。

后台进程专门向终端设备充值,待充值成功,修改用户购电记录。

再提供一个查询功能。

呵呵,你的功能依赖前台页面?
莫非是购电页面定时通过ajax进行操作,所以关闭页面后操作就中断了。

页面请求--发送请求-->服务器(负责购电业务)--指令-->终端
|->页面获得一个业务ID号
|->服务器负责接收终端响应指令
---------
|
页面 业务反馈查询--业务id号-->服务器返回操作结果(业务处理中、已成功、失败)

[quote] 对于第一方案,现系统对所有专变采集终端都是有的。即对所有终端2分钟一次的握手功能!但是您说的操作挂起,是怎么回事能具体描述下吗?
对于第二方案,"终端进行自动回退",这个好像可以实现,谢谢,附图:Q/GDW 376.1-2009《电力用户用电信息采集系统通信协议:主站与采集终端通信协议》及编制说明.doc[/quote]

操作挂起:终端检测到系统连接失败了,修改充值请求状态待确认状态。该状态可能出现2种情况,一种是终端还没有受理充值既用户账户余额还没有发生修改时将该条记录放入到挂起线程队列中。另外一种是终端已经受理了充值,用户账户余额发生了变化,将该充值记录发到待回退队列线程中。
第一种情况需要对用户充值金额设置生效时间的,充值生效时间要大于线程生效时间

呵呵,有时候确实是丢失了。看规约是不是能保证不会丢失。

  1. 找到有问题的记录时间
  2. 根据时间查看通讯日志和报文
  3. 分析报文

以前我们的程序2\3这一块衔接不好,所以导致分析报文基本是靠人工——看

最后导致没有人关心了。
貌似有时候是厂家原因,甚至有时候是通讯模块不稳定。

立即提问