记又一次对Makefile的重构

我平常有一个习惯,就是不断看以前写的代码,想着有没有哪些方面可以改进,如果每天能把代码可读性量变​ 1%,那么日积月累就是质变:前些天我们写过一次对 Makefile 的重构,去掉了一处重复代码的坏味道,没过多久我便又发现了一处重复代码的坏味道,本文就让我们看看如何消灭它!

继续阅读

关于OCR项目的流水账

最近一直在开发某个 OCR 项目:底层用的是 ABBYY 提供的 FineReader 引擎,应用层把 FineReader 包装成 gRPC 对外提供服务,因为 FineReader 项目是 C++ 实现的,而我们团队使用的编程语言是 Golang,所以二者间通过 CGO 来完成交互。整个项目没有什么特殊的需求,只是鉴于 OCR 耗时较长,为了提升产品体验,要求在处理过程中:客户端可以主动退出;服务端能够实时返回已处理百分比。下面是根据需求画出来的流程图:

流程图

流程图

看上去很简单,不过我还是遇到不少问题,虽然这些问题主要都是一些细枝末节,基本上和 OCR 没什么关系,但是对别的项目还是会有所帮助的,下面让我一一道来。

继续阅读

实战CGO

某项目要集成 PDF 文件的 OCR 功能,不过由于此功能技术难度太大,网络上找不到靠谱的开源实现,最终不得不选择 ABBYY FineReader Engine 的付费服务。可惜 ABBYY 只提供了 C++ 和 Java 两种编程语言的 SDK,而我们的项目采用的编程语言是 Golang,此时通常的集成方法是使用 C++ 或 Java 实现一个服务,然后在 Golang 项目里通过 RPC 调用服务,不过如此一来明显增加了系统的复杂度,好在 Golang 支持 CGO,让我们可以很方便的在 Golang 中使用 C 模块,本文总结了我在学习 CGO 过程中的心得体会。

继续阅读

浅谈pprof

对于大多数 Gopher 而言,一般平时最主要的工作内容除了实现各种无聊的业务逻辑之外,剩下的就是解决各种琐碎的问题。比如:查询性能瓶颈在哪里?查询内存泄漏在哪里?好在 pprof 是处理此类问题的利器,共有两套标准库,分别适用于不同的场景:

命令行工具「go test」就包含了 runtime/pprof,相关参数请参考「go help testflag」:

shell> go test -cpuprofile cpu.out -memprofile mem.out -bench .

不过和 runtime/pprof 相比,更常用的是 net/http/pprof,接下来我们主要通过它来解决一些常见问题,想要激活 net/http/pprof 的话很简单,只要导入对应的包并启动服务即可:

import _ "net/http/pprof"

func main() {
	_ = http.ListenAndServe("localhost:6060", nil)
}

需要注意的是,千万别让外网访问到 pprof,否则可能会导致出现安全问题。有兴趣的读者可以尝试通过 google 搜索「intitle:/debug/pprof/ inurl:/debug/pprof/」看看反面例子。

继续阅读

浅谈NATS消息系统

我用过很多消息系统,比如:简单的 Redis Streams;高效的 Kafaka 等等,不过自从我把编程语言切换到 Golang 以后,总觉得必须找个用 Golang 开发的消息系统才配得上门当户对,原本我已经和小家碧玉的 NSQ 厮守终生,不过当我认识了上流社会 CNCF 钦定的大家闺秀 NATS 后,刹那间就仿佛徐志摩遇到了林徽因,扭头就给结发妻子写了休书。

继续阅读

浅谈微服务

虽说微服务早已是一个老生常谈的话题了,在 infoq 或者 thoughtworks 上可以找到很多案例,不过可惜的是其中相当比例的案例是失败的案例,究其原因,除了技术门槛之外,主要是因为很多人脱离了实际情况,只是为了微服务而微服务。本文通过一个例子带领大家从头到尾体验一下微服务的演化过程,不仅要做到知其然,更要做到知其所以然。

继续阅读