GenScript SAP项目

项目背景

GenScript是一家做生物的跨国公司,我有幸任职在IT部门担任Java开发工程师(在职),主要负责公司内部的SCM系统的开发及维护,虽然叫SCM,但是个人感觉这个系统就是一个ERP,里面包括了客户管理、物料管理、订单管理、生产管理、库存管理、发货管理、报表和财务等众多模块,由于功能太多,所以使得整个系统非常臃肿,而且由于是跨国公司,系统又没有做分布式部署,使用人群又是在全球各个地方,使得整个系统使用起来很慢,并因为各个站点不同的需求都集中到一个系统中,导致很多逻辑和程序上的Bug,或者因为一个Bug影响到所有站点的用户,非常影响公司内客户的使用体验,有些Bug可能会导致公司同事的日常工作会进行不下去,所以最终领导层决定,将这些模块拆分开,形成了3个订单系统(包括客户管理、订单管理),1个生产系统,2个发货系统,1个物料系统,将库存管理、发货管理以及报表、财务部分都整合进SAP,各个系统之间通过数据库层面同步、WebService传输、RFC/JCO传输等方式进行数据同步,通过这样的拆分达到各个系统因为地理位置进行分布式部署的目的,从而解决前面提到的问题。

优点:

  • 各个模块独立部署解决了SCM系统整体反应慢的问题
  • 不会因为一个站点需求导致的Bug而影响所有模块
  • 通过集成SAP使财务报表的数据更完整准确
  • 考验了IT的技术能力

缺点

  • 使IT的维护成本增加了数倍
  • 个人感觉SAP太贵了…

问题总结

SCM拆分

由于SCM系统包括了很多模块,而模块间的耦合度很高,在拆分的过程中经常会出现A模块使用B模块的数据,或者B模块需要更新A模块的字段,比如生产完成后需要插入待发货数据、发货后需要更新订单状态等诸如此类的问题,大量的模块间的数据更新存在,所以这里我们统一使用WebService的方式,个人认为WebService的方式相对古老,但是由于SCM架构本身的固化,不太方便加入更加新颖流行的Rest API的形式,所以也就作罢。

数据同步

拆分后订单系统有3个,而生产系统只有1个,发货系统就2个,可是生产系统和发货系统都需要使用订单系统的客户、订单数据,这就要求必须同步到生产系统和发货系统,目前采用的是DB层面的增量同步的方式,这部分是DBA在数据库层面处理的,其实增量同步有一个问题,如果在订单系统删除了一条数据,那么这条数据是不会在生产和发货系统中删除的,所以为了达到正确的目的,我们统一的将所有删数据的操作改为了变更状态,从而达到数据准确的目的,包括其他模块间数据同步也是如此处理的。

主数据同步进SAP

客户数据是各个系统都需要使用的数据,对于非SAP系统来说都好办,因为使用同样的数据,同样的scheme,只是需要保存到不同的数据库中,所以这点由DBA处理即可,但是对于SAP则不一样,SAP是标准的(定死了的)模块,虽然可以扩展,但是和SCM系统的架构设计不可能一样,所以就必须按照SAP的规则将数据传进去.其实有两种途径,一是DBA使用ETL工具进行数据清洗转换直接写进SAP数据,但是这种方式注定是不能成功的,因为SAP不可能给这样的权限,于是就只剩下了第二种途径,通过程序接口将数据传进去,SAP可以提供WebService和RFC/JCO两种方式,最终我们采用了RFC/JCO的方式。在前期和业务部门、SAP沟通确认了数据的传入规则后,我们就着手进行开发,对于单个客户来说,很简单,只需要点击下保存即可,而前期我们公司已经有很多客户了,具体数量不便透露,只能说是百万级,所以就有了期初的批量导入的需求。由于SCM和SAP的scheme不同,需要通过一些逻辑来组合数据,所以无法简单的通过Excel的方式来处理,只能通过程序动态读取数据进行组合然后传入SAP。

  • 第一阶段:同步传输
    通过接口传输数据,没有多想,同步写法,百万的数据读一条写一条,再读一条写一条,再……由于美国SCM数据在美国,SAP在苏州,中间还要经过Zato(在南京)、JCO才能连接到RFC,每一个客户需要平均8次读取美国数据库的操作,所以网络延迟浪费了很长的时间,只能达到3-5秒每条,这里包括拼装数据和传入SAP的时间,按照这个速度需要400+W秒=1100+小时=46+天,这里还不计算网络中断等其他因素,这个必须改。
  • 第二阶段:多线程同步传输
    开多个线程同时读取,这个时候发现速度上还是不理想,因为即使我开10个线程,还是需要4-5天时间,并且这里还不能保证数据完全准确,因为程序可能有Bug,业务部门可能有新的需求或逻辑,这个时候就要重传。
  • 第三阶段:多线程异步传输
    虽然从读取操作拼装数据到传入SAP是个完整操作,但是从实现上完全可以分开,所以我将拼装数据和传入SAP分开了,用十个线程拼装数据生产json文件,用2个线程读取已经生成的json传入SAP,这样节省了同步的时间,可是效果还是不明显,因为瓶颈还是读取数据的网络延迟上。
  • 第四阶段:拷贝美国数据库到南京
    由于网络延迟是制约速度的最大问题,那么只能放大招了,拷贝美国数据库到南京本地,去除了网络延迟的问题后发现这个速度简直要命了,快到不行不行的,完全不用多线程生成json了,一个线程就能2个小时内将百万数据生成json,然后用2个线程进行读取传入SAP,虽然完整传入SAP还是需要将进1天的时间,因为南京到苏州也有网络延迟,但是这个时间已经是大家可以接受的了,这里还有一个目的就是给Zato和JCO做压力测试,就没有做更多的优化,其实还可以将数据库拷贝的苏州,去掉Zato的转发,直接连接苏州的JCO,并开更多线程读json往JCO丢,这样我想速度上会更快,只是不晓得SAP能不能抗住。