基于PaaS平台架构的BPM应用系统于去年年末上线,此系统待办任务在与Portal接口稽核过程中,出现了问题,总是反馈“新增待办失败”。
注:门户系统是2012年上线的稳定系统,为应用系统提供了接口规范。现由运维人员在提供系统维护支撑(配置级的)。
自从2016年1月25日,收到门户待办稽核问题反馈,痛苦的过程就开始了,因为门户是稳定系统,其开发人员早已经撤出,运维人员支撑有限,而我们又是刚刚上线的新系统,理论上问题出在我这个新上线系统上。
稽核问题分析过程历时3个月,我方投入了5个人(设计、测试、开发、协调沟通等相关分工人员),超过2个人月的工作量,本人作为项目经理,投入也不少于1个人月的工作量。
整个过程大概分为四个阶段:
通过修改接口稽核视图,逐步定位问题点,并解除了系统隐患和BUG。例如,通过稽核发现退回操作存在BUG。
这个阶段的稽核,仍是帮助新上线系统排查BUG阶段。
按规范推荐要求,把由业务数据转换为稽核视图的接口,改造成增量操作日志型的接口视图。
问题依旧。
此阶段是在三月初至四月上旬,是最痛苦阶段,客户每天反馈稽核问题,关于稽核却没有实际进展,不过令人欣慰的是还是发现些问题,例如:
应用、数据库、不同数据库间时间不一致问题。
另外,门户维护人员反馈了接口数据,并按数据内容逐项及组合,几乎每天做验证测试。
无奈之下,我查找曾经参与门户项目(注:我只是负责其中二期流程服务的开发)开发时的资料,反编译稽核工具,终于找到了问题点,原来是如此简单。
如上表所示,门户端数据“_id”是由appID(也就是pendingNode)+pengCode+appToken构成。
如果appToken设置为“123456”,则_id最后将是“123456”,如果appToken设置为“”,则_id由appID+pengCode构成,符合一期设计表结构。
反编译稽核工具代码片段如下:
boolean exist = false;
DBCollection DBCollection = this.pendingDB.getCollection("pending");
String pendingId = pendingNote + pendingCode.trim();
BasicDBObject query = new BasicDBObject("_id", pendingId);
query = query.append("pendingStatus", "0");
通过代码和先前业务测试,稽核新增待办是否存在的规则是:取专业系统待办推送日志的中待办状态(pendingStatus)为待办(0)的pendingNode+pendingCode,与门户数据比较,如果不存在则记录为“新增待办失败”。
把调用推送门户的服务参数,appToken串配置置成空即可。
UCLOUD_ASSIGN_APP_ID= 此处隐去
UCLOUD_AUTH_TOKEN=
对应应用端调用代码如下:
/** * 实现推送,更新表中数据 * * @param 准备推送的数据 * @param 状态 * @return 根据类的实例调用该类中定义的非静态方法,实现其他实现类与主类的代码分离 */
public String addUcloudPanding(PendingEntity pendingEntity, String appID, String adppToken, String eipPendingRestUrl) {
TaskAppService taskAppService = ProxyFactory.create(TaskAppService.class, eipPendingRestUrl);
PendingEntity[] pe = { pendingEntity };
Map<String, String> map = taskAppService.addPending(appID, adppToken, pe);
return map.get(pe[0].getPendingCode());
}
在稽核出现问题时,门户维护人员多次提示时间容易出现问题,我们则沿着待办任务创建时间、写日志时间、门户接收创建时间的顺序梳理,发现了稽核日志中时间存在不一致、时区问题。
时间一致性、时区问题是大型复杂系统必须重视、小心处理的的业务规则,发现问题如下。
(1)、由于使用的系统平台Cordys产品是国外产品,时间是标准时间,与北京时间差8个时区,也就是少8个小时。
(2)、Oracle时间转换字符时,分钟与月份的混淆,如上述原代码想用mm表述分钟,但是SQL中不区分大小写,MM和mm被认为是相同的格式代码,被转换成月份。
对比SQL代码如下:
--原sql语句
to_char(t.create_datetime, 'yyyyMMddHHmmss') as pendingDate,
--修改后
to_char(t.create_datetime + interval '8' hour ,'yyyymmddHH24MIss') as pendingDate,
(3)、系统由Oracle数据库(小型机)、MySQL(PC Server)、MongoDB、OpenText Cordys构成,共计9台服务器设备,其中小型机服务器时间慢10分钟。
(4)、系统使用时间来源不统一,例如有Oracle数据库、有应用服务 Cordys等等。
时间问题仍是永恒的话题,特别是大型集群系统,虽然本系统中应用服务器已经部署了集群时间同步服务,但是,Oracle服务器却无法集成在一起,需要日后维护多关注。
在门户待办任务管理中,任务只有待办、已办;而在专业系统中,任务管理要复杂的多,不仅存在待办、已办,还有退回、转发等等。
以“转发”为例,与门户待办任务对应关系如下:
专业系统待办任务在做转发处理时,先推送此待办更新为已办状态服务,然后再推送一条新待办,此新待办为转发目标。
门户建设者为后续接入系统应用的开发者提供了详尽的接口开发规范,例如新增待办的说明片段如下:
理论上可以通过业务操作,获取到此上图中操作推送门户的日志,但是应该按规范的建议,做成增量型日志。
但是,对此简单的增量型日志,给接口开发人员造成了很多误解,“为什么同一个待办任务,为什么会有多条记录呢?”。
看来,文字加图形描述也未必说的清楚,开发者间直接沟通多么重要,可惜没有开发者能与你交流。
如果有代码样例就好了。
try {
PendingEntity pe = new PendingEntity();
// 云门户接口需要推送的信息 ---在taskXML获取需要的值
// 待办id
pe.setPendingCode(getNodeValue(taskXml, "PendingCode"));
// 待办标题
pe.setPendingTitle(getNodeValue(taskXml, "PendingTitle"));
......
// 实现推送云门户
C_SYNCPORTAL C_SYNCPORTAL = new C_SYNCPORTAL();
//新增日志 C_SYNCPORTAL.addUcloudTasklog(pe,UCLOUD_ASSIGN_APP_ID,"a");
s = C_SYNCPORTAL.addUcloudPanding(pe, UCLOUD_ASSIGN_APP_ID, UCLOUD_AUTH_TOKEN, UCLOUD_SERVER_REST_IP_ADD_TASK);
LoggerManager.logAsync(LoggerManager.DEBUG, LoggerManager.LOG_TYPE_SOAP, "UNICOM_BPM", "UCLOUD", "TaskAppService.addPending", "", "", Node.writeToString(taskXml, true), s, "Call TaskAppService.addPending OK");
} catch (Exception e) {
logger.error(">>>>>>>>>>>>>>>>>>>>>>>>>>>>> UCLOUD_TASK_SYNC_ERROR: UCLOUD推送待办失败:" + writeException(e));
LoggerManager.logAsync(LoggerManager.ERROR, LoggerManager.LOG_TYPE_SOAP, "UNICOM_BPM", "UCLOUD", "TaskAppService.addPending", "", "", Node.writeToString(taskXml, true), writeException(e), "Call TaskAppService.addPending KO");
}
上文已经提到了,我们曾经参与门户二期并承担流程服务部分的建设,如下图所示,当时统一待办的设计是这样描述的:
开发人员依据当时的设计和理解,在开发此系统时,推送门户待办时,为appToken初始化了值。
噩梦自此开始了。
现在,回头看看上线前,门户接入申请内容,申请内容及反馈内容中,都未提及appToken。
圈内开发人员的信息未必可靠,一定要以接口规范、申请单内容为准。为这个信息耽误了2个月时间和耗费了2个人月的成本。
交流、沟通是必须的,帮助信息是否可行,需要预判和快速识别。在信息不对称的情况下,是非常要命的。
规范太重要了!
由于系统中存在多台服务器,在上线前后都出现过多次配置参数不一致问题,例如本次修改appToken参数,开发部署人员修改143服务器配置不成功。
而本人检查时,先从143开始检查的,在检查时,143还未修改完成,就此遗漏,好悬错过。
集群配置统一、检查,应该配合好,小心、仔细。
总结:
系统设计者在制定、执行开发及接口规范时,一定要严禁、慎重,重视规范出处。
作为项目经理,在大部分开发人员撤出后,亲自组织、亲自开发分析稽核问题,对分析、预判系统中存在的问题,有很大的帮助。
后记:
今天,门户稽核顺利通过了,小庆祝下!
但是,维护人员反馈门户侧的待办不消失了,即使按照我先前写的《接入门户统一待办运维经验小结——更新待办为已办》方法,也不好使!
我立马回复: pengdingCode后面追加“123456”试试,这两天估计要处理下大量的更新的工作。
本系统运维人员反馈:果然加上123456就好使了。也给我一个抓狂的图标。
没有更简洁的办法了,只能逐条处理这样的后遗症。
参考:
《外部系统接口稽核经验谈》 肖永威 2016.2
《基于运营架构的办公流程能力平台》 肖永威 2015.6