成人午夜视频全免费观看高清-秋霞福利视频一区二区三区-国产精品久久久久电影小说-亚洲不卡区三一区三区一区

go語言轉(zhuǎn)發(fā)ip Go語言發(fā)展

Golang 端口轉(zhuǎn)發(fā)工具

初學go,寫一個端口轉(zhuǎn)發(fā)工具。很方便的小工具,希望能對大家學習go語言有所幫助。

創(chuàng)新互聯(lián)建站主要從事網(wǎng)站建設、成都網(wǎng)站設計、網(wǎng)頁設計、企業(yè)做網(wǎng)站、公司建網(wǎng)站等業(yè)務。立足成都服務江南,十多年網(wǎng)站建設經(jīng)驗,價格優(yōu)惠、服務專業(yè),歡迎來電咨詢建站服務:13518219792

```Golang

package main

import(

"fmt"

"io"

"net"

"sync"

)

varlocksync.Mutex

vartrueList[]string

varipstring

varliststring

funcmain(){

ip="0.0.0.0:888"

server()

}

funcserver(){

fmt.Printf("Listening%s",ip)

lis,err:=net.Listen("tcp",ip)

iferr!=nil{

fmt.Println(err)

return

}

deferlis.Close()

for{

conn,err:=lis.Accept()

iferr!=nil{

fmt.Println("建立連接錯誤:%v\n",err)

continue

}

fmt.Println(conn.RemoteAddr(),conn.LocalAddr())

gohandle(conn)

}

}

funchandle(sconnnet.Conn){

defersconn.Close()

ip:="127.0.0.1:8888"

dconn,err:=net.Dial("tcp",ip)

iferr!=nil{

fmt.Printf("連接%v失敗:%v\n",ip,err)

return

}

ExitChan:=make(chanbool,1)

gofunc(sconnnet.Conn,dconnnet.Conn,Exitchanbool){

io.Copy(dconn,sconn)

ExitChan-true

}(sconn,dconn,ExitChan)

gofunc(sconnnet.Conn,dconnnet.Conn,Exitchanbool){

io.Copy(sconn,dconn)

ExitChan-true

}(sconn,dconn,ExitChan)

-ExitChan

dconn.Close()

}

WebSocket+SLB(負載均衡)會話保持解決重連問題

寫在最前面:由于現(xiàn)在游戲基本上采用全球大區(qū)的模式,全球玩家在同一個大區(qū)進行游戲,傳統(tǒng)的單服模式已經(jīng)不能夠滿足當前的服務需求,所以現(xiàn)在游戲服務器都在往微服務架構(gòu)發(fā)展。當前我們游戲也是利用微服務架構(gòu)來實現(xiàn)全球玩家同服游戲。

玩家每次斷線(包括切換網(wǎng)絡/超時斷線)后應該會重新連接服務器,重連成功的話可以繼續(xù)當前情景繼續(xù)游戲,但是之前寫的底層重連機制一直不能生效,導致每次玩家斷線后重連都失敗,要從賬號登陸開始重新登陸,該文章寫在已經(jīng)定位了重連問題是由SLB引起后,提出的解決方案。

每次重連后,客戶端向SLB發(fā)送建立連接,SLB都會重新分配一個網(wǎng)關節(jié)點,導致客戶端連接到其他網(wǎng)關,重連失敗。

會話保持的作用是什么?

開啟SLB會話保持功能后,SLB會記錄客戶端的IP地址,在一定時間內(nèi),自動將同一個IP的連接轉(zhuǎn)發(fā)到上次連接的網(wǎng)關。

在網(wǎng)絡不穩(wěn)定的情況下,游戲容易心跳或者發(fā)包超時,開啟會話保持,能解決大部分情況下的重連問題。

但是在切換網(wǎng)絡的時候,手機網(wǎng)絡從Wifi切換成4G,自身IP會變,這時候連接必定和服務器斷開,需要重新建立連接。由于IP已經(jīng)變化,SLB不能識別到是同一個客戶端發(fā)出的請求,會將連接轉(zhuǎn)發(fā)到其他網(wǎng)關節(jié)點。所以使用TCP連接的情況下,SLB開啟會話保持并不能解決所有的重連問題。

另外某些時刻,手機頻繁開啟和斷開WI-FI,有時候可能不會斷開網(wǎng)絡,這并不是因為4G切換WI-FI時網(wǎng)絡沒斷開,從4G切換到Wi-Fi網(wǎng)絡,因為IP變了,服務器不能識別到新的IP,連接肯定是斷開的。這時候網(wǎng)絡沒斷開,主要是因為現(xiàn)在智能手機會對4G和Wi-Fi網(wǎng)絡做個權(quán)重判斷,當Wi-Fi網(wǎng)絡頻繁打開關閉時,手機會判斷Wi-Fi網(wǎng)絡不穩(wěn)定,所有流量都走4G。所以網(wǎng)絡沒斷開是因為一直使用4G連接,才沒有斷開。想要驗證,只需要切換Wi-Fi時,把4G網(wǎng)絡關閉,這樣流量就必定走Wi-Fi。

上面說過,四層的TCP協(xié)議主要是基于IP來實現(xiàn)會話保持。但是切換網(wǎng)絡的時候客戶端的IP會變。所以要解決切換網(wǎng)絡時的重連問題,只有兩個方法:1. 當客戶端成功連接網(wǎng)關節(jié)點后,記錄下網(wǎng)關節(jié)點的IP,下次重連后不經(jīng)過SLB,直接向網(wǎng)關節(jié)點發(fā)送連接請求。2.使用 SLB的七層(HTTP)轉(zhuǎn)發(fā)服務。

當客戶端經(jīng)過SLB將連接轉(zhuǎn)發(fā)到網(wǎng)關時,二次握手驗證成功后向客戶端發(fā)送自己節(jié)點的IP,這樣客戶端下次連接的時候就能直接連接網(wǎng)關節(jié)點。但是這樣會暴露網(wǎng)關的IP地址,為安全留下隱患。

如果不希望暴露網(wǎng)關的IP地址,就需要增加一層代理層,SLB將客戶端請求轉(zhuǎn)發(fā)到代理層,代理層再根據(jù)客戶端帶有的key,轉(zhuǎn)發(fā)到正確的網(wǎng)關節(jié)點上。增加一層代理層,不僅會增加請求的響應時間,還會增加整體框架的復雜度。

阿里云的七層SLB會話保持服務,主要是基于cookie的會話保持??蛻舳嗽谕掌靼l(fā)送HTTP請求后,服務器會返回客戶端一個Response,SLB會在這時候,將經(jīng)過的Response插入或者重寫cookie??蛻舳双@取到這個cookie,下次請求時會帶上cookie,SLB判斷Request的Headers里面有cookie,就將連接轉(zhuǎn)發(fā)到之前的網(wǎng)關節(jié)點。

HTTP是短鏈接,我們游戲是長連接,所以用HTTP肯定不合適。但是可以考慮基于HTTP的WebSocket。

什么是WebSocket?

WSS(Web Socket Secure)是WebSocket的加密版本。

SLB對WebSocket的支持

查看阿里云SLB文檔對WS的支持,說明SLB是支持WS協(xié)議的,并且SLB對于WS無需配置,只需要選用HTTP監(jiān)聽時,就能夠轉(zhuǎn)發(fā)WS協(xié)議。說明WS協(xié)議在SLB這邊看來就是一個HTTP,這樣WS走的也是七層的轉(zhuǎn)發(fā)服務。只要SLB能夠正常識別WS握手協(xié)議里Request的cookie和正常識別服務器返回的Response并且往里面插入cookie,就可以利用會話保持解決重連問題。

Go語言實現(xiàn)WS服務器有兩種方法,一種是利用golang.org/x/net下的websocket包,另外一種方法就是自己解讀Websocket協(xié)議來實現(xiàn),由于WS協(xié)議一樣是基于TCP協(xié)議之上,完全可以通過監(jiān)聽TCP端口來實現(xiàn)。

客戶端發(fā)送Request消息

服務器返回Response消息

其中服務器返回的Sec-WebSocket-Accept字段,主要是用于客戶端需要驗證服務器是否支持WS。RFC6455文檔中規(guī)定,在WebSocket通信協(xié)議中服務端為了證實已經(jīng)接收了握手,它需要把兩部分的數(shù)據(jù)合并成一個響應。一部分信息來自客戶端握手的Sec-WebSocket-Keyt頭字段:Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==。對于這個字段,服務端必須得到這個值(頭字段中經(jīng)過base64編碼的值減去前后的空格)并與GUID"258EAFA5-E914-47DA-95CA-C5AB0DC85B11"組合成一個字符串,這個字符串對于不懂WebSocket協(xié)議的網(wǎng)絡終端來說是不能使用的。這個組合經(jīng)過SHA-1掩碼,base64編碼后在服務端的握手中返回。如果這個Sec-WebSocket-Accept計算錯誤瀏覽器會提示:Sec-WebSocket-Accept dismatch

如果返回成功,Websocket就會回調(diào)onopen事件

游戲服務器的使用的TCP協(xié)議,是在協(xié)議的包頭使用4Byte來聲明本協(xié)議長度,然后將協(xié)議一次性發(fā)送。但是在WS協(xié)議是通過Frame形式發(fā)送的,會將一條消息分為幾個frame,按照先后順序傳輸出去。這樣做會有幾個好處:

websocket的協(xié)議格式:

參數(shù)說明如下:

阿里云的SLB開啟HTTP監(jiān)聽后,會檢查過往的Request和Response請求,收到服務器返回的Response后,會往Response插入一個Cookie

客戶端收到服務器的Response后,可以在Header中查到有個“Set-Cookie”字段,里面是SLB插入的Cookie值

客戶端斷開連接后,下次發(fā)送請求需要往Headers插入Cookie字段

分別在阿里云的兩臺ECS實例上部署WS服務器,打開8000端口,開啟一個SLB服務,SLB服務選擇HTTP方式監(jiān)聽,并且打開會話保持功能,Cookie處理方式選擇植入Cookie。Demo服務器沒有做HTTP健康監(jiān)聽的處理,健康檢查這塊可以先關掉。

在兩臺ECS上啟動WS服務器,然后本地運行客戶端,分別測試兩臺服務器是否能正常連接,測試完畢后,測試SLB能否正常工作。服務器和SLB都正常的情況下,運行客戶端,客戶端會得到以下結(jié)果

收到的三次Cookie都相同,說明Cookie是有正常植入工作的,并且三次都被SLB正確抓取了。

收到的三次serverId也都是同樣的值,說明三次都是同一個ECS上的服務器響應。

至此,驗證成功。

Websocket+SLB會話保持能夠解決超時重連和切換網(wǎng)絡時重連的問題。

參考:

阿里云會話保持

解答Wi-Fi與4G網(wǎng)絡切換的困惑

WebSocket的實現(xiàn)原理

阿里云SLB對WebSocket的支持

HTTP Headers和Cookie

go語言聊天室實現(xiàn)(六)創(chuàng)建HTTP連接,并升級為長連接

我們在mian函數(shù)中,首先初始化配置文件,然后新建http連接。

這個連接創(chuàng)建之后,監(jiān)聽服務器的9999端口。如果url的路徑后綴為 "/ws",就轉(zhuǎn)發(fā)到ws/ws.go中的IndexHandler方法中。

這個方法中首先我們創(chuàng)建一個websocket的Upgrader實例,然后我們使用Upgrader的upgrade方法來升級一下我們的連接為長連接。

升級完成之后會返回一個*websocket.Conn的連接,我們之后所有的關于連接的操作,都是基于該conn的。

在該連接完成之后,我們將連接存放到一個名為Client的map中,以便之后管理更為方便。

之后,我們啟動一個goroutine來讀取連接中發(fā)送的信息內(nèi)容,再根據(jù)內(nèi)容進行相應的操作。

基于go的websocket消息推送的集群實現(xiàn)

目前websocket技術已經(jīng)很成熟,選型Go語言,當然是為了節(jié)省成本以及它強大的高并發(fā)性能。我使用的是第三方開源的websocket庫即gorilla/websocket。

由于我們線上推送的量不小,推送后端需要部署多節(jié)點保持高可用,所以需要自己做集群,具體架構(gòu)方案如圖:

Auth Service:鑒權(quán)服務,根據(jù)Token驗證用戶權(quán)限。

Collect Service:消息采集服務,負責收集業(yè)務系統(tǒng)消息,存入MongoDB后,發(fā)送給消息分發(fā)服務。

Dispatch Service:消息分發(fā)服務,根據(jù)路由規(guī)則分發(fā)至對應消息推送服務節(jié)點上。

Push Service:消息推送服務,通過websocket將消息推送給用戶。

集群推送的關鍵點在于,web端與服務端建立長連接之后,具體跟哪個推送節(jié)點保持長連接的,如果我們能夠找到對應的連接節(jié)點,那么我們就可以將消息推送出去。下面講解一下集群的大致流程:

1. web端用戶登錄之后,帶上token與后端推送服務(Push Service)保持長連接。

2. 推送服務收到連接請求之后,攜帶token去鑒權(quán)服務(Auth Service)驗證此token權(quán)限,并返回用戶ID。

3. 把返回的用戶ID與長連接存入本地緩存,保持用戶ID與長連接綁定關系。

4. 再將用戶ID與本推送節(jié)點IP存入redis,建立用戶(即長連接)與節(jié)點綁定關系,并設置失效時間。

5. 采集服務(Collect Service)收集業(yè)務消息,首先存入mongodb,然后將消息透傳給分發(fā)服務(Dispatch Service)。

6. 分發(fā)服務收到消息之后,根據(jù)消息體中的用戶ID,從redis中獲取對應的推送服務節(jié)點IP,然后轉(zhuǎn)發(fā)給對應的推送節(jié)點。

7. 推送服務節(jié)點收到消息之后,根據(jù)用戶ID,從本地緩存中取出對應的長連接,將消息推送給客戶端。

其他注意事項:

分享題目:go語言轉(zhuǎn)發(fā)ip Go語言發(fā)展
URL地址:http://jinyejixie.com/article16/dodosgg.html

成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供標簽優(yōu)化、動態(tài)網(wǎng)站品牌網(wǎng)站制作、網(wǎng)站導航、微信小程序定制開發(fā)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

營銷型網(wǎng)站建設
三明市| 礼泉县| 庄浪县| 青州市| 浏阳市| 崇州市| 崇州市| 炉霍县| 清丰县| 宜都市| 图们市| 陈巴尔虎旗| 龙山县| 渭南市| 乐陵市| 内丘县| 乐至县| 高淳县| 阿拉尔市| 大化| 芦山县| 扬中市| 台湾省| 沈丘县| 比如县| 大安市| 乳山市| 嵩明县| 华阴市| 海城市| 临沂市| 循化| 焉耆| 云林县| 济阳县| 会昌县| 灵宝市| 汤原县| 土默特右旗| 重庆市| 黄石市|