docker版jxTMS使用指南:使用webSocket

本文讲解4.6版jxTMS中如何使用webSocket,整个系列的文章请查看:4.6版升级内容

docker版本的使用,请查看:docker版jxTMS使用指南

4.0版jxTMS的说明,请查看:4.0版升级内容

4.2版jxTMS的说明,请查看:4.2版升级内容

4.4版jxTMS的说明,请查看:4.4版升级内容

4.6版jxTMS的核心是解决分布式问题,但之所以要考虑分布式处理,诱因就是一个高频数据处理问题。这个问题需要对采集到的数据进行分析后建立一个模型。

由于对此问题还没有充分的认识,所以想先做一个简单的数据分析并显示到页面上,好先建立起一个感性的认识。

过程比较简单,就是抓数据然后做成一个四分位的图来显示一下,这个用matplotlib来做很容易。但问题在于数据频次要求比较高,用javascript轮询来显示,0.1秒一次就已经开始丢数据了【报ns_binding_aborted错误】,频率再高一点根本就不显示了。

所以就想到使用webSocket来做。干起来!

实现起来并不难,关键是要无缝的嵌入到我们之前的web体系中。所以整个解决方案是:

1、增加了两个和websocket相关的uri:

  • /openWS:用来打开webSocket

  • /ws:用来处理webSocket的数据交换

2、webSocket功能是动态的,通过命令行开关【–webSocket】进行控制,即命令行中给出了开关【–webSocket】,就注册并使能上面的两个路由,否则webSocket功能是关闭的

3、webSocket功能是可定制、可扩展的

即webSocket功能可以灵活的嵌入到任何一个页面中,使用纯javascript编写前端,可以非常容易的就为任何一个页面提供webSocket功能。

后端可支持多个具有webSocket功能的不同页面的不同用户的同时访问,增加后端对应功能也非常简单。

示例

我们想实现在浏览器中显示一个图片,该图片是由后台实时刷新的,每接收通过webSocket发送过来的一帧图像数据,我们就动态的刷新到该图片中。

1、定义一个需要启用webSocket功能的页面,我们直接上代码:

def webPage():
    '''




test



    


    '''
    pass

上述代码定义了一个webPage函数,其__doc__是一个用html描述的web页面,该页面的核心就是【{{WSJSCript}}】,除了这个之外的都是用户根据自己的需要进行定义就好,然后在需要启用webSocke功能前增加此语句即可。

jxTMS启用webSocke功能后,对所有访问路由【/openWS】的请求,都会直接返回上述定义的html,并将其中的{{WSJSCript}}替换为dsWebSocket类的定义。

dsWebSocket类的对象在初始时有5个参数:

  • name:该页面名,也是该webSocke功能的名字,前后端要统一起来,否则会无法显示

  • cid:用来区分不同的用户id

  • wsRecv:接收webSocke数据的回调函数

  • wsOpen:webSocke打开事件,同时回送所创建的dsWebSocket对象,可以调用其send函数来发送数据

  • wsClosed:webSocke关闭事件

2、将此页面注册到系统中:

from jx.web import openWebSocketHandler
openWebSocketHandler.register('p1',webPage.__doc__)

register有两个参数:

  • page:该参数就是创建dsWebSocket对象时应给出的name,两者必须一致,否则无法正确访问到

  • html描述,我们是用一个函数的__doc__来存放的

注册后,我们只要访问:http://127.0.0.1:10028/openWS?page=p1。就会显示我们在webPage函数的__doc__中定义的web页面了。

3、定义处理webSocke数据的函数

def recvFromWS(event,ws,cid,data):
    if event == 'open':
        print(f'recvFromWS open {cid}:{data}')
        t=threading.Thread(target=dispImg,name='dispImgThread',args=[ws])
        t.start()
    else:
        print(type(data))
        print(f'recvFromWS {cid}:{data}')

该函数有四个参数:

  • event:webSocke触发的事件,有两个:open和recv,前者是连接打开,后者是接收到webSocke发送的数据

  • ws:后端的webSocke管理对象,主要用来发送数据

  • cid:就是上面在创建dsWebSocket对象时给出的cid,用来区分不同的用户,具体含义由用户自己定义与设置

  • data:前端发送过来的数据,都是字符串类型,所以如果前端发送的是json对象,需要自己转换;如果是open事件,则为None

大家看到在open时,我们启动了一个线程并把ws作为参数送入。这是由于python的webSocke使用了asyncio,其需要启动事件循环来分发异步事件,而我们的主线程并没有启用这样的事件循环,所以我们单独启动一个线程来执行webSocke的数据发送工作,并在此线程中启动asyncio所需要的事件循环:

def dispImg(ws):
    loop = asyncio.new_event_loop()
    asyncio.set_event_loop(loop)
    while True:
        image = getImage()
        #print(f'ws send data:{len(image)}')
        ws.write_message(image, binary=True)
        time.sleep(0.005)

dispImg在启动asyncio所需要的事件循环之外,主要就是以5毫秒为间隔循环来生成数据对象并发送到web前端。

getImage的代码我们也贴一下吧:

import matplotlib.pyplot as plt

y_list = []
def getImage():
	#用随机数填充数列,只保留最新的20个数据
    y_list.append(random.randint(1, 100))
    if len(y_list) > 20:
        y_list.pop(0)
	#清空当前图形
    plt.clf()
    fig, ax = plt.subplots()
    #用y_list中的数据生成四分位图
    ax.boxplot(y_list)
    #设置x坐标
    ax.set_xticklabels(['test123'], rotation=90)
    #设置y轴的范围
    ax.set_ylim(1,100)

    #将生成的四分位图以png图片格式保存到内存的字节流中
    memdata = io.BytesIO()
    plt.savefig(memdata, format='png')
    image = memdata.getvalue()

	#我们是5毫秒生成一张图片,速度太快,手动清除以避免内存消耗过快而有溢出
    plt.close()
    return image

上述代码,都在【app/module/web_test.py】文件中。

注:需要pip install matplotlib

4、注册webSocke数据的接收函数

webSocketHandler.register('p1',recvFromWS)

大家看到,我们又使用了【p1】注册了recvFromWS函数,表明我们前端所使用的p1页面将和recvFromWS函数进行数据的交互。

这样一来,我们用一个共同的名字【应用名,这里是p1】将下面三个东东绑到了一起:

  • 页面网址,通过uri【/openWS?page=应用名】来访问

  • 前端页面,通过openWebSocketHandler.register(应用名,htmlDoc)进行注册

  • 后端数据接收函数,通过webSocketHandler.register(应用名,处理函数)进行注册

完成上述工作后,我们需要通过命令行启用webSocket功能:

python3 main_slave.py --web --module --webSocket
其中:
--web开关是启动web服务,默认端口是10028
--module开关是加载module目录下的各个模块,因为我们的web_test.py文件就放在module目录下
--webSocket开关是启用webSocket功能,即自动注册【/openWS、/ws】两个webSocket相关的路由

webSocket开关单独启用是不起作用的,必须配合–web开关一起使用。

参考资料:

jxTMS设计思想

jxTMS编程手册

下面的系列文章讲述了如何用jxTMS开发一个实用的业务功能:

如何用jxTMS开发一个功能

下面的系列文章讲述了jxTMS的一些基本开发能力:

jxTMS的HelloWorld

你可能感兴趣的:(jxTMS,docker,websocket,python,jxTMS,SaaS,分布式)