本文目录一览:
- 1、zstd,未来可期的数据压缩算法
- 2、golang中compress/gzip
- 3、集中式日志分析平台 - ELK Stack - Filebeat 压测
- 4、如何部署Golang应用
- 5、网络:什么是 MIME TYPE?
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