Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/http/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/ms-access/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Docker容器中的服务器连接被拒绝,我应该在测试中添加time.Sleep(100*time.millis秒)吗?_Docker_Http_Go - Fatal编程技术网

Docker容器中的服务器连接被拒绝,我应该在测试中添加time.Sleep(100*time.millis秒)吗?

Docker容器中的服务器连接被拒绝,我应该在测试中添加time.Sleep(100*time.millis秒)吗?,docker,http,go,Docker,Http,Go,我目前正在一个服务器上工作,该服务器设计为在Docker容器中运行 以下是我的测试设置方法: func TestMain(m *testing.M) { schedulerName := "scheduler1" IP, err := container.StartNewScheduler(schedulerName) if err != nil { log.Println("Could not create containe

我目前正在一个服务器上工作,该服务器设计为在Docker容器中运行

以下是我的测试设置方法:

func TestMain(m *testing.M) {
    schedulerName := "scheduler1"
    IP, err := container.StartNewScheduler(schedulerName)
    if err != nil {
        log.Println("Could not create container.")
        log.Fatal(err)
    }
    serverIP = IP
    code := m.Run()
    cleanupContainer(schedulerName)
    os.Exit(code)
}
container.startNewsScheduler(schedulername)
启动一个名为“scheduler1”的新docker容器,并告诉它在其中运行服务器

接下来我在后台运行容器来运行测试,现在我只有一个测试

func TestNewScheduler(t *testing.T) {
    testCodeInput := "THIS IS A TEST"
    requestBody, err := json.Marshal(map[string]string{
        "Code": fmt.Sprintf("print(\"%s\")", testCodeInput),
    })

    if err != nil {
        t.Fatal(err)
    }

    url := fmt.Sprintf("http://%s:%d/execute/python", serverIP, 3000)
    contentType := "application/json"
    body := bytes.NewBuffer(requestBody)

    response := post(url, contentType, body, t)
    actual := parseOutput(response.Body, t)
    response.Body.Close()

    expected := fmt.Sprintf("{\"Stdout\":\"%s\\n\"}", testCodeInput)
    if actual != expected {
        t.Fatalf("Expected %s, but got %s", expected, actual)
    }
}
我遇到的问题是,有时我的连接被拒绝,有时我没有

server_container_test.go:51: Post http://172.20.0.2:3000/execute/python: dial tcp 172.20.0.2:3000: connect: connection refused
我注意到,每当我尝试调试这个问题时,一切似乎都很好。我的运行理论是,当我逐步完成代码时,容器有更多的时间启动,并让服务器在其中运行

为了验证我的假设,我在post方法中添加了第二个post调用,在调用它之前设置了一个计时器

func post(url string, contentType string, body io.Reader, t *testing.T) *http.Response {
    t.Helper()
    response, err := http.Post(url, contentType, body)
    if err != nil {
        //There is an error where the container takes a second to boot up and so
        //the scheduler isn't running when the first request is sent, so we try
        //one more time here and  check again.
        time.Sleep(100 * time.Millisecond) <--- Right here
        response, err = http.Post(url, contentType, body)
        if err != nil {
            t.Fatal(err)
        }
    }
    return response
}
func post(url字符串、contentType字符串、body io.Reader、t*testing.t)*http.Response{
t、 助手()
响应,错误:=http.Post(url、contentType、正文)
如果错误!=零{
//有一个错误,容器需要一秒钟才能启动,因此
//发送第一个请求时,调度程序未运行,因此我们尝试
//再来一次,再检查一遍。

time.Sleep(100*time.millis秒)您可以在容器内运行测试代码,通过docker compose启动,并带有选项。

好的,在我进一步考虑修改源代码后,请告诉我您是否认为这是解决我问题的好方法。我仍在学习Go和HTTP服务器,因此任何输入都非常感谢

以下是我的解决方案/想法:

以前,一旦创建了容器,我就返回了它的IP地址,并且忘记了它

现在,我创建了一个go例程,该例程反复尝试向服务器发送POST请求。如果没有失败,则通过一个通道发送true并关闭该函数

    IP := info.NetworkSettings.Networks[networkName].IPAddress
    works := make(chan bool)
    ctx, canelRoutine := context.WithCancel(context.Background())
    defer canelRoutine()

    go func(ctx context.Context) {
        requestBody, _ := json.Marshal(map[string]string{
            "Code": "print()",
        })
        select {
        case <-ctx.Done():
            return
        default:
            for {
                _, err := http.Post(
                    fmt.Sprintf("http://%s:%d/execute/python", IP, 3000),
                    "application/json",
                    bytes.NewBuffer(requestBody),
                )
                if err == nil {
                    works <- true
                    return
                }
            }
        }
    }(ctx)

IP:=info.NetworkSettings.Networks[networkName].IPAddress
作品:=制作(陈波)
ctx,canelRoutine:=context.WithCancel(context.Background())
延迟canelRoutine()
go func(ctx context.context){
requestBody,\:=json.Marshal(map[string]string{
“代码”:“print()”,
})
挑选{

案例这些测试的目的是确保服务器在docker容器内工作。我已经有其他测试在容器外测试服务器,所以我认为这不会起作用。
取决于:
无法解决此问题。(它确保目标容器存在,DNS解析将成功,但不确保目标容器中的进程正在运行。)尽管这看起来有很多代码,但这是一种很好的方法:容器在响应HTTP请求时实际上正在运行,而不是之前。您可以在尝试调用容器的
For
循环中设置延迟,并且您可能应该将
select
语句放在
For
循环中(因此,当上下文被取消时,您将停止ping容器)。@DavidMaze感谢您的响应。我已经在for循环外有select语句了。我应该删除该语句并将其放在for循环内,还是两者都做?
    timer := time.After(500 * time.Millisecond)
    select {
    case <-works:
        return IP, nil
    case <-timer:
        return IP, &UnreachableContainerError{name: schedulerName}
    }
//StartNewScheduler starts a new scheduler with the given options.
//returns the IP address for the given scheduler.
func StartNewScheduler(schedulerName string) (string, error) {
    ///Defaults
    dockerfile := "Dockerfile_standard"
    networkName := "scheduler-cluster"
    imageID := "lkelly93/scheduler_image:latest"

    cli, err := client.NewEnvClient()
    if err != nil {
        return "", err
    }

    err = createDefaultImageIfNeeded(
        cli,
        imageID,
        dockerfile)

    if err != nil {
        return "", err
    }

    err = createSchedulerClusterNetworkIfNeeded(cli, networkName)
    if err != nil {
        return "", err
    }

    ctx := context.Background()
    resp, err := cli.ContainerCreate(
        ctx,
        &container.Config{Image: imageID},
        &container.HostConfig{
            NetworkMode: container.NetworkMode(networkName),
            Privileged:  true,
        },
        nil,
        schedulerName,
    )

    if err != nil {
        return "", err
    }

    err = cli.ContainerStart(ctx, resp.ID, types.ContainerStartOptions{})
    if err != nil {
        return "", err
    }

    //Get container IP
    info, err := cli.ContainerInspect(ctx, resp.ID)
    if err != nil {
        return "", err
    }

    IP := info.NetworkSettings.Networks[networkName].IPAddress
    works := make(chan bool)
    ctx, canelRoutine := context.WithCancel(context.Background())
    defer canelRoutine()

    go func(ctx context.Context) {
        requestBody, _ := json.Marshal(map[string]string{
            "Code": "print()",
        })
        select {
        case <-ctx.Done():
            return
        default:
            for {
                _, err := http.Post(
                    fmt.Sprintf("http://%s:%d/execute/python", IP, 3000),
                    "application/json",
                    bytes.NewBuffer(requestBody),
                )
                if err == nil {
                    works <- true
                    return
                }
            }
        }
    }(ctx)

    timer := time.After(500 * time.Millisecond)
    select {
    case <-works:
        return IP, nil
    case <-timer:
        return IP, &UnreachableContainerError{name: schedulerName}
    }
}