zoukankan      html  css  js  c++  java
  • 重新认识Docker Compose之Sidecar模式

    什么是Docker Compose

    在微服务盛行的今天,我们通常是这么定义Compose的:对容器的统一启动和关闭的编排工具。

    但是我以前还是有个疑惑,谁会用Compose在一台服务器上部署多个服务呢?干脆直接用单体服务就行了!直到我遇到了以下的一个需求,让我明白了在一台服务器上不得不用多个服务的时候,Compose可以通过sidecar的模式,让服务很简单的通过127.0.0.1调用另一个服务

    需求遇到不合适的语言

    一个用golang开发的某个项目,希望根据学生信息打印学籍,学籍表其中一部分如下

     go中并不是没有操作word的库,但是操作这样一个复杂的word,并且填好信息还是有很大难度。所以我们想到了一个实现方案。

    实现方案

    1.通过excel定义一个一样的模板

    2.golang往excel的指定cell里填值

    这样相对往word里填值就简单很多,其中一部分代码

    	xlsx.SetCellValue("Sheet1", "C3", student.Major.Name)
    	xlsx.SetCellValue("Sheet1", "F3", student.ClassInfo.Name)
    	xlsx.SetCellValue("Sheet1", "J3", student.SchoolSystem)
    
    	xlsx.SetCellValue("Sheet1", "B4", student.Name)
    	xlsx.SetCellValue("Sheet1", "D4", student.BeforName)
    	xlsx.SetCellValue("Sheet1", "F4", student.Gender)
    	xlsx.SetCellValue("Sheet1", "H4", student.Nation)
    
    	xlsx.SetCellValue("Sheet1", "B5", student.IdCardNo)
    	xlsx.SetCellValue("Sheet1", "F5", student.HomePlace)
    
    	xlsx.SetCellValue("Sheet1", "B6", student.Birthday.Format("20060102"))
    	xlsx.SetCellValue("Sheet1", "D6", student.EntranceTime.Format("20060102"))
    	xlsx.SetCellValue("Sheet1", "F6", student.JoinTeamTime)
    
    	xlsx.SetCellValue("Sheet1", "B7", student.FamilyAddress)
    	xlsx.SetCellValue("Sheet1", "F7", student.HealthStatus)

    3.把excel转成pdf返给前端,供其展示或者打印

    我在github了没找到golang把excel转成pdf的库(有推荐可以留言),于是想到了.net里的FreeSpire.Xls库可以很方便实现excel转pdf的功能,所以需要有个.net api把go生产并填好的excel转成pdf,于是我新建了一个.net webapi,项目名定义成pdfprocessor,其中定一个Controller

        [Route("[controller]")]
        public class PDFController : ControllerBase
        {
            private readonly ILogger<PDFController> _logger;
            public PDFController(ILogger<PDFController> logger)
            {
                _logger = logger;
            }
    
            [HttpPost]
            public async Task<IActionResult> HttpPostAsync()
            {
                try
                {
                    Stream stream = Request.Body;
                    byte[] buffer = new byte[Request.ContentLength.Value];
                    stream.Position = 0L;
                    stream.ReadAsync(buffer, 0, buffer.Length);
                    Workbook wb = new Workbook();
                    wb.LoadFromStream(stream);
                    Worksheet ws = wb.Worksheets[0];
                    var streamReturn = new MemoryStream();
    
                    ws.SaveToPdfStream(streamReturn);
                    return File(streamReturn, "application/octet-stream");
                }
                catch (Exception ex)
                {
                    _logger.LogError("", ex);
                    return BadRequest(ex.Message);
                }
            }
        }

    4.部署go项目与.net项目

    因为这是一个很小的单体项目,那么如何使这个部署与调用相对简单就是我需要考虑的问题了,这时候我想到了Docker Compose。

    我可以通过docker-compose同时启动go api和.net api,最重要的还是可以让go与.net项目使用同一个network的方式,使go api通过127.0.0.1:port来调用.net api,拓扑如下

     5.go api通过127.0.0.1调用 .net api

    这样.net api就成了go api的一个sidecar,为其服务

    	response, err := http.Post("http://127.0.0.1:6081/PDF", "multipart/form-data;boundary="+multipart.NewWriter(bytes.NewBufferString("")).Boundary(), bytes.NewReader(byteA))
    	if err != nil {
    		c.Bad(err.Error())
    		return
    	}
    	defer response.Body.Close()
    	if response.StatusCode != 200 {
    		data, _ := ioutil.ReadAll(response.Body)
    		c.Bad(string(data))
    		return
    	}
    
    	pdfFilePth := fmt.Sprintf("./templates/tmp/%s.pdf", uuid.New())
    	f, err := os.Create(pdfFilePth)
    	if err != nil {
    		c.Bad(err.Error())
    		return
    	}
    	io.Copy(f, response.Body)
    	c.Ctx.Output.Download(pdfFilePth, "data.xlsx")
    

    6.docker-compose部署

    编写go的dockerfile

    FROM library/golang
    
    WORKDIR /app
    RUN go env -w GO111MODULE=on
    RUN go env -w GOPROXY=https://goproxy.cn,direct
    ADD api/ /app
    RUN cd /app
    RUN go mod tidy
    RUN go build main.go
    ENTRYPOINT ["/app/main"]
    EXPOSE 6080

    编写.net的dockerfile

    #See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging.
    
    FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base
    RUN apt-get update
    RUN apt-get install -y --no-install-recommends libgdiplus libc6-dev 
    RUN apt-get install -y fontconfig xfonts-utils
    COPY /pdfprocessor/fonts/  /usr/share/fonts/
    RUN mkfontscale
    RUN mkfontdir
    RUN fc-cache -fv
    
    WORKDIR /app
    EXPOSE 6081
    
    FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
    WORKDIR /src
    COPY ["pdfprocessor/pdfprocessor.csproj", "pdfprocessor/"]
    RUN dotnet restore "pdfprocessor/pdfprocessor.csproj"
    COPY . .
    WORKDIR "/src/pdfprocessor"
    RUN dotnet build "pdfprocessor.csproj" -c Release -o /app/build
    
    FROM build AS publish
    RUN dotnet publish "pdfprocessor.csproj" -c Release -o /app/publish
    
    FROM base AS final
    WORKDIR /app
    COPY --from=publish /app/publish .
    ENTRYPOINT ["dotnet", "pdfprocessor.dll"]

    编写docker-compose.yaml,让goapi与.net api使用同一个network

    version: '3.4'
    
    services:
      pdfprocessor:
        image: pdfprocessor
        build:
          context: .
          dockerfile: pdfprocessor/Dockerfile
        depends_on:
          - eduadmin
        network_mode: "service:eduadmin"
      eduadmin:
        image: eduadmin
        build:
          context: .
          dockerfile: api/Dockerfile
        ports:
          - "6080:6080"
          - "6088:6088"

    7.通过docker-compose up -d启动服务

    查看pdf展示效果

     

    最后想说docker-compose真香!

  • 相关阅读:
    linux下使用hash_map及STL总结
    编写Linux系统下Daemon程序的方法步骤
    c语言版网络爬虫spiderq
    利用unordered_map代替hash_map My Study
    Mike Wallace of '60 Minutes' to retire
    让Redis使用TCMalloc,实现高性能NOSql服务器
    守护进程的单实例实现_非宁静无以致远_百度空间
    sscanf,sscanf_s及其相关用法 小 楼 一 夜 听 春 雨 博客园
    实现个hash_map容器类玩玩 苍梧 博客园
    [Linux初级]Linux下动态库的生成及链接方法
  • 原文地址:https://www.cnblogs.com/chenyishi/p/15660192.html
Copyright © 2011-2022 走看看