Golang - 部署Go語言項目的多種方法


部署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
│   ├── 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 ./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] 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; } # index.html頁面請求 # 因為是單頁面應用這里使用 try_files 處理一下,避免刷新頁面時出現404的問題 location / { root /data/app/bluebell/templates; index index.html; try_files $uri $uri/ /index.html; } # API請求 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; } } } 

前后端分開部署

前后端的代碼沒必要都部署到相同的服務器上,也可以分開部署到不同的服務器上,下圖是前端服務將 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 是項目名稱。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM