RODBC 查询导致 Shiny Server 宕机

RODBC query brings down Shiny Server

我们运行在 RedHat 6.7 上安装了 Shiny Server(和 Shiny Dashboard),并且在尝试使用 RODBC 查询数据库时运行遇到了段错误。当我们将文件源到 app.R 或向 server.R 文件中的数据库发出查询请求时,就会发生这种情况。当我们 运行 在 R 控制台中使用相同的代码时,它工作得很好。

似乎 Shiny 和 RODBC 之间一定有某种类型的交互导致了这个问题。作为一种变通方法,我们使用 RJDBC,它工作正常,但我们担心它不会为我们很好地扩展。而且速度很慢。

有人知道我们可以做些什么来让 RODBC 正常工作吗?

这里是我们的代码运行生成错误:

library(RODBC)
myConn <- odbcConnect("DSN_Name")
segment <- sqlQuery(myConn, "SELECT * FROM foo")

如果您使用基本的 Shiny 应用程序并添加上面的代码,您将能够重现错误。这是来自 RStudio.

的代码

ui.R

library(shiny)
# Define UI for application that draws a histogram
shinyUI(fluidPage(
# Application title
titlePanel("Hello Shiny!"),
# Sidebar with a slider input for the number of bins
sidebarLayout(
  sidebarPanel(
    sliderInput("bins",
              "Number of bins:",
              min = 1,
              max = 50,
              value = 30)
),

# Show a plot of the generated distribution
mainPanel(
  plotOutput("distPlot")
)
  )
    ))

server.R

library(shiny)
# Define server logic required to draw a histogram
shinyServer(function(input, output) {
# Expression that generates a histogram. The expression is
# wrapped in a call to renderPlot to indicate that:
#
#  1) It is "reactive" and therefore should re-execute automatically
#     when inputs change
#  2) Its output type is a plot
output$distPlot <- renderPlot({
x    <- faithful[, 2]  # Old Faithful Geyser data
bins <- seq(min(x), max(x), length.out = input$bins + 1)

# draw the histogram with the specified number of bins
hist(x, breaks = bins, col = 'darkgray', border = 'white')
})
  })

这是来自服务器的错误信息:

An error has occurred

The application exited unexpectedly.

socket hang up

Listening on http://127.0.0.1:37079 Attaching package: ‘shinydashboard’

The following object is masked from ‘package:graphics’: box

Loading required package: ggplot2

Attaching package: ‘plotly’ The following object is masked from ‘package:ggplot2’: last_plot

The following object is masked from ‘package:graphics’: layout Attaching package: ‘DT’

The following objects are masked from ‘package:shiny’: dataTableOutput, renderDataTable

Loading required package: DBI Loading required package: rJava Loading required package:

NLP Attaching package: ‘NLP’ The following object is masked from ‘package:ggplot2’: annotate

Loading required package: RColorBrewer

*** caught segfault ***
address (nil), cause 'unknown'

Traceback:
1: .Call(C_RODBCDriverConnect, as.character(connection), id, as.integer(believeNRows), as.logical(readOnlyOptimize))
2: odbcDriverConnect("DSN=DB_Name")
3: eval(expr, envir, enclos)
4: eval(expr, p)
5: eval.parent(Call)
6: odbcConnect("DB_Name")
7: eval(expr, envir, enclos)
8: eval(ei, envir)
9: withVisible(eval(ei, envir))
10: source("RODBC.R")
11: eval(expr, envir, enclos)
12: eval(ei, envir)
13: withVisible(eval(ei, envir))
14: source(file, ..., keep.source = TRUE, encoding = checkEncoding(file))
15: sourceUTF8(fullpath, local = new.env(parent = globalenv()))
16: func(fname, ...)
17: appObj()
18: handler(req)
19: handler(req)
20: handler(...)
21: handlers$invoke(req)
22: handler(req)
23: func(req)
24: doTryCatch(return(expr), name, parentenv, handler)
25: tryCatchOne(expr, names, parentenv, handlers[[1L]])
26: tryCatchList(expr, classes, parentenv, handlers)
27: tryCatch(expr, error = function(e) { call <- conditionCall(e) if (!is.null(call)) { if (identical(call[[1L]], quote(doTryCatch))) call <- sys.call(-4L) dcall <- deparse(call)[1L] prefix <- paste("Error in", dcall, ": ") LONG <- 75L msg <- conditionMessage(e) sm <- strsplit(msg, "\n")[[1L]] w <- 14L + nchar(dcall, type = "w") + nchar(sm[1L], type = "w") if (is.na(w)) w <- 14L + nchar(dcall, type = "b") + nchar(sm[1L], type = "b") if (w > LONG) prefix <- paste0(prefix, "\n ") } else prefix <- "Error : " msg <- paste0(prefix, conditionMessage(e), "\n") .Internal(seterrmessage(msg[1L])) if (!silent && identical(getOption("show.error.messages"), TRUE)) { cat(msg, file = stderr()) .Internal(printDeferredWarnings()) } invisible(structure(msg, class = "try-error", condition = e))})
28: try({ inputStream <- if (is.null(data)) nullInputStream else InputStream$new(data, dataLength) req$rook.input <- inputStream req$rook.errors <- ErrorStream$new() req$httpuv.version <- packageVersion("httpuv") if (!is.null(req$HTTP_CONTENT_TYPE)) req$CONTENT_TYPE <- req$HTTP_CONTENT_TYPE if (!is.null(req$HTTP_CONTENT_LENGTH)) req$CONTENT_LENGTH <- req$HTTP_CONTENT_LENGTH resp <- func(req) if (is.null(resp) || length(resp) == 0) return(NULL) resp$headers <- lapply(resp$headers, paste) if ("file" %in% names(resp$body)) { filename <- resp$body[["file"]] owned <- FALSE if ("owned" %in% names(resp$body)) owned <- as.logical(resp$body$owned) resp$body <- NULL resp$bodyFile <- filename resp$bodyFileOwned <- owned } resp})
29: rookCall(.app$call, req, req$.bodyData, seek(req$.bodyData))
30: (function (req) { on.exit({ if (!is.null(req$.bodyData)) { close(req$.bodyData) } req$.bodyData <- NULL }) rookCall(.app$call, req, req$.bodyData, seek(req$.bodyData))})(<environment>)
31: eval(substitute(expr), envir, enclos)
32: evalq((function (req) { on.exit({ if (!is.null(req$.bodyData)) { close(req$.bodyData) } req$.bodyData <- NULL }) rookCall(.app$call, req, req$.bodyData, seek(req$.bodyData))})(<environment>), <environment>)
33: doTryCatch(return(expr), name, parentenv, handler)
34: tryCatchOne(expr, names, parentenv, handlers[[1L]])
35: tryCatchList(expr, names[-nh], parentenv, handlers[-nh])
36: doTryCatch(return(expr), name, parentenv, handler)
37: tryCatchOne(tryCatchList(expr, names[-nh], parentenv, handlers[-nh]), names[nh], parentenv, handlers[[nh]])
38: tryCatchList(expr, classes, parentenv, handlers)
39: tryCatch(evalq((function (req) { on.exit({ if (!is.null(req$.bodyData)) { close(req$.bodyData) } req$.bodyData <- NULL }) rookCall(.app$call, req, req$.bodyData, seek(req$.bodyData))})(<environment>), <environment>), error = function (x) x, interrupt = function (x) x)
40: .Call("httpuv_run", PACKAGE = "httpuv", timeoutMillis)
41: run(timeoutMs)
42: service(timeout)
43: serviceApp()
44: withCallingHandlers(expr, error = function(e) { handle <- getOption("shiny.error") if (is.function(handle)) handle()})
45: shinyCallingHandlers(while (!.globals$stopped) { serviceApp() Sys.sleep(0.001)})
46: runApp(Sys.getenv("SHINY_APP"), port = port, launch.browser = FALSE) aborting ...

首先,我要感谢 RStudio 的 Joe Cheng。他帮了大忙,真的竭尽全力帮助我解决这个问题。非常感谢。

所以我 运行 遇到的问题是(恕我直言)代码结构不佳的结果。以下是我犯的错误,修正后一切正常。

  • 错误 1 ​​- 我正在调用 server.R 文件 app.R。这是个 过时的命名约定,不应使用。
  • 错误2—— 我的 server.R 文件的最后一行调用了函数 shinyApp(ui, 服务器)。这导致我的 odbc 驱动程序出现重大问题 数据库。它在我的客户所在的地方创建了一个非常大的堆栈 向下推得太远会导致段错误。故事的道德启示, 使用服务器功能结束 server.R 文件。

我闪亮的服务器现在很开心运行! :)

感谢乔的所有帮助。

这是完整的线程 - https://groups.google.com/forum/#!topic/shiny-discuss/66Ve60ugmHs