如何解决shinyapps.io中“HTTP/2 stream 1未正常关闭”错误?
部署shinyapps.io时bold包HTTP/2连接错误排查与解决
问题现象
本地运行正常的R Shiny应用,部署到shinyapps.io后出现连接错误,日志报错如下:
2024-01-24T11:05:27.044583+00:00 shinyapps[2720261]: Warning: Error in curl::curl_fetch_memory: HTTP/2 stream 1 was not closed cleanly before end of the underlying stream 2024-01-24T11:05:27.049958+00:00 shinyapps[2720261]: 15: <Anonymous> 2024-01-24T11:05:27.054170+00:00 shinyapps[2720261]: 13: fn 2024-01-24T11:05:27.059003+00:00 shinyapps[2720261]: 8: retry 2024-01-24T11:05:27.063181+00:00 shinyapps[2720261]: 7: connect$retryingStartServer 2024-01-24T11:05:27.067618+00:00 shinyapps[2720261]: 6: eval 2024-01-24T11:05:27.071758+00:00 shinyapps[2720261]: 5: eval 2024-01-24T11:05:27.075890+00:00 shinyapps[2720261]: 4: eval 2024-01-24T11:05:27.079757+00:00 shinyapps[2720261]: 3: eval 2024-01-24T11:05:27.083979+00:00 shinyapps[2720261]: 2: eval.parent 2024-01-24T11:05:27.088113+00:00 shinyapps[2720261]: 1: local
错误源自以下调用bold包批量获取数据的代码段:
library(bold) species<-unique(checklist[,1]) x<-length(species) taxon_total = data.frame() y <- ceiling(x / 300) + 1 i <- 1 while (i < y){ ini<-1+(300*(i-1)) fin <- min(300 * i, x) tmp <- bold_seqspec(taxon=species[ini:fin], response = TRUE) tt <- paste0(rawToChar(tmp$content, multiple = TRUE), collapse = "") Encoding(tt) <- "UTF-8" taxa <- utils::read.delim(text = tt, header = TRUE, sep = "\t", stringsAsFactors = FALSE, quote = "") taxon_total <- rbind(taxon_total,taxa) i = i+1 } taxon<-taxon_total
示例物种向量:
species<-c("Zeus faber","Zeus capensis","Zenopsis stabilispinosa","Zenopsis nebulosa","Zenopsis conchifer")
解决方案
1. 强制使用HTTP/1.1协议
shinyapps.io的网络环境对HTTP/2支持存在兼容性问题,在调用bold_seqspec时指定curl选项强制使用HTTP/1.1:
# 修改bold_seqspec调用,添加curlopts参数 tmp <- bold_seqspec(taxon=species[ini:fin], response = TRUE, curlopts = list(http_version = 0)) # 0对应HTTP/1.1
2. 添加请求延迟避免API限流
bold API存在请求频率限制,短时间内批量请求容易触发限流,在循环末尾添加延迟:
# 循环内每次请求后暂停1秒(可根据需求调整时长) i = i+1 Sys.sleep(1)
3. 优化数据拼接效率
原代码用rbind循环拼接数据框效率极低且易出问题,改用列表存储后一次性合并:
# 初始化空列表替代空数据框 taxon_list <- list() i <- 1 while (i < y){ ini<-1+(300*(i-1)) fin <- min(300 * i, x) tmp <- bold_seqspec(taxon=species[ini:fin], response = TRUE, curlopts = list(http_version = 0)) tt <- paste0(rawToChar(tmp$content, multiple = TRUE), collapse = "") Encoding(tt) <- "UTF-8" taxa <- utils::read.delim(text = tt, header = TRUE, sep = "\t", stringsAsFactors = FALSE, quote = "") taxon_list[[i]] <- taxa # 将结果存入列表 i = i+1 Sys.sleep(1) } # 一次性合并所有列表元素 taxon_total <- do.call(rbind, taxon_list)
4. 增加错误捕获机制
添加tryCatch避免单个请求失败导致整个应用崩溃,同时记录错误信息:
while (i < y){ ini<-1+(300*(i-1)) fin <- min(300 * i, x) tryCatch({ tmp <- bold_seqspec(taxon=species[ini:fin], response = TRUE, curlopts = list(http_version = 0)) tt <- paste0(rawToChar(tmp$content, multiple = TRUE), collapse = "") Encoding(tt) <- "UTF-8" taxa <- utils::read.delim(text = tt, header = TRUE, sep = "\t", stringsAsFactors = FALSE, quote = "") taxon_list[[i]] <- taxa }, error = function(e){ # 打印错误日志,方便排查 message(paste("批次", i, "请求失败:", e$message)) }) i = i+1 Sys.sleep(1) }
内容的提问来源于stack exchange,提问作者tadeufontes
相关产品推荐
相关产品推荐

