<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      golang倒騰一款簡配的具有請求排隊功能的并發受限服務器

      golang官方指南給了一些代碼片段來,層層遞進演示了信道的能力:

      1>. 信號量
      2>. 限流能力

      var sem = make(chan int, MaxOutstanding) 
       
      func Serve(queue chan *Request) {
          for req := range queue {
              req:= req
              sem <- 1   
              go func() {   // 只會開啟MaxOutstanding個并發協程
                  process(req)
                  <-sem
              }()
          }
      }
      

      上面出現了兩個信道:

      sem 提供了限制服務端并發處理請求的信號量
      queue 提供了一個客戶端請求隊列,起媒介/解耦的作用


      進一步指南給出了信道的另一個用法:
      3>. 解多路復用

      多路復用是網絡編程中一個耳熟能詳的概念,nginx redis等高性能web、內存kv都用到了這個技術 。

      這個解多路復用是怎么理解呢?

      離散/獨立/并發的客戶端請求被服務端Serve收斂之后, Serve就起到了多路復用的概念,在Request定義resultChan信道,就給每個客戶端請求提供了獨立獲取請求結果的能力,這便是一種解多路復用。


      從實際效果看這就是常見的互聯網web服務器:一款具備請求排隊功能的并發限流服務器

      官方指南并沒有完整實現客戶端和服務器端工程。

      下面是我的工程化實現, 記錄下實踐中遇到的問題。

      并發受限服務器

      • 信道queue接收客戶端請求,解耦客戶端和服務器,天然具備排隊能力
      • 信號量信道sem提供了并發受限的能力
      • 服務器處理完,向解多路復用信道req.resultChan寫入響應結果。
      /* 實現一個有請求隊列功能的并發請求受限服務器*/
      
      package main
      
      import (
      	"fmt"
      	"sync"
      	"time"
      )
      
      var sem = make(chan int, Maxoutstanding)
      
      var wg2 sync.WaitGroup
      
      func server(queue chan *Request) {
      	fmt.Printf("Server is already, listen req \n")
      
      	for req := range queue {
      		req := req
      		sem <- 1
      
      		wg2.Add(1)
      		go func() {
      			defer wg2.Done()
      			process(req)
      			<-sem
      		}()
      	}
      }
      
      func process(req *Request) {
      	s := sum(req.args)
      	req.resultChan <- s
      }
      func sum(a []int) (s int) {
      	for i := 1; i <= a[0]; i++ {
      		s += i
      	}
      	time.Sleep(time.Millisecond * 20)
      	return s
      }
      
      

      time.Sleep模擬服務器處理請求單次耗時20ms, 輸出數字的累加,
      eg: input: 100;
      output: 1+100/2*100 =5050

      wg2 sync.WaitGroup是一個動態活躍的Goroutine計數器,注意用法和位置,wg2的作用是:等待所有請求處理完成。

      并發客戶端請求

      for循環開啟并發客戶端請求,

      • 每個請求入駐一個獨立的Goroutine,獨立向信道queue投遞請求和接收響應
      package main
      
      import (
      	"fmt"
      	"sync"
      )
      
      type Request struct {
      	args       []int
      	resultChan chan int
      }
      
      var wg1 sync.WaitGroup
      
      func clients() {
      	fmt.Printf("start %d concurrency client request\n ", concurrencyClients)
      	for i := 1; i <= concurrencyClients; i++ {
      		r := &Request{
      			args:       []int{i},
      			resultChan: make(chan int),
      		}
      		wg1.Add(1)
      		go ClientReq(r)
      	}
      	wg1.Wait() 
      
      }
      
      func ClientReq(r *Request) {
      	defer wg1.Done()
      	queue <- r
      	go func() {
      		res := <-r.resultChan
      		fmt.Printf("current args is %d, the result is %d \n", r.args[0], res)
      	}()
      }
      

      wg1 WaitGroup的目的是確保所有的客戶端請求都已經發出,之后客戶端任務結束,所以此處我們新開Goroutine處理響應結果(這里又有閉包的參與)。

      工程化

      工程化代碼的先后順序,決定了代碼是否死鎖。
      server需要處于監聽狀態,故先啟動。

      本處clients在主協程整體上是同步發送,如果放在clients()的后面,clients內的wg1可能會有部分請求Goroutine阻塞在信道queue且沒法喚醒 運行時會檢測到報死鎖。

      package main
      
      import (
      	"fmt"
      	"time"
      )
      
      var concurrencyClients = 1000
      var queueLength = 100
      var queue = make(chan *Request, queueLength) // 請求隊列長度
      var Maxoutstanding int = 10                  // 服務器并發受限10
      
      func main() {
      
      	go server(queue)
      	var start = time.Now()
      
      	clients() // 確保所有的請求都已經發出去
      
      	wg2.Wait() // 確保服務器處理完所有的請求
      	fmt.Printf("客戶端并發%d請求,服務器請求隊列長度%d,服務器限流%d,總共耗時%d ms \n", concurrencyClients, queueLength, Maxoutstanding, time.Since(start).Milliseconds())
      }
      

      上面出現了3個配置變量
      1>. 客戶端并發請求數量concurrencyClients=100
      2>. 服務器排隊隊列長度queueLength, 會作用到信道queue=50
      3>. 服務器并發受限閾值Maxoutstanding=10

      start 1000 concurrency client request
       Server is already, listen req 
      current args is 14, the result is 105 
      current args is 2, the result is 3 
      current args is 3, the result is 6 
      current args is 1, the result is 1 
      current args is 4, the result is 10 
      current args is 8, the result is 36 
      current args is 6, the result is 21 
      current args is 12, the result is 78 
      current args is 5, the result is 15 
      current args is 7, the result is 28 
      current args is 18, the result is 171 
      current args is 16, the result is 136 
      current args is 15, the result is 120 
      current args is 20, the result is 210 
      current args is 19, the result is 190 
      current args is 13, the result is 91 
      current args is 21, the result is 231 
      current args is 10, the result is 55 
      current args is 17, the result is 153 
      current args is 9, the result is 45 
      current args is 22, the result is 253 
      current args is 28, the result is 406 
      current args is 27, the result is 378 
      current args is 11, the result is 66 
      current args is 26, the result is 351 
      current args is 30, the result is 465 
      current args is 23, the result is 276 
      current args is 25, the result is 325 
      current args is 29, the result is 435 
      current args is 24, the result is 300 
      current args is 31, the result is 496 
      current args is 34, the result is 595 
      current args is 38, the result is 741 
      current args is 36, the result is 666 
      current args is 41, the result is 861 
      current args is 32, the result is 528 
      current args is 35, the result is 630 
      current args is 33, the result is 561 
      current args is 37, the result is 703 
      current args is 39, the result is 780 
      current args is 52, the result is 1378 
      current args is 46, the result is 1081 
      current args is 47, the result is 1128 
      current args is 49, the result is 1225 
      current args is 45, the result is 1035 
      current args is 43, the result is 946 
      current args is 48, the result is 1176 
      current args is 40, the result is 820 
      current args is 42, the result is 903 
      current args is 44, the result is 990 
      current args is 59, the result is 1770 
      current args is 55, the result is 1540 
      current args is 53, the result is 1431 
      current args is 57, the result is 1653 
      current args is 51, the result is 1326 
      current args is 54, the result is 1485 
      current args is 50, the result is 1275 
      current args is 56, the result is 1596 
      current args is 58, the result is 1711 
      current args is 60, the result is 1830 
      current args is 66, the result is 2211 
      current args is 63, the result is 2016 
      current args is 70, the result is 2485 
      current args is 62, the result is 1953 
      current args is 61, the result is 1891 
      current args is 65, the result is 2145 
      current args is 67, the result is 2278 
      current args is 64, the result is 2080 
      current args is 68, the result is 2346 
      current args is 69, the result is 2415 
      current args is 76, the result is 2926 
      current args is 77, the result is 3003 
      current args is 71, the result is 2556 
      current args is 80, the result is 3240 
      current args is 75, the result is 2850 
      current args is 74, the result is 2775 
      current args is 73, the result is 2701 
      current args is 72, the result is 2628 
      current args is 78, the result is 3081 
      current args is 81, the result is 3321 
      current args is 89, the result is 4005 
      current args is 83, the result is 3486 
      current args is 88, the result is 3916 
      current args is 82, the result is 3403 
      current args is 79, the result is 3160 
      current args is 86, the result is 3741 
      current args is 84, the result is 3570 
      current args is 90, the result is 4095 
      current args is 85, the result is 3655 
      ......
      
      current args is 981, the result is 481671 
      current args is 978, the result is 478731 
      current args is 982, the result is 482653 
      current args is 970, the result is 470935 
      current args is 979, the result is 479710 
      current args is 980, the result is 480690 
      current args is 983, the result is 483636 
      current args is 989, the result is 489555 
      current args is 986, the result is 486591 
      current args is 987, the result is 487578 
      current args is 985, the result is 485605 
      current args is 977, the result is 477753 
      current args is 988, the result is 488566 
      current args is 992, the result is 492528 
      current args is 976, the result is 476776 
      current args is 984, the result is 484620 
      current args is 995, the result is 495510 
      current args is 999, the result is 499500 
      current args is 1000, the result is 500500 
      current args is 990, the result is 490545 
      客戶端并發1000請求,服務器請求隊列長度100,服務器限流10,總共耗時2099 ms  
      

      讀者可以隨意調整3個參數的大小,來感受服務器調參的魅力。

      并發客戶端請求數concurrencyClients 服務器請求隊列queueLength 服務器限流閾值 Maxoutstanding 耗時ms
      1000 100 10 2067
      1000 100 50 454
      1000 100 100 210
      1000 300 10 2082
      1000 500 10 2071
      3000 100 10 6259
      5000 500 10 10516

      完整代碼傳送門

      That’s All,本文根據golang有關信道的指南, 實現了一個帶有請求隊列功能的首先服務器, 鞏固了信道、WaitGroup的用法。

      posted @ 2025-03-12 17:11  碼甲哥不卷  閱讀(266)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 色婷婷欧美在线播放内射 | 97精品久久久大香线焦| 国内极度色诱视频网站| 国内自拍偷拍一区二区三区| 日本中文一区二区三区亚洲| 天堂网av成人在线观看| 2022最新国产在线不卡a| 爱性久久久久久久久| 久久精品免费无码区| 精品不卡一区二区三区| 国产蜜臀久久av一区二区| 人妻中文字幕不卡精品| 毛片网站在线观看| 国产成人综合网在线观看| 丰满人妻一区二区三区色| 毛片tv网站无套内射tv网站| 国产成人av一区二区三| 韩城市| 亚洲一二三四区中文字幕| 亚洲av成人无码精品电影在线| 中文字幕人妻不卡精品| 午夜激情福利在线免费看| 内地自拍三级在线观看| 四房播色综合久久婷婷| 无码精品一区二区三区在线| 国内不卡的一区二区三区| 国产精品中文字幕日韩| 亚洲一区二区三区自拍高清| 免费人成网上在线观看网址| 亚洲精品一二三四区| 少妇人妻综合久久中文字幕| 国产午夜91福利一区二区| 国产在线啪| 日韩精品中文女同在线播放| 亚洲精品蜜桃久久久久久| 国产成人精品午夜在线观看| 亚洲日韩性欧美中文字幕| 亚洲国产成人久久综合三区| 国产精品99中文字幕| 狠狠躁日日躁夜夜躁欧美老妇| 毛片无码一区二区三区|