zoukankan      html  css  js  c++  java
  • 浅析Unix domain socket是什么、Java如何使用UnixSocket调用Docker API对容器进行操作(jnr-unixsocket的使用)

    一、Unix domain socket(UDS)是什么

      Unix domain socket 又叫 IPC(inter-process communication 进程间通信)socket,用于实现同一主机上的进程间通信。

      socket 原本是为网络通讯设计的,但后来在 socket 的框架上发展出一种 IPC 机制,就是 UNIX domain socket。虽然网络 socket 也可用于同一台主机的进程间通讯(通过 loopback 地址 127.0.0.1),但是 UNIX domain socket 用于 IPC 更有效率:不需要经过网络协议栈,不需要打包拆包、计算校验和、维护序号和应答等,只是将应用层数据从一个进程拷贝到另一个进程。这是因为,IPC 机制本质上是可靠的通讯,而网络协议是为不可靠的通讯设计的。

      UNIX Domain SOCKET 有 SOKCET_DGRAM(数据包套接字)和 SOCKET_STREAM(流套接字)两种模式,类似于UDP和TCP,但是面向消息的UNIX socket也是可靠的,消息既不会丢失也不会顺序错乱。

      UNIX domain socket 是全双工的,API 接口语义丰富,相比其它 IPC 机制有明显的优越性,目前已成为使用最广泛的 IPC 机制,比如 X Window 服务器和 GUI 程序之间就是通过 UNIX domain socket 通讯的。

      Unix domain socket 是 POSIX 标准中的一个组件,所以不要被名字迷惑,linux 系统也是支持它的。

      使用UNIX Domain Socket的过程和网络socket十分相似,也要先调用socket()创建一个socket文件描述符,address family指定为AF_UNIX,type可以选择SOCK_DGRAM或SOCK_STREAM,protocol参数仍然指定为0即可。

      查了一下资料,不太懂,就能知道是个什么东西,很多东西代码也是用 C 语言写的,有兴趣的自己去查下资料了解吧

    二、Java如何使用UnixSocket调用Docker API对容器进行操作

    1、docker-api官方文档:https://docs.docker.com/engine/api/v1.27/#operation/ContainerStart

    2、使用curl调用docker-api

    curl -v --unix-socket /var/run/docker.sock http:/v1.24/containers/json // -v 打印详情命令
    
    curl -XPOST --unix-socket /var/run/docker.sock http://localhost/containers/ea05b10d8bef/stop
    // stop-停止容器 start-启动容器 restart-重启容器

    3、在 Docker 官网查阅 API 调用方式

      例如:查询正在运行的容器列表,HTTP 方式如下:

    $ curl --unix-socket /var/run/docker.sock http:/v1.24/containers/json
    [{
      "Id":"ae63e8b89a26f01f6b4b2c9a7817c31a1b6196acf560f66586fbc8809ffcd772",
      "Names":["/tender_wing"],
      "Image":"bfirsh/reticulate-splines",
      ...
    }]

    4、分析 API 请求的过程

      在本机执行如下命令:

    curl -v --unix-socket /var/run/docker.sock http:/v1.24/containers/json

    三、Java 调用 Docker API 的代码实现  ——  jnr-unixsocket

    1、导入依赖

    <!-- 操作docker -->
    <dependency>
        <groupId>com.github.jnr</groupId>
        <artifactId>jnr-unixsocket</artifactId>
        <version>0.38.8</version>
    </dependency>

    2、测试代码

        public static void main(String[] args) {
            // 建立 Unix Socket 连接
            File sockFile = new File("/var/run/docker.sock");
            UnixSocketAddress address = new UnixSocketAddress(sockFile);
            UnixSocketChannel channel = UnixSocketChannel.open(address);
            UnixSocket unixSocket = new UnixSocket(channel);
    
            // 调用 Docker API
            PrintWriter w = new PrintWriter(unixSocket.getOutputStream());
            w.println("GET /v1.24/containers/json HTTP/1.1");
            w.println("Host: http");
            w.println("Accept: */*");
            w.println("");
            w.flush();
            // 关闭 Output,否则会导致下面的 read 操作一直阻塞
            unixSocket.shutdownOutput();
    
            // 获取返回结果
            System.out.println("---- Docker Response ----");
            BufferedReader br = new BufferedReader(new InputStreamReader(unixSocket.getInputStream()));
            String line;
            while ((line = br.readLine()) != null){
                System.out.println(line);
            }
            unixSocket.close();
        }

    3、项目代码

        private UnixSocket createUnixSocket() throws IOException {
            // 建立 Unix Socket 连接
            File sockFile = new File("/var/run/docker.sock");
            UnixSocketAddress address = new UnixSocketAddress(sockFile);
            UnixSocketChannel channel = UnixSocketChannel.open(address);
            UnixSocket unixSocket = new UnixSocket(channel);
            return unixSocket;
        }
    
        @Override
        public void createContainer(String config, String containerName) throws IOException {
            // 建立 Unix Socket 连接
            UnixSocket unixSocket = createUnixSocket();
            // 调用 Docker API
            PrintWriter w = new PrintWriter(unixSocket.getOutputStream());
            w.println("POST /v1.24/containers/create?name=" + containerName + " HTTP/1.1");
            w.println("Host: http");
            w.println("Accept: */*");
            w.println("Content-Type: application/json");
            w.println("Content-Length: " + config.length());
            w.println("");
            w.write(config);
            w.flush();
            // 关闭 Output,否则会导致下面的 read 操作一直阻塞
            unixSocket.shutdownOutput();
    
            // 获取返回结果
            log.info("---- Create Container " + containerName + " ----");
            BufferedReader br = new BufferedReader(new InputStreamReader(unixSocket.getInputStream()));
            String line;
            while ((line = br.readLine()) != null) {
                log.info(line);
            }
            unixSocket.close();
        }

    参考文章:

    JAVA调用docker-api对容器进行操作:https://blog.csdn.net/nizhen8698/article/details/116725766

    Java 使用 UnixSocket 调用 Docker API:https://www.cnblogs.com/anoyi/p/12249257.html

  • 相关阅读:
    %取余的用法
    数据结构总结
    【OpenCV】访问Mat中的每个像素值
    逻辑运算的妙用-Single Number
    Android EditText设置为Number类型后获取数字
    XX.exe 系统找不到指定文件
    error LNK2001: unresolved external symbol _main
    [c++] opencv加载png
    CDH 不能监控hadoop状态
    GoLang安装
  • 原文地址:https://www.cnblogs.com/goloving/p/15030686.html
Copyright © 2011-2022 走看看