零拷贝读取文件成 Go 对象

taowen 发表了文章 • 2 个评论 • 330 次浏览 • 2017-12-06 23:32 • 来自相关话题

我们观察到从文件读取到go对象,需要两次拷贝:

  1. 从文件拷贝到内存,成为[]byte
  2. 从[]byte,按照格式进行读取,拷贝到go对象上

怎么样优化这个读取速度呢?

    ... 查看全部

我们观察到从文件读取到go对象,需要两次拷贝:



  1. 从文件拷贝到内存,成为[]byte

  2. 从[]byte,按照格式进行读取,拷贝到go对象上


怎么样优化这个读取速度呢?



  1. 利用mmap,把文件直接映射到内存,go允许把这片内存已经转化成[]byte来使用

  2. 直接在这个[]byte上“展开”go对象


所谓”展开“就是一个reinterpret cast,对一个指针的类型重新解读。


var bytes = []byte{
16, 0, 0, 0, 0, 0, 0, 0,
5, 0, 0, 0, 0, 0, 0, 0,
'h', 'e', 'l', 'l', 'o'}

假设有这样一个[]byte数组。这个是直接用mmap读取出来的。


var ptr = &bytes[0]

这个ptr就是这片内存区域的指针,指向了开头的第一个元素


type stringHeader struct {
Data uintptr
Len int
}

header := (*stringHeader)(unsafe.Pointer(ptr))

这样我们就把这个内存重新解读为了一个stringHeader了。利用stringHeader就可以构造出string来。


header.Data = uintptr(unsafe.Pointer(&bytes[16]))

把stringHeader的指针指向实际的hello数据部分。


str := (*string)(unsafe.Pointer(ptr))
fmt.Println(str) // "hello"

最后再把同一片内存区域解读为string类型,就得到了"hello"字符串了。整个解码过程只做了一次header.Data的更新,没有做任何内存分配。


相比Java来说,go允许我们使用go自己的heap外的内存。甚至允许把go的对象直接在这片内存上构造出来。这使得我们的应用可以和文件系统的缓存共享一片内存,达到内存利用率的最大化。同时相比protobuf/thrift来说,gocodec就是把cpu对值的内存表示(little endian的integer等),以及go语言对象的内存表示(stringHeader,sliceHeader)直接拷贝了,减少了编解码的计算成本。


完整的代码,欢迎star:bloomfilter_test.go


设计了一个编解码格式叫 github.com/esdb/gocodec


和protobuf的对比还没有测,和json相比,毫无悬念地不在一个量级上。


gocodec 200000 10893 ns/op 288 B/op 2 allocs/op
json 300 3746169 ns/op 910434 B/op 27 allocs/op

推荐一个简化搜索的web小工具“咸鱼SOS”【附上服务器端代码】

kaesalai 发表了文章 • 1 个评论 • 259 次浏览 • 2017-12-06 16:01 • 来自相关话题

咸鱼SOS 链接地址:http://xianyusos.fun

查看全部

咸鱼SOS 链接地址:http://xianyusos.fun



反正不要钱,不用白不用~ —— 周树人



使用咸鱼SOS可以简化搜索步骤,举个栗子,老师要小明同学在github中搜索“golang”关键字,查看golang的开源项目




  1. 普通小明会在浏览器的输入框中输入“github.com”,等网页显示出来后再找到搜索框搜索;




  2. 2B小明会先打开百度,在百度中搜索“github”,再选中github官网,等网页显示出来后再找到搜索框搜索;



  3. 文艺小明会把咸鱼SOS设置为首页或者加入书签,只用选中左边的GitHub,就可以直接使用中央的搜索框搜索github里的内容了。




服务端代码如下,请斧正:
server.go


package main

import (
"github.com/labstack/echo"
"xianyusos/handlers"
"io"
"html/template"
"time"
"gopkg.in/redis.v5"
"github.com/sirupsen/logrus"
"os"
"fmt"
)

const (
PERIOD = 1*time.Hour
)

type Template struct {
Templates *template.Template
}

func (t *Template) Render(w io.Writer, name string, data interface{}, c echo.Context) error {
return t.Templates.ExecuteTemplate(w, name, data)
}

func main() {
if err := getEnvs(); err != nil {
panic(err)
}
e := echo.New()
defer e.Close()
h, err := handlers.New()
if err != nil {
panic(err)
}
defer h.Client.Close()
e.Renderer = &Template{
Templates: template.Must(template.ParseGlob("views/*.html")),
}
logrus.SetOutput(os.Stdout)

go func() {
for {
time.Sleep(PERIOD)
if err := h.Client.Ping().Err(); err != nil {
logrus.Errorf("Error in h.Client.Ping: [%s].", err.Error())
h.Client = redis.NewClient(&redis.Options{
Addr: handlers.REDIS_ADDRESS,
Password: handlers.REDIS_PASSWORD,
MaxRetries: 5,
})
logrus.Infof("Reconnect redis[%s].", handlers.REDIS_ADDRESS)
}
for k, v := range h.VisitorsIp {
if err := h.Client.HSet("visitors", k, v).Err(); err != nil {
logrus.Errorf("Error in h.Client.Set: [%s].", err.Error())
continue
}
}
logrus.Info("Update the value of visitors success.")
}
}()

e.GET("/", h.Home)
e.GET("/:routerName", h.Search)
e.Static("/static", "views")
e.File("/favicon.ico", "views/katongxianyu.png")
//h.RouterName["163music"] = true
h.RouterName["github"] = true
h.RouterName["baidu"] = true
h.RouterName["bilibili"] = true
h.RouterName["iqiyi"] = true
h.RouterName["jd"] = true
h.RouterName["mooc"] = true
h.RouterName["qidian"] = true
h.RouterName["runoob"] = true
h.RouterName["segmentfault"] = true
h.RouterName["stackoverflow"] = true
h.RouterName["taobao"] = true
h.RouterName["weibo"] = true
h.RouterName["youku"] = true
h.RouterName["zhihu"] = true
e.Start(":8823")
}

func getEnvs() error {
handlers.REDIS_ADDRESS = os.Getenv("REDIS_ADDRESS")
if len(handlers.REDIS_ADDRESS) == 0 {
return fmt.Errorf("Env [REDIS_ADDRESS] is nil.")
}
handlers.REDIS_PASSWORD = os.Getenv("REDIS_PASSWORD")
if len(handlers.REDIS_PASSWORD) == 0 {
return fmt.Errorf("Env [REDIS_PASSWORD] is nil.")
}
return nil
}

handler.go


package handlers

import (
"github.com/labstack/echo"
"net/http"
"gopkg.in/redis.v5"
"sync"
"strings"
)

var (
REDIS_ADDRESS = "na.huanyu0w0.cn:2333"
REDIS_PASSWORD = "3.1415926"
)

type (
handler struct {
Client *redis.Client
Mux sync.Mutex
RouterName map[string]bool
VisitorsIp map[string]string
}
)

func New() (*handler, error) {
h := new(handler)
h.Client = redis.NewClient(&redis.Options{
Addr: REDIS_ADDRESS,
Password: REDIS_PASSWORD,
MaxRetries: 5,
})
var err error
h.VisitorsIp, err = h.Client.HGetAll("visitors").Result()
if err != nil {
return nil, err
}
h.Mux = sync.Mutex{}
h.RouterName = make(map[string]bool)
return h, nil
}

func (h *handler) Home(c echo.Context) error {
routerName := ""
for routerName = range h.RouterName {
break
}
return c.Redirect(http.StatusFound, "/"+routerName)
}

func (h *handler) Search(c echo.Context) error {
h.Mux.Lock()
ip := strings.Split(c.Request().RemoteAddr, ":")[0]
h.VisitorsIp[ip] = ip
h.Mux.Unlock()
routerName := c.Param("routerName")
if len(routerName) == 0 {
return echo.ErrNotFound
}
if b, ok := h.RouterName[routerName]; !ok && b == true {
return echo.ErrNotFound
}
return c.Render(http.StatusOK, routerName, len(h.VisitorsIp))
}

分享一个带 TTL 以及失效回调的 LRU 库. https://github.com/Akagi201/kvcache

Akagi201 发表了文章 • 0 个评论 • 275 次浏览 • 2017-12-06 15:04 • 来自相关话题

https://github.com/Akagi201/kvcache

包含一个完整功能版本(每一个 TTL 的 key 用一个 gorou... 查看全部

https://github.com/Akagi201/kvcache


包含一个完整功能版本(每一个 TTL 的 key 用一个 goroutine 进行维护), 以及轻量级版本 (不使用 goroutine, 这样 TTL 时间计算不是很准确, 具体看代码逻辑)


完美达到我的业务需要的效果. 大家有同样的需求可以测试测试.


有问题一定向我反馈. akagi201@gmail.com

tsdump-用于导出数据库表结构的工具(支持导出为text、markdown、csv、json)

voidint 发表了文章 • 0 个评论 • 306 次浏览 • 2017-12-03 20:32 • 来自相关话题

项目地址: https://github.com/voidint/tsdump

特性

  • 支持将数据库(当前仅支持查看全部

项目地址: https://github.com/voidint/tsdump


特性



  • 支持将数据库(当前仅支持MySQL)及其表结构的元数据以textmarkdownjsoncsv形式输出。


安装


$ go get -u github.com/voidint/tsdump

基本使用




  • 全局选项


    GLOBAL OPTIONS:
    -H value, --host value Connect to host. (default: "127.0.0.1")
    -P value, --port value Port number to use for connection. (default: 3306)
    -u value, --user value User for login if not current user. (default: "voidint")
    -p value, --password value Password to use when connecting to server.
    -d value, --db value Database name.
    -V value, --viewer value Output viewer. Optional values: txt|csv|json|md (default: "txt")
    -o value, --output value Write to a file, instead of STDOUT.
    -D, --debug Enable debug mode.
    --help, -h show help
    --version, -v print the version



  • 使用root用户创建一个名为mydb的数据库实例,以及一张student的表。


    CREATE DATABASE IF NOT EXISTS `mydb` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;

    USE `mydb`;

    CREATE TABLE `student` (
    `sno` char(8) NOT NULL COMMENT '学号',
    `sname` varchar(255) NOT NULL COMMENT '姓名',
    `gender` char(2) DEFAULT NULL COMMENT '性别',
    `native` char(20) DEFAULT NULL COMMENT '籍贯',
    `birthday` datetime DEFAULT NULL COMMENT '出生日期',
    `dno` char(6) DEFAULT NULL COMMENT '所在院系',
    `spno` char(8) DEFAULT NULL COMMENT '专业代码',
    `classno` char(4) DEFAULT NULL COMMENT '班级号',
    `entime` date DEFAULT NULL COMMENT '入校时间',
    `home` varchar(40) DEFAULT NULL COMMENT '家庭住址',
    `tell` varchar(40) DEFAULT NULL COMMENT '联系电话',
    PRIMARY KEY (`sno`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='学生信息表';



  • 将数据库及其表结构数据以表格形式输出到console


    $ tsdump -H 127.0.0.1 -P 3307 -u root -p "mypassword" --db mydb
    |----------|---------------|--------------------|
    | DATABASE | CHARACTER SET | COLLATION |
    |----------|---------------|--------------------|
    | mydb | utf8mb4 | utf8mb4_general_ci |
    |----------|---------------|--------------------|

    TABLE: student 学生信息表
    |----------|----------|--------------|---------------|--------------------|----------|
    | COLUMN | NULLABLE | DATA TYPE | CHARACTER SET | COLLATION | COMMENT |
    |----------|----------|--------------|---------------|--------------------|----------|
    | sno | NO | char(8) | utf8mb4 | utf8mb4_general_ci | 学号 |
    | sname | NO | varchar(255) | utf8mb4 | utf8mb4_general_ci | 姓名 |
    | gender | YES | char(2) | utf8mb4 | utf8mb4_general_ci | 性别 |
    | native | YES | char(20) | utf8mb4 | utf8mb4_general_ci | 籍贯 |
    | birthday | YES | datetime | | | 出生日期 |
    | dno | YES | char(6) | utf8mb4 | utf8mb4_general_ci | 所在院系 |
    | spno | YES | char(8) | utf8mb4 | utf8mb4_general_ci | 专业代码 |
    | classno | YES | char(4) | utf8mb4 | utf8mb4_general_ci | 班级号 |
    | entime | YES | date | | | 入校时间 |
    | home | YES | varchar(40) | utf8mb4 | utf8mb4_general_ci | 家庭住址 |
    | tell | YES | varchar(40) | utf8mb4 | utf8mb4_general_ci | 联系电话 |
    |----------|----------|--------------|---------------|--------------------|----------|



  • 将数据库及其表结构数据输出到markdown文件


    $ tsdump -H 127.0.0.1 -P 3307 -u root -p "mypassword" --db mydb -V md > ./mydb.md

    output:


    student


    学生信息表







































































































    COLUMN NULLABLE DATA TYPE CHARACTER SET COLLATION COMMENT
    sno NO char(8) utf8mb4 utf8mb4_general_ci 学号
    sname NO varchar(255) utf8mb4 utf8mb4_general_ci 姓名
    gender YES char(2) utf8mb4 utf8mb4_general_ci 性别
    native YES char(20) utf8mb4 utf8mb4_general_ci 籍贯
    birthday YES datetime 出生日期
    dno YES char(6) utf8mb4 utf8mb4_general_ci 所在院系
    spno YES char(8) utf8mb4 utf8mb4_general_ci 专业代码
    classno YES char(4) utf8mb4 utf8mb4_general_ci 班级号
    entime YES date 入校时间
    home YES varchar(40) utf8mb4 utf8mb4_general_ci 家庭住址
    tell YES varchar(40) utf8mb4 utf8mb4_general_ci 联系电话



  • 将数据库及其表结构数据输出到csv文件


    $ tsdump -H 127.0.0.1 -P 3307 -u root -p "mypassword" --db mydb -V csv -o ./mydb.csv


  • 将数据库及其表结构数据输出到JSON文件
    $ tsdump -H 127.0.0.1 -P 3307 -u root -p "mypassword" --db mydb -V json -o ./mydb.json

搭建轻量级的 Docker 容器云管理平台

bobliu0909 发表了文章 • 0 个评论 • 460 次浏览 • 2017-12-02 11:09 • 来自相关话题

什么是 Humpback?

Humpback 可以帮助企业快速搭建轻量级的 Docker 容器云管理平台,若将你的 Docker 主机接入到 Humpback 平台中,就能够为你带来更快捷稳定的容器操作体验。

查看全部

什么是 Humpback?


Humpback 可以帮助企业快速搭建轻量级的 Docker 容器云管理平台,若将你的 Docker 主机接入到 Humpback 平台中,就能够为你带来更快捷稳定的容器操作体验。


humpback架构


Humpback 功能特点


-Web操作,简单易用

-权限分组隔离

-容器升级与克隆

-容器监控

-容器日志

-集群容器调度

-集群弹性伸缩

-私有仓库


Humpback 模式介绍


-Single Mode 单一模式,对单组主机实现容器管理,提供容器创建,容器操作,容器重命名,容器升级与克隆,容器监控,容器日志输出等功能。

-Cluster Mode 容器集群模式,实现按实例数批量创建容器,容器调度,批量操作容器,升级和迁移等功能。


平台采用分组方式(Group)来管理多主机,多组之间权限操作隔离,同时也可以将一台主机加入到多个分组中交叉管理。


系统登录


Single Mode

SingleMode


Cluster Mode

ClusterMode


Container Monitor

ContainerMonitor


Container Logs

Container Logs


Container Detail

ContainerDetail


ContainerDetail


项目地址:https://humpback.github.io/humpback

授权协议:Apache

开发语言:TypeScript、Golang

操作系统:垮平台

分享一个简易淘宝爬虫

smallfish1 发表了文章 • 1 个评论 • 380 次浏览 • 2017-11-29 12:31 • 来自相关话题

项目原因:朋友说,想有个 Windows 程序 抓取淘宝某些商品数据(主要是链接),然后我想了想,golang 交叉编译很方便嘛,不如自己搞一个,所以就码了,欢迎大家试用。

地址: 查看全部

项目原因:朋友说,想有个 Windows 程序 抓取淘宝某些商品数据(主要是链接),然后我想了想,golang 交叉编译很方便嘛,不如自己搞一个,所以就码了,欢迎大家试用。


地址: https://github.com/songjiayang/tbspider


主要功能: 就是抓取商品列表数据,支持所有查询参数,例如多种排序,价格区间,发货地筛选;简单易用, 还加了点点防反爬虫。

riot 搜索引擎 v0.10.0 发布, 优化引擎和分词等

回复

veni 发起了问题 • 2 人关注 • 0 个回复 • 479 次浏览 • 2017-11-21 22:45 • 来自相关话题

go 分布式全文搜索引擎 RiotSearch

veni 回复了问题 • 5 人关注 • 9 个回复 • 957 次浏览 • 2017-11-21 22:27 • 来自相关话题

改进版glide golang版本控制

xkey 发表了文章 • 0 个评论 • 418 次浏览 • 2017-11-21 12:07 • 来自相关话题

仅对于无法翻墙的情况

由于GFW的原因使用glide get golang.org/x/sys/unix 的时候会出现问题,首先肯定是fetch不下来的。

github上会有所有x包的镜像,glide只要使用glide mir... 查看全部

仅对于无法翻墙的情况


由于GFW的原因使用glide get golang.org/x/sys/unix 的时候会出现问题,首先肯定是fetch不下来的。


github上会有所有x包的镜像,glide只要使用glide mirror set一下即可。


但是当拉取上面的子包的时候会出现目录复制错误的问题:


当你使用某个包下的某个目录时,glide会自动下载这个包。 例如:golang.org/x/net/context 要知道这个在国内是取不到的。 所以使用mirror转到github.com镜像的net/context下,这也取不到,必须指定到net包下面。 但这样他拷贝的文件目录就变了了,会把net包拷贝到net/context下面


针对上述问题 xkeyideal/glide 对glide mirror的代码进行了改进,即添加了 --base参数,让用户能够指定复制的目录。


具体的请参考项目的readme文件。

Go 语言高效分词, 支持英文、中文、日文等

veni 回复了问题 • 1 人关注 • 2 个回复 • 491 次浏览 • 2017-11-17 14:05 • 来自相关话题

fx 简单介绍 [Go Hack 2017]

metrue 发表了文章 • 2 个评论 • 437 次浏览 • 2017-11-12 17:43 • 来自相关话题

fx 是我在 Go Hack的一个小作品,Go Hack 是一个以Go语言为主要编程语言的黑客马拉松比赛。虽然我和我队友两人都是写... 查看全部


fx 是我在 Go Hack的一个小作品,Go Hack 是一个以Go语言为主要编程语言的黑客马拉松比赛。虽然我和我队友两人都是写JavaScript的前端工程师, 以Golang 零基础参加这次比赛,不过很开心我们完成了fx,也喜欢上 Golang 这门语言.


前言


读了那么多年书,写了那么久的代码,如果说有什么概念是深入骨髓的,只能说是”函数“了。虽然在数学上和编程上,“函数”这个词有很大的不一样的,但是有一点上它们是类似:


接受输入(可能为空值),然后进行处理,最后输出处理结果。

我们几乎可以用这个概念来描述所有的行为. 比如我们可以用下面的函数的来描述我们 fx 的诞生过程:


函数 f = Go Hack (以 Golang 为项目编程语言的黑客马拉松活动)
输入 input = [两个Go语言零基础的JavaScript工程师,两台Macbook,很多很多的功能饮料]
fx = f(input)

fx 是什么


那么 fx 是什么呢,一句话来说就是 : fx 是一个可以把一个函数变成一个服务的工具. 一个简单的例子来说一下 fx 的功能吧. 比如你写好了很棒的函数 , 它是这样的:


func.js


module.exports = (input) => {
return parseInt(input.a, 10) + parseInt(input.b, 10)
}

它的作用就是计算两个数的和. 你把这个函数写在 func.js 这个文件里面。 这时候你希望可以将这个函数编程一个服务,对外提供一个 url 可以供外界访问. 但是想到 nginx, web server, api gateway…, 你头有点大了。 现在你可以简单的这样做。


fx up func.js

如果一切没有什么问题,你可以得到一个url.


$fx list
Function ID Service URL
743a9b0ee5 0.0.0.0:61098

访问你的服务试试看


$ curl -X POST 0.0.0.0:61098 -H "Content-Type: application/json" -d '{"a": 1, "b": 1}'

你会得到 2. 这说明你的函数已经变成了一个服务了。


fx 如何工作


                upload function definition
fx client -------------------------------> fx server
<-------------------------------
url of deployed service

fx 有两个部分组成,fx server 和 fx client . client 很简单,主要就是把 function 的定义内容通过 Websocket 发给 server 而已,而 server 是一个 Websocket sever,接受到 function 的内容了之后,匹配到正确的 Dockerfile 和对应的构建镜像所需的资源, 然后会调用 Docker Engine 的 api 去构建相应的服务,最后把生成的服务的 URL 返回给客户端.


fx 支持哪些编程语言


由于 fx 的一个服务的背后都是一个 Docker Container, 所以 fx 几乎可以支持所有的编程语言,由于精力有限,目前 fx 支持这些编程语言:



  • Golang

  • JavaScript/Node

  • Ruby

  • Python


Code


https://github.com/metrue/fx

RobotGo v0.46.6 发布, 大幅度优化 bitmap

回复

veni 发起了问题 • 1 人关注 • 0 个回复 • 519 次浏览 • 2017-11-10 21:53 • 来自相关话题

Top25 gopher项目梳理

songtianyi 发表了文章 • 2 个评论 • 576 次浏览 • 2017-11-04 10:28 • 来自相关话题

Top25 gopher: golang项目star数前25的github用户

数字代表该类项目的数量

查看全部

Top25 gopher: golang项目star数前25的github用户


数字代表该类项目的数量


LiteIDE X33 发布,Go 语言开发工具

visualfc 发表了文章 • 0 个评论 • 655 次浏览 • 2017-11-03 08:15 • 来自相关话题

Go 语言开发工具 LiteIDE X33 正式发布。这个版本优化了编辑器功能,读取文件支持 codec 自动检测,重新加载文件使用 diff 方式进行优化,重新实现 Mark API 并增加了新的 Bookmarks 插件;Go 语言视图和大纲增加了 ... 查看全部

Go 语言开发工具 LiteIDE X33 正式发布。这个版本优化了编辑器功能,读取文件支持 codec 自动检测,重新加载文件使用 diff 方式进行优化,重新实现 Mark API 并增加了新的 Bookmarks 插件;Go 语言视图和大纲增加了 TodoList 显示;修复了 GolangEdit 的 查找使用 偶而无效错误, 代码查询 guru (备份使用内置oracle) 增加了 GOPATH 内查询接口功能。调试和查找插件也有所增强……。


更多的功能实现和错误修复详见更新记录



2017.11.2 Ver X33



  • LiteIDE

    • optimization editor plugin, load file check codec, reload file by diff

    • add astview TodoList

    • add new bookmarks plugin

    • fix liteapp clean plugin order


  • LiteApp

    • filemanager auto reload file default YesToAll

    • fix liteapp clean plugins reverse order

    • fix #832, sidebar change action by combox

    • fix folder sync editor same prefix error


  • LiteEditor

    • reload file use diff to keep state and mark

    • load file check is binary and report

    • load file check codec use libucd if utf8 decode failed.

    • load file check decode error and report

    • load file is readonly set editor widget readonly

    • load and save file support utf8 bom

    • add codec and lineend info on statusbar

    • add copied text into the clipboard as HTML option

    • add Solarized Dark color theme, thanks xgdgsc

    • reimplemented editor mark api

    • fix copy to clipboard tab escape


  • GolangAst

    • add TodoList for classview and outline

    • fix #848, astwidget double clicked index check.


  • GolangCode

    • update pkglist to go1.9


  • GolangEdit

    • add stop source query action

    • add source query action implement_GOPATH for GOPATH scope

    • fix golang lexer parser folding end

    • fix GolangHighlighter fold indent error set

    • fix findUsage wordUnderCursor offset

    • fix find usages findStart signal late


  • GolangFmt

    • load diff check modify current block text


  • GolangCode

    • fix update gopath process stop and wait


  • LiteDebug

    • fix cmd to native separator

    • build target add -a build flag

    • change debug targget name to target.debug (custom by LiteBuild)


  • LiteBuild

    • add custom debug name in build config


  • LiteFind

    • fix memory leak by GolangEdit GolangFileSearch

    • fix findInFiles berore saveAllEditor

    • fix FindEditor replace all


  • Bookmarks

    • new plugin for show open editors bookmarks and jump


  • gotools

    • update stdlib for go1.9.1

    • astview add TodoList support


天下武功,唯快不破 go-pcurl

thimoonxy 发表了文章 • 2 个评论 • 592 次浏览 • 2017-10-27 10:59 • 来自相关话题

初衷

写这个玩意的初衷是想解决海外研发往国内节点传文件慢的问题( 当然,这里不考虑土堆拦路的问题) 一开始研发抱怨即便用了国际专线,既有的单线传输方案仍然没有充分利用带宽。 于是人家用torrent走公网对比了一下,完胜专线。虽然专线是... 查看全部

初衷


写这个玩意的初衷是想解决海外研发往国内节点传文件慢的问题( 当然,这里不考虑土堆拦路的问题)
一开始研发抱怨即便用了国际专线,既有的单线传输方案仍然没有充分利用带宽。
于是人家用torrent走公网对比了一下,完胜专线。虽然专线是有guarantee的,仍然被歪果仁严重鄙视。
可是生产环境,用torrent未免过于粗暴啊!
快的时候,入口流量窜了尖,你到底开不开清洗?是被DDOS了?业务受影响了?一脸懵。
网不好的时候,速度变成毛线咋办,何意百炼刚,化为绕指柔?


想到了大学时候一门基础课程,叫什么什么拆装实习。于是,萌生了拆range,并发download,然后重新组装的办法。听起来很土吧。


go-pcurl


cURL in parallel way, Written in golang
REPO


实际测试了一把



  • 用wget去官网下载docker.rpm,需要6分21秒

  • 同样的url,用go-pcurl下载用了47秒


后面想想怎么限制带宽,是否可控还是很重要的。


萌新练武术,各位多指教 ;P