重新認識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真香!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章