本文目錄一覽:
- 1、LiteIDE使用
- 2、Golang項目部署3,容器部署
- 3、Go 1.8使用Protocol Buffer
- 4、阿里雲 CentOS 7.6 yum 安裝 go(golang) 語言環境
- 5、Supervisor與Logrotate
- 6、WebSocket+SLB(負載均衡)會話保持解決重連問題
LiteIDE使用
LiteIDE是一款開源,跨平台的輕量級Go語言集成開發環境。操作簡單,提示迅速!當然不足之處也有很多,不過除了golad之外,個人覺得比vscode,eclipse等用的更舒心一點(ps:指的是編寫golang,每個人的感受不一樣,勿噴)
目前本人使用的LiteIDE版本號是:x36.1
其中讓我感受不是很好的兩個點是:1.沒有自動go lint檢測,需要手動。2.更改鍵盤映射不能捕獲按鍵的內容,需要自己粘貼複製比方說Ctrl+C之類的上去,如果不能接受這兩點需要考慮考慮。當然也有可能是我玩的不夠透徹,如果有人知道,請評論告知,感激不敬:)。
那麼,接下來就讓我們來學習一下LiteIDE這款國人開發的編輯器的簡單用法:
當我們使用一款IDE的時候,首先當然是配置一下環境,其次是快捷鍵,界面布局之類的了。所以,我們先來
1.配置環境:
LiteIDE給我們提供了多種的環境,目的是為了讓我們能將程序編譯成不同的系統所能執行的文件,例如我目前使用的是windows64系統,而且我的伺服器也是windows64,那我只需要選擇system的環境就可以,這樣在我執行編譯執行後,編譯器將會自動生成windows中可執行的.exe文件。
1.1配置管理GOPATH/Modules/GOPROXY
在我們項目是需要使用GOPATH或者是Modules的時候可以點擊旁邊的倒三角選項,on表示使用mod,off表示不使用,auto表示根據檢測,有的話使用。
底下的GOPROXY可以設置代理,畢竟我們大中華的牆不設置代理還是很給力得。設置代理得另外一種方法是點擊 工具-編輯當前環境,然後在裡面輸入代理,我一般用得是阿里雲得代理:GOPROXY=,編輯當前環境得作用其實就跟我們在命令行中輸入go env然後去設置是一個道理。
2.設置快捷鍵
點擊查看-選項-LiteApp中點擊鍵盤,然後就可以設置快捷鍵了,當然目前我這個版本需要粘貼複製進去
3.使用
3.1現在我們一般都是使用mod來管理,當然首先要設置GOPATH了。
將自己本地得GOPATH添加進去就可以了,如圖所示可以添加多個。
3.2編輯器自動生成go.mod文件
點擊M鍵,會彈出下拉菜單,選擇go module init將會自動生成mod文件
3.3獲取第三方包
可以使用M裡面得go mod tidy也可以使用G鍵裡面得Get按鈕
目前記起來得就這麼多,後續想起來後再添加。::)
Golang項目部署3,容器部署
容器部署即使用 docker 化部署 golang 應用程序,這是在雲服務時代最流行的部署方式,也是最推薦的部署方式。
跨平台交叉編譯是 golang 的特點之一,可以非常方便地編譯出我們需要的目標伺服器平台的版本,而且是靜態編譯,非常容易地解決了運行依賴問題。
使用以下指令可以靜態編譯 Linux 平台 amd64 架構的可執行文件:
生成的 main 便是我們靜態編譯的,可部署於 Linux amd64 上的可執行文件。
我們需要將該可執行文件 main 編譯生成 docker 鏡像,以便於分發及部署。 Golang 的運行環境推薦使用 alpine 基礎系統鏡像,編譯出的容器鏡像約為 20MB 左右。
一個參考的 Dockerfile 文件如下:
其中,我們的基礎鏡像使用了 loads/alpine:3.8 ,中國國內的用戶推薦使用該基礎鏡像,基礎鏡像的 Dockerfile 地址: ,倉庫地址:
隨後使用 ” docker build -t main . ” 指令編譯生成名為 main 的 docker 鏡像。
需要注意的是,在某些項目的架構設計中, 靜態文件 和 配置文件 可能不會隨著鏡像進行編譯發布,而是分開進行管理和發布。
例如,使用 MVVM 模式的項目中(例如使用 vue 框架),往往是前後端非常獨立的,因此在鏡像中往往並不會包含 public 目錄。而使用了 配置管理中心 (例如使用 consul / etcd / zookeeper )的項目中,也往往並不需要 config 目錄。
因此對於以上示例的 Dockerfile 的使用,僅作參考,根據實際情況請進行必要的調整。
使用以下指令可直接運行剛才編譯成的鏡像:
容器的分發可以使用 docker 官方的平台: ,國內也可以考慮使用阿里云: 。
在企業級生產環境中, docker 容器往往需要結合 kubernetes 或者 docker swarm 容器編排工具一起使用。
容器編排涉及到的內容比較多,感興趣的同學可以參考以下資料:
Go 1.8使用Protocol Buffer
最近在寫一個在線客服模塊,秉著簡單,可控,可維護,可擴展,滿足需求的原則,找了一個開源項目: 。
當然對於原始項目,肯定還是需要一些改動的,比如:鑒權,用戶體系,文件類型消息的處理(存在阿里雲OSS上)等等。
為了滿足需求,修改了原始的基於protocol buffer的message,修改後在重新生成對應的go文件時候,遇到了一些問題,可以參考以下解決方法。
github上的protobuf( )已經說明,需要使用: google.golang.org/protobuf 。
安裝官方文檔 安裝對應的插件模塊,mac需要在.zshrc文件添加以下內容:
以下是message proto文件:
執行以下命令生產對應的go文件:
阿里雲 CentOS 7.6 yum 安裝 go(golang) 語言環境
前言:記錄下安裝過程以便下次有需要無需百度!
輸入 yum search golang
Supervisor與Logrotate
在golang的gin項目中使用supervisor守護進程,用子進程配置將標準輸出日誌轉移到指定目錄下,然後使用阿里雲的日誌服務將標準輸出日誌轉移到線上做一些分析和預警。
項目上線之後一切正常,可是周日夜裡三點左右阿里雲的日誌服務採集不到日誌,一頓pv為0的告警過來,趕緊打開電腦,線上服務正常,鬆一口氣,supervisor狀態也正常,觀察了一會業務數據正常就安然入睡了,心想可能是因為配置項有缺陷吧,回頭好好整整supervisor的配置再觀察一波。
早上起來打開伺服器,cd /var/log/supervisor/,發現存在兩個日誌文件,分別是xxxx.log-20201223和xxxx.log,xxxx.log的大小為0,xxxx.log-20201223還在繼續寫入請求日誌,許可權問題?chmod 777之後發現新的文件還是不寫入日誌,重啟 supervisor之後發現日誌能正常寫入了。。。一開始懷疑是supervisor日誌切割備份有問題,將配置stdout日誌文件大小的stdout_logfile_maxbytes配置項,默認 50MB改成0,代表無限大,stdout日誌文件備份數的stdout_logfile_backups配置項,默認10改為0,代表不備份,重啟supervisor,心想不切割總不會再出現切割之後不往新文件寫內容的問題了,真乃明智之選。:)
一周過去,0pv的告警如期而至,雖然不影響線上業務,如鯁在喉讓我久久不能釋懷。全網翻,百度谷歌,中文英文,去github上翻issue等等,看到一個歷史issue1090,Better support for logrotate,感覺和日誌轉儲相關,於是查了下logrotate相關資料,logrotate程序是一個日誌文件管理工具。用於分割日誌文件,刪除舊的日誌文件,並創建新的日誌文件,起到「轉儲」作用。centos系統默認安裝,於是找到對應的配置文件,果不其然裡面就有supervisor,默認配置如下:
/var/log/supervisor/*.log {
missingok
weekly
notifempty
nocompress
},看到weekly感覺離這個問題的答案不遠了,於是去查找linux的logrotate往舊文件寫入的問題,在一篇logrotate writing to old app.log.1 instead of app.log的文章中找到需要配置參數copytruncate,是用於還在打開中的日誌文件,把當前日誌備份並截斷;是先拷貝再清空的方式,拷貝和清空之間有一個時間差,可能會丟失部分日誌數據。增加完配置之後,為了快速驗證結果,修改weekly為daily,第二天日誌正常切割了,新的文件也正常寫入了標準日誌。至此問題解決。
linux的logrotate對於運維來說可能是常識,作為開發剛接觸運維,只能慢慢積累了,工作之餘看看相關的運維知識,盡量少採坑。
WebSocket+SLB(負載均衡)會話保持解決重連問題
寫在最前面:由於現在遊戲基本上採用全球大區的模式,全球玩家在同一個大區進行遊戲,傳統的單服模式已經不能夠滿足當前的服務需求,所以現在遊戲伺服器都在往微服務架構發展。當前我們遊戲也是利用微服務架構來實現全球玩家同服遊戲。
玩家每次斷線(包括切換網路/超時斷線)後應該會重新連接伺服器,重連成功的話可以繼續當前情景繼續遊戲,但是之前寫的底層重連機制一直不能生效,導致每次玩家斷線後重連都失敗,要從賬號登陸開始重新登陸,該文章寫在已經定位了重連問題是由SLB引起後,提出的解決方案。
每次重連後,客戶端向SLB發送建立連接,SLB都會重新分配一個網關節點,導致客戶端連接到其他網關,重連失敗。
會話保持的作用是什麼?
開啟SLB會話保持功能後,SLB會記錄客戶端的IP地址,在一定時間內,自動將同一個IP的連接轉發到上次連接的網關。
在網路不穩定的情況下,遊戲容易心跳或者發包超時,開啟會話保持,能解決大部分情況下的重連問題。
但是在切換網路的時候,手機網路從Wifi切換成4G,自身IP會變,這時候連接必定和伺服器斷開,需要重新建立連接。由於IP已經變化,SLB不能識別到是同一個客戶端發出的請求,會將連接轉發到其他網關節點。所以使用TCP連接的情況下,SLB開啟會話保持並不能解決所有的重連問題。
另外某些時刻,手機頻繁開啟和斷開WI-FI,有時候可能不會斷開網路,這並不是因為4G切換WI-FI時網路沒斷開,從4G切換到Wi-Fi網路,因為IP變了,伺服器不能識別到新的IP,連接肯定是斷開的。這時候網路沒斷開,主要是因為現在智能手機會對4G和Wi-Fi網路做個權重判斷,當Wi-Fi網路頻繁打開關閉時,手機會判斷Wi-Fi網路不穩定,所有流量都走4G。所以網路沒斷開是因為一直使用4G連接,才沒有斷開。想要驗證,只需要切換Wi-Fi時,把4G網路關閉,這樣流量就必定走Wi-Fi。
上面說過,四層的TCP協議主要是基於IP來實現會話保持。但是切換網路的時候客戶端的IP會變。所以要解決切換網路時的重連問題,只有兩個方法:1. 當客戶端成功連接網關節點後,記錄下網關節點的IP,下次重連後不經過SLB,直接向網關節點發送連接請求。2.使用 SLB的七層(HTTP)轉發服務。
當客戶端經過SLB將連接轉發到網關時,二次握手驗證成功後向客戶端發送自己節點的IP,這樣客戶端下次連接的時候就能直接連接網關節點。但是這樣會暴露網關的IP地址,為安全留下隱患。
如果不希望暴露網關的IP地址,就需要增加一層代理層,SLB將客戶端請求轉發到代理層,代理層再根據客戶端帶有的key,轉發到正確的網關節點上。增加一層代理層,不僅會增加請求的響應時間,還會增加整體框架的複雜度。
阿里雲的七層SLB會話保持服務,主要是基於cookie的會話保持。客戶端在往伺服器發送HTTP請求後,伺服器會返回客戶端一個Response,SLB會在這時候,將經過的Response插入或者重寫cookie。客戶端獲取到這個cookie,下次請求時會帶上cookie,SLB判斷Request的Headers裡面有cookie,就將連接轉發到之前的網關節點。
HTTP是短鏈接,我們遊戲是長連接,所以用HTTP肯定不合適。但是可以考慮基於HTTP的WebSocket。
什麼是WebSocket?
WSS(Web Socket Secure)是WebSocket的加密版本。
SLB對WebSocket的支持
查看阿里雲SLB文檔對WS的支持,說明SLB是支持WS協議的,並且SLB對於WS無需配置,只需要選用HTTP監聽時,就能夠轉發WS協議。說明WS協議在SLB這邊看來就是一個HTTP,這樣WS走的也是七層的轉發服務。只要SLB能夠正常識別WS握手協議里Request的cookie和正常識別伺服器返回的Response並且往裡面插入cookie,就可以利用會話保持解決重連問題。
Go語言實現WS伺服器有兩種方法,一種是利用golang.org/x/net下的websocket包,另外一種方法就是自己解讀Websocket協議來實現,由於WS協議一樣是基於TCP協議之上,完全可以通過監聽TCP埠來實現。
客戶端發送Request消息
伺服器返回Response消息
其中伺服器返回的Sec-WebSocket-Accept欄位,主要是用於客戶端需要驗證伺服器是否支持WS。RFC6455文檔中規定,在WebSocket通信協議中服務端為了證實已經接收了握手,它需要把兩部分的數據合併成一個響應。一部分信息來自客戶端握手的Sec-WebSocket-Keyt頭欄位:Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==。對於這個欄位,服務端必須得到這個值(頭欄位中經過base64編碼的值減去前後的空格)並與GUID”258EAFA5-E914-47DA-95CA-C5AB0DC85B11″組合成一個字元串,這個字元串對於不懂WebSocket協議的網路終端來說是不能使用的。這個組合經過SHA-1掩碼,base64編碼後在服務端的握手中返回。如果這個Sec-WebSocket-Accept計算錯誤瀏覽器會提示:Sec-WebSocket-Accept dismatch
如果返回成功,Websocket就會回調onopen事件
遊戲伺服器的使用的TCP協議,是在協議的包頭使用4Byte來聲明本協議長度,然後將協議一次性發送。但是在WS協議是通過Frame形式發送的,會將一條消息分為幾個frame,按照先後順序傳輸出去。這樣做會有幾個好處:
websocket的協議格式:
參數說明如下:
阿里雲的SLB開啟HTTP監聽後,會檢查過往的Request和Response請求,收到伺服器返回的Response後,會往Response插入一個Cookie
客戶端收到伺服器的Response後,可以在Header中查到有個「Set-Cookie」欄位,裡面是SLB插入的Cookie值
客戶端斷開連接後,下次發送請求需要往Headers插入Cookie欄位
分別在阿里雲的兩台ECS實例上部署WS伺服器,打開8000埠,開啟一個SLB服務,SLB服務選擇HTTP方式監聽,並且打開會話保持功能,Cookie處理方式選擇植入Cookie。Demo伺服器沒有做HTTP健康監聽的處理,健康檢查這塊可以先關掉。
在兩台ECS上啟動WS伺服器,然後本地運行客戶端,分別測試兩台伺服器是否能正常連接,測試完畢後,測試SLB能否正常工作。伺服器和SLB都正常的情況下,運行客戶端,客戶端會得到以下結果
收到的三次Cookie都相同,說明Cookie是有正常植入工作的,並且三次都被SLB正確抓取了。
收到的三次serverId也都是同樣的值,說明三次都是同一個ECS上的伺服器響應。
至此,驗證成功。
Websocket+SLB會話保持能夠解決超時重連和切換網路時重連的問題。
參考:
阿里雲會話保持
解答Wi-Fi與4G網路切換的困惑
WebSocket的實現原理
阿里雲SLB對WebSocket的支持
HTTP Headers和Cookie
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/280905.html