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

Docker化Go客户端无法连接Liftbridge服务求助

问题描述

Docker化的Go应用使用go-liftbridge客户端,DNS解析正常,也明确传入了解析后的IP和端口,但客户端始终尝试连接[::1]:9292,无法连接Liftbridge服务。

环境信息

  • Liftbridge版本: v1.9.0
  • Go Liftbridge客户端版本: v2.3.0
  • Go版本: 1.22
  • 操作系统: Pop!_OS 22.04 LTS x86_64
  • Docker版本: v26.0.1
  • Docker Compose版本: v2.26.1

复现步骤

  1. 将使用go-liftbridge客户端的简单Go应用Docker化。
  2. 用Docker Compose管理Liftbridge服务和Go应用。
  3. 尝试通过Docker Compose内的服务主机名解析出的IP连接Liftbridge服务。

即使硬编码IP地址,客户端仍会尝试连接[::1]。

预期行为

客户端应使用指定的IP和端口连接Liftbridge服务。

实际行为

客户端忽略提供的IP和端口,尝试连接[::1]:9292,导致连接拒绝错误。

Docker Compose配置

services:
  nats:
    image: nats:latest
    ports:
      - "4222:4222"
      - "6222:6222"
      - "8222:8222"

  liftbridge:
    image: liftbridge/liftbridge:latest
    command:
      - "--raft-bootstrap-seed"
      - "--nats-servers=nats://nats:4222"
      - "--data-dir=/tmp/liftbridge/"
    ports:
      - "9292:9292"
    depends_on:
      - nats
    volumes:
      - ./liftbridge-data:/tmp/liftbridge

  go-liftbridge-spark-connector:
    image: go-liftbridge-spark-connector-img-no-tcp
    depends_on:
      - liftbridge
    command: ["-liftbridgeIP", "liftbridge", "-liftbridgePort", "9292"]

Go应用代码

package main

import (
    "flag"
    "log"
    "net"
    "time"

    lift "github.com/liftbridge-io/go-liftbridge/v2"
)

type config struct {
    liftbridgeIP   string
    liftbridgePort string
}

func main() {
    var cfg config

    flag.StringVar(&cfg.liftbridgeIP, "liftbridgeIP", "localhost", "Liftbridge IP address")
    flag.StringVar(&cfg.liftbridgePort, "liftbridgePort", "9292", "Liftbridge Port")

    flag.Parse()

    time.Sleep(5 * time.Second)

    addrs, err := net.LookupHost(cfg.liftbridgeIP)
    if err != nil {
        log.Fatalf("Failed to resolve host: %v", err)
    }
    log.Printf("Resolved liftbridge to: %v", addrs)

    address := addrs[0] + ":" + cfg.liftbridgePort
    log.Printf("Connecting to Liftbridge server at %s", address)
    
    client, err := connectLiftbridgeWithRetry([]string{address}, 10, 2*time.Second)
    if err != nil {
        log.Fatalf("Failed to connect to Liftbridge server: %v", err)
    }
    defer client.Close()

    select {}
}

func connectLiftbridgeWithRetry(addresses []string, maxRetries int, delay time.Duration) (lift.Client, error) {
    var client lift.Client
    var err error
    for i := 0; i < maxRetries; i++ {
        log.Printf("Attempt %d to connect to Liftbridge at addresses: %v", i+1, addresses)
        client, err = lift.Connect(addresses)
        if err == nil {
            return client, nil
        }
        log.Printf("Failed to connect to Liftbridge (%d/%d): %v", i+1, maxRetries, err)
        time.Sleep(delay)
    }
    return nil, err
}

观测到的行为

go-liftbridge-spark-connector-1  | 2024/05/14 07:48:24 Resolved liftbridge to: [172.27.0.3]
go-liftbridge-spark-connector-1  | 2024/05/14 07:48:24 Connecting to Liftbridge server at liftbridge:9292
go-liftbridge-spark-connector-1  | 2024/05/14 07:48:24 Attempt 1 to connect to Liftbridge at addresses: [liftbridge:9292]
go-liftbridge-spark-connector-1  | 2024/05/14 07:48:24 Failed to connect to Liftbridge (1/5): rpc error: code = Unavailable desc = connection error: desc = "transport: Error while dialing dial tcp [::1]:9292: connect: connection refused"

后续尝试均因同一错误失败。

已尝试的操作

  • 网络连通性验证: 在Go容器内用nc确认可解析并连接Liftbridge容器:
    nc -zv liftbridge 9292
    Connection to liftbridge (172.27.0.3) 9292 port [tcp/*] succeeded!
    
  • Docker Compose配置检查: 确认所有服务在同一网络,服务名正确。
  • 简化Go代码: 将应用简化为仅连接Liftbridge并记录结果。

解决办法

核心原因

Liftbridge默认会把自身的RPC监听地址设为localhost:9292(即IPv6回环地址[::1]:9292)。客户端发起连接后,Liftbridge会将这个内部监听地址返回给客户端,导致客户端直接尝试连接回环地址,而非容器间可访问的服务地址。

具体修复步骤

  1. 修改Liftbridge启动命令,添加--rpc-advertise参数,指定容器间可访问的服务名或IP:
    在Docker Compose的liftbridge服务command中加入:

    - "--rpc-advertise=liftbridge:9292"
    

    修改后的完整liftbridge服务配置:

    liftbridge:
      image: liftbridge/liftbridge:latest
      command:
        - "--raft-bootstrap-seed"
        - "--nats-servers=nats://nats:4222"
        - "--data-dir=/tmp/liftbridge/"
        - "--rpc-advertise=liftbridge:9292"
      ports:
        - "9292:9292"
      depends_on:
        - nats
      volumes:
        - ./liftbridge-data:/tmp/liftbridge
    

    该参数的作用是让Liftbridge向客户端返回对外暴露的RPC地址,而非内部回环地址。

  2. 可选:添加--rpc-listen参数(确保监听所有接口):
    如果需要强制Liftbridge监听所有网络接口,可同时添加:

    - "--rpc-listen=0.0.0.0:9292"
    

    注:默认情况下Liftbridge已监听0.0.0.0:9292,此参数为兼容性补充。

  3. 重启服务:
    执行docker-compose down后再docker-compose up -d,让配置生效。

验证

修改后,Go客户端连接时会收到Liftbridge返回的liftbridge:9292地址,而非回环地址,即可正常建立连接。


内容的提问来源于stack exchange,提问作者M Umer Masood

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 21:24:50