• grpc-go 连接backoff协议


    当我们连接到一个失败的后端时,通常希望不要立即重试(以避免泛滥的网络或服务器的请求),而是做某种形式的指数backoff。

    我们有几个参数:

    1. INITIAL_BACKOFF (第一次失败重试前后需等待多久)
    2. MULTIPLIER (在失败的重试后乘以的倍数)
    3. JITTER (随机抖动因子).
    4. MAX_BACKOFF (backoff上限)
    5. MIN_CONNECT_TIMEOUT (最短重试间隔)

    建议backoff算法

    以指数形式返回连接尝试的起始时间,达到MAX_BACKOFF的极限,并带有抖动。

    1
    2
    3
    4
    5
    6
    7
    ConnectWithBackoff()
    current_backoff = INITIAL_BACKOFF
    current_deadline = now() + INITIAL_BACKOFF
    while (TryConnect(Max(current_deadline, now() + MIN_CONNECT_TIMEOUT))!= SUCCESS)
    SleepUntil(current_deadline)
    current_backoff = Min(current_backoff * MULTIPLIER, MAX_BACKOFF)
    current_deadline = now() + current_backoff + UniformRandom(-JITTER * current_backoff, JITTER * current_backoff)

    参数默认值MIN_CONNECT_TIMEOUT=20sec INITIAL_BACKOFF=1sec MULTIPLIER=1.6 MAX_BACKOFF=120sec JITTER=0.2

    根据的确切的关注点实现(例如最小化手机的唤醒次数)可能希望使用不同的算法,特别是不同的抖动逻辑。

    备用的实现必须确保连接退避在同一时间开始分散,并且不得比上述算法更频繁地尝试连接。

    重置backoff

    backoff应在某个时间点重置为INITIAL_BACKOFF,以便重新连接行为是一致的,不管连接的是新开始的还是先前断开的连接。

    当接收到SETTINGS帧时重置backoff,在那个时候,我们确定这个连接被服务器已经接受了。


    grpc-go

    源码位于google.golang.org/grpc/backoff,代码不多,直接在代码上分析。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57

    import (
    "math/rand"
    "time"
    )

    // 对应上面的默认值但是没有实现MIN_CONNECT_TIMEOUT参数
    var DefaultBackoffConfig = BackoffConfig{
    MaxDelay: 120 * time.Second,
    baseDelay: 1.0 * time.Second,
    factor: 1.6,
    jitter: 0.2,
    }

    // backoffStrategy是backoff算法的接口
    type backoffStrategy interface {
    // 通过重试次数返回在下一次重试之前等待的时间量
    backoff(retries int) time.Duration
    }

    type BackoffConfig struct {
    MaxDelay time.Duration
    baseDelay time.Duration
    factor float64
    jitter float64
    }

    func setDefaults(bc *BackoffConfig) {
    md := bc.MaxDelay
    *bc = DefaultBackoffConfig

    if md > 0 {
    bc.MaxDelay = md
    }
    }

    // backoff算法的基础实现
    func (bc BackoffConfig) backoff(retries int) time.Duration {
    if retries == 0 {
    return bc.baseDelay
    }
    backoff, max := float64(bc.baseDelay), float64(bc.MaxDelay)
    for backoff < max && retries > 0 {
    backoff *= bc.factor
    retries--
    }
    if backoff > max {
    backoff = max
    }
    // Randomize backoff delays so that if a cluster of requests start at
    // the same time, they won't operate in lockstep.
    backoff *= 1 + bc.jitter*(rand.Float64()*2-1)
    if backoff < 0 {
    return 0
    }
    return time.Duration(backoff)
    }

    如果默认的backoff算法不满足需求的时候,还可以自定义backoff算法,通过实现backoffStrategy接口。

    1
    2
    3
    4
    5
    6
    7
    func withBackoff(bs backoffStrategy) DialOption {
    return func(o *dialOptions) {
    o.bs = bs
    }
    }

    grpc.Dial(addr, grpc.withBackoff(mybackoff))
  • 相关阅读:
    爬虫-某游戏交易网站商品信息爬取
    爬虫-淘宝selenium模拟登录取cookie
    设计模式
    xadmin安装2
    MySQL用户授权 和 bin-log日志 详解和实战
    用Redis实现分布式锁 与 实现任务队列
    基于H5的微信支付开发详解
    静态资源文件自动压缩并替换成压缩版本(大型网站优化技术)
    IP、TCP和DNS与HTTP的密切关系
    减少HTTP请求之将图片转成二进制并生成Base64编码,可以在网页中通过url查看图片(大型网站优化技术)
  • 原文地址:https://www.cnblogs.com/gao88/p/12121102.html
Copyright © 2020-2023  润新知