Go小課02:第一次Say Hello

頭圖

1、Say Hello請求

一、環境配置
  • 安裝Go的包依賴管理命令行工具govendor
go get -u github.com/kardianos/govendor
複製代碼
  • 建立項目文件夾
mkdir -p $GOPATH/src/github.com/yourusername/project && cd "$_"
複製代碼
  • govendor初始化
govendor init
複製代碼
  • 獲取go的web框架gin
govendor fetch github.com/gin-gonic/gin
複製代碼
  • 在項目根路徑下,新建文件main.go文件
二、Get請求和Post請求代碼
//main.go
package main

import (
"github.com/gin-gonic/gin"
"net/http"
"strconv"
)
func main() {

	// gin的Default方法建立一個路由handler。而後經過HTTP方法綁定路由規則和路由函數,gin把request和response都封裝到gin.Context的上下文環境。
	// 最後啓動路由的Run方法監聽端口。
	router := gin.Default()

	// get請求
	router.GET("/user/welcome", func(c *gin.Context) {
		//獲取url中的參數信息
		namestr := c.DefaultQuery("name", "Guest")
		agestr := c.DefaultQuery("age", "18")

		//各類處理邏輯

		ageValue, err := strconv.Atoi(agestr)
		role := "小夥子"
		if err != nil {
			role = "可疑的人"
		} else {
			if ageValue > 28 {
				role = "大哥"
			}
		}

		//返回
		c.String(http.StatusOK, "%s %s,你好呀", role, namestr)
	})

	//curl http://127.0.0.1:8000/user/welcome\?name\=jack\&age\=18

	router.POST("/user/postdata", func(c *gin.Context) {

		message := c.PostForm("message")

		namestr := c.DefaultPostForm("name", "anonymous")
		agestr := c.DefaultPostForm("age", "18")

		//各類處理邏輯
		ageValue, err := strconv.Atoi(agestr)
		role := "小夥子"
		if err != nil {
			role = "可疑的人"
		} else {
			if ageValue > 28 {
				role = "大哥"
			}
		}

		message = role + namestr + " 你好呀"

		c.JSON(http.StatusOK, gin.H{
			"status": gin.H{
				"code":   http.StatusOK,
				"status": "ok",
			},
			"data": gin.H{
				"message": message,
			},
		})
	})

	//curl -X POST http://127.0.0.1:8000/user/postdata -H "Content-Type:application/x-www-form-urlencoded" -d "name=jack&age=28" | python -m json.tool
	router.Run(":8000")
}
複製代碼

說明:啓動服務後,能夠用curl命令工具來發請求,也能夠用Postman來發請求,藉此來測試接口是否能夠訪問。python

2、接口聯調

一、GET請求聯調
  • 接口名:/user/welcomegit

  • 端口:80000程序員

curl http://127.0.0.1:8000/user/welcome\?name\=jack\&age\=38
大哥 jack,你好呀**%**                                                              
複製代碼
curl http://127.0.0.1:8000/user/welcome\?name\=jack\&age\=18
小夥子 jack,你好呀**%**                                                            
複製代碼
curl http://127.0.0.1:8000/user/welcome\?name\=jack\&age\=hhah
可疑的人 jack,你好呀**%** 
複製代碼

說明:可使用本機的ip地址。github

二、POST請求聯調
  • 接口名:/user/postdatagolang

  • 端口:80000web

curl -X POST http://127.0.0.1:8000/user/postdata -H "Content-Type:application/x-www-form-urlencoded" -d "name=jack&age=28" | python -m json.tool
 % Total % Received % Xferd Average Speed Time Time Time Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   123  100   107  100    16   104k  16000 --:--:-- --:--:-- --:--:--  120k
{
    "data": {
        "message": "54GP5b+O57Su54Cb5oGTYWNrIOa1o+eKsuOCvemNm+KCrA=="
    },
    "status": {
        "code": 200,
        "status": "ok"
    }
}
複製代碼

3、接口性能測試

一、接口性能指標

衡量接口性能能夠從下面幾個指標來看:shell

  • QPS(TPS):每秒鐘 Request/事務 數量,在互聯網領域,指每秒響應請求數(指http請求)編程

  • 事務: 用戶某一步或幾步操做的集合,咱們要保證它有一個完整意義。好比用戶對某一個頁面的一次請求,用戶對某系統的一次登陸,淘寶用戶對商品的一次確認支付過程。這些咱們均可以看做一個事務json

  • 響應時間:系統對一個請求作出響應的平均時間。例如系統處理一個HTTP請求須要200ms,這個200ms就是系統的響應時間(我認爲這裏應該僅包含處理時間,網絡傳輸時間忽略)segmentfault

  • 併發數:系統同時處理的request / 事務數

  • 吞吐量:單位時間內處理的請求數量(一般由QPS與併發數決定);

參考:Web開發中,什麼級別纔算是高併發

二、性能測試工具安裝

​ 咱們將利用wrk工具簡單測試下接口的QPS和響應時間,wrk是輕量級的 HTTP 性能測試工具,在這裏咱們使用wrk簡單測試下咱們剛寫接口的QPS和響應時間

#安裝
brew install wrk
複製代碼
三、接口性能測試
#以get請求爲例
wrk -t4 -c1000 -d30s -T30s --latency http://127.0.0.1:8000/user/welcome\?name\=jack\&age\=38
Running 30s test @ http://127.0.0.1:8000/user/welcome?name=jack&age=38
  4 threads and 1000 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency     2.48ms    1.15ms  36.87ms   80.11%
    Req/Sec    24.44k     2.48k   33.65k    72.67%
  Latency Distribution
     50%    2.33ms
     75%    2.81ms
     90%    3.71ms
     99%    6.53ms
  2919566 requests in 30.03s, 389.80MB read
  Socket errors: connect 751, read 89, write 0, timeout 0
Requests/sec:  97228.78
Transfer/sec:     12.98MB
複製代碼

解釋1:用4個線程來模擬1000個併發鏈接,整個測試持續30秒,鏈接超時30秒,打印出請求的延遲統計信息。 wrk 使用異步非阻塞的 io,並非用線程去模擬併發鏈接,所以不須要設置不少的線程,通常根據 CPU 的核心數量設置便可。(網絡通訊不會阻塞線程執行,用不多的線程模擬大量網路鏈接)

解釋2:

- Socket errors socket 錯誤的數量
- Requests/sec 每秒請求數量,也就是併發能力
- Latency 響應時間
Avg:平均、Max:最大、Stdev:標準差、+/- Stdev: 正負一個標準差佔比
複製代碼
四、性能說明
  • 使用Go寫一個簡單接口,在咱們的開發機器上的QPS大約是9w7左右,哈哈,咱們也算寫了一個"高性能,低延遲"接口,固然這歸功於優秀的go語言的併發處理能力和web框架gin

  • 實際的後臺接口的延遲不可能這麼快,它涉及到業務處理,服務間調用,複雜的網絡環境,真實的QPS遠遠沒有這麼誇張。

#測試百度首頁的QPS和Latency
wrk -t4 -c1000 -d30s -T30s https://www.baidu.com
Running 30s test @ https://www.baidu.com
  4 threads and 1000 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency   196.47ms   44.94ms   1.18s    88.71%
    Req/Sec   310.42     59.95   494.00     69.06%
  37095 requests in 30.09s, 548.20MB read
  Socket errors: connect 754, read 111, write 0, timeout 0
Requests/sec:   1232.74
Transfer/sec:     18.22MB
複製代碼

4、小課堂

一、govendor
  • 基於 vendor 機制實現的 Go 包依賴管理命令行工具。與原生 vendor 無侵入性融合,也支持從其餘依賴管理工具遷移,能夠很方便的實現同一個包在不一樣項目中不一樣版本、以及無相互侵入的開發和管理。

  • 最開始的時候,Go 並無提供較爲穩當的包管理工具。從 1.5 版本開始提供了 vendor 特性,但須要手動設置環境變量 GO15VENDOREXPERIMENT=1

  • 在執行 go buildgo run 命令時,會按照如下順序去查找包:

    • 當前包下的 vendor 目錄
    • 向上級目錄查找,直到找到 src 下的 vendor 目錄
    • 在 GOROOT 目錄下查找
    • 在 GOPATH 下面查找依賴包
  • 在發佈 1.6 版本時,該環境變量的值已經默認設置爲 1 了,該值可使用 go env 命令查看;在發佈 1.7 版本時,已去掉該環境變量,默認開啓 vendor 特性。

  • govendor一些經常使用命令以下:

//初始化
govendor init

//將已被引用且在 $GOPATH 下的全部包複製到 vendor 目錄
govendor add +external

//僅從 $GOPATH 中複製指定包
govendor add gopkg.in/yaml.v2

//列出代碼中全部被引用到的包及其狀態
govendor list

//列出一個包被哪些包引用
govendor list -v fmt

//從遠程倉庫添加或更新某個包(不會在 $GOPATH 也存一份)
govendor fetch golang.org/x/net/context

//安裝指定版本的包,eg:
govendor fetch golang.org/x/net/context@a4bbce9fcae005b22ae5443f6af064d80a6f5a55
govendor fetch golang.org/x/net/context@v1   # Get latest v1.*.* tag or branch.
govendor fetch golang.org/x/net/context@=v1  # Get the tag or branch named "v1".
複製代碼

參考Go 包依賴管理工具 —— govendor

二、C10k問題
  • C10K 是 Client 10000 問題,即「在同時鏈接到服務器的客戶端數量超過 10000 個的環境中,即使硬件性能足夠, 依然沒法正常提供服務」,簡而言之,就是單機1萬個併發鏈接問題。

  • 計算機程序可依據其瓶頸分爲磁盤IO瓶頸型,CPU計算瓶頸型,網絡帶寬瓶頸型,分佈式場景下有時候也會外部系統而致使自身瓶頸。

  • Web系統打交道最多的是網絡,不管是接收,解析用戶請求,訪問存儲,仍是把響應數據返回給用戶,都是要走網絡的。在沒有epoll/kqueue之類的系統提供的IO多路複用接口以前,多個核心的現代計算機最頭痛的是C10k問題,C10k問題會致使計算機沒有辦法充分利用CPU來處理更多的用戶鏈接,進而沒有辦法經過優化程序提高CPU利用率來處理更多的請求。

  • 自從Linux實現了epoll,FreeBSD實現了kqueue,這個問題基本解決了,咱們能夠藉助內核提供的API輕鬆解決當年的C10k問題,也就是說現在若是你的程序主要是和網絡打交道,那麼瓶頸必定在用戶程序而不在操做系統內核。

  • 隨着時代的發展,編程語言對這些系統調用又進一步進行了封裝,現在作應用層開發,幾乎不會在程序中看到epoll之類的字眼,大多數時候咱們就只要聚焦在業務邏輯上就好。Go 的 net 庫針對不一樣平臺封裝了不一樣的syscall API,http庫又是構建在net庫之上,因此在Go語言中咱們能夠藉助標準庫,很輕鬆地寫出高性能的http服務

參考程序員怎麼會不知道 C10K 問題呢?

相關文章
相關標籤/搜索