精华内容
下载资源
问答
  • 负载均衡策略

    2019-12-17 17:54:00
  • 前言这篇文章将介绍如何实现自定义负载均衡策略-- 加权随机法 。加权随机法 可以根据服务器的处理能力而分配不同的权重,从而实现处理能力高的服务器可承担更多的请求,处理能力低的服务器少承担请求。自定义负载...

    前言

    这篇文章将介绍如何实现自定义负载均衡策略-- 加权随机法 。

    9c6fe8b7c6cc8c858ae4a4d22b6c8b41.png

    加权随机法 可以根据服务器的处理能力而分配不同的权重,从而实现处理能力高的服务器可承担更多的请求,处理能力低的服务器少承担请求。

    自定义负载均衡策略

    gRPC提供了 V2PickerBuilder 和 V2Picker 接口让我们实现自己的负载均衡策略。

    type V2PickerBuilder interface {Build(info PickerBuildInfo) balancer.V2Picker}

    V2PickerBuilder 接口:创建V2版本的子连接选择器。

    Build 方法:返回一个V2选择器,将用于gRPC选择子连接。

    type V2Picker interface {Pick(info PickInfo) (PickResult, error)}

    V2Picker 接口:用于gRPC选择子连接去发送请求。 Pick 方法:子连接选择

    问题来了,我们需要把服务器地址的权重添加进去,但是地址 resolver.Address 并没有提供权重的属性。官方给的答复是:把权重存储到地址的元数据 metadata 中。

    // attributeKey is the type used as the key to store AddrInfo in the Attributes// field of resolver.Address.type attributeKey struct{}// AddrInfo will be stored inside Address metadata in order to use weighted balancer.type AddrInfo struct {Weight int}// SetAddrInfo returns a copy of addr in which the Attributes field is updated// with addrInfo.func SetAddrInfo(addr resolver.Address, addrInfo AddrInfo) resolver.Address {addr.Attributes = attributes.New()addr.Attributes = addr.Attributes.WithValues(attributeKey{}, addrInfo)return addr}// GetAddrInfo returns the AddrInfo stored in the Attributes fields of addr.func GetAddrInfo(addr resolver.Address) AddrInfo {v := addr.Attributes.Value(attributeKey{})ai, _ := v.(AddrInfo)return ai}

    定义 AddrInfo 结构体并添加权重 Weight 属性, Set 方法把 Weight 存储到 resolver.Address 中, Get 方法从 resolver.Address 获取 Weight 。

    解决权重存储问题后,接下来我们实现加权随机法负载均衡策略。

    首先实现 V2PickerBuilder 接口,返回子连接选择器。

    func (*rrPickerBuilder) Build(info base.PickerBuildInfo) balancer.V2Picker {grpclog.Infof("weightPicker: newPicker called with info: %v", info)if len(info.ReadySCs) == 0 {return base.NewErrPickerV2(balancer.ErrNoSubConnAvailable)}var scs []balancer.SubConnfor subConn, addr := range info.ReadySCs {node := GetAddrInfo(addr.Address)if node.Weight <= 0 {node.Weight = minWeight} else if node.Weight > 5 {node.Weight = maxWeight}for i := 0; i < node.Weight; i++ {scs = append(scs, subConn)}}return &rrPicker{subConns: scs,}}

    加权随机法 中,我使用空间换时间的方式,把权重转成地址个数(例如 addr1 的权重是 3 ,那么添加 3 个子连接到切片中; addr2 权重为 1 ,则添加 1 个子连接;选择子连接时候,按子连接切片长度生成随机数,以随机数作为下标就是选中的子连接),避免重复计算权重。考虑到内存占用,权重定义从 1 到 5 权重。

    接下来实现子连接的选择,获取随机数,选择子连接

    type rrPicker struct {subConns []balancer.SubConnmu sync.Mutex}func (p *rrPicker) Pick(balancer.PickInfo) (balancer.PickResult, error) {p.mu.Lock()index := rand.Intn(len(p.subConns))sc := p.subConns[index]p.mu.Unlock()return balancer.PickResult{SubConn: sc}, nil}

    关键代码完成后,我们把加权随机法负载均衡策略命名为 weight ,并注册到gRPC的负载均衡策略中。

    // Name is the name of weight balancer.const Name = "weight"// NewBuilder creates a new weight balancer builder.func newBuilder() balancer.Builder {return base.NewBalancerBuilderV2(Name, &rrPickerBuilder{}, base.Config{HealthCheck: false})}func init() {balancer.Register(newBuilder())}

    完整代码 weight.go

    最后,我们只需要在服务端注册服务时候附带权重,然后客户端在服务发现时把权重 Set 到 resolver.Address 中,最后客户端把负载论衡策略改成 weight 就完成了。

    //SetServiceList 设置服务地址func (s *ServiceDiscovery) SetServiceList(key, val string) {s.lock.Lock()defer s.lock.Unlock()//获取服务地址addr := resolver.Address{Addr: strings.TrimPrefix(key, s.prefix)}//获取服务地址权重nodeWeight, err := strconv.Atoi(val)if err != nil {//非数字字符默认权重为1nodeWeight = 1}//把服务地址权重存储到resolver.Address的元数据中addr = weight.SetAddrInfo(addr, weight.AddrInfo{Weight: nodeWeight})s.serverList[key] = addrs.cc.UpdateState(resolver.State{Addresses: s.getServices()})log.Println("put key :", key, "wieght:", val)}

    客户端使用 weight 负载均衡策略

    func main() {r := etcdv3.NewServiceDiscovery(EtcdEndpoints)resolver.Register(r)// 连接服务器conn, err := grpc.Dial(fmt.Sprintf("%s:///%s", r.Scheme(), SerName),grpc.WithBalancerName("weight"),grpc.WithInsecure(),)if err != nil {log.Fatalf("net.Connect err: %v", err)}defer conn.Close()

    运行效果:

    运行 服务1 ,权重为 1

    c6daaadbaea25294f1ec7fefd587a534.png

    运行 服务2 ,权重为 4

    aed11bdf148c033b8a3d961f6fe67c31.png

    运行客户端

    9b6ff3f40decd062c6adf24f3c514937.png

    查看前50次请求在 服务1 和 服务器2 的负载情况。 服务1 分配了 9 次请求, 服务2 分配了 41 次请求,接近权重比值。

    ff177644bb53b6a9369734a8436c86f0.png
    d225af7499cf69c65eca0c04d96a75df.png

    断开 服务2 ,所有请求流向 服务1

    4a23afcf177fb0da971e863ea1ce3b13.png

    以权重为 4 ,重启 服务2 ,请求以加权随机法流向两个服务器

    67c08bc14d017bb721b9e47464015b49.png

    总结

    本篇文章以加权随机法为例,介绍了如何实现gRPC自定义负载均衡策略,以满足我们的需求。

    源码地址:https://github.com/Bingjian-Zhu/etcd-example

    展开全文
  • 负载均衡策略有哪些?在实际应用中,我们可能不想仅仅是把客户端的服务请求平均地分配给内部服务器,而不管服务器是否宕机。而是想使Pentium III服务器比Pentium II能接受更多的服务请求,一台处理服务请求较少的...

    65de33a9627e957011a3feaf15481ac4.png

    负载均衡策略有哪些?在实际应用中,我们可能不想仅仅是把客户端的服务请求平均地分配给内部服务器,而不管服务器是否宕机。而是想使Pentium III服务器比Pentium II能接受更多的服务请求,一台处理服务请求较少的服务器能分配到更多的服务请求,出现故障的服务器将不再接受服务请求直至故障恢复等等。

    1640b87af371868cb769f77515918ee7.png

    负载均衡策略有哪些

    选择合适的策略,使多个设备能很好的共同完成任务,消除或避免现有网络负载分布不均、数据流量拥挤反应时间长的瓶颈。在各负载均衡方式中,针对不同的应用需求,在OSI参考模型的第二层负载均衡、三层负载均衡、、七层的负载均衡都有相应的负载均衡策略。

    负载均衡策略的优劣及其实现的难易程度有两个关键因素:一、负载均衡算法,二、对网络系统状况的检测方式和能力。

    考虑到服务请求的不同类型、服务器的不同处理能力以及随机选择造成的负载分配不均匀等问题,为了更加合理的把负载分配给内部的多个服务器,就需要应用相应的能够正确反映各个服务器处理能力及网络状态的负载均衡算法:

    轮循均衡(Round Robin):每一次来自网络的请求轮流分配给内部中的服务器,从1至N然后重新开始。此种均衡算法适合于服务器组中的所有服务器都有相同的软硬件配置并且平均服务请求相对均衡的情况。

    权重轮循均衡(Weighted Round Robin):根据服务器的不同处理能力,给每个服务器分配不同的权值,使其能够接受相应权值数的服务请求。例如:服务器A的权值被设计成1,B的权值是 3,C的权值是6,则服务器A、B、C将分别接受到10%、30%、60%的服务请求。此种均衡算法能确保高性能的服务器得到更多的使用率,避免低性能的服务器负载过重。

    随机均衡(Random):把来自网络的请求随机分配给内部中的多个服务器。

    权重随机均衡(Weighted Random):此种均衡算法类似于权重轮循算法,不过在处理请求分担时是个随机选择的过程。

    响应速度均衡(Response Time):负载均衡设备对内部各服务器发出一个探测请求(例如Ping),然后根据内部中各服务器对探测请求的最快响应时间来决定哪一台服务器来响应客户端的服务请求。此种均衡算法能较好的反映服务器的当前运行状态,但这最快响应时间仅仅指的是负载均衡设备与服务器间的最快响应时间,而不是客户端与服务器间的最快响应时间。

    最少连接数均衡(Least Connection):客户端的每一次请求服务在服务器停留的时间可能会有较大的差异,随着工作时间加长,如果采用简单的轮循或随机均衡算法,每一台服务器上的连接进程可能会产生极大的不同,并没有达到真正的负载均衡。最少连接数均衡算法对内部中需负载的每一台服务器都有一个数据记录,记录当前该服务器正在处理的连接数量,当有新的服务连接请求时,将把当前请求分配给连接数最少的服务器,使均衡更加符合实际情况,负载更加均衡。此种均衡算法适合长时处理的请求服务,如FTP。

    处理能力均衡:此种均衡算法将把服务请求分配给内部中处理负荷(根据服务器CPU型号、CPU数量、内存大小及当前连接数等换算而成)最轻的服务器,由于考虑到了内部服务器的处理能力及当前网络运行状况,所以此种均衡算法相对来说更加精确,尤其适合运用到第七层(应用层)负载均衡的情况下。

    DNS响应均衡(Flash DNS):在Internet上,无论是HTTP、FTP或是其它的服务请求,客户端一般都是通过域名解析来找到服务器确切的IP地址的。在此均衡算法下,分处在不同地理位置的负载均衡设备收到同一个客户端的域名解析请求,并在同一时间内把此域名解析成各自相对应服务器的IP地址(即与此负载均衡设备在同一位地理位置的服务器的IP地址)并返回给客户端,则客户端将以最先收到的域名解析IP地址来继续请求服务,而忽略其它的IP地址响应。在种均衡策略适合应用在全局负载均衡的情况下,对本地负载均衡是没有意义的。

    尽管有多种的负载均衡算法可以较好的把数据流量分配给服务器去负载,但如果负载均衡策略没有对网络系统状况的检测方式和能力,一旦在某台服务器或某段负载均衡设备与服务器网络间出现故障的情况下,负载均衡设备依然把一部分数据流量引向那台服务器,这势必造成大量的服务请求被丢失,达不到不间断可用性的要求。所以良好的负载均衡策略应有对网络故障、服务器系统故障、应用服务故障的检测方式和能力:

    Ping侦测:通过ping的方式检测服务器及网络系统状况,此种方式简单快速,但只能大致检测出网络及服务器上的操作系统是否正常,对服务器上的应用服务检测就无能为力了。

    TCP Open侦测:每个服务都会开放某个通过TCP连接,检测服务器上某个TCP端口(如Telnet的23口,HTTP的80口等)是否开放来判断服务是否正常。

    HTTP URL侦测:比如向HTTP服务器发出一个对main.html文件的访问请求,如果收到错误信息,则认为服务器出现故障。

    负载均衡策略的优劣除受上面所讲的两个因素影响外,在有些应用情况下,我们需要将来自同一客户端的所有请求都分配给同一台服务器去负担,例如服务器将客户端注册、购物等服务请求信息保存的本地数据库的情况下,把客户端的子请求分配给同一台服务器来处理就显的至关重要了。有两种方式可以解决此问题,一是根据IP地址把来自同一客户端的多次请求分配给同一台服务器处理,客户端IP地址与服务器的对应信息是保存在负载均衡设备上的;二是在客户端浏览器 cookie内做独一无二的标识来把多次请求分配给同一台服务器处理,适合通过代理服务器上网的客户端。

    还有一种路径外返回模式(Out of Path Return),当客户端连接请求发送给负载均衡设备的时候,中心负载均衡设备将请求引向某个服务器,服务器的回应请求不再返回给中心负载均衡设备,即绕过流量分配器,直接返回给客户端,因此中心负载均衡设备只负责接受并转发请求,其网络负担就减少了很多,并且给客户端提供了更快的响应时间。此种模式一般用于HTTP服务器群,在各服务器上要安装一块虚拟网络适配器,并将其IP地址设为服务器群的VIP,这样才能在服务器直接回应客户端请求时顺利的达成三次握手

    展开全文
  • Ribbon负载均衡策略——随机负载均衡策略使用 /** * 该类为Ribbon的配置类 * 注意:该类不能放在主应用程序上下文@ComponentScan所扫描的包中,否则配置将会被所有Ribbon Client共享。*/ @Configuration public ...

    Ribbon负载均衡策略——随机负载均衡策略使用


    /**
     * 该类为Ribbon的配置类
     * 注意:该类不能放在主应用程序上下文@ComponentScan所扫描的包中,否则配置将会被所有Ribbon Client共享。*/
    @Configuration
    public class RibbonConfiguration {
      @Bean
      public IRule ribbonRule() {
        // 负载均衡规则,改为随机
        return new RandomRule();
      }
    }
    
    展开全文
  • 可以自行扩展负载均衡策略,参见 :负载均衡扩展负载均衡策略Random LoadBalance随机,按权重设置随机概率。在一个截面上碰撞的概率高,但调用量越大分布越均匀,而且按概率使用权重后也比较均匀,有利于动态调整...
  • 二、Nginx负载均衡策略 负载均衡用于从“upstream”模块定义的后端服务器列表中选取一台服务器接受用户的请求。一个最基本的upstream模块是这样的,模块内的server是服务器列表: 在upstream模块配置完成后,要让...
  • Ribbon负载均衡策略——重试负载均衡策略使用 RetryRule 先按照轮转策略分发,如果不能访问,在指定时间内重试,分发其他可用服务。 /** * 该类为Ribbon的配置类 * 注意:该类不能放在主应用程序上下文@...
  • spring-cloud学习笔记之负载均衡:spring-cloud-Ribbon 负载均衡器策略 自定义负载均衡策略spring-cloud学习笔记之负载均衡:spring-cloud-Ribbon 负载均衡器策略 自定义负载均衡策略 spring-cloud学习笔记之负载...
  • Dubbo负载均衡策略.pdf

    2020-04-05 12:51:57
    Dubbo负载均衡策略
  • 1、Dubbo支持的负载均衡策略1)、随机:Random LoadBalance随机,按权重设置随机概率。在一个截面上碰撞的概率高,但调用量越大分布越均匀,而且按概率使用权重后也比较均匀,有利于动态调整提供者权重。2)、轮询:...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 7,340
精华内容 2,936
关键字:

负载均衡策略