对gin应用基于TCP窗口的流量控制
Tag gin, tcp, 窗口, 流量控制, on by view 77

TCP可以基于滑动窗口进行流量控制,使用setsockopt系统调用实现,可以限定客户端或者服务端连接的入网或出网流量,http是基于TCP协议的,因此http也可以基于TCP滑动窗口实现流量控制。golang自有的net包不支持server端TCP窗口设置,因此无法直接实现基于TCP窗口的流量控制。今天我们要对一个基于gin实现的微服务进行流量限制。

首先,gin自带的r.Run()启动的http肯定是不行的,然后http包中的http.ListenAndServer()也是不行的,那么我们就基于TCP来实现,但是golang得net包中的net.Listen()也是不行的。这时候我们只有调用底层的系统调用了(不是cgo),我们可以使用syscall包来实现系统调用。我们分为五步:创建socket,设置socket选项,绑定端口地址,转换为golang的listener,listen。

  • 创建原生的socket

s, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_STREAM|syscall.SOCK_NONBLOCK|syscall.SOCK_CLOEXEC, 0)
if err != nil {
    log.Println("create socket failed, err:", err.Error())
    return
}
  • 设置socket选项

// set receive buffer here
err = syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_RCVBUF, 2350)
if err != nil {
    log.Println("set socket option receive buffer failed, err:", err.Error())
    return
}

// set send buffer here
err = syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_SNDBUF, 2450)
if err != nil {
    log.Println("set socket option send buffer failed, err:", err.Error())
    return
}
  • 绑定端口地址

err = syscall.Bind(s, &syscall.SockaddrInet4{Port: 8099, Addr: inetAddr("192.168.31.11")})
if err != nil {
    log.Println("bind socket failed, err:", err.Error())
    return
}
  • 转换为golang的listener

f := os.NewFile(uintptr(s), "")
ln, err := net.FileListener(f)
if err != nil {
    log.Println("create listener failed, err:", err.Error())
    return
}
  • listen

err = syscall.Listen(s, 0)
if err != nil {
    log.Println("listen failed, err:", err.Error())
    return
}

最后我们把我们自定义的支持限流的listener应用于gin上

r := gin.Default()

r.GET("/", func(context *gin.Context) {
    context.File("socket")
})

err = http.Serve(ln, r)
if err != nil {
    log.Println("create http server failed, err:", err.Error())
    return
}

一个支持限流的http server就此实现。


将caffemodel编译为movidius的graph模型
Tag caffe,model,movidius, on by view 168

首先需要安装ncsdk, 去movidius官网下载 https://developer.movidius.com/start 

mkdir -p ~/workspace
cd ~/workspace
wget https://ncs-forum-uploads.s3.amazonaws.com/ncsdk/ncsdk-01_12_00_01-full/ncsdk-1.12.00.01.tar.gz
tar xvf ncsdk-1.12.00.01.tar.gz
cd ncsdk-1.12.00.01
make install

安装完毕后可以调用mvNCCompile进行编译

mvNCCompile ./deploy.prototxt -w ./resnet_50_1by2_nsfw.caffemodel -s 12 -0 ./nsfw.graph

若是遇到编译失败

mvNCCompile v02.00, Copyright @ Movidius Ltd 2016

Error importing caffe

请设定环境变量后重试

export PYTHONPATH=/opt/movidius/caffe/python:$PYTHONPATH

编译成功后会生成 msfw.graph 文件,接下来可以使用 movidius 和 graph 模型进行推导了。


幸福的孤独者
Tag 散文, on by view 1279

人,一旦进入天命之年后就意味着进入了孤独期。尤其是独生子女家庭。记得二十几年前,父亲常常喊:“兵伢,来,来坐哈?”那时无知的我面对老父的招呼,显出明显的不耐烦,甚至冷漠,无动于衷。那时我是多么的冷酷自私呀!为什么那时我心中就没有一丝的对老人的怜悯或同情呢?其实我内心是非常悲悯老父老母的,只是自己不愿表露而已。我不想因为自己的“行孝而招来弟兄之间更深的仇隙”。这就是事实的症结,别人的不孝姑且不论,人在做天在看!我心底的内疚从没有消失过,时至今天他还让自己难安。就让自已在时间中慢慢讦悔吧!那时,而且那时父亲已经身患重病:老血栓。父亲在喊叫几遍无应后,他就孤独地喃喃自语地拖着垂暮之年的病弱之躯慢慢地走入他那低矮的老房子……

当时我为什么心中有恁大的抵触情绪呢?根源还是因为弟兄之间的不和。这不和的根源多是由老人的厚此薄彼引起的,当时自己为什么就过不了自己心魔那道坎呢?归根结底还是自已太自私了。现在父亲走了十一年,母亲也走了三年,我们也进入了天命之年还多五的光景,幸运的是我们还在工作还能工作!虽然如此,空闲时就感觉日子中似乎少了点什么?那就是孩子不在身边的空虚!这时自已就常常于寂寞中感受到“孤独的可怕”!是的,父辈们的“今天就是我们的明天。”“我的今天就是父亲的昨天”啊!我这不孝之子,现在终于体味到当年父亲为什么老是喊我陪他坐坐……?啊!往事堪追忆?可是这后悔能改变一切吗?能回到当年吗?能让自己重新“行孝”吗?俱往矣!现在我终于懂得了父亲当年常对我唠叨的“养儿方知父母恩”是什么意思!“寂寞使人孤独,孤独使人易老”。我现在感受到“寂寞的可怕”,或者这是“上天对自己的警告吧”!我有个和协美满的家,可是一家几囗常年在外工作,儿子儿媳他们就是把全年的假期算在内,在家住的时间也没有一个月?我现在能要求他在家陪陪我们吗?笑话!这是不可能的。当年父亲不就是这样要求我吗?可是当年父亲求孩子在身边陪坐几十分钟的愿望就变成了奢侈?唉!现在我们的孩子他为了自己的发展跑到天涯海角去打拼,如果想孩子就默默地盯住天空飞来飞去的银色机冀吧!说不定那架飞机内就坐着自己的小子呢!



golang客户端取消http请求
Tag golang, cancelable, http, on by view 1321

首先,创建带有Cancel Context的http请求

var cx context.Context
cx, req.cancel = context.WithCancel(context.Background())

if req.httpreq, err = http.NewRequest(req.method, req.url, reqbody); err != nil {
    return
}
req.httpreq = req.httpreq.WithContext(cx)
req.httpreq.Header = req.Headers
req.httpreq.ContentLength = reqbodyLength

然后,需要停止请求的时候调用req.cancel()方法

if req.cancel != nil {
    req.cancel()
    fmt.Println("running cancel...")
}

return nil

这样才能够客户端强行主动取消正在进行的http连接。就是这么简单


webp动图循环n+1的问题
Tag webp,循环, on by view 1747

最近需要用ffmpeg将视频截取转为webp动图,但是发现截取后的视频在Chrome浏览器上打开播放循环次数不对

./ffmpeg -i xxx.mp4 -map_metadata -1 -s 640x360 -r 15 -t 00:00:02 -loop 1 xxx1.webp

以上命令中 -loop 1 指定动画循环1次,但是所生成的图片在Chrome上播放却是循环2次,同时发现截取 gif 也存在这个问题

./ffmpeg -i xxx.mp4 -map_metadata -1 -s 640x360 -r 15 -t 00:00:02 -loop 1 xxx1.gif

但是后来我发现将 -loop 指定为-1却可以截取一次循环的gif,但是 -loop -1 这个参数如果用在截取 webp 就会报错。

最后我找到了 libwebp 项目,在其压缩包目录中找到了官方的 webp 查看工具 vwebp.exe ,用它播放 webp 发现却是正常的,Chrome上播放循环两次的图用它播放只有一次。这说明是 Chrome 的bug,并非 ffmpeg 转码的问题。有人也发现了这个问题。 链接  



linux打开文件数太多
Tag linux,打开文件数, on by view 1600

今天dus服务并发量稍高,然后程序内部不停地报错 too many open files ,linux 系统对打开文件数是有限制的。介绍这个的文章很多。查看服务器上系统设置的最大限制,运维设置的是 102400,列出所有进程的打开文件数目 lsof -n|awk '{print $2}'|sort|uniq -c |sort -nr|more ,服务程序打开文件数最大时也才1w多,所有进程打开文件最大值加起来也才五六万,远远没有达到 102400,一直不解为何报这个错误,最后查看程序进程的限制 cat /proc/32523/limits ,发现限定值居然是 1024

Limit                     Soft Limit           Hard Limit           Units     
Max cpu time              unlimited            unlimited            seconds   
Max file size             unlimited            unlimited            bytes     
Max data size             unlimited            unlimited            bytes     
Max stack size            8388608              unlimited            bytes     
Max core file size        0                    unlimited            bytes     
Max resident set          unlimited            unlimited            bytes     
Max processes             31170                31170                processes 
Max open files            1024                 4096                 files     
Max locked memory         65536                65536                bytes     
Max address space         unlimited            unlimited            bytes     
Max file locks            unlimited            unlimited            locks     
Max pending signals       31170                31170                signals   
Max msgqueue size         819200               819200               bytes     
Max nice priority         0                    0                    
Max realtime priority     0                    0                    
Max realtime timeout      unlimited            unlimited            us

服务是通过 systemd 启动的,原来在 service 中有个设置项可以设置程序能打开的最大文件数,可是我的 service 文件中没有设置,于是默认限定为 1024,很容易就超了。修改添加配置项

[Service]
LimitCORE=infinity
LimitNOFILE=102400
LimitNPROC=102400

重启服务,再次查看 cat /proc/32523/limits ,Max open files 成功变为 102400,再也没有报这个错,解决。



下一页