糖糖发烧了,好担心
Tag 琐碎, on by view 1094

糖糖昨天下午开始就发烧了,晚上喝了布洛芬退烧了,半夜2点又发烧了,爸爸妈妈外婆起来给糖糖吃退烧药和物理降温,今天一早又发烧了,温度高的时候有39度。一早妈妈请假,外婆和妈妈带糖糖去儿童医院看病,爸爸去公司上班。

爸爸现在完全无心工作,看病回来下午这会儿糖糖又发烧了。再加上公司的事情,昨天凌晨手欠在公司某系统评论了某事,一早被领导diss了,心情真是糟糟的,烦烦的,真是手欠,半夜两点还关心公司的事情,更欠的事情是还顺手评论了某事。

希望糖糖能够早日康复,健康快乐成长。公司的事情该忙的还是要继续忙,吃一堑长一智,谨行慎言。


矛盾
Tag 情感, on by view 1356

已经结婚快要2年了,娃也已经开始整天“babababa”的咿呀学语了。

休完产假刚上班,工作上的事情并不太多,挺闲的。所以就上网刷知乎玩儿。最近刷到几个问题,“爸爸能爱女儿到什么程度?”,大概就是这样的问题,主题在表现爸爸对女儿的爱。刷了挺多答案的,看到了各种各样爸爸疼女儿的回答。每个回答都是满满的爱,虽然都各有各的可爱,每个故事都可爱的与别人不同。

想到了娃爸,似乎没有网上那样,难道这就是说的别人家的爸爸?难道我糖以后也只能看着别人家的爸爸然后满满羡慕?每次想到这里都很替我糖抱不平,会找娃爸抱怨几句。

但是回头想一想,其实娃爸也很爱臭糖,从来都想要把最好的给她,从来都愿意惯着她的小脾气(别看小小一个人,还穿纸尿裤,甚至还不会爬,但是小脾气绝对是足足的)。比如臭糖要吃奶睡觉觉,比如臭糖要抱抱不肯自己做着玩,比如臭糖要人陪着不肯自己呆着,比如臭糖睡觉觉的时候要把腿放在我身上,比如臭糖吃奶睡觉觉的时候大脚丫子使劲在我身上蹬,等等等等这些时候。她爸都会说,哎呀你糖喜欢这样就让她这样嘛。嗯,反正折腾的都是麻麻,不是爸爸!手动白眼。

这么说来,似乎糖爸对糖的爱也很假,都不是需要他付出的他就很慷慨,是不是这样?老实说,心里有时候也是这样觉得的。可是看着糖爸的眼睛,又知道他其实是真的很爱糖。

其实糖爸很信任我,他只是将我当成了他最放心的人,将他心里最重要的部分交给了我,并认为我一定能照顾好他最爱的人。

所以,我想他是爱我的,很爱我。不然,如何敢将自己最脆弱的部分完全依靠在我身上。虽然有时候又会突然怀疑他是不是像别人口中的渣男一样,并没有我想的那么伟大,只是单纯的不在乎我和糖。不过静下心来,我还是选择相信我的男人。

即便心里偶尔很矛盾。偶尔不平衡。



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

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 3056

首先需要安装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 2786

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

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



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

首先,创建带有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 3869

最近需要用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 2999

今天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,再也没有报这个错,解决。



2016阶段总结
Tag 工作, 总结, on by view 4251

随着时间的推移,我的上一份工作已经告一段落,今后的一段时间离我将会作为Golang软件工程师而存在,而不是现在的Java程序员。

关于语言

我由初入职场时的Java语言开发到现在的转向Golang开发,这并不意味着我觉得Golang比Java好,只是单纯的改变了一下技术方向而已。对于编程语言,我并不像大多数人那样有固定的偏好,而且部分人在语言之争上比较偏激;对于我来说我接触过的所有的编程语言我都喜欢,同时,我也不像大多数人那样只会一门编程语言,比如Java或PHP,在某些技术社区上Java开发者与PHP开发者总是为了诸如“谁是最好的编程语言”这一议题争得不可开交。

从我接触编程到现在先后接触了一些语言,最早在高中的时候是Visual Basic,后来进入大学了正式学习编程了,在大一上学期自学入门的语言是JavaScript,因为我在高中时候就有一个建网站的梦想,所以了解前端技术栈相对于我的同学要早,因此我进入大学的时候就知道了JavaScript在前端技术中的地位。大一下学期大学课程开始学习C++了,与此同时我开始自学PHP,开始了解并使用MySQL数据库,也是此时我正式开始理解“面向对象”这一概念,后来大二学校课程学习了C#这门语言,同时这一年我在学校学生组织里面开始为学校建设网站,用的是PHP语言,MySQL数据库以及Linux服务器,对Linux服务器的了解也是从此时开始的。用PHP写网站大概写了一年多的时间,期间由于我对前端非常了解,那时的我算是个比较菜的全栈工程师了。大二是疯狂的一年,每天晚上至少凌晨2点才睡觉,因此导致一些课程挂科了,大三是反省的一年。同时大三也是技术沉淀的一年,大三我开始重新学习C语言,这回是认认真真的学习,在解决了一个个的内存错误(segment fault)之后,对编程有了新的理解,对于内存,指针,文件,网络这些东西有了进一步的了解。那一年我开始写了一些小项目以及pinyin-php,同时学习了Golang,当时我觉得Golang太好学了,从完全不了解Golang到用Golang的Beego框架写出一个博客系统只用了两周时间,或许是因为之前在学C语言,初学Golang感觉自己如同解放了一般。

总之,我对任何语言都是一视同仁,我并没有觉得Java不好,相反,我觉得Java是各方面都比较完备的一门语言。而且,就我目前来看,我更想了解的是语言的本身,因此我将编译原理作为我之后要研究的领域之一。

关于项目

论项目经验,我从大学时开始做第一个真正的项目到现在也有大约4年了吧。最初无人领路不框架为何物,靠着自己的毅力不停的堆代码,发现最后自己堆砌的PHP代码的复杂都已经超出了我的理解范围了,项目开始混乱得我已经无法维护了,于是,第一个项目以失败告终。后来,了解并学习了Web框架发现使用框架写代码更加得心应手。而最近的项目中的经历再次印证了一个好的框架是多么的重要;由于目前的项目的创始人打着“验证无框架开发的思路”的旗号搞了现在这么个项目——底层封装度非常底,该封装的都没有封装,而他所写的简单的封装并没有做到一个“框架”所应当做的事情,导致现在这个项目面临了许多比较坑的问题,比如数据库不能使用联查,这一问题同时导致了大家尽量避免联查,因此,项目在建数据表的时候也尽量的避免联查,于是数据表中出现了大量的冗余,再加上项目的各种改需求,数据结构已经变得不能看了。

这些项目经历告诉我“无框架”是扯淡,当项目复杂到一定程度“无框架”的项目将会复杂到无法维护,一个比较好的项目首先是要有一个比较好的框架,而不是无框架,好的框架应该是低耦合的,而且该有的基础功能都是有的,并且应该是可以扩充的,比如某些框架中的中间件概念。

关于工作

有时候在一个岗位上待久了并不是一件好事。首先,时间一长,在技术上就难以有新的收获,每天过着写业务逻辑的日子早就让我厌倦。然后,呆久了就不知道自己现在的价值如何了,也不了解市场的行情如何,所以我觉得不管是否有换工作的打算,每年都应该出去面试一波,一来了解一下自己目前的价值,二来了解一下市场行情。

关于生活

这一年,我有了她……


用latex排版中文书籍
Tag latex, ctex, 排版, on by view 7810

由于最近在翻译《parsing techniques》,所以想着待翻译完毕将其打印成标准书册自己研习,于是学习了如何用latex排版书籍出版物。

之前也曾用过两次latex,第一次是大学期间想着使用latex排版毕业论文,于是想用latex做一个毕业论文模板,奈何,长江大学的论文只能用Word写,还在格式上死扣,时间紧迫也只好作罢,模板残篇在这儿 https://github.com/duguying/report  。第二次使用latex是在自己的简历上,因为毕业了需要找工作,在网上找了一波简历模板,发现Modern CV这套模板很漂亮,于是也就用了,Modern CV是基于latex的模板,简历在这儿欢迎勾搭 https://github.com/duguying/resume 。经历三次使用latex(尤其是最近一次)对latex中文书籍排版也有了一定的了解。

  • latex工具选择

我选用的是texlive套装,里面包含了latex、xelatex等工具,我们编译中文书籍主要用到的是xelatex,因为xelatex原生支持UTF8,不需要任何的额外包。

  • 包选择

中文支持最常用的自然是ctex,我使用的是ctex中的ctexbook类包,他专为长篇书籍排版而生。

  • 编辑器

只要有latex语法高亮支持即可,依个人的爱好选择,我用的是sublime text作为编辑器。

  • 书籍结构

ctexbook中,一般有如下结构:chapter(章), section(节), subsection(子节), subsubsection(三级子节), paragraph(段落), subparagraph(子段落)等,用得最多的是前五种。最基础的文章结构为段落,分段常用空行的方式进行,之前我误以为 \paragraph{内容} 是分段的方式,结果发现段落全部默认粗体字了,后来才明白,\paragraph{} 应当作为“段落标题”或是成为“段落首句加粗”,其起着重作用。上一层结构就是三级子节了,如果书籍中没有那么细的分节,三级子节可以不要,三级子节默认加粗,左对齐,\subsubsection{三级子节} 被\subsubsection命令括起来的部分就是三级子节的标题了,如下图;

subsubsection.png

再上一层的结构就是子节,\subsection{子节} 子节标题默认左对齐,\subsection命令中括起来的就是子节名,带章节号,如下图

subsection.png

再上一层就是节,\section{节} 节标题默认居中对齐,\section命令括起来的就是节名,带章节号,如下图

section.png

再上一层就是章,\chapter{章} 章标题居中对齐,\chapter命令括起来的就是章名,章节号为汉字,如下图

chapter.png

  • 内容结构

内容结构可分为,前序言正文后序言 这三者。\frontmatter 命令表示接下来的内容是前序言部分,\mainmatter 命令表示接下来的内容是正文部分,\backmatter 表示接下来的部分是后序言部分。一般来说,序言部分的页码系统是与正文部分的页码系统区分的,例如前序言部分的内容,页码会以罗马数字标注(i,ii,iii,iv), 而正文部分的页码会以常规的阿拉伯数字标注(1,2,3,4),下面是示例代码展示了如何使用该三个命令定义内容区

\documentclass[hyperref,UTF8]{ctexbook}
% \documentclass{amslatex}
\usepackage{src/pt}

\begin{document}

% \pagestyle{plain}

% 前言开始
\frontmatter

\include{data/preface2}
\include{data/preface1}

% 正文开始
\mainmatter

\tableofcontents

\include{data/chap1}
\include{data/chap2}

% 尾言开始
\backmatter

\end{document}
  • 前言中定义章节

我们有时候会有多个前言,或者书籍请多个名人来作序,于是可能对每个前言/序需要区分为一章节,但是又不希望出现“第x章”这样的字样。其实在序言部分的章节默认是不带章节号的,因此,可以如同正文一般在序言中做章节处理,无须顾忌其他。如下图

preface_chapter.png

不过,如有节(section)应当用如下命令以不产生节号

\section*{关于练习和问题}

如下图

preface_section.png

若没有*号将会产生章名为0的节号。

  • 绘制表格

绘制表格常用的命令对是 \begin{tabular}\end{tabular},详细的使用可以在谷歌上查阅,示例颇多不再赘述,下面只给一段示例代码

\begin{figure}[!htbp]
\centering
\begin{tabular}{llp{5cm}ll}
    & \textbf{S}      &  &    & \textbf{S}      \\
 1b &                 &  & 1b &                 \\
    & \textbf{L\&N}   &  &    & \textbf{L\&N}   \\
 2a &                 &  & 0c &                 \\
    & \textbf{N,L\&N} &  &    & \textbf{L\&h}   \\
 0b &                 &  & 2a &                 \\
    & \textbf{d,L\&N} &  &    & \textbf{N,L\&h} \\
 2b &                 &  & 2b &                 \\
    & \textbf{d,N\&N} &  &    & \textbf{N,N\&h} \\
 0c &                 &  & 0c &                 \\
    & \textbf{d,h\&N} &  &    & \textbf{N,h\&h} \\
 0c &                 &  & 0c &                 \\
    & \textbf{d,h\&h} &  &    & \textbf{d,h\&h} \\
\end{tabular}
\caption{句子形式变为\textbf{d,h\&h}, 与最左边和最右边替换}
\label{fig:method}
\end{figure}
  • 绘制插图

这里只介绍常见的普通线条插图绘制。普通的无规律线条插图我们可以借助Adobe Illustrator绘制矢量图,然后将其另存为eps格式的矢量图。接下来用如下命令转化为pdf图(假设eps文件名fig2_19.eps)

epstopdf fig2_19.eps

如此,同目录下将会生成名为 fig2_19.pdf 的图片。然后在正文中按如下引用

\begin{figure}[!htbp]
\centering
\includegraphics[scale=0.6]{figure/fig2_19.pdf}
\caption{Production tree for a context-free grammar}
\label{fig:method}
\end{figure}

其中\caption为图片介绍,图片会自动编号。

若是规律性比较强的图片可以使用latex代码画图,其中会用到tikz等包,可自行查找研究如何使用。若是插入位图的话,引用graphicx包后可以直接插入,将上述路径中的pdf图改为相应的位图便可以轻松插入。

  • 页面结构

页面结构一般纵向会分为页眉主体页脚三部分,横向会分为左边距主体右边距测注。默认是页面布局会给正面(奇数页)的右侧预留侧注的空间,因此,看起来右边会比左边宽。

许多初接触ctexbook的人会奇怪,这个空白多的一侧应该是装订预留白吧,可是为啥会在右侧呢,其实人家仅仅只是为侧注留的空间而已。侧注是个啥?如下图左侧注

side_note.png

那么如何调整使得看不到为侧注所预留的空间呢,我们可以自定义边距即可

\usepackage[left=2.2cm,right=1.8cm,top=2.0cm,bottom=2.5cm]{geometry}
\geometry{papersize={18.00cm,23.00cm}}

上例调整左边距2.2cm,右边距1.8cm,上边距2.0cm,底边距2.5cm。