You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

AWS Lambda部署Go+chromedp遇WebSocket超时问题排查

问题:AWS Lambda部署chromedp时WebSocket URL超时错误

我用Go开发AWS Lambda服务,通过Docker镜像部署集成chromedp的代码时,碰到WebSocket URL超时错误。当前Lambda配置:3008MB内存、512MB存储、15分钟超时时间。以下是相关代码和Dockerfile,求排查问题并给出修复方案。


相关代码文件

main.go(chromedp部分)

func getPage(URL string, lineNum string, stationNm string) {
    // settings for crawling
    ctx, cancle := chromedp.NewContext(
        context.Background(),
        chromedp.WithLogf(log.Printf),
    )
    defer cancle()

    opts := []chromedp.ExecAllocatorOption{
        chromedp.DisableGPU,
        chromedp.NoSandbox,
        chromedp.Headless,
        chromedp.Flag("no-zygote", true),
        chromedp.Flag("single-process", true),
        chromedp.Flag("homedir", "/tmp"),
        chromedp.Flag("data-path", "/tmp/data-path"),
        chromedp.Flag("disk-cache-dir", "/tmp/cache-dir"),
        chromedp.Flag("remote-debugging-port", "9222"),
        chromedp.Flag("remote-debugging-address", "0.0.0.0"),
        chromedp.Flag("disable-dev-shm-usage", true),
    }

    allocCtx, cancel := chromedp.NewExecAllocator(ctx, opts...)
    defer cancel()

    ctx, cancel = chromedp.NewContext(allocCtx, chromedp.WithLogf(log.Printf))
    defer cancel()

    var htmlContent string

    ch := chromedp.WaitNewTarget(ctx, func(i *target.Info) bool {
        return strings.Contains(i.URL, "/timetable/web/")
    })

}

Dockerfile

FROM public.ecr.aws/lambda/provided:al2 AS build

ENV GO111MODULE=on \
    CGO_ENABLED=0 \
    GOOS=linux \
    GOARCH=amd64

# Get rid of the extension warning
RUN mkdir -p /opt/extensions
RUN yum -y install golang
RUN go env -w GOPROXY=direct

# Clone git, copying go.mod, go.sum, main.go
WORKDIR /var/task/
RUN yum install git -y
RUN git clone https://github.com/seedspirit/NaverCrawler-CICD-go.git
RUN cp NaverCrawler-CICD-go/main.go /var/task/
RUN cp NaverCrawler-CICD-go/go.mod /var/task/
RUN cp NaverCrawler-CICD-go/go.sum /var/task/

# cache dependencies
RUN go mod download
RUN go build -o main .

FROM public.ecr.aws/lambda/provided:al2
COPY --from=build /var/task/main /var/task/main

# Install Chrome dependencies
RUN curl https://dl.google.com/linux/direct/google-chrome-stable_current_x86_64.rpm -o chrome.rpm && \
    yum install -y ./chrome.rpm && \
    yum install -y fontconfig libX11 GConf2 dbus-x11

ENTRYPOINT ["/var/task/main"]

排查分析

  1. 上下文初始化顺序错误:先创建chromedp上下文再创建执行分配器,导致指定的Chrome启动参数无法生效,chromedp无法正确连接Chrome的调试端口,引发WebSocket超时。
  2. Chrome启动参数冲突:single-process参数在Lambda隔离环境中易导致Chrome启动不稳定;手动指定remote-debugging-port=9222可能引发端口占用问题,chromedp默认会自动分配可用端口,无需手动指定。
  3. Docker镜像依赖不全:Amazon Linux 2上安装Chrome后缺少部分必要依赖(如libXext、libXtst),导致Chrome启动失败,间接触发WebSocket连接超时。
  4. 无超时的阻塞逻辑:代码中调用chromedp.WaitNewTarget后未设置超时处理,若目标未出现会一直阻塞,最终触发Lambda超时。

修复方案

1. 修正chromedp上下文初始化逻辑

调整顺序,先创建执行分配器再生成chromedp上下文,同时移除冲突参数、增加超时控制:

import (
    "context"
    "log"
    "strings"
    "time"

    "github.com/chromedp/chromedp"
    "github.com/chromedp/chromedp/kb"
)

func getPage(URL string, lineNum string, stationNm string) error {
    // 定义Chrome启动参数,移除冲突项
    opts := []chromedp.ExecAllocatorOption{
        chromedp.DisableGPU,
        chromedp.NoSandbox,
        chromedp.Headless,
        chromedp.Flag("no-zygote", true),
        chromedp.Flag("disable-dev-shm-usage", true),
        chromedp.Flag("homedir", "/tmp"),
        chromedp.Flag("data-path", "/tmp/data-path"),
        chromedp.Flag("disk-cache-dir", "/tmp/cache-dir"),
        // 移除手动指定调试端口和单进程参数
    }

    // 先创建执行分配器上下文
    allocCtx, cancelAlloc := chromedp.NewExecAllocator(context.Background(), opts...)
    defer cancelAlloc()

    // 基于分配器创建chromedp上下文
    ctx, cancelCtx := chromedp.NewContext(allocCtx, chromedp.WithLogf(log.Printf))
    defer cancelCtx()

    // 设置上下文超时,避免无限阻塞
    ctx, cancelTimeout := context.WithTimeout(ctx, 5*time.Minute)
    defer cancelTimeout()

    var htmlContent string

    // 先执行页面导航,确保Chrome正常启动
    if err := chromedp.Run(ctx,
        chromedp.Navigate(URL),
        chromedp.WaitVisible("body", chromedp.ByQuery),
    ); err != nil {
        return err
    }

    // 带超时处理的目标等待逻辑
    select {
    case target := <-chromedp.WaitNewTarget(ctx, func(i *chromedp.Target) bool {
        return strings.Contains(i.URL, "/timetable/web/")
    }):
        log.Printf("匹配到目标页面: %s", target.URL)
        // 切换到目标页面并获取内容
        if err := chromedp.Run(ctx,
            chromedp.SwitchTarget(target),
            chromedp.OuterHTML("body", &htmlContent, chromedp.ByQuery),
        ); err != nil {
            return err
        }
    case <-ctx.Done():
        return ctx.Err() // 返回超时或取消错误
    }

    // 后续处理htmlContent...
    return nil
}

2. 完善Dockerfile的Chrome依赖

补充安装缺失的系统依赖,确保Chrome能正常启动:

FROM public.ecr.aws/lambda/provided:al2 AS build

ENV GO111MODULE=on \
    CGO_ENABLED=0 \
    GOOS=linux \
    GOARCH=amd64

RUN mkdir -p /opt/extensions
RUN yum -y install golang
RUN go env -w GOPROXY=direct

WORKDIR /var/task/
RUN yum install git -y
RUN git clone https://github.com/seedspirit/NaverCrawler-CICD-go.git
RUN cp NaverCrawler-CICD-go/main.go /var/task/
RUN cp NaverCrawler-CICD-go/go.mod /var/task/
RUN cp NaverCrawler-CICD-go/go.sum /var/task/

RUN go mod download
RUN go build -o main .

FROM public.ecr.aws/lambda/provided:al2
COPY --from=build /var/task/main /var/task/main

# 安装Chrome及完整依赖包
RUN curl https://dl.google.com/linux/direct/google-chrome-stable_current_x86_64.rpm -o chrome.rpm && \
    yum install -y ./chrome.rpm && \
    yum install -y fontconfig libX11 GConf2 dbus-x11 libXext libXtst libXScrnSaver libXrandr alsa-lib && \
    yum clean all && rm -f ./chrome.rpm

ENTRYPOINT ["/var/task/main"]

3. Lambda配置优化

  • 存储调整:将Lambda存储从512MB提升至1024MB,Chrome会在/tmp目录生成大量缓存文件,更大的存储能避免磁盘空间不足导致的启动失败。
  • 日志权限:确保Lambda执行角色拥有CloudWatchLogsFullAccess权限,方便查看Chrome启动和chromedp运行的详细日志。

内容的提问来源于stack exchange,提问作者kim

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 10:05:34