如何通过基础认证发起并发HTTP请求以加速Shopify订单导入
优化Shopify历史订单导入:并发HTTP请求方案
嘿,针对你用httr串行请求Shopify订单速度慢的问题,我给你整理了两个带基础认证的并发请求方案,能大幅提升导入效率,同时适配Shopify的API限制:
首先先搞定Shopify的基础认证——Shopify Admin API的基础认证需要把你的API密钥和密码拼成{api_key}:{password}的格式,再做Base64编码,放到请求头里。代码示例如下:
# 替换成你自己的Shopify信息 api_key <- "你的Shopify API密钥" api_password <- "你的Shopify API密码" shop_domain <- "abc-store.myshopify.com" # 生成基础认证头 auth_header <- httr::add_headers( Authorization = paste0("Basic ", openssl::base64_encode(paste0(api_key, ":", api_password))), Accept = "application/json" )
方案1:用furrr + httr实现并行请求
如果你习惯用httr,那用furrr(purrr的并行版)过渡最顺畅,它能把原来的串行循环改成并行执行:
步骤拆解:
- 先获取总订单数算出总页数:先请求第一页,从响应里拿到
total_count,再计算需要请求多少页(每页250条)。 - 配置并行环境:控制并发数,别超过Shopify的速率限制(默认每分钟40请求,所以设5个并发比较安全)。
- 并行请求所有页面,最后合并数据。
library(httr) library(furrr) library(jsonlite) library(dplyr) # 1. 先获取总页数 first_page_url <- paste0("https://", shop_domain, "/admin/orders.json?limit=250") first_response <- GET(first_page_url, auth_header) first_data <- fromJSON(content(first_response, "text")) total_orders <- first_data$total_count total_pages <- ceiling(total_orders / 250) # 2. 设置并行会话,workers是并发数,别调太高 plan(multisession, workers = 5) # 3. 定义单个页面的请求函数,包含错误处理 fetch_single_page <- function(page_num) { request_url <- paste0("https://", shop_domain, "/admin/orders.json?limit=250&page=", page_num) response <- GET(request_url, auth_header) # 处理请求失败的情况 if (httr::http_error(response)) { warning(paste("页面", page_num, "请求失败,状态码:", httr::http_status(response)$status_code)) return(NULL) } # 提取订单数据 fromJSON(content(response, "text"))$orders } # 并行执行所有页面请求 fetched_pages <- future_map(1:total_pages, fetch_single_page) # 合并所有订单到一个数据框 all_orders <- bind_rows(fetched_pages)
方案2:用httr2异步请求(更现代的选择)
httr2是httr的升级版,原生支持异步请求,代码更简洁,错误处理也更灵活:
library(httr2) library(jsonlite) library(dplyr) # 先创建基础请求模板,包含认证和默认参数 base_req <- request(paste0("https://", shop_domain, "/admin/orders.json")) %>% req_headers( Authorization = paste0("Basic ", openssl::base64_encode(paste0(api_key, ":", api_password))), Accept = "application/json" ) %>% req_url_query(limit = 250) # 1. 获取总页数 first_resp <- base_req %>% req_perform() first_data <- fromJSON(resp_body_string(first_resp)) total_pages <- ceiling(first_data$total_count / 250) # 2. 生成所有页面的请求列表 page_requests <- purrr::map(1:total_pages, function(page) { base_req %>% req_url_query(page = page) }) # 3. 异步执行请求,控制并发数 responses <- req_perform_parallel(page_requests, workers = 5) # 4. 处理响应,合并数据 all_orders <- purrr::map_dfr(responses, function(resp) { if (resp_is_error(resp)) { warning(paste("请求失败,状态码:", resp_status(resp))) return(tibble()) } fromJSON(resp_body_string(resp))$orders })
关键注意点:
- 速率限制:Shopify默认每分钟40个请求(Plus商店是80),所以并发数别设太高,5-8之间比较稳妥。如果遇到429限流错误,可以给请求加重试逻辑,比如用
httr::RETRY或者httr2::req_retry。 - 错误处理:一定要加错误检查,避免某个页面请求失败导致整个导入流程崩溃。
- 分页方案:Shopify还支持
since_id分页(比基于page的分页更可靠,尤其是导入过程中新增订单的情况),如果你的场景允许,可以考虑改用这种方式,避免重复或遗漏订单。
内容的提问来源于stack exchange,提问作者Ben
相关产品推荐
相关产品推荐

