5.2 Rserve的R语言客户端RSclient

问题

R原生程序怎么访问Rserve?

引言

RSclient是实现Rserve通信的R语言客户端程序,这种通信对于实际应用架构来说是很有帮助的,因为这不仅可以统一Rserve的接口,还可以从架构上实现R语言的跨虚拟机的分步式程序设计。

之前我们讲过,Rserve是基于TCP/IP协议的,支持R语言与其他语言通信基于C/S结构的网络通信服务器端程序。那么如何让R语言与Rserve服务器通信呢?RSclient就是Rserve客户端访问的R语言实现,通过RSclient可以让R语言访问Rserve服务器实例。这样,R语言本身用就有了分步式程序调用的基础了。

5.2.1 配置Rserve服务器

本节使用的系统环境是:

  • Linux: Ubuntu 12.04.2 LTS 64bit
  • R: 3.0.1 x86_64-pc-linux-gnu
  • Rserve: Rserve v1.7-1

注:Rserve同时支持Win7环境和Linux环境,由于Rserve主要用来做通信服务器,建议使用Linux环境。

启动Rserve服务器

~ R CMD Rserve  # 通过命令启动Rserve
~ ps -aux|grep Rserve
conan    28339  0.0  1.2 116292 25240 ?        Ss   22:31   0:00 /usr/lib/R/bin/Rserve
~ netstat -ntlp|grep Rserve
tcp        0      0 0.0.0.0:6311            0.0.0.0:*               LISTEN      28339/Rserve
Rserve环境

•    IP: 192.168.1.201,允许远程访问
•    端口: 6311
•    登陆认证: 用户名:conan, 密码:conan
•    字符编码: utf-8

~ R CMD Rserve --RS-settings   #查看Rserve服务器的配置
Rserve v1.7-1
config file: /etc/Rserv.conf
working root: /tmp/Rserv
port: 6311
local socket: [none, TCP/IP used]
authorization required: yes
plain text password: allowed
passwords file: [none]
allow I/O: yes
allow remote access: yes
control commands: yes
interactive: yes
max.input buffer size: 262144 kB

启动好Rserve服务器后,接下来,我们使用RSclient访问Rserve服务器。

5.2.2 RSclient安装

由于RSclient和Rserve通信可以通过远程访问,所以我们使用Win7的客户端环境安装RSclient。RSclient的系统环境:

  • Win7 64bit
  • R: 3.0.1 x86_64-w64-mingw32/x64 b4bit

RSclient安装和加载

~ R   # 启动R程序
> install.packages("RSclient")  # 安装RSclient
> library(RSclient)  # 加载RSclient

5.2.3 RSclient的API

RSclient的API分为两组,Rclient(旧版本)和RCC(新版本)。 Rclient 旧版本API:函数名是大小写连写的,如下所示:

RSassign           RSattach           RSclose
RSconnect          RSdetach           RSeval             RSevalDetach
RShowDoc           RSiteSearch        RSlogin            RSserverEval
RSserverSource     RSshutdown         RSclient::

RCC 新版本API:函数名是以.分隔的,如下所示:

RS.assign          RS.authkey         RS.close           RS.collect
RS.connect         RS.eval            RS.eval.qap        RS.login
RS.oobCallbacks    RS.server.eval     RS.server.shutdown RS.server.source
RS.switch

本节主要介绍新版本API的使用,其中客户端操作函数如下:

  • RS.connect: 创建与Rserve的连接
  • RS.close: 关闭与Rserve的连接
  • RS.login: 登陆认证
  • RS.authkey: 设置认证时加密算法
  • RS.eval: 在Rserve远程执行R语句
  • RS.eval.qap: 远程执行R语句,使用Rserve QAP序列化对象代替本地对象
  • RS.collect: 等待异步执行的eval的结果,一起返回
  • RS.assign: 远程执行赋值
  • RS.switch: 协议转换,从QAP1到TLS QAP1
  • RS.oobCallbacks: 回调函数, 通过OOB_SEND函数和OOB_MSG函数中执行

服务器管理函数(Rserve启动时,需要设置–RS-enable-control)如下:

  • RS.server.eval: 服务器控制函数,执行脚步
  • RS.server.shutdown: 服务器控制函数,关闭服务器
  • RS.server.source: 服务器控制函数,执行服务器端本地文件

5.2.4 RSclient的使用

> library(RSclient)
> conn<-RS.connect(host="192.168.1.201")  # 建立远程连接
> conn
 Rserve QAP1 connection 0x000000000445cd60 (socket 308, queue length 0)
> RS.login(conn,"conan","conan",authkey=RS.authkey(conn))  # 登陆Rserve服务器,并完成认证检查
[1] TRUE
> RS.eval(conn,rnorm(5))  # 执行脚本
[1] -2.6762608  1.4435144 -0.4298395 -0.7046573 -1.4056073
> RS.assign(conn,"xx",99)  # 设置变量
raw(0)
> RS.eval(conn,xx-55)
[1] 44
> RS.eval(conn,head(rnorm(10000000)),wait=TRUE)  # 同步执行
[1] -4.20217390  0.22353317 -1.70256992  0.30053213 -0.01427486 -0.70522254
> RS.eval(conn,head(rnorm(10000000)),wait=FALSE)  # 异步执行,结果要通过RS.collect()再取一次
NULL
> RS.collect(conn)
[1] -0.2814752  0.3215521 -1.0978825 -0.8534461 -0.2459560 -0.4804882
> RS.close(conn)  # 关闭连接
NULL
> conn
 Closed Rserve connection 0x000000000445cc80

5.2.5 两个客户端同时访问

客户端A的操作。

~ R
> library(RSclient)
> conn<-RS.connect(host="192.168.1.201")
> RS.login(conn,"conan","conan",authkey=RS.authkey(conn))
> RS.assign(conn,"A",1234)

> RS.eval(conn,A)
[1] 1234
> RS.eval(conn,getwd())
[1] "/tmp/Rserv/conn29039"

客户端B的操作。

~ R
> library(RSclient)
> conn<-RS.connect(host="192.168.1.201")
> RS.login(conn,"conan","conan",authkey=RS.authkey(conn))
> RS.assign(conn,"B",5678)
> RS.eval(conn,B)
[1] 5678
> RS.eval(conn,ls())
[1] "B"
> RS.eval(conn,getwd())
[1] "/tmp/Rserv/conn29040"

我们看到A,B两个客户端建立接口后,服务器端的Rserve会在两个单独的空间运行。因此,A,B两个客户端的访问是独立的。如果想让两个客户端通信,我们应该怎么去测试这个想法呢? 答案是通过全局变量。在客户端A,设置Rserve服务器全局变量,代码如下。

> RS.server.eval(conn, "G<-999") :
command failed with status code 0x48: access denied

出现拒绝访问的错误,虽然我们已经打开了--RS-enable-control,但还是有错误,不知道是不是Rserve的bug。全局变量这种方式,被证明是不行的。那么我们还可以通过中间存储的方式,间接地实现两个客户端的交互,需要交互数据存储在MySQL和Redis中。

通过RSclient我们实现了R语言远程连接Rserve服务器。如果大家发散一下想法,就可以通过Rserve和RSclient构建一个纯R的分步式计算环境,再配合上其他的开源技术,R真的能达到线上应用的标准。

results matching ""

    No results matching ""