您现在的位置是:首页 >学无止境 >docker版jxTMS使用指南:python服务动态升级网站首页学无止境
docker版jxTMS使用指南:python服务动态升级
jxTMS增加了python服务的动态升级能力,整个系列的文章请查看:docker版jxTMS使用指南
最近笔者在开发一个数据采集系统,体系架构就采用了jxTMS+python,其中python主要用来做接口机,通过mqtt来接收前端设备发送的实时数据加以处理和保存,管控则通过jxTMS来做。
原本已经依托一个公有的物联云做了数据采集,所以需要逐步将各个站点迁移到新系统。但时间紧、任务急,不同的站点的不同设备又需要一个个的实现采集接口和管控功能,所以没办法整体交付,只能是一个个的来。
自然的,也就不希望每次增加一个新种类的数据采集模块和管控功能,就停机重启接口机。
所以笔者就考虑给python服务增加动态升级能力。
python本身就具备动态加载模块的能力,所以本功能其实主要就是解决如何将其融入jxTMS勾连python的能力中来。考虑到本功能虽然很实用,但较为简单,目前的时间又比较紧张,所以就暂不打包到docker镜像中做一次发布了。大家按我下面的说明即可自行完成。
给python服务增加模块加载能力
在python服务所在的py文件【tms的docker镜像里是/home/tms/python/py.py】中增加三个东东:
1、导包语句中增加:
import importlib
from jx.mainService import mainService
2、给Py类增加一个对象函数loadNewPy:
class Py(jxGoBaseService):
def loadNewPy(self,params):
try:
mn = params['moduleName']
module = importlib.import_module(mn)
jxGo.log('info',f'接收到命令,加载模块【{mn}】:ok')
return {'ty':'response','cmd':'loadNewPy','rc':'ok'}
except Exception as e:
jxUtils.error(repr(e))
return {'ty':'response','cmd':'loadNewPy','rc':'error'}
loadNewPy函数就是用来加载新模块的。
3、设置主服务
py = Py('pyService',hn,'demo1')
#
#在这里增加新的语句
mainService.set(py)
#
py.start()
增加主服务的动态扩展能力
1、在python目录的jx子目录下的jxGoBaseService.py文件中给jxGoBaseService类增加一个对象函数:
def addCmd(self, cmd, func):
self._cmdSwitch[cmd] = lambda ps:func(ps)
2、在python目录的jx子目录中增加一个mainService.py文件,在其中输入:
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import traceback
class mainService:
_Service = {}
@classmethod
def set(cls, s):
ms = cls.__dict__['_Service']
ms['main'] = s
@classmethod
def register(cls, cmd, func):
ms = cls.__dict__['_Service']
ms['main'].addCmd(cmd,func)
上面三步就已经完成了给python服务增加动态升级能力的所有工作,我们下面就测试一下。
测试动态扩展能力
1、在python目录中新建一个test子目录,在命令行执行:
cd /home/tms/python
mkdir test
cd test
touch __init__.py
即将test子目录作为模块,否则放入其中的py文件无法加载。
然后启动python服务:
cd /home/tms/python
python3 py.py
2、另起一个登录会话,在test子目录中增加一个test1.py,在其中输入:
#!/usr/bin/python
# -*- coding: UTF-8 -*-
from system.mainService import mainService
def testSAF(params):
print(params)
return {'ty':'response','cmd':'testSAF','data':'okkk'}
mainService.addCmd('testSAF',testSAF)
test1.py是在主服务启动后添加的,所以我们的目标就是如何通过jxTMS来执行test1.py中的testSAF函数。
下面我们在jxTMS增加相应的测试页面和代码。
3、在web文件中增加:
//testCmd
web testCmd type div;
web testCmdT1 parent testCmd type table title='testCmd',width=900,alone=true;
with testCmdT1 row 0 col c0 web n type text text="testCmd:",width=150;
with testCmdT1 row 0 col c1 web n bind testInput type input width=150;
with testCmdT1 row 1 col c0 web n type button width=150,text='testCmd',
motion=cmd,demand=testCmd;
with testCmdT1 row 1 col c1 web n type button width=150,text='testCmd2',
motion=cmd,demand=testCmd2;
4、在capa.py文件中增加:
@myModule.event('cmd', 'testCmd')
def testCmd(self, db, ctx):
#加载新的模块
ps = jxJson.getObjectNode()
mn = self.getInputString('testInput')
ps.set('moduleName',mn)
#向python扩展发送命令,并送入参数ps
rs = catalogService.call('pyService.pythonDemo.demo1','loadNewPy',ps)
jx.log('rs:{}',rs)
@myModule.event('cmd', 'testCmd2')
def testCmd2(self, db, ctx):
#测试新的模块中扩展的能力
ps = jxJson.getObjectNode()
mn = self.getInputString('testInput')
ps.set('testSAFPPPP',mn)
#向python扩展发送命令,并送入参数ps
rs = catalogService.call('pyService.pythonDemo.demo1','testSAF',ps)
jx.log('rs:{}',rs)
5、在op.py文件中增加:
@biz.Demand('disp','testCmd')
@biz.OPDescr
def op1(json):
json.setShortcut('演示'.decode('utf-8'),'testCmd'.decode('utf-8'))
保存web、capa.py、op.py三文件,并上传,然后做一次热机刷新。
然后刷新页面以重新登录。
点击快捷栏【演示->testCmd】,然后在输入框后输入:test.test1后点击【testCmd】按钮,可在python控制台看到日志输出【去除日期等信息】:
pyService.pythonDemo.demo1 从【demoHost1】接收到控制命令:loadNewPy
这代表test1.py加载成功.
点击【testCmd2】按钮,可在python控制台看到日志输出【去除日期等信息】:
pyService.pythonDemo.demo1 从【demoHost1】接收到控制命令:testSAF
同时在控制台看到print打印的jxTMS送入的参数:
{'testSAFPPPP': 'test.test1'}
与此同时,还在jxTMS的日志输出中看到testSAF命令执行后的响应:
rs:{"cmd":"testSAF","data":"okkk","ty":"response"}
这代表test1.py中的新功能testSAF得到了正确的执行。
结语
jxTMS本就具备热机刷新的动态升级能力,现在python服务也具备了动态升级能力,jxTMS就拥有了完整的动态升级能力。
这将有助于充分发挥jxTMS在业务管理方面强大的低成本定制能力,再结合python的生态,实现了强大的、稳定的全能力业务支持与定制。
注1:上面的演示其实还缺了一个重要的能力:如果python服务重启了,通过loadNewPy动态扩展的模块是无法自动加载的。解决办法是利用python的pickle实现本地存储
注2:目前的迭代中,loadNewPy已经移入了jxGoBaseService,并用本地存储弥补了上面的缺失,过些天会和其它升级一起打包到新版本的docker镜像中发布
参考资料:
下面的系列文章讲述了如何用jxTMS开发一个实用的业务功能:
下面的系列文章讲述了jxTMS的一些基本开发能力: