Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

添加按照出口网速进行选择的负载均衡 #1924

Closed
wants to merge 1 commit into from

Conversation

strongbugman
Copy link

@strongbugman strongbugman commented Oct 3, 2019

相关issues:#1857 #1825

简单实现了下按照网速快慢来进行负载均衡,定时向相关的outbound发送请求,按照网速选择最优

TOOD:

  1. 如何注入配置,不知道是否接受下面的配置,或者其他方式, done
    "balancers": [
      {
        "tag": "b1",
        "strategy": "optimal",   //new
        "optimal_strategy_config": {
          "timeout": 60,
          "interval": 120, //多久进行一次测速
          "url": "https://github.com/v2ray/v2ray-core/releases/download/v4.21.3/v2ray-linux-64.zip",
          "count": 1 // 一次测速中测试几轮,最后会取平均值得分
        },
        "selector": [
          "jms4",
          "jms3",
          "jms2",
          "jms1",
        ]
      }

2,支持HTTP/HTTPS测试 done
3,测试覆盖率 done

关于测试链接的选择,就这俩天自己使用情况来看,如果是为了照顾浏览网页等内容小但频率高的场景,可以选择返回内容少的targer,进行多轮测试选择平均值;相反,如果为了看视频更快点,可以选择返回内容多的targer,进行单轮测试拿到网速进行比较选择。网络环境错综复杂,如果有更好的策略欢迎讨论

waiting for review 第一次写go项目,欢迎各种指正😅

@ghost
Copy link

ghost commented Oct 3, 2019

还是觉得 #1825 提的方法好一些,因为不用下载完整数据,服务器压力小很多。

我不太懂代码,根据你的描述来看,大概是通过定时下载某个用户指定的网址来测出最快的服务器。这样会有问题。假设某个服务器用github作为target测出来很快,但是那个服务器禁止访问youtube那么用这个方法选服务器就会没法看youtube。

非常感谢大佬努力,等了这么久终于有人开发负载均衡功能!大佬加油!

@strongbugman
Copy link
Author

还是觉得 #1825 提的方法好一些,因为不用下载完整数据,服务器压力小很多。

我不太懂代码,根据你的描述来看,大概是通过定时下载某个用户指定的网址来测出最快的服务器。这样会有问题。假设某个服务器用github作为target测出来很快,但是那个服务器禁止访问youtube那么用这个方法选服务器就会没法看youtube。

非常感谢大佬努力,等了这么久终于有人开发负载均衡功能!大佬加油!

下载什么内容,下载大小都是自己可以配置的,你可以配置一个返回内容小的测试请求比如gstatic/generate_204
第二个问题的话应该属于路由选择的范畴,目前v2ray已经支持根据不同的请求地址匹配不同的outbound或者balancer,如果这个outbound禁止youtube的话这个请求就不应该进到对应的负载均衡里,当然如果可以支持多个测速地址的话更好,但也可以通过选择一个合适测速地址来提高准确性

@Cwek
Copy link

Cwek commented Oct 10, 2019

好像以前提过类似的建议,可以按照给outbound不同的权重、或者直接按照顺序循环来调用。

@wjx0912
Copy link

wjx0912 commented Oct 24, 2019

@strongbugman 值得期待的功能,现在合入主干了吗?

2楼提的ping值不太好,只有下载完整数据才能得到真正网速。如果二级代理用了kcp,ping一点意义也没有。

@m1heng
Copy link

m1heng commented Nov 25, 2019

是否可以将负载均衡策略作为可配置模块进行开发?
@kslr

@strongbugman
Copy link
Author

@ALL 目前功能已完成,看看怎么把测试补上就提交PR了,感兴趣的同学可以先自行编译,在配置文件中加入如下配置:

    "balancers": [
      {
        "tag": "b1",
        "strategy": "optimal",   //new
        "optimal_strategy_config": {
          "timeout": 60,
          "interval": 120, //多久进行一次测速
          "url": "https://github.com/v2ray/v2ray-core/releases/download/v4.21.3/v2ray-linux-64.zip",
          "count": 1 // 一次测速中测试几轮,最后会取平均值得分
        },
        "selector": [
          "jms4",
          "jms3",
          "jms2",
          "jms1",
        ]
      }

@chancat87
Copy link

这样呢?
`{

"inbounds": [
...
],
"outbounds": [
{
"tag": "us1",
...
},
{
"tag": "jp1",
...
},
{
"tag": "jp2",
...
},
{
"tag": "hk1",
...
},
{
"tag": "direct",
...
}
],
"routing": {
"domainStrategy": "IPOnDemand",
"balancers": [
{
"tag": "b1",
"selector": [
"jp1",
"jp2"
]
},
{
"tag": "b2",
"selector": [
"us1",
"hk1"
]
}
],
"rules": [
{
"type": "field",
"outboundTag": "direct",
"ip": [
"geoip:private",
"geoip:cn"
]
},
{
"type": "field",
"outboundTag": "direct",
"domain": [
"geosite:cn"
]
},
{
"type": "field",
"network": "tcp,udp",
"balancerTag": "b1"
}
]
}
}`

@chancat87
Copy link

能弄成clash那样的路由策略就好了...省得每次都要到客户端自己手动设置

@strongbugman
Copy link
Author

@chancat87
balancers要配置strategy哦,为了兼容以前的功能,默认不启用

    "balancers": [
      {
        "tag": "b1",
        "strategy": "optimal",  // 加在这里,默认使用google主页测试
        ......
      }
]

@strongbugman strongbugman changed the title 添加按照出口网速进行选择的负载均衡(未完成!) 添加按照出口网速进行选择的负载均衡 Dec 8, 2019
@jonas-burn
Copy link

我基于这个 PR 做了一些修改,我的分支:
https://github.com/v2ray/v2ray-core/compare/master...jonas-burn:optimal-balancer?expand=1

与这个 PR 的 diff:
https://github.com/strongbugman/v2ray-core/compare/master...jonas-burn:optimal-balancer-strongbugman?expand=1

主要修改内容:

  1. task.Periodic 的初始化加了锁,避免同时起多个定时器。
  2. 异步启动定时器(go s.periodic.Start())。
  3. 配置中,测速请求超时时间(timeout)和测速间隔(interval)的单位从 秒 改为 毫秒。
  4. 重新生成了 protobuf 文件。
  5. 调整了测速执行逻辑,全部测速完成之后再更新实际使用的出口。
  6. 测速时关闭压缩和 KeepAlive 选项(DisableCompressionDisableKeepAlives)。
  7. 配置文件中字段名从 optimal_strategy_config 调整为 optimalSettings
  8. 修正了构建时 v2ctl 无法构建的问题(balancing_optimal_strategy.go 上设置 tag)。

同样不常写 golang 项目,欢迎大家指正交流。

@strongbugman
Copy link
Author

@jonas-burn 我有几个疑问哦

  1. 为啥要加锁呢,有并发的场景嘛
  2. 为啥要包到go程里,我看定时器启动本身是异步的
  3. 我觉的这个方案复杂而且没原来的好,如果一个outbound超时了。。。
  4. 测速时建议跟常用使用场景(浏览网页等)一致

还是感谢改我的烂代码,但要记得保留我的commit哦,另外这个PR还没官方回复,如果我们达成一致,可以先PR到我的分支上

@jonas-burn
Copy link

@strongbugman

为啥要加锁呢,有并发的场景嘛

向上跟踪 PickOutbound() 调用点的话,会发现这个地方起了新的 goroutine:

https://github.com/jonas-burn/v2ray-core/blob/1cc7702/app/dispatcher/default.go#L205-L225

为啥要包到go程里,我看定时器启动本身是异步的

https://github.com/jonas-burn/v2ray-core/blob/1cc7702/common/task/periodic.go#L63

Periodic.Start() 里直接调用了 checkedExecute()checkedExecute() 里直接调用了传入的 func。因此调用 Start() 时会阻塞调用一次传入 func。

我觉的这个方案复杂而且没原来的好,如果一个outbound超时了。。。

是指“全部测速完成之后再更新实际使用的出口”这个修改吗?一个 outbound 超时应该不会影响测速结果吧,只不过会等待一个 timeout 而已,其它部分没有等待测速结果,因此这个 timeout 引入的延迟不会影响到实际功能,只是测速结果更新慢一点而已。

我做这个更改的主要考虑是,不希望在测速过程中持续变更 outbound,因为 outbound 的变更通常意味着出口 IP 的更改,这种变化可能会给很多应用带来问题,因此希望能够尽可能少的变更出口 IP。

测速时建议跟常用使用场景(浏览网页等)一致

这个测速我认为跟场景无关,正如你说的,需要优化网页访问,就填一个响应比较小的测速地址,如果希望优化串流之类的,就填一个响应大一点的。

测速时关闭压缩的主要考虑有两点,一是启用压缩会导致使用者不能非常准确的判断一个测速地址实际的传输大小(比如一个 JS 文件,下载下来 10k,压缩传输也许只有 5k),二是启用压缩可能会带来额外的性能开销,比如服务端压缩可能会引入延迟,客户端解压缩还会无意义地消耗 CPU 时间。

换句话说,我希望“测速”测的是链路的尽可能真实的传输速度,而不是一个包含各种客户端、服务端处理延迟的请求速度,这些不应该是 v2ray 应该考虑的。


如果没有问题,会先 PR 到你的分支上的。

@strongbugman
Copy link
Author

@jonas-burn 多谢解答 我觉得没问题

@ghost
Copy link

ghost commented Feb 9, 2020

我建议 @strongbugman 把 json 中 optimal_strategy_config一项重命名成 settings, 这样比较便于日后的更多类型的 balancer 统一设置
(参考outbound settings 和 inbound settings)

@github-actions
Copy link

github-actions bot commented Sep 3, 2020

It has been open 120 days with no activity. Remove stale label or comment or this will be closed in 5 days

@alexzhang2015
Copy link

相关issues:#1857 #1825

简单实现了下按照网速快慢来进行负载均衡,定时向相关的outbound发送请求,按照网速选择最优

TOOD:

  1. 如何注入配置,不知道是否接受下面的配置,或者其他方式, done
    "balancers": [
      {
        "tag": "b1",
        "strategy": "optimal",   //new
        "optimal_strategy_config": {
          "timeout": 60,
          "interval": 120, //多久进行一次测速
          "url": "https://github.com/v2ray/v2ray-core/releases/download/v4.21.3/v2ray-linux-64.zip",
          "count": 1 // 一次测速中测试几轮,最后会取平均值得分
        },
        "selector": [
          "jms4",
          "jms3",
          "jms2",
          "jms1",
        ]
      }

2,支持HTTP/HTTPS测试 done 3,测试覆盖率 done

关于测试链接的选择,就这俩天自己使用情况来看,如果是为了照顾浏览网页等内容小但频率高的场景,可以选择返回内容少的targer,进行多轮测试选择平均值;相反,如果为了看视频更快点,可以选择返回内容多的targer,进行单轮测试拿到网速进行比较选择。网络环境错综复杂,如果有更好的策略欢迎讨论

waiting for review 第一次写go项目,欢迎各种指正😅

已经合并到主分支了吗

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

7 participants