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

Service Weaver多独立监听器配置异常问题求助

解决Service Weaver多监听器部署模式下的请求中断问题

你遇到的“http: proxy error: context canceled”通常和组件拆分不彻底、监听器绑定错误或请求上下文管理不当有关。以下是针对你的需求的正确实现方案:

1. 拆分独立组件

将Web和API处理逻辑拆分为两个独立的Service Weaver组件,避免在同一组件内绑定多个监听器,这是部署模式下分离运行的核心:

// WebComponent 处理Web端请求
type WebComponent interface {
    ServeHTTP(http.ResponseWriter, *http.Request)
}

// APIComponent 处理API接口请求
type APIComponent interface {
    ServeHTTP(http.ResponseWriter, *http.Request)
}

// 实现WebComponent
type webComponent struct {
    weaver.Implements[WebComponent]
}

func (w *webComponent) ServeHTTP(writer http.ResponseWriter, req *http.Request) {
    // 这里写Web端的处理逻辑,注意使用req.Context()作为请求上下文
    fmt.Fprintf(writer, "Web Response: %s", req.URL.Path)
}

// 实现APIComponent
type apiComponent struct {
    weaver.Implements[APIComponent]
}

func (a *apiComponent) ServeHTTP(writer http.ResponseWriter, req *http.Request) {
    // 这里写API的处理逻辑,同样使用req.Context()
    writer.Header().Set("Content-Type", "application/json")
    fmt.Fprintf(writer, `{"path":"%s","message":"API Response"}`, req.URL.Path)
}

2. 注册监听器并启动服务

在main函数中分别为两个组件绑定独立的监听器,确保各自的服务在部署时被分配到独立的实例:

func main() {
    if err := weaver.Run(context.Background(), run); err != nil {
        log.Fatal(err)
    }
}

func run(ctx context.Context, root weaver.Instance) error {
    // 初始化Web组件并绑定web监听器
    webComp, err := weaver.Get[WebComponent](root)
    if err != nil {
        return fmt.Errorf("get WebComponent: %w", err)
    }
    webListener, err := root.Listener("web")
    if err != nil {
        return fmt.Errorf("get web listener: %w", err)
    }
    go func() {
        log.Printf("Web service listening on %s", webListener)
        if err := http.Serve(webListener, webComp); err != nil && !errors.Is(err, http.ErrServerClosed) {
            log.Printf("web server failed: %v", err)
        }
    }()

    // 初始化API组件并绑定api监听器
    apiComp, err := weaver.Get[APIComponent](root)
    if err != nil {
        return fmt.Errorf("get APIComponent: %w", err)
    }
    apiListener, err := root.Listener("api")
    if err != nil {
        return fmt.Errorf("get api listener: %w", err)
    }
    go func() {
        log.Printf("API service listening on %s", apiListener)
        if err := http.Serve(apiListener, apiComp); err != nil && !errors.Is(err, http.ErrServerClosed) {
            log.Printf("api server failed: %v", err)
        }
    }()

    <-ctx.Done()
    return nil
}

3. 配置文件(weaver.toml)

明确指定两个监听器的地址,并为组件设置独立的部署配置:

[service]
name = "my_multi_listener_app"

# 定义两个独立监听器
[listeners]
web = { address = ":8080" }
api = { address = ":8081" }

# 可选:为组件指定副本数,实现水平扩展
[components.WebComponent]
replicas = 2

[components.APIComponent]
replicas = 3

关键注意事项

  • 上下文管理:所有请求处理必须使用req.Context(),不要手动创建并提前取消上下文,否则会导致代理连接被提前终止。
  • 组件隔离:绝对不要在同一组件内绑定多个监听器,部署模式下这会导致组件实例共享端口,引发连接冲突和中断。
  • 日志排查:部署时查看组件日志,确认是否有实例重启(如OOM、健康检查失败),这类情况会直接导致代理抛出context canceled错误。
  • 代理超时:如果使用Service Weaver的内置代理,可检查配置中的超时参数(如proxy_timeout),调整为合理值避免过早断开连接。

按照以上方案实现后,Web和API组件会在部署模式下独立运行,请求中断的问题应该会得到解决。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 01:20:33