高級!能用上go語言了嗎?不會是Android Studio吧?!
創新互聯建站專注于賽罕網站建設服務及定制,我們擁有豐富的企業做網站經驗。 熱誠為您提供賽罕營銷型網站建設,賽罕網站制作、賽罕網頁設計、賽罕網站官網定制、重慶小程序開發公司服務,打造賽罕網絡公司原創品牌,更為您提供賽罕網站排名全網營銷落地服務。
如果是Apk是連不上SQL的,訪問WebService,手機做SQL服務一般用WEB,不用WAP,手機可以直接訪問WEB,無論什么編寫的,如果是特殊需要,那就用WebService去返回查詢結果
寫在最前面:由于現在游戲基本上采用全球大區的模式,全球玩家在同一個大區進行游戲,傳統的單服模式已經不能夠滿足當前的服務需求,所以現在游戲服務器都在往微服務架構發展。當前我們游戲也是利用微服務架構來實現全球玩家同服游戲。
玩家每次斷線(包括切換網絡/超時斷線)后應該會重新連接服務器,重連成功的話可以繼續當前情景繼續游戲,但是之前寫的底層重連機制一直不能生效,導致每次玩家斷線后重連都失敗,要從賬號登陸開始重新登陸,該文章寫在已經定位了重連問題是由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
安裝:
go get -v -u github.com/rocket049/connpool
go get -v -u gitee.com/rocket049/connpool
rocket049/connpool 包是本人用go語言開發的,提供一個通用的TCP連接池,初始化參數包括最高連接數、超時秒數、連接函數,放回連接池的連接被重新取出時,如果已經超時,將會自動重新連接;如果沒有超時,連接將被復用。
可調用的函數:
調用示例:
前段時間在golang-China讀到這個貼:
個人覺得golang十分適合進行網游服務器端開發,寫下這篇文章總結一下。
從網游的角度看:
要成功的運營一款網游,很大程度上依賴于玩家自發形成的社區。只有玩家自發形成一個穩定的生態系統,游戲才能持續下去,避免鬼城的出現。而這就需要多次大量導入用戶,在同時在線用戶量達到某個臨界點的時候,才有可能完成。因此,多人同時在線十分有必要。
再來看網游的常見玩法,除了排行榜這類統計和數據匯總的功能外,基本沒有需要大量CPU時間的應用。以前的項目里,即時戰斗產生的各種傷害計算對CPU的消耗也不大。玩家要完成一次操作,需要通過客戶端-服務器端-客戶端這樣一個來回,為了獲得高響應速度,滿足玩家體驗,服務器端的處理也不能占用太多時間。所以,每次請求對應的CPU占用是比較小的。
網游的IO主要分兩個方面,一個是網絡IO,一個是磁盤IO。網絡IO方面,可以分成美術資源的IO和游戲邏輯指令的IO,這里主要分析游戲邏輯的IO。游戲邏輯的IO跟CPU占用的情況相似,每次請求的字節數很小,但由于多人同時在線,因此并發數相當高。另外,地圖信息的廣播也會帶來比較頻繁的網絡通信。磁盤IO方面,主要是游戲數據的保存。采用不同的數據庫,會有比較大的區別。以前的項目里,就經歷了從MySQL轉向MongoDB這種內存數據庫的過程,磁盤IO不再是瓶頸。總體來說,還是用內存做一級緩沖,避免大量小數據塊讀寫的方案。
針對網游的這些特點,golang的語言特性十分適合開發游戲服務器端。
首先,go語言提供goroutine機制作為原生的并發機制。每個goroutine所需的內存很少,實際應用中可以啟動大量的goroutine對并發連接進行響應。goroutine與gevent中的greenlet很相像,遇到IO阻塞的時候,調度器就會自動切換到另一個goroutine執行,保證CPU不會因為IO而發生等待。而goroutine與gevent相比,沒有了python底層的GIL限制,就不需要利用多進程來榨取多核機器的性能了。通過設置最大線程數,可以控制go所啟動的線程,每個線程執行一個goroutine,讓CPU滿負載運行。
同時,go語言為goroutine提供了獨到的通信機制channel。channel發生讀寫的時候,也會掛起當前操作channel的goroutine,是一種同步阻塞通信。這樣既達到了通信的目的,又實現同步,用CSP模型的觀點看,并發模型就是通過一組進程和進程間的事件觸發解決任務的。雖然說,主流的編程語言之間,只要是圖靈完備的,他們就都能實現相同的功能。但go語言提供的這種協程間通信機制,十分優雅地揭示了協程通信的本質,避免了以往鎖的顯式使用帶給程序員的心理負擔,確是一大優勢。進行網游開發的程序員,可以將游戲邏輯按照單線程阻塞式的寫,不需要額外考慮線程調度的問題,以及線程間數據依賴的問題。因為,線程間的channel通信,已經表達了線程間的數據依賴關系了,而go的調度器會給予妥善的處理。
另外,go語言提供的gc機制,以及對指針的保護式使用,可以大大減輕程序員的開發壓力,提高開發效率。
展望未來,我期待go語言社區能夠提供更多的goroutine間的隔離機制。個人十分推崇erlang社區的脆崩哲學,推動應用發生預期外行為時,盡早崩潰,再fork出新進程處理新的請求。對于協程機制,需要由程序員保證執行的函數不會發生死循環,導致線程卡死。如果能夠定制goroutine所執行函數的最大CPU執行時間,及所能使用的最大內存空間,對于提升系統的魯棒性,大有裨益。
//假設的GOPATH指向C:\gohome
0. 執行 go get github.com/wendal/go-oci8 ,然后肯定是報錯了,沒關系,代碼會下載下來.
1. 首先,你需要安裝mingw到C:\mingw
2. 然后,到Oracle官網,下載OCI及其SDK,解壓到instantclient_11_2 -- 當前最新版
3. 從我的go-oci8庫的windows文件夾,拷貝pkg-config.exe到C:\mingw\bin\,拷貝oci8.pc到C:\mingw\lib\pkg-config\
4. 設置環境變量 PATH ,值為 原有PATH;C:\instantclient_11_2;C:\mingw\bin;
5. 設置環境變量 PKG_CONFIG_PATH,值為 C:\mingw\lib\pkg-config
6. 接下來,就最重要的,就是再執行一次,這次應該能成功的: go get github.com/wendal/go-oci8
7. 測試一下:
cd %GOPATH%/src/github.com/wendal/go-oci8/example
go run oracle.go
#提醒一句, oracle.go里面的寫的密碼是system/123456, 實例名XE
我們在mian函數中,首先初始化配置文件,然后新建http連接。
這個連接創建之后,監聽服務器的9999端口。如果url的路徑后綴為 "/ws",就轉發到ws/ws.go中的IndexHandler方法中。
這個方法中首先我們創建一個websocket的Upgrader實例,然后我們使用Upgrader的upgrade方法來升級一下我們的連接為長連接。
升級完成之后會返回一個*websocket.Conn的連接,我們之后所有的關于連接的操作,都是基于該conn的。
在該連接完成之后,我們將連接存放到一個名為Client的map中,以便之后管理更為方便。
之后,我們啟動一個goroutine來讀取連接中發送的信息內容,再根據內容進行相應的操作。
分享名稱:go語言連接服務器,go服務端
文章來源:http://m.kartarina.com/article40/heisho.html
成都網站建設公司_創新互聯,為您提供外貿建站、關鍵詞優化、、網頁設計公司、標簽優化、App設計
聲明:本網站發布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創新互聯