限制HTTP GET的带宽

huangapple go评论94阅读模式
英文:

Limiting bandwidth of http get

问题

我是一个对golang初学者。

有没有办法限制golang的http.Get()的带宽使用?我找到了这个链接:http://godoc.org/code.google.com/p/mxk/go1/flowcontrol,但我不确定如何将它们组合在一起。我如何访问http Reader?

英文:

I'm a beginner to golang.

Is there any way to limit golang's http.Get() bandwidth usage? I found this: http://godoc.org/code.google.com/p/mxk/go1/flowcontrol, but I'm not sure how to piece the two together. How would I get access to the http Reader?

答案1

得分: 17

第三方包提供了方便的封装。但是如果你对底层的工作原理感兴趣,那就很容易了。

package main

import (
	"io"
	"net/http"
	"os"
	"time"
)

var datachunk int64 = 500       //字节
var timelapse time.Duration = 1 //每秒

func main() {
	responce, _ := http.Get("http://google.com")
	for range time.Tick(timelapse * time.Second) {
		_, err := io.CopyN(os.Stdout, responce.Body, datachunk)
		if err != nil {
			break
		}
	}
}

没有什么魔法。

英文:

Thirdparty packages have convenient wrappers. But if you interested in how things work under the hood - it's quite easy.

package main

import (
	"io"
	"net/http"
	"os"
	"time"
)

var datachunk int64 = 500       //Bytes
var timelapse time.Duration = 1 //per seconds

func main() {
	responce, _ := http.Get("http://google.com")
	for range time.Tick(timelapse * time.Second) {
		_, err :=io.CopyN(os.Stdout, responce.Body, datachunk)
		if err!=nil {break}
	}
}

Nothing magic.

答案2

得分: 6

GitHub 上有一个更新版本的包

你可以通过包装一个 io.Reader 来使用它。

下面是一个完整的示例,它会非常慢地显示 Google 的主页。

在 Go 中,通过包装接口来实现新功能是非常好的编码风格,在你学习 Go 的过程中会经常遇到。

package main

import (
	"io"
	"log"
	"net/http"
	"os"

	"github.com/mxk/go-flowrate/flowrate"
)

func main() {
	resp, err := http.Get("http://google.com")
	if err != nil {
		log.Fatalf("Get failed: %v", err)
	}
	defer resp.Body.Close()

	// 每秒限制为 10 字节
	wrappedIn := flowrate.NewReader(resp.Body, 10)

	// 复制到标准输出
	_, err = io.Copy(os.Stdout, wrappedIn)
	if err != nil {
		log.Fatalf("Copy failed: %v", err)
	}
}
英文:

There is an updated version of the package on github

You use it by wrapping an io.Reader

Here is a complete example which will show the homepage of Google veeeery sloooowly.

This wrapping an interface to make new functionality is very good Go style, and you'll see a lot of it in your journey into Go.

package main

import (
	"io"
	"log"
	"net/http"
	"os"

	"github.com/mxk/go-flowrate/flowrate"
)

func main() {
	resp, err := http.Get("http://google.com")
	if err != nil {
		log.Fatalf("Get failed: %v", err)
	}
	defer resp.Body.Close()

	// Limit to 10 bytes per second
	wrappedIn := flowrate.NewReader(resp.Body, 10)

	// Copy to stdout
	_, err = io.Copy(os.Stdout, wrappedIn)
	if err != nil {
		log.Fatalf("Copy failed: %v", err)
	}
}

答案3

得分: 0

你可以使用https://github.com/ConduitIO/bwlimit来限制服务器和客户端请求的带宽。它与其他库不同之处在于,它尊重读/写截止时间(超时时间),并且限制整个请求(包括标头)的带宽,而不仅仅是请求体。

以下是在客户端上如何使用它的示例代码:

package main

import (
	"io"
	"net"
	"net/http"
	"time"

	"github.com/conduitio/bwlimit"
)

const (
	writeLimit = 1 * bwlimit.Mebibyte // 写入限制为1048576 B/s
	readLimit  = 4 * bwlimit.KB       // 读取限制为4000 B/s
)

func main() {
	// 更改默认传输中的拨号器以使用带宽限制
	dialer := bwlimit.NewDialer(&net.Dialer{
		Timeout:   30 * time.Second,
		KeepAlive: 30 * time.Second,
	}, writeLimit, readLimit)
	http.DefaultTransport.(*http.Transport).DialContext = dialer.DialContext

	// 默认客户端的请求现在遵守带宽限制
	resp, _ := http.DefaultClient.Get("http://google.com")
	_, _ = io.Copy(resp.Body)
}

然而,正如Graham King指出的那样,请记住,从远程读取的数据仍然会尽可能快地填充TCP缓冲区,而该库只会从缓冲区中慢慢读取。不过,限制写入的带宽会产生预期的结果。

英文:

You can use https://github.com/ConduitIO/bwlimit to limit the bandwidth of requests on the server and the client. It differs from other libraries, because it respects read/write deadlines (timeouts) and limits the bandwidth of the whole request including headers, not only the request body.

Here's how to use it on the client:

package main

import (
	"io"
	"net"
	"net/http"
	"time"

	"github.com/conduitio/bwlimit"
)

const (
	writeLimit = 1 * bwlimit.Mebibyte // write limit is 1048576 B/s
	readLimit  = 4 * bwlimit.KB       // read limit is 4000 B/s
)

func main() {
	// change dialer in the default transport to use a bandwidth limit
	dialer := bwlimit.NewDialer(&net.Dialer{
		Timeout:   30 * time.Second,
		KeepAlive: 30 * time.Second,
	}, writeLimit, readLimit)
	http.DefaultTransport.(*http.Transport).DialContext = dialer.DialContext

	// requests through the default client respect the bandwidth limit now
	resp, _ := http.DefaultClient.Get("http://google.com")
	_, _ = io.Copy(resp.Body)
}

However, as Graham King pointed out, keep in mind that reads from remote will still fill the TCP buffer as fast as possible, this library will only read slowly from the buffer. Limiting the bandwidth of writes produces the expected result though.

huangapple
  • 本文由 发表于 2015年1月10日 05:52:54
  • 转载请务必保留本文链接:https://go.coder-hub.com/27869858.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定