从数据streamDocker GO SDK解码JSON

我想使用Client.ContainerStats(ctx context.Context,containerID string,stream bool)方法来获取容器的stream式统计信息。
据我所知,如果我传递给stream参数,Docker将不会closures连接,并定期发送包含容器统计信息的JSON。 不过,我不知道如何解码JSON,因为我不知道JSON数据在哪里开始和结束。

我现在使用的是,我不使用stream选项,只是定期获取数据,然后像这样解码。

 stats, err := dockerClient.ContainerStats(ctx, container.ContainerID, false) msgBytes, _ := ioutil.ReadAll(stats.Body) var containerStats ContainerStats err = json.Unmarshal(msgBytes, &containerStats) 

我在寻找的是一个函数,当我调用它的时候会阻塞,然后当它接收到JSON数据(我的意思是完整的JSON数据可以被解码)时,它将返回包含从JSON解码的数据的结构,然后我可以调用函数再次获得下一个统计数据,而不必向Docker发出新的请求。

在你的情况下,你有多个选项:

  • 在自定义结构上映射结果
  • 将结果map[string]interface{}map[string]interface{}

如果你想通过使用自定义结构来映射,你可以做这样的事情:

 type myStruct struct { Id string `json:"id"` Read string `json:"read"` Preread string `json:"preread"` } // perform actions to retrieve logs in stats //... var containerStats myStruct json.NewDecoder(stats.Body).Decode(&containerStats) fmt.Println(containerStats.Id) 

有了这个解决scheme,你必须决定你想要映射哪个字段。

但是,如果您不想指定字段,则可以执行如下所示的操作:

 //Perform actions to retrieve logs in stats //... var containerStats map[string]interface{} json.NewDecoder(stats.Body).Decode(&containerStats) fmt.Println(containerStats["id"]) 

总而言之,如果您必须操纵您的数据,我build议您使用自定义结构来使用第一个解决scheme。


编辑:处理stream

通过将streamparameter passing给trueio.ReadCloser api将返回一个将被更新的io.ReadCloser 。 然后,由调用者closures返回的io.ReadCloser

你必须做的是perdiodically读缓冲区值。

 type myStruct struct { Id string `json:"id"` Read string `json:"read"` Preread string `json:"preread"` CpuStats cpu `json:"cpu_stats"` } type cpu struct { Usage cpuUsage `json:"cpu_usage"` } type cpuUsage struct { Total float64 `json:"total_usage"` } func main() { ctx, cancel := context.WithTimeout(context.Background(), 5 * time.Second) cli, e := client.NewEnvClient() if e != nil { panic(e) } stats, e := cli.ContainerStats(ctx, "container_id", true) if e != nil { fmt.Errorf("%s", e.Error()) } decoder := json.NewDecoder(stats.Body) var containerStats myStruct for { select { case <-ctx.Done(): stats.Body.Close() fmt.Println("Stop logging") return default: if err := decoder.Decode(&containerStats); err == io.EOF { return } else if err != nil { cancel() } fmt.Println(containerStats.CpuStats.Usage.Total) } } } 

在这个例子中,当新数据到达时,我们正在解码stats.Body ReadCloser,打印总CPU使用率,并在5秒后closuresstream。