文章目录
第2章 扫盲网关前置技术:必备网络基础2-1 为什么要学习网络基础2-3 tcpdump抓包分析三次握手和四次挥手2-4 为啥time_wait需要等待2msl_必备网络基础2-5 节流开源 - TCP为啥需要流量控制
网络代理4-3 并发限速的意义漏桶限流令牌桶限流
第9章 项目实战:开发前准备 Vue+Go组合10-1 数据表整理与创建
第10章 项目实战之后台管理后端功能swagger日志10-3 后端开发步骤
第2章 扫盲网关前置技术:必备网络基础
2-1 为什么要学习网络基础
2-3 tcpdump抓包分析三次握手和四次挥手
双工:双方都是能够发送、接收消息
2-4 为啥time_wait需要等待2msl_
必备网络基础
2-5 节流开源 - TCP为啥需要流量控制
网络代理
4-3 并发限速的意义
漏桶限流
package main
import (
"context"
"golang.org/x/time/rate"
"log"
"testing"
"time"
)
func Test_RateLimiter(t
*testing
.T
) {
l
:= rate
.NewLimiter(1, 5)
log
.Println(l
.Limit(), l
.Burst())
for i
:= 0; i
< 100; i
++ {
log
.Println("before Wait")
c
, _ := context
.WithTimeout(context
.Background(), time
.Second
*2)
if err
:= l
.Wait(c
); err
!= nil {
log
.Println("limiter wait err:" + err
.Error())
}
log
.Println("after Wait")
r
:= l
.Reserve()
log
.Println("reserve Delay:", r
.Delay())
a
:= l
.Allow()
log
.Println("Allow:", a
)
}
}
令牌桶限流
package main
import (
"fmt"
"net"
"os"
"sync/atomic"
"time"
)
var (
limiting
int32 = 1
)
func main() {
tcpAddr
, err
:= net
.ResolveTCPAddr("tcp4", "0.0.0.0:9090")
checkError(err
)
listener
, err
:= net
.ListenTCP("tcp", tcpAddr
)
checkError(err
)
defer listener
.Close()
for {
conn
, err
:= listener
.Accept()
if err
!= nil {
fmt
.Println(err
)
continue
}
go handle(&conn
)
}
}
func handle(conn
*net
.Conn
) {
defer (*conn
).Close()
n
:= atomic
.AddInt32(&limiting
, -1)
if n
< 0 {
(*conn
).Write([]byte("HTTP/1.1 404 NOT FOUND\r\n\r\nError, too many request, please try again."))
} else {
time
.Sleep(1 * time
.Second
)
(*conn
).Write([]byte("HTTP/1.1 200 OK\r\n\r\nI can change the world!"))
}
atomic
.AddInt32(&limiting
, 1)
}
func checkError(err
error) {
if err
!= nil {
fmt
.Fprintf(os
.Stderr
, "Fatal error: %s", err
.Error())
os
.Exit(1)
}
}
https://www.jianshu.com/p/9032c6f41f1e
第9章 项目实战:开发前准备 Vue+Go组合
10-1 数据表整理与创建
第10章 项目实战之后台管理后端功能
一键解决 go get golang.org/x 包失败
export GOPROXY=https://goproxy.io
go mod tidy
swagger日志
swagger init
http://localhost:8880/swagger/index.html
10-3 后端开发步骤