本文以部署 Go Web 程序?yàn)槔?,介紹了在 CentOS7 服務(wù)器上部署 Go 語(yǔ)言程序的若干方法。
部署Go語(yǔ)言項(xiàng)目
本文以部署 Go Web 程序?yàn)槔?,介紹了在 CentOS7 服務(wù)器上部署 Go 語(yǔ)言程序的若干方法。
獨(dú)立部署
Go 語(yǔ)言支持跨平臺(tái)交叉編譯,也就是說(shuō)我們可以在 Windows 或 Mac 平臺(tái)下編寫代碼,并且將代碼編譯成能夠在 Linux amd64 服務(wù)器上運(yùn)行的程序。
對(duì)于簡(jiǎn)單的項(xiàng)目,通常我們只需要將編譯后的二進(jìn)制文件拷貝到服務(wù)器上,然后設(shè)置為后臺(tái)守護(hù)進(jìn)程運(yùn)行即可。
編譯
編譯可以通過(guò)以下命令或編寫 makefile 來(lái)操作。
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o ./bin/bluebell
下面假設(shè)我們將本地編譯好的 bluebell 二進(jìn)制文件、配置文件和靜態(tài)文件等上傳到服務(wù)器的/data/app/bluebell目錄下。
補(bǔ)充一點(diǎn),如果嫌棄編譯后的二進(jìn)制文件太大,可以在編譯的時(shí)候加上-ldflags "-s -w"參數(shù)去掉符號(hào)表和調(diào)試信息,一般能減小20%的大小。
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags "-s -w" -o ./bin/bluebell
如果還是嫌大的話可以繼續(xù)使用 upx 工具對(duì)二進(jìn)制可執(zhí)行文件進(jìn)行壓縮。
我們編譯好 bluebell 項(xiàng)目后,相關(guān)必要文件的目錄結(jié)構(gòu)如下:
├── bin
│ └── bluebell
├── conf
│ └── config.yaml
├── 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 用于在系統(tǒng)后臺(tái) 不掛斷 地運(yùn)行命令,不掛斷指的是退出執(zhí)行命令的終端也不會(huì)影響程序的運(yùn)行。
我們可以使用 nohup 命令來(lái)運(yùn)行應(yīng)用程序,使其作為后臺(tái)守護(hù)進(jìn)程運(yùn)行。由于在主流的 Linux 發(fā)行版中都會(huì)默認(rèn)安裝 nohup 命令工具,我們可以直接輸入以下命令來(lái)啟動(dòng)我們的項(xiàng)目:
sudo nohup ./bin/bluebell conf/config.yaml > nohup_bluebell.log 2>1
其中:
- ./bluebell conf/config.yaml是我們應(yīng)用程序的啟動(dòng)命令
- nohup ... 表示在后臺(tái)不掛斷的執(zhí)行上述應(yīng)用程序的啟動(dòng)命令
- > nohup_bluebell.log表示將命令的標(biāo)準(zhǔn)輸出重定向到 nohup_bluebell.log 文件
- 2>1表示將標(biāo)準(zhǔn)錯(cuò)誤輸出也重定向到標(biāo)準(zhǔn)輸出中,結(jié)合上一條就是把執(zhí)行命令的輸出都定向到 nohup_bluebell.log 文件
上面的命令執(zhí)行后會(huì)返回進(jìn)程 id
當(dāng)然我們也可以通過(guò)以下命令查看 bluebell 相關(guān)活動(dòng)進(jìn)程:
輸出:
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
此時(shí)就可以打開瀏覽器輸入 http://服務(wù)器公網(wǎng)ip:端口
查看應(yīng)用程序的展示效果了。
supervisor
Supervisor 是業(yè)界流行的一個(gè)通用的進(jìn)程管理程序,它能將一個(gè)普通的命令行進(jìn)程變?yōu)楹笈_(tái)守護(hù)進(jìn)程,并監(jiān)控該進(jìn)程的運(yùn)行狀態(tài),當(dāng)該進(jìn)程異常退出時(shí)能將其自動(dòng)重啟。
首先使用 yum 來(lái)安裝 supervisor:
如果你還沒(méi)有安裝過(guò) EPEL,可以通過(guò)運(yùn)行下面的命令來(lái)完成安裝,如果已安裝則跳過(guò)此步驟:
sudo yum install epel-release
安裝 supervisor
sudo yum install supervisor
Supervisor 的配置文件為: /etc/supervisord.conf
,Supervisor 所管理的應(yīng)用的配置文件放在 /etc/supervisord.d/
目錄中,這個(gè)目錄可以在 supervisord.conf 中的 include
配置。
[include]
files = /etc/supervisord.d/*.conf
啟動(dòng)supervisor服務(wù):
sudo supervisord -c /etc/supervisord.conf
我們?cè)?/etc/supervisord.d
目錄下創(chuàng)建一個(gè)名為 bluebell.conf
的配置文件,具體內(nèi)容如下。
[program:bluebell] ;程序名稱
user=root ;執(zhí)行程序的用戶
command=/data/app/bluebell/bin/bluebell /data/app/bluebell/conf/config.yaml ;執(zhí)行的命令
directory=/data/app/bluebell/ ;命令執(zhí)行的目錄
stopsignal=TERM ;重啟時(shí)發(fā)送的信號(hào)
autostart=true
autorestart=true ;是否自動(dòng)重啟
stdout_logfile=/var/log/bluebell-stdout.log ;標(biāo)準(zhǔn)輸出日志位置
stderr_logfile=/var/log/bluebell-stderr.log ;標(biāo)準(zhǔn)錯(cuò)誤日志位置
創(chuàng)建好配置文件之后,重啟supervisor服務(wù)
sudo supervisorctl update # 更新配置文件并重啟相關(guān)的程序
查看bluebell的運(yùn)行狀態(tài):
sudo supervisorctl status bluebell
輸出:
bluebell RUNNING pid 10918, uptime 0:05:46
最后補(bǔ)充一下常用的supervisr管理命令:
supervisorctl status # 查看所有任務(wù)狀態(tài)
supervisorctl shutdown # 關(guān)閉所有任務(wù)
supervisorctl start 程序名 # 啟動(dòng)任務(wù)
supervisorctl stop 程序名 # 關(guān)閉任務(wù)
supervisorctl reload # 重啟supervisor
接下來(lái)就是打開瀏覽器查看網(wǎng)站是否正常了。
搭配nginx部署
在需要靜態(tài)文件分離、需要配置多個(gè)域名及證書、需要自建負(fù)載均衡層等稍復(fù)雜的場(chǎng)景下,我們一般需要搭配第三方的web服務(wù)器(Nginx、Apache)來(lái)部署我們的程序。
正向代理與反向代理
正向代理可以簡(jiǎn)單理解為客戶端的代理,你訪問(wèn)墻外的網(wǎng)站用的那個(gè)屬于正向代理。
反向代理可以簡(jiǎn)單理解為服務(wù)器的代理,通常說(shuō)的 Nginx 和 Apache 就屬于反向代理。
Nginx 是一個(gè)免費(fèi)的、開源的、高性能的 HTTP 和反向代理服務(wù),主要負(fù)責(zé)負(fù)載一些訪問(wèn)量比較大的站點(diǎn)。Nginx 可以作為一個(gè)獨(dú)立的 Web 服務(wù),也可以用來(lái)給 Apache 或是其他的 Web 服務(wù)做反向代理。相比于 Apache,Nginx 可以處理更多的并發(fā)連接,而且每個(gè)連接的內(nèi)存占用的非常小。
使用yum安裝nginx
EPEL 倉(cāng)庫(kù)中有 Nginx 的安裝包。如果你還沒(méi)有安裝過(guò) EPEL,可以通過(guò)運(yùn)行下面的命令來(lái)完成安裝:
sudo yum install epel-release
安裝nginx
安裝完成后,執(zhí)行下面的命令設(shè)置Nginx開機(jī)啟動(dòng):
sudo systemctl enable nginx
啟動(dòng)Nginx
sudo systemctl start nginx
查看Nginx運(yùn)行狀態(tài):
sudo systemctl status nginx
Nginx配置文件
通過(guò)上面的方法安裝的 nginx,所有相關(guān)的配置文件都在 /etc/nginx/
目錄中。Nginx 的主配置文件是 /etc/nginx/nginx.conf
。
默認(rèn)還有一個(gè) nginx.conf.default
的配置文件示例,可以作為參考。你可以為多個(gè)服務(wù)創(chuàng)建不同的配置文件(建議為每個(gè)服務(wù)(域名)創(chuàng)建一個(gè)單獨(dú)的配置文件),每一個(gè)獨(dú)立的 Nginx 服務(wù)配置文件都必須以 .conf
結(jié)尾,并存儲(chǔ)在 /etc/nginx/conf.d
目錄中。
Nginx常用命令
補(bǔ)充幾個(gè) Nginx 常用命令。
nginx -s stop # 停止 Nginx 服務(wù)
nginx -s reload # 重新加載配置文件
nginx -s quit # 平滑停止 Nginx 服務(wù)
nginx -t # 測(cè)試配置文件是否正確
Nginx反向代理部署
我們推薦使用 nginx 作為反向代理來(lái)部署我們的程序,按下面的內(nèi)容修改 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;
}
}
}
執(zhí)行下面的命令檢查配置文件語(yǔ)法:
執(zhí)行下面的命令重新加載配置文件:
接下來(lái)就是打開瀏覽器查看網(wǎng)站是否正常了。
當(dāng)然我們還可以使用 nginx 的 upstream 配置來(lái)添加多個(gè)服務(wù)器地址實(shí)現(xiàn)負(fù)載均衡。
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;
# 這里需要填真實(shí)可用的地址,默認(rèn)輪詢
#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分離靜態(tài)文件請(qǐng)求
上面的配置是簡(jiǎn)單的使用 nginx 作為反向代理處理所有的請(qǐng)求并轉(zhuǎn)發(fā)給我們的 Go 程序處理,其實(shí)我們還可以有選擇的將靜態(tài)文件部分的請(qǐng)求直接使用 nginx 處理,而將 API 接口類的動(dòng)態(tài)處理請(qǐng)求轉(zhuǎn)發(fā)給后端的 Go 程序來(lái)處理。
下面繼續(xù)修改我們的 nginx 的配置文件來(lái)實(shí)現(xiàn)上述功能。
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;
# 靜態(tài)文件請(qǐng)求
location ~ .*\.(gif|jpg|jpeg|png|js|css|eot|ttf|woff|svg|otf)$ {
access_log off;
expires 1d;
root /data/app/bluebell;
}
# index.html頁(yè)面請(qǐng)求
# 因?yàn)槭菃雾?yè)面應(yīng)用這里使用 try_files 處理一下,避免刷新頁(yè)面時(shí)出現(xiàn)404的問(wèn)題
location / {
root /data/app/bluebell/templates;
index index.html;
try_files $uri $uri/ /index.html;
}
# API請(qǐng)求
location /api {
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;
}
}
}
前后端分開部署
前后端的代碼沒(méi)必要都部署到相同的服務(wù)器上,也可以分開部署到不同的服務(wù)器上,下圖是前端服務(wù)將API請(qǐng)求轉(zhuǎn)發(fā)至后端服務(wù)的方案。
上面的部署方案中,所有瀏覽器的請(qǐng)求都是直接訪問(wèn)前端服務(wù),而如果是瀏覽器直接訪問(wèn)后端API服務(wù)的部署模式下,如下圖。
此時(shí)前端和后端通常不在同一個(gè)域下,我們還需要在后端代碼中添加跨域支持。
這里使用 github.com/gin-contrib/cors 庫(kù)來(lái)支持跨域請(qǐng)求。
最簡(jiǎn)單的允許跨域的配置是使用 cors.Default()
,它默認(rèn)允許所有跨域請(qǐng)求。
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
自定義具體的跨域請(qǐng)求相關(guān)配置項(xiàng):
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應(yīng)用 ,這里就不再贅述了。
到此這篇關(guān)于部署Go語(yǔ)言項(xiàng)目的 N 種方法(小結(jié))的文章就介紹到這了,更多相關(guān)部署Go語(yǔ)言項(xiàng)目?jī)?nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
您可能感興趣的文章:- golang項(xiàng)目如何上線部署到Linu服務(wù)器(方法詳解)
- 利用systemd部署golang項(xiàng)目的實(shí)現(xiàn)方法
- 利用rpm打包上線部署golang代碼的方法教程
- 使用docker構(gòu)建golang線上部署環(huán)境的步驟詳解
- docker中部署golang項(xiàng)目的步驟詳解