重磅|RServe源代码解析(中)

本文通过对Rserve的设计初衷、运行机制、核心对象和方法进行粗浅探讨,为利用Rserve做深度产品开发的开发者提供初始帮助。上篇(点此查看)介绍了研究Rserve代码需要的基础知识和Rserve的常用名词,以及Rserve的工作流程、QAP1消息协议和主要的Command,今天我们着重分析Rserve服务器端的代码结构和核心函数。

重磅|RServe源代码解析(中)

服务器端主要函数/方法逻辑

◆ 3.1 源代码结构

研究代码的一个捷径就是从makefile开始,看编译时各个文件的依赖关系,对软件代码结构有个大概了解。在/src目录下,RServe存在两处makefile:

1)/src/proxy下有forward的makefile。forward是个代理程序(proxy),通过HTTP协议接受QAP1请求,然后转发给Rserve,在获得结果后,再forward给client连接。proxy的目的是提升网络安全,Rserve运行在一个本地端口(local unix socket),proxy程序负责外部端口请求的监听。

2)/src/下针对Windows、非Windows(Unix、OS等)操作系统各有一个makevars文件。makefile除了可以生成Rserve server和client端的可执行文件外,非Windows系统还调用forward的makefile生成proxy执行文件。

重磅|RServe源代码解析(中)

下面是/src目录下主要文件的作用列表

重磅|RServe源代码解析(中)

proxy的实现机制与standalone类似,并且standalone功能更丰富,因此下面主要以standalone为主线进行讨论。在standalone入口下,主要程序文件的调用关系如下图所示:

重磅|RServe源代码解析(中)

其中Rserv.c是RServe核心处理逻辑引擎(有5000余行代码),RSserver、websockets、http是处理端口连接的主要逻辑,下面分别分析其核心代码逻辑,最后总结了RServe的主要数据结构。

◆ 3.2 standalone.c代码

standalone的作用是在命令行启动RServe服务。下图仅保留其核心代码逻辑,主要有如下基本步骤:

1)R动态库的初始化

2)创建Rserve服务对象, 在Unix下,Rserve服务可以作为一个守护进程(daemon,即没有控制终端的后台运行程序,生存周期一般较长)。编写守护进程程序的通常规则如下:

· 调用 umask 将文件模式创建屏蔽字设置为 0 ,防止继承得来的文件模式创建屏蔽字会拒绝设置某些权限的情况。

· 调用 fork ,然后使父进程退出(exit)。目的是令启动 daemon 进程的 shell 认为命令已经执行完毕。

· 调用 setsid 以创建一个新会话。将当前工作目录更改为根目录(防止出现不能 umount 的问题)。关闭不再需要的文件描述符,令守护进程不再持有从父进程继承来的某些文件描述符。

· 某些守护进程打开 /dev/null 使其具有文件描述符0、1和2,防止守护进程与终端设备相关联。

3) Rsrv的消息机制设置、监听启动及终止时候的处理

/* main function - start Rserve */

◆ 3.3 Rserv.c代码

Rserv.c中的函数调用关系如下图所示:

重磅|RServe源代码解析(中)

从上图可以看出2个重要的入口函数,

1)Rserve_QAP1_connected()函数,标准websocket新连接后的处理函数,

2)run_Rserve(),在R环境中启动Rserve。

◆ 3.4 serverLoop()函数

在standalone.c中,在创建完服务接口后,进入了serverLoop的多个服务端口的轮询处理流程。

1)在Rserve中,服务端口被设置为非阻塞模式。select()函数在500ms的等待时间(由timv.tv_usec定义)内,如果端口可操作(可读或可写),返回一个正数,否则就返回0。

2)如果selRet返回为正,就执行对应的处理程序(*srv->connected(sa)*)。

3)在一个连接请求处理后,运行R全局环境中的自定义函数 .Rserve.served(如果被定义)进行一些后续操作。.Rserve.served、.Rserve.done()是Rserve提供的一种回调函数机制,分析在请求处理后、连接清除后运行用户定制一些个性化逻辑。

void serverLoop() {

下篇,我们将重点分析Rserve_QAP1_connected()函数,敬请期待。

田春华博士,昆仑数据首席数据科学家,2004年1月清华大学自动化系博士毕业。2004年-2015年在IBM中国研究院,负责数据挖掘算法研究和产品工作,在高端装备、产品运维服务、新能源运营优化等多领域,帮助中国、亚太、欧美领先企业,成功实施资产管理、运营优化、营销洞察等各类数据分析项目,为客户创造上亿美元收益。发表学术论文(长文)82篇(其中第一作者42篇),拥有36项专利申请(10项已授权)。研究兴趣:数据挖掘算法与应用。

参考文献

1. 张丹. R的极客理想:工具篇,2014,机械工业出版社

2. Simon Urbanek. A Fast Way to Provide R Functionality to Applications, Proceedings of the 3rd International Workshop on Distributed Statistical Computing (DSC 2003), March 20–22, Vienna, Austria

Simon Urbanek

2. https://cran.r-project.org/doc/manuals/R-ints.html

3. https://cran.r-project.org/doc/manuals/R-exts.html

4. Elliotte Rusty Harold,Java网络编程, O'Reilly Media Inc.、中国电力出版社, 2013.

5. W.Richard Stevens,Bill Fenner,Andrew M. Rudoff. UNIX网络编程 卷1 套接字联网API(第3版),北京邮电出版社

6. http://www.rforge.net/Rserve/doc.html

7. http://www.rforge.net/Rserve/dev.html

8. http://blog.csdn.NET/liang13664759/article/details/1771246

未经允许不得转载:新闻 » 重磅|RServe源代码解析(中)