我的第一個GO應(yīng)用

剛結(jié)束一個項目的開發(fā)葡公,需要做一些壓力測試,這時想起來用GO寫更合適彼水。
接口是一個TCP協(xié)議,沒有web接口极舔,大家知道JVM平臺的線程跟物理線程是一
比一的關(guān)系凤覆,切換線程開銷比較大。
想在一臺PC上模擬比較高的并發(fā)拆魏,其實是有點不切實際盯桦,因為JVM平臺已經(jīng)決定了,要模擬并發(fā)渤刃,只有不斷的往上創(chuàng)建線程拥峦,而GOLang在設(shè)計之初就考慮到這樣的問題,所以它基于協(xié)程的思想來支持多任務(wù)的執(zhí)行卖子。

因為之前沒有用GO寫過東西略号,所以從最簡單的"Hello Wolrd"小程序 開始:

package main
import (
    "fmt"
    "net"
)
func SimpleTcp() {
    tcpAddr, err := net.ResolveTCPAddr("tcp4", "localhost:21211")
    conn, err := net.DialTCP("tcp", nil, tcpAddr)
    _, err = conn.Write([]byte("order 123 \r\n"))
    buf := make([]byte, 6)
    _, err = conn.Read(buf)
    _ = err
    fmt.Println(string(buf))
}

第一次優(yōu)化
分解 SimpleTcp 函數(shù),提取三個不同的函數(shù)

  • 創(chuàng)建連接的函數(shù)
  • 寫入tcp指令的函數(shù)
  • 從網(wǎng)絡(luò)中讀取響應(yīng)體的函數(shù)
func Conn(ip string) (conn *net.TCPConn, err error) {
   tcpAddr, err := net.ResolveTCPAddr("tcp4", ip)
   if err != nil {
       panic("ResolveTCPAddr error,ip:" + ip)
   }
   conn, err = net.DialTCP("tcp", nil, tcpAddr)
   if err != nil {
       panic("DialTCP error,ip:" + ip)
   }
   return conn, err
}
func Write(conn *net.TCPConn, body string) error {
   defer func() {
       if err := recover(); err != nil {
           fmt.Println(err)
       }
   }()

   _, err := conn.Write([]byte("order 123 \r\n"))

   return err
}
func Read(conn *net.TCPConn) (res string, err error) {
   buf := make([]byte, 6)
   _, err = conn.Read(buf)
   fmt.Println(string(buf))
   return string(buf), err
}

入口方法

func Simpletest(cmd string) {
   //創(chuàng)建連接
    conn, err := Conn("localhost:21211")
  //確保被關(guān)閉
    defer func() {
        conn.Close()
    }()
    if err != nil {
        fmt.Println(err)
        return
    } else {
        fmt.Println("connected", conn)
    }
    Write(conn, cmd)
    res, err := Read(conn)
    fmt.Println(res, err)
}

執(zhí)行結(jié)果

start
connected &{{0xc042092000}}
OK
OK<nil>
end

第二次優(yōu)化
加入并行測試

  • 添加channel
  • 用WaitGroup等待操作執(zhí)行結(jié)束
const COUNT = 500 * 100
const WORKERS = 40
//啟動測試洋闽,創(chuàng)建協(xié)議玄柠,主線程進(jìn)入等待
func StartWorker(works int) {
    var wg sync.WaitGroup
    var c1 = make(chan string, WORKERS)
    wg.Add(COUNT)
    go func() {
        for i := 0; i < COUNT; i++ {
            fmt.Println(i)
            PushChan(c1, "order 123 \r\n", &wg)
        }
    }()
    for i := 0; i < works; i++ {

        go PollChan(c1, &wg)
    }

    wg.Wait()
}
//投遞消息
func PushChan(c1 chan string, cmd string, wg *sync.WaitGroup) {
    c1 <- cmd

}
//拉取消息
func PollChan(c1 chan string, wg *sync.WaitGroup) {
    select {
    case cmd := <-c1:
        Dispose(wg, cmd)
        //遞歸獲取
        PollChan(c1, wg)
    }
}
//整合處理流程,創(chuàng)建連接讀入指令讀取響應(yīng)
func Dispose(wg *sync.WaitGroup, cmd string) (res string, er error) {
    var start = time.Now()
    var conn, err = Conn("localhost:21211")
    defer func() {
        wg.Done()
        if conn != nil {
            conn.Close()
        }
    }()
    if err != nil {
        return "", err
    } else {
        //fmt.Println("connected", conn)
    }
    Write(conn, cmd)
    res, err = Read(conn)
    //fmt.Println("res:", res)
    if !strings.Contains(res, "STORED") {
        fmt.Println("e:", (time.Now().Sub(start) / 1e9), res)
    }
    return res, err
}

第三次優(yōu)化
前面的測試都是基于短連接的測試诫舅,連接用完就刪除了羽利,生產(chǎn)環(huán)境用的是長連接,所以后面的測試加入了長連接測試

  • 加入sync.Pool用于保存連接實例
var pool = InitPool(0, "localhost:21211")
func InitPool(poolSize int, ip string) *sync.Pool {
    pool := &sync.Pool{New: func() interface{} {
        conn, _ := Conn(ip)
        return conn
    }}
    return pool
}
func DisposeWithPool(wg *sync.WaitGroup, cmd string) (res string, err error) {
    var start = time.Now()
    var conn *net.TCPConn = pool.Get().(*net.TCPConn)
        defer func() {
                pool.Put(conn)
        wg.Done()
    }()
    Write(conn, cmd)
    res, err = Read(conn)
    if !strings.Contains(res, "STORED") {
        fmt.Println("e:", (time.Now().Sub(start)), res)
    }
    return res, err
}

第四次優(yōu)化
上面讀取響應(yīng)的時候用的指定的字節(jié)數(shù)刊懈,而實際情況是每個響應(yīng)都是一行消息这弧。

  • 加入bufio娃闲,用于優(yōu)化讀取
func Readx(conn *net.TCPConn) (res string, err error) {
    defer func() {
        if err := recover(); err != nil {
            fmt.Println(err)
        }
    }()
    pReader := bufio.NewReader(conn)
    line, _, err := pReader.ReadLine()
    return strings.TrimSpace(string(line)), err
}

后記:
一直用java做開發(fā),里面的不少內(nèi)容在學(xué)習(xí)golang時對照著學(xué)習(xí)匾浪,golang提供了更簡潔的api畜吊,還比較容易上手。后面會對golang的一些包深入學(xué)習(xí)户矢。本文里沒有給出嚴(yán)格的壓測標(biāo)準(zhǔn)和輸出玲献,其實就是給自己一個學(xué)習(xí)使用golang的理由,沒有需求驅(qū)動很多知識只是知道不能形成完整的知識結(jié)構(gòu)梯浪,在需求中會有方向捌年,自己需要什么就去找相關(guān)的資料。
目前為止有些go的語法還不是很清楚怎么用挂洛,我想通過一個一個實踐礼预,都會解決的。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末虏劲,一起剝皮案震驚了整個濱河市托酸,隨后出現(xiàn)的幾起案子嫂侍,更是在濱河造成了極大的恐慌苇羡,老刑警劉巖响疚,帶你破解...
    沈念sama閱讀 217,907評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件晦毙,死亡現(xiàn)場離奇詭異临谱,居然都是意外死亡腾窝,警方通過查閱死者的電腦和手機(jī)堆生,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,987評論 3 395
  • 文/潘曉璐 我一進(jìn)店門虐译,熙熙樓的掌柜王于貴愁眉苦臉地迎上來泉唁,“玉大人鹅龄,你說我怎么就攤上這事⊥ば螅” “怎么了扮休?”我有些...
    開封第一講書人閱讀 164,298評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長拴鸵。 經(jīng)常有香客問我玷坠,道長,這世上最難降的妖魔是什么宝踪? 我笑而不...
    開封第一講書人閱讀 58,586評論 1 293
  • 正文 為了忘掉前任侨糟,我火速辦了婚禮,結(jié)果婚禮上瘩燥,老公的妹妹穿的比我還像新娘秕重。我一直安慰自己,他們只是感情好厉膀,可當(dāng)我...
    茶點故事閱讀 67,633評論 6 392
  • 文/花漫 我一把揭開白布溶耘。 她就那樣靜靜地躺著二拐,像睡著了一般。 火紅的嫁衣襯著肌膚如雪凳兵。 梳的紋絲不亂的頭發(fā)上百新,一...
    開封第一講書人閱讀 51,488評論 1 302
  • 那天,我揣著相機(jī)與錄音庐扫,去河邊找鬼饭望。 笑死,一個胖子當(dāng)著我的面吹牛形庭,可吹牛的內(nèi)容都是我干的铅辞。 我是一名探鬼主播,決...
    沈念sama閱讀 40,275評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼萨醒,長吁一口氣:“原來是場噩夢啊……” “哼斟珊!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起富纸,我...
    開封第一講書人閱讀 39,176評論 0 276
  • 序言:老撾萬榮一對情侶失蹤囤踩,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后晓褪,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體堵漱,經(jīng)...
    沈念sama閱讀 45,619評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,819評論 3 336
  • 正文 我和宋清朗相戀三年辞州,在試婚紗的時候發(fā)現(xiàn)自己被綠了怔锌。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,932評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡变过,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出涝涤,到底是詐尸還是另有隱情媚狰,我是刑警寧澤,帶...
    沈念sama閱讀 35,655評論 5 346
  • 正文 年R本政府宣布阔拳,位于F島的核電站崭孤,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏糊肠。R本人自食惡果不足惜辨宠,卻給世界環(huán)境...
    茶點故事閱讀 41,265評論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望货裹。 院中可真熱鬧嗤形,春花似錦、人聲如沸弧圆。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,871評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至霹期,卻和暖如春叶组,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背历造。 一陣腳步聲響...
    開封第一講書人閱讀 32,994評論 1 269
  • 我被黑心中介騙來泰國打工甩十, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人吭产。 一個月前我還...
    沈念sama閱讀 48,095評論 3 370
  • 正文 我出身青樓侣监,卻偏偏與公主長得像,于是被迫代替她去往敵國和親垮刹。 傳聞我的和親對象是個殘疾皇子达吞,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,884評論 2 354

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)荒典,斷路器酪劫,智...
    卡卡羅2017閱讀 134,656評論 18 139
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,129評論 25 707
  • 誰說學(xué)霸們只會讀書遮咖?滩字! 《英雄聯(lián)盟》官方近日公布了最新的全國高校實力排行榜,清華御吞、北大依然遙遙領(lǐng)先其他大學(xué)麦箍,分別位...
    f伐木累閱讀 10,984評論 0 0
  • 今晨寒,天已放晴陶珠,霧輕風(fēng)息挟裂,四野一片潔白。所見樹木揍诽,均鑲銀嵌玉诀蓉,出少見之霧凇。美麗極了暑脆! 窈窕霓裳渠啤,晶瑩冰羽...
    悠一悠閱讀 249評論 0 0
  • 一個人如何看待自己,恰是決定了此人的命運添吗,指明了他的歸宿
    黑藤z閱讀 207評論 0 0