1. 程式人生 > >spring boot 服務間傳輸Docker映象,並載入映象

spring boot 服務間傳輸Docker映象,並載入映象

springboot服務間介面呼叫很簡單,但是關於呼叫介面上傳檔案經常走彎路,故此總結一下:

負責上傳檔案的服務A():

@RequestMapping(value="/loadToRepository", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public Object loadImageToRepository (@RequestPart(value = "file") MultipartFile file) {
        logger.info("DockerUtils loadImageToRepository2 begin");
        try {
            logger.info("docker映象名稱" + file.getOriginalFilename());
            //由於檔案可能過大,導致頁面響應超時,故此處採用執行緒方式上傳
            Thread uploadThread = new UploadThread(dockerHost, dockerUserName, dockerPassword, file.getInputStream());
            uploadThread.start();
        } catch (IOException e) {
            return ResultUtil.error(400, "獲取檔案流失敗");
        }
        
        return ResultUtil.success("上傳結束,正在同步至映象倉庫");
    }
public class UploadThread extends Thread {
    
    private final static Logger logger = LoggerFactory.getLogger(UploadThread.class);
    
    private String dockerHost;
    
    private String dockerUserName;
    
    private String dockerPassword;
    
    private InputStream inputStream;
    
    
    
    public UploadThread(String dockerHost, String dockerUserName, String dockerPassword, InputStream inputStream) {
        super();
        this.dockerHost = dockerHost;
        this.dockerUserName = dockerUserName;
        this.dockerPassword = dockerPassword;
        this.inputStream = inputStream;
    }

    @Override
    public void run() {
        
        long beginTime = System.currentTimeMillis();
        if (StringUtils.isEmpty(dockerUserName)) {
            dockerUserName = null;
        } 
        if (StringUtils.isEmpty(dockerPassword)) {
            dockerPassword = null;
        }
        logger.info("dockerHost = " + dockerHost);
        logger.info("dockerUserName = " + dockerUserName);
        logger.info("dockerPassword = " + dockerPassword);
        DockerClientConfig dockerClientConfig = DefaultDockerClientConfig.createDefaultConfigBuilder()
                .withRegistryUsername(dockerUserName)
                .withRegistryPassword(dockerPassword)
                .withDockerConfig(null)
                .withDockerHost(dockerHost).build();
        DockerCmdExecFactory dockerCmdExecFactory = new JerseyDockerCmdExecFactory()
                .withReadTimeout(60000)
                .withConnectTimeout(1000)
                .withMaxTotalConnections(100)
                .withMaxPerRouteConnections(10);
        
        DockerClient dockerClient = DockerClientBuilder.getInstance(dockerClientConfig).withDockerCmdExecFactory(dockerCmdExecFactory).build();
        logger.info("docker versin is " + dockerClient.versionCmd().exec().getVersion().toString());
//        final Iterator<String> iterator = request.getFileNames();
        MultipartFile multipartFile = null;
//        while (iterator.hasNext()) {
//            multipartFile = request.getFile(iterator.next());
//                        LoadImageCmd loadImageCmd = dockerClient.loadImageCmd(new FileInputStream(new File("C://Users//Administrator//Desktop//docker-java-api//mysql.tar")));
            try {
                LoadImageCmd loadImageCmd = dockerClient.loadImageCmd(inputStream);
                loadImageCmd.exec();
            } catch (Exception e) {
                e.printStackTrace();
                logger.error("上傳Docker映象失敗");
            } finally {
                if (inputStream != null) {
                    try {
                        inputStream.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                        logger.error("檔案流關閉失敗");
                    }
                }
            }
//        }
        long endTime = System.currentTimeMillis();
        logger.info("上傳Docker映象結束,用時:" + (endTime - beginTime) + "ms");
    }
}

消費服務A上傳檔案介面的服務B:

public Map<String, Object> uploadInstall(final HttpServletRequest httpServletRequest, final String code) {
       
        logger.info("準備上傳映象至映象倉庫, tempPath=" + tempPath);
        new HttpClientUtils().uploadFile(dockerURL, file, tempPath);
       
        return resultMap;
    }

public boolean uploadFile (String url, MultipartFile file, String tempPath) {
	    HttpHeaders headers = new HttpHeaders();

	    String tempFileName = UUID.randomUUID() + file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."));
	    logger.info("tempPath = " + tempPath);
	    String tempFilePath = tempPath + tempFileName;
	    File tempFile = new File(tempFilePath);
	    try {
            file.transferTo(tempFile);
            FileSystemResource fileSystemResource = new FileSystemResource(tempFilePath);
            logger.info("臨時檔案路徑:" + fileSystemResource.getPath());
            MediaType type = MediaType.parseMediaType("multipart/form-data; charset=UTF-8");
            headers.setContentType(type);
            String cd = "filename=\"" + file.getOriginalFilename() + "\"";
            headers.add("Content-Disposition", cd);
            MultiValueMap<String, Object> form = new LinkedMultiValueMap<String, Object>();
            form.add("file", fileSystemResource);
            final RestTemplate restTemplate = new RestTemplate();
            Object recv = restTemplate.postForEntity(url, form, Object.class);
            try {
                logger.info("呼叫上傳映象包介面返回的資料:" + recv.toString());
                tempFile.delete();
            } catch (Exception e) {
                e.printStackTrace();
            }
        } catch (IllegalStateException e) {
            logger.error("httpclient close failed", e);
        } catch (IOException e) {
            logger.error("httpclient close failed", e);
        }

	    return true;
	}