SAP ABAP守护进程(ABAP Daemon)的实现方式

Jerry本科学习《计算机操作系统》这门专业课时,了解到了守护进程的理念,当时我们是从Linux操作系统里的守护进程开始学习这个概念的:Linux守护进程是运行在后台的一种特殊进程,独立于控制终端并且周期性地执行某种任务,或等待处理某些将要发生的事件。Linux系统很多服务都通过守护进程实现,常见的守护进程有系统日志进程syslogd,web服务器httpd,邮件服务器sendmail和数据库服务器mysqld等。

当时Jerry上这门专业课时,《暗黑破坏神II》在国内各大高校的战网上正进行得如火如荼,Jerry也和其他暗黑爱好者一样,天天在战网上KB,KC, 刷暴躁外皮。

暗黑破坏神II里有很多对恶魔(Demon)造成额外伤害的武器,比如下面这把用符文之语悔恨(Grief)制成的幻化之刃,对恶魔生物造成额外185%伤害:

SAP ABAP守护进程(ABAP Daemon)的实现方式

当时Jerry在战网上刷怪的时候,心想,Linux守护进程的名称咋这么酷?Demon Process - 恶魔进程。第二天翻开教材仔细一看,顿时尴尬了,原来守护进程的英文应该是Daemon Process…

SAP ABAP守护进程(ABAP Daemon)的实现方式

那么在ABAP里能否实现具有守护进程特性的报表?这个需求翻译成ABAP的术语,即是否能够开发一个满足下列特征的ABAP程序?

终端(SAPGUI或ABAP Development Tool)关闭后仍然能够继续运行,且能继续接收用户输入,处理并推送结果给用户。

很多朋友一定很快就会想到ABAP后台作业。没错,开发一个ABAP报表,以后台作业的方式启动,的确可以实现脱离终端运行的效果。然而这种后台作业无法再以普通方式接受用户输入,一种比较笨重的解决方式是采取生产者-消费者的思路,定义一个数据库表,充当任务队列;用户将请求插入到该数据库表里,而后台作业程序周期性地去查询该数据库表,如果非空,则取出请求并处理。

另一种思路就是在事务码SICF里创建一个新的节点并在其handler class里书写处理逻辑,这样消费者可以发送HTTP请求到该ICF节点负责的url,并接收处理结果。

之前Jerry的文章一个13年ABAP老兵的建议:了解这些基础知识,对ABAP开发有百利而无一害介绍过,ABAP服务器同外界通过HTTP交互,会经过Internet Communication Manager(ICM)这个模块,通过这种方式实现的ABAP程序,表面上看也勉强模仿了守护进程的效果,但请求处理的性能和真正的守护进程相比相差甚远,并且本质上是借助Web服务器实现的。

一个好消息是,在2018年SAP发布的ABAP Platform 1809中,提到了一些激动人心的新特性,比如针对工业物联网(Industrial IoT)和Machine-to-Machine通信的增强,MQTT的引入,以及对ABAP Daemons的原生支持。

SAP ABAP守护进程(ABAP Daemon)的实现方式

本文我们就用ABAP平台1809新引入的ABAP MQTT和ABAP Daemons来实现一个Hello World级别的ABAP守护进程。

MQTT(Message Queuing Telemetry Transport,消息队列遥测传输协议)是一种基于发布/订阅模式的轻量级通讯协议,构建于TCP/IP协议上,因其低开销和低带宽占用的优点,在物联网、小型设备、移动应用等方面应用特别广泛。

SAP ABAP守护进程(ABAP Daemon)的实现方式

关于ABAP平台1809新特性的更多介绍,请参阅SAP社区博客:

https://blogs.sap.com/2018/10/01/abap-platform-for-sap-s4hana-1809/

ABAP守护进程和MQTT密切相关,因此我们先来了解ABAP平台1809新引入的对MQTT的支持。

SAP ABAP守护进程(ABAP Daemon)的实现方式

设想一个简单的“一问一答”的场景,在ABAP平台上开发一个MQTT客户端,往第三方的MQTT broker(代理)发送消息,并接收其回复。

新建一个ABAP类,实现SAP标准接口IF_MQTT_EVENT_HANDLER的对应方法。

SAP ABAP守护进程(ABAP Daemon)的实现方式

至于MQTT broker,我选择了一个基于HiveMQ的公开Broker:broker.mqttdashboard.com,可以使用下面这个用webSocket实现的MQTT客户端来操作该broker:
http://www.hivemq.com/demos/websocket-client/

这个broker专门用于测试用途,收到MQTT消息后,会原封不动地将其回复给发送方。

SAP ABAP守护进程(ABAP Daemon)的实现方式

在ABAP类的构造函数里连接MQTT broker,把返回的MQTT客户端实例存储在类的成员变量mo_mqtt_client里,接下来就能使用该实例的publish方法去发送消息,subscribe方法订阅消息,on_message方法接收消息。

SAP ABAP守护进程(ABAP Daemon)的实现方式

打开MQTT客户端,订阅渠道:abaptopic/jerry/test

SAP ABAP守护进程(ABAP Daemon)的实现方式

接着我首先在第66行,往该渠道发送一条Hello World的消息,broker收到后会将其原封不动地返回,但因为我的ABAP类并没有订阅这个渠道,因此不会收到这条hello world消息的回复。

第68行订阅该渠道后,第69行发送第二条消息给broker,这次就能收到其回复了。

SAP ABAP守护进程(ABAP Daemon)的实现方式

回到broker客户端,看到从ABAP端发送过来的两条消息:

SAP ABAP守护进程(ABAP Daemon)的实现方式

回到ABAP端,看到代码第69行发送的第二条消息的回复:

SAP ABAP守护进程(ABAP Daemon)的实现方式

弄清楚ABAP MQTT的用法之后,我们就可以动手开发ABAP守护进程了。虽然ABAP守护进程并没有直接使用MQTT同使用者进行交互,但是掌握这种消息通知机制的用法,对我们了解ABAP守护进程的工作原理也有帮助。

新建一个ABAP类zcl_jerry_simple_daemon,将cl_abap_daemon_ext_base设置成其父类。

从基类继承的这些ON开头的方法,即ABAP守护进程生命周期事件发生时,开发人员能够实现自定义逻辑的位置,比如在系统SHUTDOWN时,开发人员实现的ON_SYSTEM_SHUTDOWN方法会触发,在此处完成守护进程的清理动作,实现优雅退出。

SAP ABAP守护进程(ABAP Daemon)的实现方式

而最有用的方法,无疑就是ON_MESSAGE,这也是守护进程接收用户输入并响应的地方。

为简单起见,我的守护进程收到用户输入后,仅仅弹出一个弹出对话框,显示在SAPGUI里:

SAP ABAP守护进程(ABAP Daemon)的实现方式

守护进程的启动则通过框架类cl_abap_daemon_client_manager的start方法实现,第75行start方法传入的参数lo_pcp作为守护进程启动参数一并传入,pcp代表Push Channel Protocol,一种用于消息传递的数据结构。

SAP ABAP守护进程(ABAP Daemon)的实现方式

使用下列语句启动该守护进程,将其命名为jerry_daemon:

zcl_jerry_simple_daemon=>start( iv_daemon_name = ‘jerry_daemon’ ).

在事务码SMDAEMON里可以看到所有正在运行的守护进程:

SAP ABAP守护进程(ABAP Daemon)的实现方式

打开SAPGUI,使用如下的方法向jerry_daemon这个ABAP守护进程发送一条消息,会立即在SAPGUI里看到守护进程的on_message方法里弹出的对话框:

SAP ABAP守护进程(ABAP Daemon)的实现方式

因此将来我们如果遇到需要开发长时间脱离终端运行且仍需响应用户输入的ABAP程序,除了ABAP后台作业和SICF服务外,又多了ABAP守护进程这种选择。

希望本文介绍的内容对你有用,感谢阅读。

SAP ABAP守护进程(ABAP Daemon)的实现方式

要获取更多Jerry的原创文章,请关注公众号"汪子熙":
SAP ABAP守护进程(ABAP Daemon)的实现方式

上一篇:如何学习abap编程


下一篇:《全栈性能Jmeter》-7JMeter常用脚本开发