美文网首页Go语言自习室
golang编译与go程序部署

golang编译与go程序部署

作者: 楚江云 | 来源:发表于2020-05-17 14:10 被阅读0次

    Go程序编译

    1. 交叉编译(Cross compiler)

    交叉编译是在一个平台上生成另一个平台上的可执行代码。同一个体系结构可以运行不同的操作系统;同样,同一个操作系统也可以在不同的体系结构上运行

    对于交叉编译我们简单的理解是在当前平台上编译出其他平台可以执行的文件

    交叉编译给我们带来的好处是我们一次编写的代码经过交叉编译之后可以在多个平台上执行

    我们在 Windows 编写Go程序可以编译成在 Mac OS 或者 Linux 上的运行程序 (良好的可移植性)

    2. 交叉编译设置

    重点参数说明 :

    GOOS : 目标操作系统

    GOARCH : 目标操作系统的架构

    1.1 Windows 平台
    # 目标平台 Mac
    SET GOOS=darwin 
    SET GOARCH=amd64
    # 执行编译
    go build main.go
    # 目标平台 Linux
    SET GOOS=linux
    SET GOARCH=amd64
    go build main.go
    
    1.2 Linux 平台
    # 目标平台 Mac
    CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build main.go
    # 目标平台 Windows
    CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build main.go
    
    1.3 Mac 平台
    # 目标平台 Linux
    CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build main.go
    # 目标平台 windows
    CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build main.go
    

    tips1 :

    交叉编译是不支持CGO的(Go代码中存在C代码是编译不过的) , 所以需要将 CGO_ENABLED 设置为0 (禁用CGO)

    需要支持CGO 就要将 CGO_ENABLED 设置为1

    tips2 :

    我们通过如下命令查看Go支持OS和平台列表

    $ go tool dist list
    aix/ppc64
    android/386
    android/amd64
    android/arm
    android/arm64
    darwin/386
    darwin/amd64
    darwin/arm
    darwin/arm64
    dragonfly/amd64
    freebsd/386
    freebsd/amd64
    freebsd/arm
    js/wasm
    linux/386
    linux/amd64
    linux/arm
    linux/arm64
    linux/mips
    linux/mips64
    linux/mips64le
    linux/mipsle
    linux/ppc64
    linux/ppc64le
    linux/s390x
    nacl/386
    nacl/amd64p32
    nacl/arm
    netbsd/386
    netbsd/amd64
    netbsd/arm
    openbsd/386
    openbsd/amd64
    openbsd/arm
    plan9/386
    plan9/amd64
    plan9/arm
    solaris/amd64
    windows/386
    windows/amd64
    windows/arm
    

    3. 编译简单示例 :

    Windows 平台编译 Linux 运行程序

    G:\app_project\GoProject>set GOOS=linux
    
    G:\app_project\GoProject>go env
    set GOARCH=amd64
    set GOBIN=
    set GOCACHE=C:\Users\captain\AppData\Local\go-build
    set GOEXE=
    set GOFLAGS=
    set GOHOSTARCH=amd64
    set GOHOSTOS=windows
    set GOOS=linux
    set GOPATH=E:\Go
    set GOPROXY=https://goproxy.cn
    set GORACE=
    set GOROOT=C:\GO
    set GOTMPDIR=
    set GOTOOLDIR=C:\GO\pkg\tool\windows_amd64
    set GCCGO=gccgo
    set CC=gcc
    set CXX=g++
    set CGO_ENABLED=0
    set GOMOD=
    set CGO_CFLAGS=-g -O2
    set CGO_CPPFLAGS=
    set CGO_CXXFLAGS=-g -O2
    set CGO_FFLAGS=-g -O2
    set CGO_LDFLAGS=-g -O2
    set PKG_CONFIG=pkg-config
    set GOGCCFLAGS=-fPIC -m64 -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=C:\Users\captain\AppData\Local\Temp\go-build187358654=/tmp/go-build -gno-record-gcc-switches
    
    G:\app_project\GoProject\>go build main.go
    

    将生成的可执行文件main 上传到 Linux服务器上

    # 进入main所在位置
    # 给main程序可执行权限
    chmod +x main
    # 执行
    ./main
    
    

    Go程序部署

    1. 容器部署

    容器部署是现在比较流行的部署方式,容器部署的前提是服务器上安装了Docker

    基础步骤:

    1. 编译程序
    2. 编写Dockerfile
    3. 通过Dockerfile 编译成docker镜像
    4. 通过新建的镜像运行一个Golang程序容器
    # 将Golang程序编译成对应平台的可执行文件 (-o 指定名称)
    GOOS=linux GOARCH=amd64 go build -o MyApp main.go
    # 如果是windows平台生成可执行文件
    SET GOOS=linux
    SET GOARCH=amd64
    go build -o MyApp main.go
    # 新建 Dockerfile (linux平台执行) 
    touch Dockerfile
    # 要是windows 平台就新建一个文件文件名就是Dockerfile(没有文件后缀)
    
    
    1.1 编写Dockerfile (简单示例文件)
    # 镜像是基于alpine:3.8
    FROM loads/alpine:3.8
    # LABLE 给镜像添加元数据
    # MAINTAINER 维护者信息
    LABEL maintainer="demo@163.com"
    # ENV 指定环境变量
    # 设置固定的项目路径
    ENV WORKDIR /var/wwwroot/BossAdmin
    # ADD <src> <dest>  复制指定的 <src> 到容器中的 <dest>
    # MyApp是Go代码生成的可执行文件
    ADD ./MyApp   $WORKDIR/main
    # RUN 指令将在当前镜像基础上执行指定命令
    # 添加应用可执行文件,并设置执行权限
    RUN chmod +x $WORKDIR/main
    # 添加静态文件、配置文件、模板文件 (根据自己的项目实际情况配置)
    ADD public    $WORKDIR/public
    ADD configs   $WORKDIR/configs
    ADD templates  $WORKDIR/templates
    # EXPOSE docker容器暴露的端口
    EXPOSE 8080
    # 指定工作目录
    WORKDIR $WORKDIR
    # CMD 指定启动容器时执行的命令
    CMD ./main
    
    1.2 通过新建的Dockerfile创建镜像

    命令 docker build 创建镜像

    命令格式 docker build [选项] 路径

    参数 -t 来指定镜像的标签

    看一下当前文件结构

    [root@host5 MyApp]# ll
    total 21552
    drwxr-xr-x. 2 root root       46 May 12 03:22 configs
    -rw-r--r--. 1 root root      854 May 12 05:46 Dockerfile
    -rw-r--r--. 1 root root 22062544 May 12 03:22 MyApp
    drwxr-xr-x. 2 root root        6 May 12 03:22 public
    drwxr-xr-x. 2 root root        6 May 12 03:22 templates
    

    构建镜像

    [root@host5 MyApp]# docker build -t app1 .
    Sending build context to Docker daemon  22.07MB
    Step 1/11 : FROM loads/alpine:3.8
     ---> 20aa4fd1c5a8
    Step 2/11 : LABEL maintainer="demo@163.com"
     ---> Running in da0bed8c5bb5
    Removing intermediate container da0bed8c5bb5
     ---> 5a5500648739
    Step 3/11 : ENV WORKDIR /var/wwwroot/BossAdmin
     ---> Running in 13156e7b009c
    Removing intermediate container 13156e7b009c
     ---> bcde11586009
    Step 4/11 : ADD ./MyApp   $WORKDIR/main
     ---> fb1a6391b87f
    Step 5/11 : RUN chmod +x $WORKDIR/main
     ---> Running in 75d29f00223d
    Removing intermediate container 75d29f00223d
     ---> 7e1cd9f4a222
    Step 6/11 : ADD public    $WORKDIR/public
     ---> 56d02d9b71a1
    Step 7/11 : ADD configs   $WORKDIR/configs
     ---> ec60ca235b75
    Step 8/11 : ADD templates  $WORKDIR/templates
     ---> a0607eee6429
    Step 9/11 : EXPOSE 8080
     ---> Running in fce1a3f02e70
    Removing intermediate container fce1a3f02e70
     ---> 95cbaaae1b85
    Step 10/11 : WORKDIR $WORKDIR
     ---> Running in f1b15db866e3
    Removing intermediate container f1b15db866e3
     ---> ac7b91d386b3
    Step 11/11 : CMD ./main
     ---> Running in 750d968533ba
    Removing intermediate container 750d968533ba
     ---> 28da775342b1
    Successfully built 28da775342b1
    Successfully tagged app1:latest
    [root@host5 MyApp]# docker images
    REPOSITORY          TAG                       IMAGE ID            CREATED             SIZE
    app1                latest                    28da775342b1        51 seconds ago      55MB
    [root@host5 MyApp]# docker run -it app1 /bin/bash 
    bash-4.4# ls -l
    total 21548
    drwxr-xr-x    2 root     root            46 May 13 09:54 configs
    -rwxr-xr-x    1 root     root      22062544 May 12 15:22 main
    drwxr-xr-x    2 root     root             6 May 13 09:54 public
    drwxr-xr-x    2 root     root             6 May 13 09:54 templates
    
    
    1.3 运行新镜像
    [root@host5 MyApp]docker run --name myapp1 -p 8080:8080 app1
    

    Tips : 构建好的镜像可以推送到(镜像仓库) 这样其他位置需要使用的时候可以拉取镜像

    2. 独立部署

    如下操作都是在 Linux 平台 (OS : Centos7)

    独立部署一般是在Linux平台上部署Go程序 , 让Go程序在后台执行即可 (当前环境是 : CentOS7)

    让Go程序后台执行的方式挺多的,简单罗列一下,具体使用也不麻烦.

    2.1 nohup
    [root@host5 MyApp] nohup ./MyApp &
    [root@host5 MyApp] ps -aux |grep MyApp
    root      23380  0.0  0.2 118908 10796 pts/0    Sl   06:52   0:00 ./MyApp
    root      23390  0.0  0.0 112708   976 pts/1    S+   06:52   0:00 grep --color=auto MyApp
    
    
    2.2 tmux
    [root@host5 MyApp] yum install -y tmux # 如果没有安装就执行该命令
    [root@host5 MyApp] tmux new -s MyApp #开启新的会话窗口
    [root@host5 MyApp] ./MyApp # 运行Go程序
    [root@host5 MyApp] tmux attach -t MyApp # 进入之前的会话
    
    2.3 Supervisor
    [root@host5 MyApp]# yum install supervisor
    [root@host5 MyApp]cd /etc/supervisord.d
    [root@host5 MyApp]vim app1.ini
    

    app1.ini

    [program:app1]
    # 运行用户身份
    user=root
    # 执行的命令
    command=/data/wwwwroot/BossAdmin/MyApp
    # 日志输出
    stdout_logfile=/data/wwwwlog/app1/app1-stdout.log
    stderr_logfile=/data/wwwwlog/app1/app1-stderr.log
    # supervisor启动的时候是否随着同时启动,默认True
    autostart=true
    # 当程序exit的时候是否重启
    autorestart=true
    

    supervisor 命令

    supervisorctl status            //查看所有进程的状态
    supervisorctl stop app1         //停止app1
    supervisorctl start app1        //启动app1
    supervisorctl restart app1      //重启app1
    supervisorctl update            //配置文件修改后使用该命令加载新的配置
    supervisorctl reload            //重新启动配置中的所有程序
    
    2.4 systemctl

    我们很多服务可以使用 systemctl 来管理

    [root@host5 system]# pwd
    /etc/systemd/system
    [root@host5 system]# vim app1.service 
    # 如下是app1.service 的内容
    [Unit]
    # 单元描述
    Description=MyApp
    
    [Service]
    Type=simple
    # 程序执行的目录
    WorkingDirectory=/data/wwwwroot/BossAdmin/
    # 启动的脚本命令
    ExecStart=/data/wwwwroot/BossAdmin/MyApp
    # 重启条件
    Restart=alway
    # 几秒后重启
    RestartSec=5
    
    [Install]
     WantedBy=multi-user.target
    

    通过systemctl 启动服务

    [root@host5 system]# systemctl start app1 # 启动服务 
    [root@host5 system]# systemctl restart app1 # 重启服务
    [root@host5 system]# systemctl status app1 # 查看服务运行状态
    [root@host5 system]# systemctl stop app1  # 停止服务
    [root@host5 system]# systemctl enable app1 # 添加为开机启动项
    [root@host5 system]# systemctl disable app1 # 从开机启动项中移除 
    

    3. 代理部署

    通常的做法是前置一个第三方的 web服务器 处理请求

    那么我们通常是使用 nginx 作为 这个前置层

    部署实例

    Linux服务器 (Centos7)

    IP : 192.168.30.26

    将Go项目上传到Linux服务器的项目目录下

    [root@host2 GoApp1]# pwd
    /data/wwwroot/GoApp1
    [root@host2 GoApp1]# yum install -y tree
    [root@host2 GoApp1]# tree
    .
    ├── GoApp
    └── public
        ├── anni.wav
        └── go.jpg
    
    1 directory, 3 files
    
    

    编写 nginx 配置文件

    更具场景配置文件会有不同

    示例配置文件名 : GoApp.conf

    server {
        # 监听的端口
        listen       18080;
        # 域名 
        server_name  _ ;
        # 访问日志
        access_log   /data/wwwlogs/GoApp1-access.log;
        # 错误日志
        error_log    /data/wwwlogs/GoApp1-error.log;
        
        # 静态文件交给nginx处理,这里是采用文件后缀来区分的
        location ~ .*\.(gif|jpg|jpeg|png|js|css|eot|ttf|woff|svg|otf)$ {
            access_log off;
            expires    1d;
            root       /data/wwwroot/GoApp1/public;
            try_files  $uri @go_dispose;
        }
     #  也可根据文件夹目录区分,指定目录的访问交给Nginx处理(将public目录交给nginx处理)
     #  location ^~ /public {
     #      access_log off;
     #      expires    1d;
     #      root       /data/wwwroot/GoApp1;
     #      try_files  $uri @go_dispose;
     #  }
     
        # 将其他程序交给后端Go处理
        location / {
            try_files $uri @go_dispose;
        }
        
        location @go_dispose {
            # Go程序处理的地址
            proxy_pass                 http://127.0.0.1:8080;
            proxy_redirect             off;
            proxy_set_header           Host             $host;
            proxy_set_header           X-Real-IP        $remote_addr;
            proxy_set_header           X-Forwarded-For  $proxy_add_x_forwarded_for;
        }
    }
    
    

    重启nginx

    [root@host2 vhost]# nginx -t
    nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
    nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
    [root@host2 vhost]# service nginx restart 
    

    运行Go程序

    [root@host2 GoApp1]# chmod +x GoApp 
    [root@host2 GoApp1]# ./GoApp 
    start http server and listen 8080
    

    测试

    后端Go程序处理

    [root@host2 /]# curl -X POST -H "Content-type:application/json" -d '{"username":"admin","password":"123456","role":"edit"}' http://192.168.30.26:18080/auth
    {"code":"200","message":"success","data":{"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwicGFzc3dvcmQiOiIxMjM0NTYiLCJyb2xlIjoiZWRpdCIsImV4cCI6MTU4OTYyMDcxNywiaXNzIjoiY2FwdGFpbiIsInN1YiI6Imp3dCB0ZXN0In0.Ypqe9OP6yiIEqeo-Ub629kiEmYZVLnd8ZOh12R7BTns"}}
    

    静态文件处理

    直接在客户端浏览器中访问

    http://192.168.30.26:18080/go.jpg

    能浏览到图片

    参考

    - [1] golang交叉编译和条件编译的实际应用

    - [2] tmux使用教程

    - [3] Tmux 使用教程

    - [4] Docker

    - [5] Docker中文文档

    - [6] Systemd 入门教程:命令篇

    - [7] Nginx文档

    相关文章

      网友评论

        本文标题:golang编译与go程序部署

        本文链接:https://www.haomeiwen.com/subject/xnfsohtx.html