部署Go语言程序的N种方式
部署Go语言项目
本文以部署 Go Web 程序为例,介绍了在 CentOS7 服务器上部署 Go 语言程序的若干方法。
独立部署
Go 语言支持跨平台交叉编译,也就是说我们可以在 Windows 或 Mac 平台下编写代码,并且将代码编译成能够在 Linux amd64 服务器上运行的程序。
对于简单的项目,通常我们只需要将编译后的二进制文件拷贝到服务器上,然后设置为后台守护进程运行即可。
编译
编译可以通过以下命令或编写 makefile 来操作。
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o ./bin/bluebell
下面假设我们将本地编译好的 bluebell 程序、配置文件个静态文件等上传到服务器的/data/app/bluebell
目录下。
补充一点,如果嫌弃编译后的二进制文件太大,可以在编译的时候加上-ldflags "-s -w"
参数去掉符号表和调试信息,一般能减小20%的大小。
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags "-s -w" -o ./bin/bluebell
如果还是嫌大的话可以继续使用 upx 工具对二进制可执行文件进行压缩。
我们编译好 bluebell 项目后,相关必要文件的目录结构如下:
├── bin
│ └── bluebell
├── conf
│ └── config.yaml
├── static
│ └── static
│ ├── css
│ │ └── app.0afe9dae.css
│ ├── favicon.ico
│ ├── img
│ │ ├── avatar.7b0a9835.png
│ │ ├── iconfont.cdbe38a0.svg
│ │ ├── logo.da56125f.png
│ │ └── search.8e85063d.png
│ └── js
│ ├── app.9f3efa6d.js
│ ├── app.9f3efa6d.js.map
│ ├── chunk-vendors.57f9e9d6.js
│ └── chunk-vendors.57f9e9d6.js.map
└── templates
└── index.html
nohup
nohup 用于在系统后台不挂断地运行命令,不挂断指的是退出执行命令的终端也不会影响程序的运行。
我们可以使用 nohup 命令来运行应用程序,使其作为后台守护进程运行。由于在主流的 Linux 发行版中都会默认安装 nohup 命令工具,我们可以直接输入以下命令来启动我们的项目:
sudo nohup ./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] 6338
当然我们也可以通过以下命令查看 bluebell 相关活动进程:
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:端口
查看应用程序的展示效果了。
bluebell效果
supervisor
Supervisor 是业界流行的一个通用的进程管理程序,它能将一个普通的命令行进程变为后台守护进程,并监控该进程的运行状态,当该进程异常退出时能将其自动重启。
首先使用 yum 来安装 supervisor:
如果你还没有安装过 EPEL,可以通过运行下面的命令来完成安装,如果已安装则跳过此步骤:
sudo yum install epel-release
安装 supervisor
sudo yum install supervisor
Supervisor 的配置文件为:/etc/supervisord.conf
,Supervisor 所管理的应用的配置文件放在 /etc/supervisord.d/
目录中,这个目录可以在 supervisord.conf 中的include
配置。
[include]
files = /etc/supervisord.d/*.conf
启动supervisor服务:
sudo supervisord -c /etc/supervisord.conf
我们在/etc/supervisord.d
目录下创建一个名为bluebell.conf
的配置文件,具体内容如下。
[program:bluebell] ;程序名称
user=root ;执行程序的用户
command=/data/app/bluebell/bin/bluebell /data/app/bluebell/conf/config.yaml ;执行的命令
directory=/data/app/bluebell/ ;命令执行的目录
stopsignal=TERM ;重启时发送的信号
autostart=true
autorestart=true ;是否自动重启
stdout_logfile=/var/log/bluebell-stdout.log ;标准输出日志位置
stderr_logfile=/var/log/bluebell-stderr.log ;标准错误日志位置
创建好配置文件之后,重启supervisor服务
sudo supervisorctl update # 更新配置文件并重启相关的程序
查看bluebell的运行状态:
sudo supervisorctl status bluebell
输出:
bluebell RUNNING pid 10918, uptime 0:05:46
最后补充一下常用的supervisr管理命令:
supervisorctl status # 查看所有任务状态
supervisorctl shutdown # 关闭所有任务
supervisorctl start 程序名 # 启动任务
supervisorctl stop 程序名 # 关闭任务
supervisorctl reload # 重启supervisor
接下来就是打开浏览器查看网站是否正常了。
搭配nginx部署
在需要静态文件分离、需要配置多个域名及证书、需要自建负载均衡层等稍复杂的场景下,我们一般需要搭配第三方的web服务器(Nginx、Apache)来部署我们的程序。
正向代理与反向代理
正向代理可以简单理解为客户端的代理,你访问墙外的网站用的那个属于正向代理。
正向代理
反向代理可以简单理解为服务器的代理,通常说的 Nginx 和 Apache 就属于反向代理。
反向代理
Nginx 是一个免费的、开源的、高性能的 HTTP 和反向代理服务,主要负责负载一些访问量比较大的站点。Nginx 可以作为一个独立的 Web 服务,也可以用来给 Apache 或是其他的 Web 服务做反向代理。相比于 Apache,Nginx 可以处理更多的并发连接,而且每个连接的内存占用的非常小。
使用yum安装nginx
EPEL 仓库中有 Nginx 的安装包。如果你还没有安装过 EPEL,可以通过运行下面的命令来完成安装:
sudo yum install epel-release
安装nginx
sudo yum install nginx
安装完成后,执行下面的命令设置Nginx开机启动:
sudo systemctl enable nginx
启动Nginx
sudo systemctl start nginx
查看Nginx运行状态:
sudo systemctl status nginx
Nginx配置文件
通过上面的方法安装的 nginx,所有相关的配置文件都在 /etc/nginx/
目录中。Nginx 的主配置文件是 /etc/nginx/nginx.conf
。
默认还有一个nginx.conf.default
的配置文件示例,可以作为参考。你可以为多个服务创建不同的配置文件(建议为每个服务(域名)创建一个单独的配置文件),每一个独立的 Nginx 服务配置文件都必须以 .conf
结尾,并存储在 /etc/nginx/conf.d
目录中。
Nginx常用命令
补充几个 Nginx 常用命令。
nginx -s stop # 停止 Nginx 服务
nginx -s reload # 重新加载配置文件
nginx -s quit # 平滑停止 Nginx 服务
nginx -t # 测试配置文件是否正确
Nginx反向代理部署
我们推荐使用 nginx 作为反向代理来部署我们的程序,按下面的内容修改 nginx 的配置文件。
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
server_name localhost;
access_log /var/log/bluebell-access.log;
error_log /var/log/bluebell-error.log;
location / {
proxy_pass http://127.0.0.1:8084;
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 -t
执行下面的命令重新加载配置文件:
nginx -s reload
接下来就是打开浏览器查看网站是否正常了。
当然我们还可以使用 nginx 的 upstream 配置来添加多个服务器地址实现负载均衡。
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
upstream backend {
server 127.0.0.1:8084;
# 这里需要填真实可用的地址,默认轮询
#server backend1.example.com;
#server backend2.example.com;
}
server {
listen 80;
server_name localhost;
access_log /var/log/bluebell-access.log;
error_log /var/log/bluebell-error.log;
location / {
proxy_pass http://backend/;
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分离静态文件请求
上面的配置是简单的使用 nginx 作为反向代理处理所有的请求并转发给我们的 Go 程序处理,其实我们还可以有选择的将静态文件部分的请求直接使用 nginx 处理,而将 API 接口类的动态处理请求转发给后端的 Go 程序来处理。
分离静态文件请求图示
下面继续修改我们的 nginx 的配置文件来实现上述功能。
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
server_name bluebell;
access_log /var/log/bluebell-access.log;
error_log /var/log/bluebell-error.log;
# 静态文件请求
location ~ .*\.(gif|jpg|jpeg|png|js|css|eot|ttf|woff|svg|otf)$ {
access_log off;
expires 1d;
root /data/app/bluebell/static;
}
# index.html页面请求
# 因为是单页面应用这里使用 try_files 处理一下,避免刷新页面时出现404的问题
location / {
root /data/app/bluebell/templates;
index index.html;
try_files $uri $uri/ /index.html;
}
# API请求
location /api/v1 {
proxy_pass http://127.0.0.1:8084;
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;
}
}
}
前后端分开部署
前后端的代码没必要都部署到相同的服务器上,也可以分开部署到不同的服务器上,下图是前端服务将API请求转发至后端服务的方案。
前后端分开部署方案1
上面的部署方案中,所有浏览器的请求都是直接访问前端服务,而如果是浏览器直接访问后端API服务的部署模式下,如下图。
此时前端和后端通常不在同一个域下,我们还需要在后端代码中添加跨域支持。
前后端分开部署方案2
这里使用github.com/gin-contrib/cors库来支持跨域请求。
最简单的允许跨域的配置是使用cors.Default()
,它默认允许所有跨域请求。
func main() {
router := gin.Default()
// same as
// config := cors.DefaultConfig()
// config.AllowAllOrigins = true
// router.Use(cors.New(config))
router.Use(cors.Default())
router.Run()
}
此外,还可以使用cors.Config
自定义具体的跨域请求相关配置项:
package main
import (
"time"
"github.com/gin-contrib/cors"
"github.com/gin-gonic/gin"
)
func main() {
router := gin.Default()
// CORS for https://foo.com and https://github.com origins, allowing:
// - PUT and PATCH methods
// - Origin header
// - Credentials share
// - Preflight requests cached for 12 hours
router.Use(cors.New(cors.Config{
AllowOrigins: []string{"https://foo.com"},
AllowMethods: []string{"PUT", "PATCH"},
AllowHeaders: []string{"Origin"},
ExposeHeaders: []string{"Content-Length"},
AllowCredentials: true,
AllowOriginFunc: func(origin string) bool {
return origin == "https://github.com"
},
MaxAge: 12 * time.Hour,
}))
router.Run()
}
容器部署
容器部署方案可参照我之前的博客:使用Docker和Docker Compose部署Go Web应用,这里就不再赘述了。
关于 bluebell
上文提及的 bluebell 项目是我个人录制的 Go Web开发进阶项目实战课程中的项目,目前该课程已经录制完成,共计80课时。想要了解该课程的同学欢迎猛戳以下链接:
或者可以关注我的个人微信公众号:李文周
,回复bluebell
获取相关课程链接。
本文首发于我的个人博客:liwenzhou.com,点击链接查看完整Go语言教程。
部署Go语言程序的N种方式的更多相关文章
- 执行Go程序的三种方式及Go语言关键字
执行 Go 程序的三种方式及 Go 语言关键字 执行 Go 程序的三种方式 一.使用 go run 命令 二.使用 go build 命令 Step1. 对 go 源码源文件执行 go build 命 ...
- 操作系统+编程语言的分类+执行python程序的两种方式+变量
1.什么是操作系统? 操作系统就是一个协调\管理\控制计算机硬件资源与软件资源的一个控制程序. 2.为何要操作系统? a.把复杂的硬件操作封装成简单的功能\接口用来给用户或者程序来使用(文件) b.把 ...
- 周一02.3运行python程序的两种方式
一.运行python程序的两种方式 方法一:交互式: 优点:输入一行代码立刻返回结果 缺点:无法永久保存代码 方法二: ...
- PythonDay02——编程语言、python介绍以及安装解释器、运行程序的两种方式、变量
一.编程语言 1.1 机器语言:直接用计算机能理解的二进制指令编写程序,直接控制硬件 1.2 汇编语言:用英文标签取代二进制指令去编写程序,本质也是直接控制硬件 1.3 高级语言:用人能理解的表达方式 ...
- day2 编程语言介绍、Python运行程序的两种方式、变量
一 编程语言介绍 1. 机器语言 用计算机能理解的二进制指令直接编写程序,直接控制硬件 2. 汇编语言 用英文标签取代二进制指令编写程序,本质也是直接控制硬件 3. 高级语言 用人能理解的表达方式去编 ...
- day05-1 执行Python程序的两种方式
目录 执行Python程序的两种方式 第一种:交互式 第二种:命令行式 三个步骤 两种方式的区别 执行Python程序的两种方式 第一种:交互式 在cmd中运行 优点:直接给出结果,执行效率高,及时报 ...
- Ubuntu系统---编译opencv程序的几种方式g++、Makefile、Cmake
Ubuntu系统---编译opencv程序的几种方式g++.Makefile.Cmake 先建立一个工程(一个文件夹),写好xxx.cpp文件,可以是多个: //----------opencv.cp ...
- Thread类的常用方法_sleep和创建多线程程序的第二种方式_实现Runnable接口
sleep方法是在Thread类中的一个静态方法,当一个线程调用了sleep方法,被调用的那个线程就会暂时的让出指定时间的CPU执行权,在这段时间也不会参与CPU的调度,当时间到了之后,就会重新回到就 ...
- 创建多线程程序的第一种方式_创建Thread类的子类
创建多线程程序的第一种方式:创建Thread类的子类java.lang.Thread类:是描述线程的类,我们想要实现多线程程序,就必须继承Thread类 实现步骤: 1.创建一个Thread类的子类 ...
随机推荐
- 一个@Transaction哪里来这么多坑?
前言 在之前的文章中已经对Spring中的事务做了详细的分析了,这篇文章我们来聊一聊平常工作时使用事务可能出现的一些问题(本文主要针对使用@Transactional进行事务管理的方式进行讨论)以及对 ...
- SSM框架整合练习——一个简单的文章管理系统
使用SSM框架搭建的简易文章管理系统,实现了简单的增删改查功能. @ 目录 开发工具版本: 最终的项目结构 IDEA+Maven搭建项目骨架 1. 新建Maven项目: 2. 在新建的项目中添加所需要 ...
- Mysql Lost connection to MySQL server at ‘reading initial communication packet', system error: 0
在用Navicat for MySQL远程连接mysql的时候,出现了 Lost connection to MySQL server at ‘reading initial communicatio ...
- vant官网无法打开,这里教你解决
是否大家和我一样,vant-weapp官网突然打不开了 像这样: 但我发现在码云上有一个国内的版本 https://vant-contrib.gitee.io/vant/#/zh-CN/home, ...
- AltiumDesigner20画图不求人10 | 提高AD20启动速度的方法六取消加入产品改善计划 | 视频教程 | 你问我答
教程内容:AltiumDesigner20画图不求人系列,是电子芯原创的AltiumDesigner绘图技巧视频教程,每一个技巧只需要不到3分钟的时间就可以完成学习.前期经过AD19的画图不求人,帮助 ...
- 团队作业3:需求改进&系统设计
一.需求&原型改进: 1.1 选题需求改进 用户:同学你好,有什么事我们能帮到你 我:我要说的事……(咽口水)你们千万别害怕 用户:我们是杠精,我们不会怕,您请说 我:我们要做一个roguel ...
- 使用tess4j完成身份证和营业执照图片的文字识别
这两天研究了一下关于OCR图文解析的技术.当然市场上已经有开源服务,比如百度的AI开放平台,就有OCR相关的API接口.我这里选用的是Tesseract开源框架,java封装版本是tess4j.结合网 ...
- SpringBoot(19)---SpringBoot整合Apollo
SpringBoot(19)---SpringBoot整合Apollo 有关Apollo之前已经写了两篇文章: 1.[Apollo](1)--- Apollo入门介绍篇 2.[Apollo](2)-- ...
- C语言基础练习——打印乘法口诀表
C语言基础练习--打印乘法口诀表 JERRY_Z. ~ 2020 / 8 / 26 转载请注明出处! 代码: /* * @Author: JERRY_Z. * @Date: 2020-08-26 16 ...
- lynx浏览器使用教程
http://www.wocaoseo.com/thread-216-1-1.html LYNX浏览器是谷歌官方推荐的一款文本浏览器,主要用来模拟蜘蛛看到您页面时候的样子,谷歌在网站站长指南中提到: ...