闪亮的服务器:在服务器上更新数据的最佳实践是什么

Yuf*_*end 2 shiny shiny-server

我有一个闪亮的应用程序,它正在从某些文件加载​​数据。在服务器上,在不中断服务器的情况下更新这些文件的最佳方法是什么?

在网上搜索,我找到了这两个解决方案:

1) 使用reactivePoll()reactiveFileReader()

http://shiny.rstudio.com/gallery/reactive-poll-and-file-reader.html

2) 使用 reactiveValues()

在不重新启动应用程序的情况下更新闪亮的 server.R 中的数据框

values <- reactiveValues()
updateData <- function() {
  vars <- load(file = "my_data_frame.RData", envir = .GlobalEnv)
  for (var in vars)
    values[[var]] <- get(var, .GlobalEnv)
}
updateData()  # also call updateData() whenever you want to reload the data

output$foo <- reactivePlot(function() {
  # Assuming the .RData file contains a variable named mydata
  plot(values$mydata)
}
Run Code Online (Sandbox Code Playgroud)

重新加载以闪亮方式加载的文件的最佳做法是什么?

感谢您的任何意见!

Enz*_*nzo 7

让我尝试重新定义您的问题,定位您所指的一些论文/示例代码。

在非常高的层次上(即不必太担心反应性),R + shiny与将数据视为 ETL 过程的一部分(例如)的标准方式没有区别。

即您可以将以下类型的外部数据之一加载到闪亮的服务器中:

  1. 加载静态数据,即驻留在文件系统中的文件中的数据,或执行 RDBMS 查询。这是涵盖大部分用法的标准案例。
  2. 加载动态数据。这通常是指您尝试分析的某种类型的数据流(即不将其持久化到文件或 RDBMS 表中)。

让我们先谈谈第一种情况的不同变种,静止数据

server <- function(input, output, session) {
---
output$foo <- reactivePlot(function() {
  someQuery <- dbGetQuery(...)  # some query of a database
  plot(values$mydata)
}
---
}
Run Code Online (Sandbox Code Playgroud)

每次执行反应式函数,上面的代码都会运行一个查询。

这就是反应性可以提供很大帮助的地方:例如,在没有其他更改的情况下,对于每个连接到应用程序的用户,上面的代码将执行一次。

如果外部进程频繁更新底层数据,则不同用户的结果可能会有所不同。

此外,任何导致反应式构造重新执行的东西,也会重新执行查询(例如,只需刷新浏览器,查询就会重新执行,因为每次浏览器刷新都会生成不同的会话)。

正如您从任何闪亮的培训中应该知道的那样,接下来的步骤可能是将上述反应式构造链接到其他一些 UI 元素,例如操作按钮或 selectInput 以过滤数据。

server <- function(input, output, session) {
---
output$foo <- reactivePlot(function() {
if((length(input$actionbutton) ==0) | (length(input$selectData) == 0)) return()  
# the reactive now is connected to these two shiny inputs and executed every time they change

someQuery <- dbGetQuery(...)  # some query of a database, maybe with a *where* clause dependent on input$selectData
  plot(values$mydata)
}
---
}
Run Code Online (Sandbox Code Playgroud)

现在每次按下操作按钮或进行新选择时都会执行查询。

让我们假设对于您的用例,正如我确定您已经在 中看到或实现的那样ETL,您的数据经常发生变化。假设文件(或表)由外部进程持续更新。

请注意,即使经常更新(您正在通过批次处理数据,或者如果间隔非常小,则是小批次),通常仍会考虑此用例。

正是在这里,你的第一个例子,其中的不同结构reactiveFileReaderreactivePoll进入游戏。

如果您有一个文件,例如日志文件,由外部进程非常频繁地更新,您可以使用reactiveFileReader.

如果您有数据库表,您可以例如每 x 秒使用reactivePoll.

在这里,您的代码可以享受反应性的全部好处:代码将自动每 x 秒为您执行一次,并且所有其他依赖于它的反应性代码也将被刷新。

现在,让我们假设您尝试减少对数据进行闪亮检查的 *batch size”(即窗口)。您能走多远?

如果我没记错的话,不久前与 Joe Cheng 的一次讨论,他相信 Shiny50,000 events每秒最多可以处理 10次(想象一下,每秒轮询您的数据库或读取您的文件多达多少次)。

假设我没记错的话,我无论如何都会考虑50,000 events一个理论限制(您必须减少在 RBMS 中查询数据所花费的时间,可能是通过 LAN 等),因此对于文件访问,我将使用 > 1 毫秒的时间(即每秒读取<1,000 个文件),以及 RDBMS 的更大时间间隔。

因此,上述函数的时间单位是毫秒也就不足为奇了。

我认为通过上述构造,可以使用R + shiny非常雄心勃勃的微批处理管道来实现。

甚至可以想象使用Apache Kafka将数据发布到R + shiny(可能使用Shiny Server Pro具有负载平衡的多个实例为 Kafka 提供服务:美味!)`

那么,动态数据呢?

好吧,如果您以可管理的速率从消防站获取数据R and shiny,那么您就可以了(您可能无法确定该流用例使用哪种 R 算法,但这值得另一个问题)。

另一方面,如果您的流程需要非常低的延迟,远远超出上述规定,您可能需要考虑其他类型的工具和管道(例如使用Apache Flink或考虑ad hoc代码)。

为非常冗长的解释道歉。请让我知道它是否使这个复杂的主题更加清晰。