gpt4 book ai didi

在启动时将 R/Rook 作为 Web 服务器运行

转载 作者:行者123 更新时间:2023-12-04 12:48:18 25 4
gpt4 key购买 nike

我在 R 中使用 Rook 创建了一个服务器 - http://cran.r-project.org/web/packages/Rook
代码如下

#!/usr/bin/Rscript
library(Rook)
s <- Rhttpd$new()
s$add(
name="pingpong",
app=Rook::URLMap$new(
'/ping' = function(env){
req <- Rook::Request$new(env)
res <- Rook::Response$new()
res$write(sprintf('<h1><a href="%s">Pong</a></h1>',req$to_url("/pong")))
res$finish()
},
'/pong' = function(env){
req <- Rook::Request$new(env)
res <- Rook::Response$new()
res$write(sprintf('<h1><a href="%s">Ping</a></h1>',req$to_url("/ping")))
res$finish()
},
'/?' = function(env){
req <- Rook::Request$new(env)
res <- Rook::Response$new()
res$redirect(req$to_url('/pong'))
res$finish()
}
)
)
## Not run:
s$start(port=9000)

$ ./Rook.r
Loading required package: tools
Loading required package: methods
Loading required package: brew
starting httpd help server ... done

Server started on host 127.0.0.1 and port 9000 . App urls are:

http://127.0.0.1:9000/custom/pingpong
Server started on 127.0.0.1:9000
[1] pingpong http://127.0.0.1:9000/custom/pingpong

Call browse() with an index number or name to run an application.
$

该过程到此结束。

它在 R shell 中运行良好,但我想在系统启动时将它作为服务器运行。
因此,一旦调用了 start ,R 就不应退出,而是等待端口上的请求。
我将如何说服 R 只是等待或 sleep 而不是退出?
我可以使用 R 中的等待或 sleep 功能等待 N 秒,但这并不完全符合要求

最佳答案

这里有一个建议:

首先将您给出的示例拆分为(至少)两个文件:一个文件包含应用程序的定义,在您的示例中是 app 的值Rhttpd$add() 的参数功能。另一个文件是启动第一个文件中定义的应用程序的 RScript。

例如,如果您的应用程序函数的名称被命名为 pingpong在名为 Rook.R 的文件中定义,那么 Rscript 可能看起来像:

#!/usr/bin/Rscript --default-packages=methods,utils,stats,Rook

# This script takes as a single argument the port number on which to listen.

args <- commandArgs(trailingOnly=TRUE)

if (length(args) < 1) {
cat(paste("Usage:",
substring(grep("^--file=", commandArgs(), value=T), 8),
"<port-number>\n"))
quit(save="no", status=1)
} else if (length(args) > 1)
cat("Warning: extra arguments ignored\n")

s <- Rhttpd$new()
app <- RhttpdApp$new(name='pingpong', app='Rook.R')
s$add(app)
s$start(port=args[1], quiet=F)

suspend_console()

如您所见,此脚本采用一个参数来指定监听端口。现在,您可以创建一个 shell 脚本,该脚本将多次调用此 Rscript 以启动服务器的多个实例,监听不同的端口,以便在响应 HTTP 请求时启用一些并发性。

例如,如果上面的 Rscript 位于名为 start.r 的文件中。那么这样的 shell 脚本可能看起来像:
#!/bin/sh

if [ $# -lt 2 ]; then
echo "Usage: $0 <start-port> <instance-count>"
exit 1
fi

start_port=$1
instance_count=$2
end_port=$((start_port + instance_count - 1))

fifo=/tmp/`basename $0`$$

exit_command="echo $(basename $0) exiting; rm $fifo; kill \$(jobs -p)"
mkfifo $fifo

trap "$exit_command" INT TERM

cd `dirname $0`

for port in $(seq $start_port $end_port)
do ./start.r $port &
done

# block until interrupted
read < $fifo

上面的 shell 脚本有两个参数:(1)要监听的最低端口号和(2)要启动的实例数。例如,如果 shell 脚本在一个名为 start.sh 的可执行文件中。然后
./start.sh 9000 3

将启动 Rook 应用程序的三个实例,分别监听端口 9000、9001 和 9002。

您会看到从 fifo 读取的 shell 脚本的最后一行,这会阻止脚本退出,直到由接收到的信号引起。当指定的信号之一被捕获时,shell 脚本会杀死它在退出之前启动的所有 Rook 服务器进程。

现在,您可以配置反向代理将传入请求转发到任何服务器实例。例如,如果您使用 Nginx ,您的配置可能类似于:
upstream rookapp {
server localhost:9000;
server localhost:9001;
server localhost:9002;
}
server {
listen your.ip.number.here:443;
location /pingpong/ {
proxy_pass http://rookapp/custom/pingpong/;
}
}

然后,您的服务就可以在公共(public) Internet 上使用。

最后一步是创建一个带有 start 等选项的控制脚本。 (调用上面的 shell 脚本)和 stop (向它发送 TERM 信号以停止您的服务器)。这样的脚本将处理诸如使 shell 脚本作为守护进程运行并跟踪其进程 ID 号等事情。将此控制脚本安装在适当的位置,它将在机器启动时启动您的 Rook 应用程序服务器。如何做到这一点取决于您的操作系统,您的问题中缺少其身份。

笔记
  • 有关如何使用 shell 脚本中的 fifo 根据接收到的信号采取不同操作的示例,请参阅 this stack overflow question。 .
  • Jeffrey Horner 提供了 a complete Rook server application 的示例.
  • 您将看到上面的示例 shell 脚本仅捕获 INTTERM信号。我之所以选择这些是因为 INT结果是在终端输入 control-C 和 TERM是我的操作系统上的控制脚本用来停止服务的信号。您可能需要根据您的情况调整要捕获的信号的选择。
  • 关于在启动时将 R/Rook 作为 Web 服务器运行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15872440/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com