獨立部署
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%的大小。
立即學習“go語言免費學習筆記(深入)”;
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:端口查看應用程序的展示效果了。
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?#?更新配置文件并重啟相關的程序 sudo?supervisorctl?status?bluebell?#?查看bluebell的運行狀態: sudo?supervisorctl?restart?bluebell?#?重啟 sudo?supervisorctl?start?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 服務做反向代理。Nginx相對于Apache具有更高的并發連接處理能力,并且每個連接的內存占用也很小。
使用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?{?#?server組 ????????listen???????80;??#?nginx監聽端口 ????????server_name??localhost;??#?服務的域名 ????????access_log???/var/log/bluebell-access.log;??#?訪問日志 ????????error_log????/var/log/bluebell-error.log;??#?錯誤日志 ????????location?/?{?#?訪問?/?根下的所有路徑,反向代理從80轉到8084 ????????????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反向代理部署,有負載均衡
當然我們還可以使用 nginx 的 upstream 配置來添加多個服務器地址實現負載均衡。
worker_processes??1;??#?工作進程 events?{ ????worker_connections??1024;??#?連接數 } http?{ ????include???????mime.types;??#?默認配置 ????default_type??application/octet-stream;??#?默認配置 ????sendfile????????on; ????keepalive_timeout??65;??#?超時時間 #?負載均衡backend為組名 upstream?backend?{ ??????server?127.0.0.1:8084; ??????#?這里需要填真實可用的地址,默認輪詢 ??????#server?backend1.example.com; ??????#server?backend2.example.com; ????} ????server?{?#?server組 ????????listen???????80;??#?nginx監聽端口 ????????server_name??localhost;??#?服務的域名 ????????access_log???/var/log/bluebell-access.log;??#?訪問日志 ????????error_log????/var/log/bluebell-error.log;??#?錯誤日志 ????????location?/?{?#?訪問?/?根下的所有路徑,反向代理從80轉到8084 ????????????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 的配置文件來實現上述功能。
指定靜態文件所在路徑,防止前端拼接的接口,后端沒有。刷新后404情況
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;??#?指定靜態文件所在路徑,防止前端拼接的接口,后端沒有。刷新后404情況 ????????} ????????#?index.html頁面請求 ????????#?因為是單頁面應用這里使用?try_files?處理一下,避免刷新頁面時出現404的問題 ????????location?/?{ ????????????root?/data/app/bluebell/templates;??#?指定index.html前端文件所在路徑 ????????????index?index.html; ????????????try_files?$uri?$uri/?/index.html;??#?所有的請求最后指向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 請求轉發至后端服務的方案。
上面的部署方案中,所有瀏覽器的請求都是直接訪問前端服務,而如果是瀏覽器直接訪問后端API服務的部署模式下,如下圖。
此時前端和后端通常不在同一個域下,我們還需要在后端代碼中添加跨域支持。
這里使用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() }
以上就是golang項目搭配