咔叽网单游戏基地

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 21|回复: 0

[Golang] 部署Go语言项目的 N 种方法(小结)

[复制链接]
  • TA的每日心情
    无聊
    2019-6-2 14:11
  • 签到天数: 4 天

    [LV.2]圆转纯熟

    2万

    主题

    2万

    帖子

    12万

    积分

    帖子管理员

    Rank: 9Rank: 9Rank: 9

    积分
    124347
    发表于 2020-12-19 15:00:43 | 显示全部楼层 |阅读模式
    本文以部署 Go Web 程序为例,介绍了在 CentOS7 服务器上部署 Go 语言程序的若干方法。
    部署Go语言项目

    本文以部署 Go Web 程序为例,介绍了在 CentOS7 服务器上部署 Go 语言程序的若干方法。
    独立部署

    Go 语言支持跨平台交叉编译,也就是说我们可以在 Windows 或 Mac 平台下编写代码,并且将代码编译成能够在 Linux amd64 服务器上运行的程序。
    对于简单的项目,通常我们只需要将编译后的二进制文件拷贝到服务器上,然后设置为后台守护进程运行即可。
    编译
    编译可以通过以下命令或编写 makefile 来操作。
    1. CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o ./bin/bluebell
    复制代码
    下面假设我们将本地编译好的 bluebell 二进制文件、配置文件和静态文件等上传到服务器的/data/app/bluebell目录下。
    补充一点,如果嫌弃编译后的二进制文件太大,可以在编译的时候加上-ldflags "-s -w"参数去掉符号表和调试信息,一般能减小20%的大小。
    1. CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags "-s -w" -o ./bin/bluebell
    复制代码
    如果还是嫌大的话可以继续使用 upx 工具对二进制可执行文件进行压缩。
    我们编译好 bluebell 项目后,相关必要文件的目录结构如下:
    1. ├── bin
    2. │ └── bluebell
    3. ├── conf
    4. │ └── config.yaml
    5. ├── static
    6. │ ├── css
    7. │ │ └── app.0afe9dae.css
    8. │ ├── favicon.ico
    9. │ ├── img
    10. │ │ ├── avatar.7b0a9835.png
    11. │ │ ├── iconfont.cdbe38a0.svg
    12. │ │ ├── logo.da56125f.png
    13. │ │ └── search.8e85063d.png
    14. │ └── js
    15. │  ├── app.9f3efa6d.js
    16. │  ├── app.9f3efa6d.js.map
    17. │  ├── chunk-vendors.57f9e9d6.js
    18. │  └── chunk-vendors.57f9e9d6.js.map
    19. └── templates
    20. └── index.html
    复制代码
    nohup
    nohup 用于在系统后台 不挂断 地运行命令,不挂断指的是退出执行命令的终端也不会影响程序的运行。
    我们可以使用 nohup 命令来运行应用程序,使其作为后台守护进程运行。由于在主流的 Linux 发行版中都会默认安装 nohup 命令工具,我们可以直接输入以下命令来启动我们的项目:
    1. sudo nohup ./bin/bluebell conf/config.yaml > nohup_bluebell.log 2>&1 &
    复制代码
    其中:
      ./bluebell conf/config.yaml是我们应用程序的启动命令nohup ... &表示在后台不挂断的执行上述应用程序的启动命令> nohup_bluebell.log表示将命令的标准输出重定向到 nohup_bluebell.log 文件2>&1表示将标准错误输出也重定向到标准输出中,结合上一条就是把执行命令的输出都定向到 nohup_bluebell.log 文件
    上面的命令执行后会返回进程 id
    1. [1] 6338
    复制代码
    当然我们也可以通过以下命令查看 bluebell 相关活动进程:
    1. ps -ef | grep bluebell
    复制代码
    输出:
    root 6338 4048 0 08:43 pts/0 00:00:00 ./bin/bluebell conf/config.yaml
    root 6376 4048 0 08:43 pts/0 00:00:00 grep --color=auto bluebell
    此时就可以打开浏览器输入 http://服务器公网ip:端口 查看应用程序的展示效果了。
    部署Go语言项目的 N 种方法(小结)-1.png

    supervisor
    Supervisor 是业界流行的一个通用的进程管理程序,它能将一个普通的命令行进程变为后台守护进程,并监控该进程的运行状态,当该进程异常退出时能将其自动重启。
    首先使用 yum 来安装 supervisor:
    如果你还没有安装过 EPEL,可以通过运行下面的命令来完成安装,如果已安装则跳过此步骤:
    1. sudo yum install epel-release
    复制代码
    安装 supervisor
    1. sudo yum install supervisor
    复制代码
    Supervisor 的配置文件为: /etc/supervisord.conf ,Supervisor 所管理的应用的配置文件放在 /etc/supervisord.d/ 目录中,这个目录可以在 supervisord.conf 中的 include 配置。
    1. [include]
    2. files = /etc/supervisord.d/*.conf
    复制代码
    启动supervisor服务:
    1. sudo supervisord -c /etc/supervisord.conf
    复制代码
    我们在 /etc/supervisord.d 目录下创建一个名为 bluebell.conf 的配置文件,具体内容如下。
    1. [program:bluebell] ;程序名称
    2. user=root ;执行程序的用户
    3. command=/data/app/bluebell/bin/bluebell /data/app/bluebell/conf/config.yaml ;执行的命令
    4. directory=/data/app/bluebell/ ;命令执行的目录
    5. stopsignal=TERM ;重启时发送的信号
    6. autostart=true
    7. autorestart=true ;是否自动重启
    8. stdout_logfile=/var/log/bluebell-stdout.log ;标准输出日志位置
    9. stderr_logfile=/var/log/bluebell-stderr.log ;标准错误日志位置
    复制代码
    创建好配置文件之后,重启supervisor服务
    1. sudo supervisorctl update # 更新配置文件并重启相关的程序
    复制代码
    查看bluebell的运行状态:
    1. sudo supervisorctl status bluebell
    复制代码
    输出:
    bluebell RUNNING pid 10918, uptime 0:05:46
    最后补充一下常用的supervisr管理命令:
    1. supervisorctl status  # 查看所有任务状态
    2. supervisorctl shutdown  # 关闭所有任务
    3. supervisorctl start 程序名 # 启动任务
    4. supervisorctl stop 程序名 # 关闭任务
    5. supervisorctl reload  # 重启supervisor
    复制代码
    接下来就是打开浏览器查看网站是否正常了。
    搭配nginx部署

    在需要静态文件分离、需要配置多个域名及证书、需要自建负载均衡层等稍复杂的场景下,我们一般需要搭配第三方的web服务器(Nginx、Apache)来部署我们的程序。
    正向代理与反向代理
    正向代理可以简单理解为客户端的代理,你访问墙外的网站用的那个属于正向代理。
    部署Go语言项目的 N 种方法(小结)-2.png

    反向代理可以简单理解为服务器的代理,通常说的 Nginx 和 Apache 就属于反向代理。
    部署Go语言项目的 N 种方法(小结)-3.png

    Nginx 是一个免费的、开源的、高性能的 HTTP 和反向代理服务,主要负责负载一些访问量比较大的站点。Nginx 可以作为一个独立的 Web 服务,也可以用来给 Apache 或是其他的 Web 服务做反向代理。相比于 Apache,Nginx 可以处理更多的并发连接,而且每个连接的内存占用的非常小。
    使用yum安装nginx
    EPEL 仓库中有 Nginx 的安装包。如果你还没有安装过 EPEL,可以通过运行下面的命令来完成安装:
    1. sudo yum install epel-release
    复制代码
    安装nginx
    1. sudo yum install nginx
    复制代码
    安装完成后,执行下面的命令设置Nginx开机启动:
    1. sudo systemctl enable nginx
    复制代码
    启动Nginx
    1. sudo systemctl start nginx
    复制代码
    查看Nginx运行状态:
    1. sudo systemctl status nginx
    复制代码
    Nginx配置文件
    通过上面的方法安装的 nginx,所有相关的配置文件都在 /etc/nginx/ 目录中。Nginx 的主配置文件是 /etc/nginx/nginx.conf 。
    默认还有一个 nginx.conf.default 的配置文件示例,可以作为参考。你可以为多个服务创建不同的配置文件(建议为每个服务(域名)创建一个单独的配置文件),每一个独立的 Nginx 服务配置文件都必须以 .conf 结尾,并存储在 /etc/nginx/conf.d 目录中。
    Nginx常用命令
    补充几个 Nginx 常用命令。
    1. nginx -s stop # 停止 Nginx 服务
    2. nginx -s reload # 重新加载配置文件
    3. nginx -s quit # 平滑停止 Nginx 服务
    4. nginx -t   # 测试配置文件是否正确
    复制代码
    Nginx反向代理部署
    我们推荐使用 nginx 作为反向代理来部署我们的程序,按下面的内容修改 nginx 的配置文件。
    1. worker_processes 1;
    2. events {
    3. worker_connections 1024;
    4. }
    5. http {
    6. include  mime.types;
    7. default_type application/octet-stream;
    8. sendfile  on;
    9. keepalive_timeout 65;
    10. server {
    11.   listen  80;
    12.   server_name localhost;
    13.   access_log /var/log/bluebell-access.log;
    14.   error_log /var/log/bluebell-error.log;
    15.   location / {
    16.    proxy_pass     http://127.0.0.1:8084;
    17.    proxy_redirect    off;
    18.    proxy_set_header   Host    $host;
    19.    proxy_set_header   X-Real-IP  $remote_addr;
    20.    proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
    21.   }
    22. }
    23. }
    复制代码
    执行下面的命令检查配置文件语法:
    1. nginx -t
    复制代码
    执行下面的命令重新加载配置文件:
    1. nginx -s reload
    复制代码
    接下来就是打开浏览器查看网站是否正常了。
    当然我们还可以使用 nginx 的 upstream 配置来添加多个服务器地址实现负载均衡。
    1. worker_processes 1;
    2. events {
    3. worker_connections 1024;
    4. }
    5. http {
    6. include  mime.types;
    7. default_type application/octet-stream;
    8. sendfile  on;
    9. keepalive_timeout 65;
    10. upstream backend {
    11.   server 127.0.0.1:8084;
    12.   # 这里需要填真实可用的地址,默认轮询
    13.   #server backend1.example.com;
    14.   #server backend2.example.com;
    15. }
    16. server {
    17.   listen  80;
    18.   server_name localhost;
    19.   access_log /var/log/bluebell-access.log;
    20.   error_log /var/log/bluebell-error.log;
    21.   location / {
    22.    proxy_pass     http://backend/;
    23.    proxy_redirect    off;
    24.    proxy_set_header   Host    $host;
    25.    proxy_set_header   X-Real-IP  $remote_addr;
    26.    proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
    27.   }
    28. }
    29. }
    复制代码
    Nginx分离静态文件请求
    上面的配置是简单的使用 nginx 作为反向代理处理所有的请求并转发给我们的 Go 程序处理,其实我们还可以有选择的将静态文件部分的请求直接使用 nginx 处理,而将 API 接口类的动态处理请求转发给后端的 Go 程序来处理。
    部署Go语言项目的 N 种方法(小结)-4.png

    下面继续修改我们的 nginx 的配置文件来实现上述功能。
    1. worker_processes 1;
    2. events {
    3. worker_connections 1024;
    4. }
    5. http {
    6. include  mime.types;
    7. default_type application/octet-stream;
    8. sendfile  on;
    9. keepalive_timeout 65;
    10. server {
    11.   listen  80;
    12.   server_name bluebell;
    13.   access_log /var/log/bluebell-access.log;
    14.   error_log /var/log/bluebell-error.log;
    15.                 # 静态文件请求
    16.   location ~ .*\.(gif|jpg|jpeg|png|js|css|eot|ttf|woff|svg|otf)$ {
    17.    access_log off;
    18.    expires 1d;
    19.    root  /data/app/bluebell;
    20.   }
    21.   # index.html页面请求
    22.   # 因为是单页面应用这里使用 try_files 处理一下,避免刷新页面时出现404的问题
    23.   location / {
    24.    root /data/app/bluebell/templates;
    25.    index index.html;
    26.    try_files $uri $uri/ /index.html;
    27.   }
    28.                 # API请求
    29.   location /api {
    30.    proxy_pass     http://127.0.0.1:8084;
    31.    proxy_redirect    off;
    32.    proxy_set_header   Host    $host;
    33.    proxy_set_header   X-Real-IP  $remote_addr;
    34.    proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
    35.   }
    36. }
    37. }
    复制代码
    前后端分开部署
    前后端的代码没必要都部署到相同的服务器上,也可以分开部署到不同的服务器上,下图是前端服务将API请求转发至后端服务的方案。
    部署Go语言项目的 N 种方法(小结)-5.png

    上面的部署方案中,所有浏览器的请求都是直接访问前端服务,而如果是浏览器直接访问后端API服务的部署模式下,如下图。
    此时前端和后端通常不在同一个域下,我们还需要在后端代码中添加跨域支持。
    部署Go语言项目的 N 种方法(小结)-6.png

    这里使用 github.com/gin-contrib/cors 库来支持跨域请求。
    最简单的允许跨域的配置是使用 cors.Default() ,它默认允许所有跨域请求。
    1. func main() {
    2.         router := gin.Default()
    3.         // same as
    4.         // config := cors.DefaultConfig()
    5.         // config.AllowAllOrigins = true
    6.         // router.Use(cors.New(config))
    7.         router.Use(cors.Default())
    8.         router.Run()
    9. }
    复制代码
    此外,还可以使用 cors.Config 自定义具体的跨域请求相关配置项:
    1. package main
    2. import (
    3.         "time"
    4.         "github.com/gin-contrib/cors"
    5.         "github.com/gin-gonic/gin"
    6. )
    7. func main() {
    8.         router := gin.Default()
    9.         // CORS for https://foo.com and https://github.com origins, allowing:
    10.         // - PUT and PATCH methods
    11.         // - Origin header
    12.         // - Credentials share
    13.         // - Preflight requests cached for 12 hours
    14.         router.Use(cors.New(cors.Config{
    15.                 AllowOrigins:  []string{"https://foo.com"},
    16.                 AllowMethods:  []string{"PUT", "PATCH"},
    17.                 AllowHeaders:  []string{"Origin"},
    18.                 ExposeHeaders: []string{"Content-Length"},
    19.                 AllowCredentials: true,
    20.                 AllowOriginFunc: func(origin string) bool {
    21.                         return origin == "https://github.com"
    22.                 },
    23.                 MaxAge: 12 * time.Hour,
    24.         }))
    25.         router.Run()
    26. }
    复制代码
    容器部署

    容器部署方案可参照我之前的博客: 使用Docker和Docker Compose部署Go Web应用 ,这里就不再赘述了。
    到此这篇关于部署Go语言项目的 N 种方法(小结)的文章就介绍到这了,更多相关部署Go语言项目内容请搜索咔叽论坛以前的文章或继续浏览下面的相关文章希望大家以后多多支持咔叽论坛!

    原文地址:https://www.jb51.net/article/200778.htm
    回复

    使用道具 举报

    QQ|免责声明|手机版|咔叽网单

    GMT+8, 2021-3-3 03:50

    Powered by Discuz! X3.4

    Copyright © 2001-2020, Tencent Cloud.

    快速回复 返回顶部 返回列表