本文目录一览:

zstd,未来可期的数据压缩算法

最近了解到了 zstd 这种新的压缩算法。不像lz4,lzo,snappy等近几年流行的压缩算法专注于压缩和解压缩性能,zstd在性能不错的同时号称压缩率跟Deflate(zip/gzip的算法)相当。下面是 官网 列出的数据:

我们知道,压缩算法的效果和性能跟被压缩的数据类型和模式有很大的关系,光看别人的测试数据、benchmark是不够的。正好有功能开发需要,于是结合我们的使用场景真实测试的一下。

惊喜的是,实测的结果比官方提供的还好,终于找到了我们的cup of tea。

Intel(R) Core(TM) i5-4570 CPU @ 3.20GHz, 8G内存

CentOS 7.0

对几种支持流式写入的压缩算法,使用对应的命令行工具进行压缩测试。

除了snappy,各种压缩算法/工具都支持设置压缩级别,高级别意味着以更长的压缩时间换取更高的压缩率。

100万行不重复的某个应用的日志文件,大小为977MB。

从上面可以看出:

zstd无论从处理时间还是压缩率来看都占优。snappy, lz4, lzo的压缩率较低,但压缩速度都很快,而zstd甚至比这些算法更快。Gzip的压缩率比lz4等高不少,而zstd的压缩率比gzip还提升一倍。

如果从上面的比较还不是特别直观的话,我们再引入一个创造性的指标(从网上其他压缩算法对比没有见过使用这项指标):

代表单位处理时间可以压缩去掉多少冗余数据。其中 权重系数 用来指定压缩率和压缩速度哪个更重要,这里我们认为在我们的使用场景里两者同样重要,取系数为1。

从这里我们可以明显看出, zstd lz4 lzo snappy 其他 。

对1000行、大小约为1MB的文件进行压缩测试,各种算法的压缩率跟1GB大文件的压缩率几乎一样。

下面再对更小的数据量——10行日志数据的压缩率进行对比。虽然我们的使用场景里没有对小数据量的压缩处理,但还是比较好奇zstd字典模式的效果。

其中最后一组数据为zstd使用10000行日志进行训练生成字典文件,并利用字典文件辅助压缩测试数据。

可以看出来,除了zstd字典模式外,各种压缩算法在处理更小的数据量时压缩率都下降很多。而zstd字典模式对压缩率带来帮助非常明显,与gzip对比,压缩率从1000行时相差1倍,到10行时变为了相差接近3倍。

下一篇文章将给大家对比这几种算法的golang开源库的性能和压缩率。敬请期待。

golang中compress/gzip

go标准库的gzip包中提供了两个操作,分别是压缩和解压

常量和变量

(1)压缩

demo

(2)解压

demo

集中式日志分析平台 - ELK Stack - Filebeat 压测

任何一款采集 agent 进行公司内全面推广前都需要进行性能测试以及资源限制功能测试,以保证:

对于 Filebeat 这款号称 golang 编写,性能强于 logstahs-forwarder 的采集 agent,我们也需要这样进行严谨对待。

硬件选择虚拟机,6cores + 16GB Mem + 175GB SSD + 1000Mbps 带宽;

Filebeat 配置,输出到 console:

Filebeat 配置,输出到 Kafka:

我们开启 Filebeat 的 6060 端口,并使用 python 脚本进行指标采集。

expvar_rates.py ,每秒统计出 Filebeat 指标,主要看:

Step1. 启动 Filebeat (172.16.134.8)

Step2. 启动统计脚本

Step3. 启动 tsar

Step4. 写入压测数据(6个进程写入,6千万条日志)

在 6 进程数据写入日志文件时,我们在开启 python 统计脚本的窗口得到如下稳定的统计数据:

我们在 tsar 看到的统计数据为:

我们在 top 中可以看到 Filebeat 大致占据了 0.8 cores。

在 6 进程数据写入日志文件后,我们在开启 python 统计脚本的窗口得到如下稳定的统计数据:

我们在 tsar 看到的统计数据为:

我们在 top 中可以看到 Filebeat 大致占据了 1.6 cores。

小结:

测试步骤和上述一致,区别在于配置文件需要输出到 Kafka。

在 6 进程数据写入日志文件时,我们在开启 python 统计脚本的窗口得到如下稳定的统计数据:

我们在 tsar 看到的统计数据为:

我们在 top 中可以看到 Filebeat 大致占据了 0.7~0.8 cores。

在 6 进程数据写入日志文件后,我们在开启 python 统计脚本的窗口得到如下稳定的统计数据:

我们在 tsar 看到的统计数据为:

我们在 top 中可以看到 Filebeat 大致占据了 2.0 cores。

小结:

测试步骤和上述一致,区别在于配置文件需要输出到 Kafka。

和上述步骤不同的是,启动 Filebeat 时需要 systemd 限制 CPU、句柄数,根据之前的理论,句柄数限制在 100 已经非常够用,CPU 限制在 1 core。

修改 /usr/lib/systemd/system/filebeat.service :

执行 reload:

对 CPU 进行限制:

确认是否限制成功:

有如下输出表示OK:

在 6 进程数据写入日志文件时,我们在开启 python 统计脚本的窗口得到如下稳定的统计数据:

我们在 tsar 看到的统计数据为:

我们在 top 中可以看到 Filebeat 大致占据了 0.7 ~ 0.8 cores。

在 6 进程数据写入日志文件后,我们在开启 python 统计脚本的窗口得到如下稳定的统计数据:

我们在 tsar 看到的统计数据为:

我们在 top 中可以看到 Filebeat 大致占据了 1.0 cores,限制生效。

小结:

在 6 进程数据写入日志文件时,我们在开启 python 统计脚本的窗口得到如下稳定的统计数据:

我们在 tsar 看到的统计数据为:

我们在 top 中可以看到 Filebeat 大致占据了 0.75 ~ 0.9 cores。

在 6 进程数据写入日志文件后,我们在开启 python 统计脚本的窗口得到如下稳定的统计数据:

我们在 tsar 看到的统计数据为:

我们在 top 中可以看到 Filebeat 大致占据了 1.0 cores,限制生效。

小结:

在 6 进程数据写入日志文件时,我们在开启 python 统计脚本的窗口得到如下稳定的统计数据:

我们在 tsar 看到的统计数据为:

我们在 top 中可以看到 Filebeat 大致占据了 0.7 ~ 0.75 cores。

在 6 进程数据写入日志文件后,我们在开启 python 统计脚本的窗口得到如下稳定的统计数据:

我们在 tsar 看到的统计数据为:

我们在 top 中可以看到 Filebeat 大致占据了 0.9 cores,未达到限制。

小结:

A. FB 全力采集 247B 数据(真实环境类似日志长度),速率为 ~ 40K/s,CPU 开销为 2 cores;

B. FB 在 CPU 限制 1 cores 情况下,采集 247B 数据速率为 ~ 20K/s,可以认为单核采集速率为 ~ 20K/s/core;

C. 日志单行数据越大,吞吐越小,5KB 每行已经非常夸张,即使如此,没有压缩的情况下带宽消耗 35MBps,gzip 压缩率一般为 0.3~0.4,占用带宽为 10.5~14MBps,对于千兆网卡来说压力较小;

如何部署Golang应用

安装supervisord

# 通过引导程序 ez_setup.py 来安装。这个引导程序会联网下载最新版本setuptools来安装,同时也可以更新本地的setuptools。

wget

sudo python ez_setup.py

# 更新setuptools:

sudo python ez_setup.py -U setuptools

# 安装supervisor

easy_install supervisor

# 生成配置文件

echo_supervisord_conf /etc/supervisord.conf

# 编辑配置文件

vim /etc/supervisord.conf

# 进入vim后找到最后两行,打开注释(取消前面的分号),

# [include]

# files = supervisor.d/*.ini

# 将所有的supervisor配置都放到 /etc/supervisor.d目录

mkdir /etc/supervisor.d

创建 supervisor 对应程序的配置文件

其中的一些路径需要换成自己对应的,这里将 zankbo 这个web 应用放在了对应的用户目录下

通过在生产服务器上设置environment可以在程序里判断是线上还是开发模式,如 zankbo 的 debug判断

当然也可已在启动命令处加入参数,如 command = /home/zankbo/gopath/src/zankbo/zankbo -d 来关闭Debug模式。

if os.Getenv("APP_NAME") == "ZANKBO_PRODUCT" {

beego.RunMode = "prod"

}

vim /etc/supervisor.d/zankbo.ini

# 写入

[program:zankbo]

directory = /home/zankbo/gopath/src/zankbo

environment=APP_NAME="ZANKBO_PRODUCT"

command = /home/zankbo/gopath/src/zankbo/zankbo

autostart = true

startsecs = 5

user = zankbo

redirect_stderr = true

stdout_logfile = /home/zankbo/log/zankbo.log

建立对应的用户

useradd zankbo

# 将www用户加入到zankbo用户组,Nginx以www用户运行

usermod -a -G zankbo www

# 更改用户家目录用户组的权限,使Nginx可以访问

chmod g+rx /home/zankbo

部署Go环境

其中的目录为,go:Go安装目录 gopath:Go工作目录,下面有src、pkg、bin三个目录 log:日志文件夹

[zankbo@MyCloudServer ~]$ pwd

/home/zankbo

[zankbo@MyCloudServer ~]$ vim .bashrc

# 设置Go环境变量,在.bashrc文件末尾写下如下内容

export GOROOT=$HOME/go

export GOPATH=$HOME/gopath

export PATH=$PATH:$GOROOT/bin:$GOPATH/bi

# 切换到用户家目录

[root@MyCloudServer ~]# su - zankbo

[zankbo@MyCloudServer ~]$ ls

go gopath log

将项目代码放到gopath/src下面,如我的播客项目:

[zankbo@MyCloudServer ~]$ tree -L 2 gopath/src/

gopath/src/

├── github.com

│ ├── astaxie

│ ├── beego

│ ├── go-sql-driver

│ ├── howeyc

│ ├── jacobsa

│ ├── smartystreets

│ └── wendal

└── zankbo

├── admin

├── blog

├── build_pkg.sh

├── common

├── conf

├── controllers

├── dbstruct.mwb

├── main.go

├── models

├── static

├── views

└── zankbo

导入项目sql文件到数据库

在项目文件夹执行build

[zankbo@MyCloudServer zankbo]$ pwd

/home/zankbo/gopath/src/zankbo

[zankbo@MyCloudServer zankbo]$ go build

会在项目下生成与包名对应的可执行文件,这里为:zankbo,build的时候可能会遇到错误,比如mysql的密码之类的,可根据提示排错。

通过supervisor 来启动服务

# supervisorctl start zankbo

配置Nginx

server {

listen 80;

server_name zankbo.com ;

root /home/zankbo/gopath/src/zankbo;

error_log logs/zankbo.com.error.log warn ;

location /static/ {

root /home/zankbo/gopath/src/zankbo;

location ~ .*\.(js|css)$ {

access_log off;

expires 1d;

}

location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$ {

gzip off;

access_log off;

expires 3d;

}

}

location / {

proxy_pass ;

}

}

网络:什么是 MIME TYPE?

最近在读 Golang 的源码,看到 mime.go 这个文件时,有点看不懂了。

MIME, Mutipurpose Internet Mail Extensions,多用途 Internet 邮箱扩展。MIME 是描述消息内容类型的 internet 标准。在创建之初,是为了在发送电子邮件时附加多媒体数据,让邮件客户程序根据其类型进行处理。现在 MIME TYPE 被 HTTP 协议支持后,使得HTTP能够传输各种各样的文件。

浏览器通过 MIME TYE,也就是该资源的媒体类型,来决定以什么形式显示数据。

媒体类型通常是通过 HTTP 协议,由 Web 服务器请求头中的 Content-Type 来告知浏览器数据类型的,比如:

表示内容是 text/HTML 类型,也就是超文本文件。注意,必须是 "text/HTML" 而不是 "HTML/text".因为 MIME 是经过 ietf 组织协商,以 RFC 的形式发布在网上的。

需要注意的是: 只有一些在互联网上获得广泛应用的格式才会获得一个 MIME Type ,如果是某个客户端自己定义的格式,一般只能以 application/x- 开头。

Internet 中有一个专门组织来对 MIME 标准进行修订,但是由于 Internet 发展过快,很多应用程序便使用在类别中以 x- 开头的方法标识这个类别还没有成为标准,例如 x-gzip,x-tar等。

其实是不是标准无关紧要,只要客户端和服务器都能识别这个格式就可以了。在 app 端会使用自定义标准来保证数据安全。

MIME类型与文档的后缀相关,因此服务器使用文档的后缀来区分不同文件的 MIME 类型,服务器中必须规定文件后缀和MIME类型之间的对应关系。而客户端从服务器上接收数据的时候,它只是从服务器接收数据流,并不了解文档的名字,因此服务器需要使用附加信息来告诉客户程序数据的 MIME 类型。服务器将首先发送以下两行 MIME 标识信息,这个信息并不是真正的数据文件的一部分。

注意,第二行为一个空格,这是必须的,使用这个空行的目的是将 MIME 信息与真正的数据内容分离开。

通用结构: type/subtype

MIME 类型对大小写不敏感,但是通常传统写法是小写。

分类

对于 text 文件类型若是没有特定的 subtype,就使用 text/plain, 类似的二进制文件如果没有特定或已知的 subtype,就使用 application/octet-stream.

还有非MIME 类型,但是比较通用的 icon 类型,image/x-icon