Skip to content

选择器

选择器负责在一个可选择的对象列表中使用选择策略选择出零个或一个对象,目前选择器所支持的对象有节点和转发链两种。 选择器可以应用于转发链组,转发链,转发链中的跳跃点,和转发器上。选择器在GOST中可以用来实现负载均衡。

strategy (string, default=round)

指定选择策略。

  • round - 轮询
  • rand - 随机
  • fifo - 自上而下,主备模式
  • hash - 基于特定Hash值(客户端IP或目标地址)
  • parallel - 竞速模式,同时向所有节点发起连接,使用最先成功的连接,可通过 maxParallel 限制参与竞速的节点数量
maxFails (int, default=1)
指定最大失败次数,当失败次数超过此设定值时,此对象会被标记为失败(Fail)状态,失败状态的对象不会被选择使用。
failTimeout (duration, default=10s)
指定失败状态的超时时长,当一个对象被标记为失败后,在此设定的时间间隔内不会被选择使用,超过此设定时间间隔后,会再次参与选择。

转发链

转发链中的每一层级跳跃点上可以设置一个选择器,默认选择器使用轮询策略进行节点选择。

gost -L http://:8080 -F "socks5://192.168.1.1:1080,192.168.1.2:1080?strategy=rand&maxFails=1&failTimeout=10s"
services:
- name: service-0
  addr: ":8080"
  handler:
    type: http
    chain: chain-0
  listener:
    type: tcp
chains:
- name: chain-0
  hops:
  - name: hop-0
    selector:
      strategy: rand
      maxFails: 1
      failTimeout: 10s
    nodes:
    - name: node-0
      addr: 192.168.1.1:1080
      connector:
        type: socks5
      dialer:
        type: tcp
      metadata:
        maxFails: 2
        failTimeout: 20s
    - name: node-1
      addr: 192.168.1.2:1080
      connector:
        type: socks5
      dialer:
        type: tcp
      metadata:
        maxFails: 3
        failTimeout: 30s

转发器

转发器用于端口转发,其本身由一个节点组和一个节点选择器组成,当进行转发时,通过选择器在节点组中选择出零个或一个节点用于转发的目标地址。此时转发器类似于只有一个层级的转发链。

gost -L "tcp://:8080/:8081,:8082?strategy=round&maxFails=1&failTimeout=30s"
services:
- name: service-0
  addr: :8080
  handler:
    type: tcp
  listener:
    type: tcp
  forwarder:
    nodes:
    - name: target-0
      addr: :8081
    - name: target-1
      addr: :8082
    selector:
      strategy: round
      maxFails: 1
      failTimeout: 30s

转发链组

转发链组中的选择器类似于转发器中的选择器,用来选择一条转发链。

services:
- name: service-0
  addr: ":8080"
  handler:
    type: http
    chainGroup:
      chains:
      - chain-0
      - chain-1
      selector:
        strategy: round
        maxFails: 1
        failTimeout: 10s
  listener:
    type: tcp
chains:
- name: chain-0
  hops:
  - name: hop-0
    nodes:
    - name: node-0
      addr: :8081
      connector:
        type: http
      dialer:
        type: tcp
- name: chain-1
  hops:
  - name: hop-0
    nodes:
    - name: node-0
      addr: :8082
      connector:
        type: http
      dialer:
        type: tcp

备用节点和备用链

通过将一个或多个节点或转发链标记为备用状态,当所有非备用节点或转发链均被标记为失败状态时才会参与选择。

备用节点

services:
- name: service-0
  addr: :8080
  handler:
    type: http
    chain: chain-0
  listener:
    type: tcp
chains:
- name: chain-0
  hops:
  - name: hop-0
    selector:
      strategy: round
      maxFails: 1
      failTimeout: 10s
    nodes:
    - name: node-0
      addr: :8081
      metadata:
        maxFails: 3
        failTimeout: 30s
      connector:
        type: http
      dialer:
        type: tcp
    - name: node-1
      addr: :8082
      connector:
        type: http
      dialer:
        type: tcp
    - name: node-2
      addr: :8083
      metadata:
        backup: true
      connector:
        type: http
      dialer:
        type: tcp
    - name: node-3
      addr: :8084
      metadata:
        backup: true
      connector:
        type: http
      dialer:
        type: tcp

通过metadata.backup选项将节点标记为备用状态。

正常情况下只有node-0和node-1两个非备用节点参与节点选择,当node-0和node-1均被标记为失败状态时,node-2和node-3才会参与节点选择。当node-0和node-1中任何一个节点恢复后,node-2和node-3退出节点选择。

节点级别失败状态控制

注意这里的node-0节点,通过metadata.maxFails和metadata.failTimeout选项可以对此节点进行单独的失败状态控制,默认使用选择器中的对应参数。

备用转发链

services:
- name: service-0
  addr: :8080
  handler:
    type: http
    chainGroup:
      chains:
      - chain-0
      - chain-1
      - chain-2
      - chain-3
      selector:
        strategy: round
        maxFails: 1
        failTimeout: 10s
  listener:
    type: tcp
chains:
- name: chain-0
  hops:
  - name: hop-0
    nodes:
    - name: node-0
      addr: :8081
      connector:
        type: http
      dialer:
        type: tcp
- name: chain-1
  hops:
  - name: hop-0
    nodes:
    - name: node-0
      addr: :8082
      connector:
        type: http
      dialer:
        type: tcp
- name: chain-2
  metadata:
    backup: true
  hops:
  - name: hop-0
    nodes:
    - name: node-0
      addr: :8083
      connector:
        type: http
      dialer:
        type: tcp
- name: chain-3
  metadata:
    backup: true
  hops:
  - name: hop-0
    nodes:
    - name: node-0
      addr: :8084
      connector:
        type: http
      dialer:
        type: tcp

与备用节点类似,通过metadata.backup选项将转发链chain-2和chain-3标记为备用状态。

加权随机选择策略

选择器在随机选择策略基础上支持对节点和转发链设置权重,权重默认值为1。

services:
- name: service-0
  addr: :8080
  handler:
    type: auto
    chain: chain-0
  listener:
    type: tcp
chains:
- name: chain-0
  hops:
  - name: hop-0
    selector:
      strategy: rand
      maxFails: 1
      failTimeout: 10s
    nodes:
    - name: node-0
      addr: :8081
      metadata:
        weight: 20 
      connector:
        type: http
      dialer:
        type: tcp
    - name: node-1
      addr: :8082
      metadata: 
        weight: 10
      connector:
        type: http
      dialer:
        type: tcp

通过metadata.weight选项对节点(转发链类似)设置权重。node-0与node-1权重比值为2:1,因此node-0被选中几率是node-1的两倍。

Hash策略

Hash策略是针对某一特定数据的Hash值来选择。目前的Hash类型支持客户端IP和请求目标主机地址,默认采用客户端IP。

gost -L http://:8080 -F "socks5://192.168.1.1:1080,192.168.1.2:1080?strategy=hash"

目标地址Hash

每个服务可以单独设置hash类型。

gost -L http://:8080?hash=host -F "socks5://192.168.1.1:1080,192.168.1.2:1080?strategy=hash&maxFails=1&failTimeout=10s"
services:
- name: service-0
  addr: ":8080"
  handler:
    type: http
    chain: chain-0
    metadata:
      hash: host
  listener:
    type: tcp
chains:
- name: chain-0
  hops:
  - name: hop-0
    selector:
      strategy: hash
      maxFails: 1
      failTimeout: 10s
    nodes:
    - name: node-0
      addr: 192.168.1.1:1080
      connector:
        type: socks5
      dialer:
        type: tcp
    - name: node-1
      addr: 192.168.1.2:1080
      connector:
        type: socks5
      dialer:
        type: tcp

通过hash选项指定hash类型为host。

竞速策略

3.3.0

竞速策略(parallel)同时向节点组中的所有节点发起连接,使用第一个成功建立的连接,并关闭其余连接。此策略适用于对延迟敏感的场景,能够自动选择响应最快的节点。

services:
- name: service-0
  addr: :8080
  handler:
    type: auto
    chain: chain-0
  listener:
    type: tcp
chains:
- name: chain-0
  hops:
  - name: hop-0
    selector:
      strategy: parallel
      maxFails: 1
      failTimeout: 10s
    nodes:
    - name: node-0
      addr: 192.168.1.1:1080
      connector:
        type: socks5
      dialer:
        type: tcp
    - name: node-1
      addr: 192.168.1.2:1080
      connector:
        type: socks5
      dialer:
        type: tcp

与负载均衡的区别

竞速策略与传统的负载均衡不同,它不是将请求分摊到各个节点,而是每次都尝试连接所有节点,使用最先成功的那一个。因此竞速策略更适合节点数量较少(2-3个)且对延迟敏感的场景。对于节点数量较多或需要均衡流量的场景,建议使用轮询(round)或随机(rand)策略。

使用 maxParallel 可以限制每次竞速的节点数量,这样节点组规模较大时也不会让每次连接都产生大量并发连接。

多路复用禁用

竞速策略的 Multiplex() 方法硬编码返回 false,即多路复用(Multiplex)功能会被强制禁用。这是因为竞速策略每次请求都可能通过不同的节点,无法保证后续请求复用同一个已建立的连接。

限制参与竞速的节点数量

3.3.1

竞速策略在每次连接时向节点组中的所有节点发起连接。当节点组规模较大时,每次连接都会产生大量并发连接。通过 maxParallel 选项可以限制每次竞速参与连接的节点数量,其余节点仍保留在节点组中,在后续的竞速中参与。

maxParallel (int, default=0)
单次连接中同时参与竞速的节点数量上限。0(默认值),或不小于节点组中节点数量的值,表示不限制,所有节点都参与竞速。
parallelMode (string, default=round)

指定每次竞速的节点在节点组中的选取方式:

  • round - 轮询,取连续的 maxParallel 个节点,每次连接的起始位置向后移动 maxParallel 个节点
  • rand - 随机,每次连接随机抽取 maxParallel 个不同的节点
gost -L http://:8080 -F "socks5://192.168.1.1:1080,192.168.1.2:1080,192.168.1.3:1080?strategy=parallel&maxParallel=2&parallelMode=round"
services:
- name: service-0
  addr: :8080
  handler:
    type: auto
    chain: chain-0
  listener:
    type: tcp
chains:
- name: chain-0
  hops:
  - name: hop-0
    selector:
      strategy: parallel
      maxParallel: 2
      parallelMode: round
      maxFails: 1
      failTimeout: 10s
    nodes:
    - name: node-0
      addr: 192.168.1.1:1080
      connector:
        type: socks5
      dialer:
        type: tcp
    - name: node-1
      addr: 192.168.1.2:1080
      connector:
        type: socks5
      dialer:
        type: tcp
    - name: node-2
      addr: 192.168.1.3:1080
      connector:
        type: socks5
      dialer:
        type: tcp

在轮询模式下,节点组有6个节点且限值为2时,各次竞速依次使用 0-1、2-3、4-5、0-1 这样的连续分组,因此每个节点参与竞速的次数相同。随机模式则每次随机选取参与竞速的节点。

未参与竞速的节点完全不会被连接,因此限值可以在节点组规模较大的情况下将并发连接数控制在一定范围内。

失败的节点仍保留在节点组中

竞速策略中连接失败时被标记的是虚拟节点,而不是竞速失败的候选节点,因此连接失败的节点仍会保留在节点组中,并可能在后续的连接中再次被选中。这与轮询(round)和自上而下(fifo)策略不同,在那些策略中节点自身被标记为失败,随后被失败过滤器跳过。

Comments