蒋洪磊
(中国电子科技集团公司第五十四研究所,河北石家庄050081)
基于Python的网管软件技术体系设计
蒋洪磊
(中国电子科技集团公司第五十四研究所,河北石家庄050081)
针对C/C++在网管开发中效率低下、维护和调试成本高的问题,提出采用动态语言Python所组成的轻量级开发架构。在介绍Python的动态类型系统及其元编程能力的基础上,给出在B/S架构的网管软件中设备监控、Web开发、ORM等技术选择:利用Python的数据结构来对二进制流格式进行描述,程序可以自动地在二进制流和JSON结构间进行双向转换。基于Flask的微Web框架,简单易用扩展,有着丰富的插件,支持服务器推送事件。SQLAlchemy作为Python中对象关系建模的事实标准,使得开发人员从各种数据库的差异中解脱出来。项目实践表明基于Python的实现代码简洁,可读性更强,具有快速开发优势。
Python;动态类型;元编程;设备监控;Web服务器架构;对象关系映射
一二十年前的网管开发,通常采用C/C++的技术体系;然而随着硬件性能的提高,其所带来的运行性能优势越来越不明显,而其高昂的学习成本,低下的开发效率,开发人员的参差不齐,以及由此带来的代码健壮性、代码维护成本等问题,以及对Web开发支持的缺乏等等,使其越来越难以适应现代网管的开发工作。为此,提出基于Python的轻量级软件开发架构。
Python[1,2]是一门面向对象的动态语言[3,4],它适用于文本处理、图形处理、科学计算[5-7]、Web网站、设备监控[8]的快速开发。在编译时获得类型的称为静态类型系统,其优势是可以在执行前发现类型不匹配错误,并能根据类型信息进行编译时优化以提高执行速度;而动态类型系统则是在运行时才能知道变量的类型,因而在编写代码时无需声明变量的类型。代码中缺少类型声明,降低了程序的执行效率,却使得代码变得更加简洁,开发人员不再关注于数据类型声明这些非本质的部分,而专注于处理业务逻辑。
动态语言还具有在程序执行时获取、改变程序信息的能力。在不同的语言中称为反射(reflection)、自省(introspection)或者元编程(meta-programming)。Python可以在运行时获取对象的类型信息(内置函数type/isinstance/issubclass)、查询对象当前拥有的属性和方法(内置函数dir/hasattr/getattr)、增删对象的属性/方法(内置方法del)、在运行时将字符串编译为程序并成为程序的一部分(内置函数eval)等等。这一能力,使得开发人员可以在运行时环境中进行即时开发。在静态语言开发中,虽然可以设置断点,查看或者修改变量的数值,但是新编写的代码只能在保存文件、整个项目重新编译再重新运行后才能得到验证。而在动态语言中,则可以在断点处的上下文中立即执行来验证代码的正确性,如果正确则保存新编写的代码,如果代码编写错误则修改后再次立即执行。例如在Python的集成开发环境WingIDE中,可以使用Debug Probe窗口进行运行时开发。元编程不仅可以简化设计模式的实现,提高开发人员对程序的操控能力,还可以在不改变已有代码的情况下而对功能进行追加和变更,这在开发中称为猴子补丁(monkey patch)。开发人员可以利用这种灵活性来修订正在运行中的程序错误[9]。
由于动态语言所具有的丰富表现力,使得动态语言的代码实现更加简洁,维护和排错成本更低[10]。根据各种实际项目的对比,动态语言的代码量只有相同静态类型代码的1/3到1/5,而开发效率是静态语言的3~5倍。例如应用C++进行国产达梦数据库开发时,需要的代码量是近两万行代码,需时数月;而迁移到Python后,利用自主开发的SQLAlchemy方言,则只需不足千行代码,用时不到1周。由于动态类型使得在执行时才能发现错误、阅读程序时可用到的线索较少,因此相比静态语言开发人员,动态语言的开发者更依赖于运行时测试用例和良好的文档编写习惯。
在卫星通讯系统的综合网管中(如图1所示),需要完成该卫星通讯系统的综合业务管理、网络运行状态监视,设备监控等各种功能。用户的操作内容在进行相应的业务逻辑处理后,以JSON格式,由DevMonitor根据对应的设备协议进行转换,由相应的SatSide或者EarthSide模块发送。Web客户端以AJAX向Web Framework发送请求并注册Server Send Event(服务器推送事件,简称SSE),当设备状态发生变化时,则沿反向路径,由DevMonitor转换为JSON格式后经Web框架推送给浏览器。
图1 卫星网管系统的基本架构
2.1 设备监控
为了获取网络运行状态,必须对网络中的设备进行监控[11]。利用Python的pySerial、pyParallel、pyUSB、PyVISA等库可以与设备的串口、并口、USB等接口进行通信。在数据包的封装格式上,底层设备通常采用自定义的二进制流封装格式[12,13],而Web开发中则通常使用JSON包作为Web客户端与服务器交互的协议格式。在协议解析部分,利用Python的语言特性,用协议格式描述来替代手工为每种格式的包进行编码解析。如下所示,pack_des_ list的协议格式描述了表1和表2所示的包格式:
可以看出只需要不到10行代码就可以将这种包格式描述完成。通过将该协议描述作为参数输入通用的解包函数depack_buffer,就可以完成自定义二进制流格式到JSON格式的转换,或者使用封包函数pack_buffer完成逆向操作。在实现新的协议格式时,只要编写协议的格式描述,就能将数据包自动解析为相应的数据结构,而不需要额外编写一行代码。
表1 站控信息帧结构
表2 设备控制响应数据字段格式
对于每一个pack_des_list的项,第一个字段表示该项(或者称为字段)的长度或者数目,第二个字段表示该项的名称,如果为None表示该字段保留,解包程序将直接跳过。第三个字段的类型可以是dict,tuple或者list,这3种类型都是Python的基本数据类型。我们用dict(字典)来描述给定项的处理方式,如”type”:str表示该字段的类型为字符串,缺省类型为整形数;”tmp”:True表示该项是临时项,在后继处理完毕后不会反应到最终结果中,缺省为非临时项。如果第三字段的类型为list(列表),则表示后面按可变长的数组解析,其长度为该项的值。如果第三字段的类型为tuple(元组),则后面为固定长数组,其长度为该项第一字段的值。list或者tuple可以进行任意层次嵌套,如“DevNum”项下面又嵌套着”ArgNum”,表示该数据包可以一次返回多个设备的,每个设备多个参数的设置状态。
可以看出,让开发人员编写协议描述比每次单独为每种包格式编写封包和解包代码要高效的多,而且不容易出错。此外,由于协议描述本身就是Python的数据结构,这使得用户编写的代码可以直接利用IDE的语法检查工具来判断是否出错。此外,该协议描述能够容易描述现有的协议格式,从而快速实现已有协议的解析。
2.2 Web服务器
Python的Web Framework有很多种,选择的是Flask,其优势是简单且易于扩展,有丰富的插件来实现认证、鉴权、会话管理、Cache、存储、文件上传、ORM等各种功能。URL路由使得用户可以使用自由弹性的网址,Flask根据约定优于配置的设计原则,约定所有静态文件,均放在/static/目录下;而所有模板文件,均放入/template/目录下。
直接使用URL路由等于将URL地址和实现代码进行了绑定,这在简化开发的同时也造成了两者的紧耦合。在进行大型项目开发时,为实现模块化并行开发,可以使用Flask的Blueprint(蓝图)技术,将一个应用划分为若干Blueprint集合,然后将一个Blueprint注册到一个应用的URL前缀或子域名之下。可以将一个blueprint以多个不同URL rules在同一个应用中注册多次。在Blueprint中提供模板filters、静态文件、模板等utilities。Blueprint除了方便模块化开发,还完成了URL组织与功能实现的解耦合。
2.3 对象关系映射
ORM将数据库的Table映射为类,Column映射为类的属性,Table中的每条Record则映射为一个类的对象。ORM通过更高层次的抽象,屏蔽数据库间的差异,并代替用户处理连接、缓存、一致性管理等细节,从而提高了开发效率。由于用户不再直接使用SQL代码,不易产生SQL注入攻击,也提高了安全性。
Python中的SQLAlchemy可以完成Object Relational Mapping(ORM)的功能,以实现通过面向对象语法来操控数据库,将商业逻辑与数据库操作逻辑分开。如图2所示,在SQLAlchemy中Dialect负责将通用的操作命令转换为各种数据库的方言,从而对上层用户操作屏蔽数据库间的差异;Connection Pooling(连接池)用于保持和维护和DB的连接,这样不用每次操作都建立和断开连接,从而提高IO性能。DBAPI则是用于连接数据库的API接口。而连接Oracle数据库需要安装对应版本的Oracle instantclient和cx_Oracle库。通过使用SQLAlchemy,用户的实现代码不在依赖于具体的数据库,只需要少量代码就可以完成从一种数据库到另一种数据库的迁移。此外,基于SQLAlchemy的Alembic库可以方便进行数据库的迁移及版本控制。
图2 SQLAlchemy的组织结构
2.4 服务器推送事件
Server Send Events(SSE)是实现服务器主动推送消息的最简单方式,可以结合RESTful技术实现协同编辑或者实时反应设备的状态。在用Python 的Flask来实现SSE非常简单,只需要将之前通过设备监控解析出得结构体直接创建为JSON包放入相应的事件队列。客户端注册SSE所需的服务器端处理函数需要对每类事件(event_name)的每个订阅者(uuid)创建一个Queue,只要Queue中有事件,则推送给该订阅者。SSE的服务器端处理函数定义如下:
介绍Python语言的动态特性,给出了实现B/S架构的网管体系中所需要的设备监控、Web服务开发、ORM的技术方案。从本文可以看出,通过采用Python的轻量级开发架构,可以极大地提高开发人员的工作效率,用更少的代码完成相同的功能,使用户关注于业务的实现而非技术细节,从而使软件的功能更加契合用户需求,并能够进行快速的响应需求变更。
[1]Mark Lutz.Learning Python(Fifth Edition)[M].Sebastopol US:O’Reilly Media,Inc.,2013.
[2]Mark Summerfield.Programming in Python 3 Second Edition[M].Boston US:Pearson Education,2010.
[3]松本行弘.松本行弘的程序世界[M].北京:人民邮电出版社,2011.
[4]Paul King.动态语言的敏捷开发实践[C]∥QCon2010.北京,2010.
[5]Sandro Tosi.Matplotlib for Python Developers[M].Birmingham UK:Packt Publishing,2009.
[6]HYRY Studio.用Python做科学计算[M].北京:清华大学出版社,2012.
[7]Hans Petter Langtangen.A Primer on Scientific Programming with Python 2rd[M].US:Springer,2015.
[8]Hughes JM.Real World Instrumentation with Python [M].Sebastopol US:O’Reilly Media,Inc,2011.
[9]王浩波,郭金鹏.星载环境下可重构技术分析[J].无线电工程,2012,42(1):40-42.
[10]孔庆玲,胡志军,刘英,等.程序复杂性度量技术分析[J].无线电工程,2011,41(2):61-64,2011.
[11]刘学辉,王国良.软件进程监控系统及其实现[J].无线电工程,2011,41(9):62-64.
[12]许静.高效信息收发软件系统设计分析[J].无线电工程,2011,41(9):7-10,43.
[12]王明,何加铭,曾兴斌.IP摄像头远程监控系统的设计与实现[J].无线电通信技术,2014,40(1):71-74.
Design on Python-based Network M anagement Software Architecture
JIANG Hong-lei
(The 54th Research Institute of CETC,Shijiazhuang Hebei050081,China)
In view of such problems as low efficiency in developmentand high cost inmaintenance for networkmanagement system with C/C++languages,this paper proposes a lightweight architecture based on dynamic language Python.On the basis of Python’s dynamic-type system and meta-programming capability,this paper presents such technical selections in networkmanagement software of browser/server(B/S)architecture as devicemonitoring,web development,ORM,etc.The Python’s data structure is used to describe binary stream protocol,and the bidirectional exchange of program can be automatically performed between binary packet and JSON.The micro web framework Flask is easy to use and extend,supports Server Send Event.SQLAlchemy,as a de facto standard for ORM in Python,makes developers handle database like objects.The project practice shows that Python-based implementation is simple,more readable and has higher development speed.
Python;dynamic types;meta programming;devicemonitoring;web server framework;ORM
TP393
A
1003-3114(2015)04-87-4
10.3969/j.issn.1003-3114.2015.04.23
蒋洪磊.基于Python的网管软件技术体系设计[J].无线电通信技术,2015,41(4):87-90.
2015-04-09
国家部委基金资助项目
蒋洪磊(1982—),男,博士,工程师,主要研究方向:分布式存储、卫星通讯网网管运控。