rinetd 在生产环境要谨慎使用

版权声明 本站原创文章 由 萌叔 发表 转载请注明 萌叔 | http://vearne.cc 起因: 购买了阿里云的redis节点,但是默认阿里云不提供公网IP,所以我在一台阿里云的机器启动了rinetd,做端口的转发服务,开始一切正常,一段时间以后,随着并发力度加大。我们发现redis连不上了,提示Connection reset by peer 排查 1. 排查Redis 为什么会这样,首先我怀疑,是否redis有问题 首先我查看了redis的负载情况,使用INFO 命令 # Clients connected_clients:192 client_longest_output_list:0 client_biggest_input_buf:0 blocked_clients:16 # Stats total_connections_received:1131 total_commands_processed:7225865 instantaneous_ops_per_sec:30 total_net_input_bytes:216949807 total_net_output_bytes:87315792 显然redis的负载并不高 instantaneous_ops_per_sec 要超过2w, 负载才算高 connected_clients还不到200, 默认的设置允许最大连接数是1w 2. 排查阿里云主机 首先这台的机器的连接数并不高 [root@xxx-xx-77 ~]# ss -s Total: 733 (kernel 751) TCP: 644 (estab 598, closed 1, orphaned 0, synrecv 0, timewait 1/0), ports 234 Transport Total IP IPv6 * 751 - - RAW 0 0 0 UDP 1 1 0 TCP 643 636 7 INET 644 637 7 FRAG 0 0 0 但是观察机器的CPU使用率 ...

January 1, 2018 · 3 min

优雅的终止docker容器

版权声明 本站原创文章 由 萌叔 发表 转载请注明 萌叔 | http://vearne.cc 起因: 本文受到参考资料1的启发 我们线上的服务有不少都是部署在docker中,部署涉及的机器多大几十台, 服务发布时,要求前一个版本的容器必须优雅的退出。 docker容器中的进程是一个任务消费者。不断得从任务队列中取任务,然后进行执行(执行时间较长) 假定docker容器的name为test_v1 docker容器中的进程名为atm 也就是说不能简单的 docker rm -vf test_v1 docker run -d --name test_v1 test:v1 解决方案 1)方案1 首先,我想到的办法是在docker容器外部使用 ps -ef| grep atm |grep -v grep |awk '{print $2}'|xargs kill -15 容器中的进程捕获 SIGTERM 信号,优雅的退出,发现所有容器中的进程都退出后再执行发布逻辑 缺点: 这个方案肯定是没有问题的,但是如果进程同名,很有可能会导致误杀,而且从docker容器外部,传信号给容器内部的进程,感觉有点奇怪 2)方案2 幸运的看到了参考资料1 root@xxxx:~/test/docker/test_dk$ docker stop --help Usage: docker stop [OPTIONS] CONTAINER [CONTAINER...] Stop a running container by sending SIGTERM and then SIGKILL after a grace period --help=false Print usage -t, --time=10 Seconds to wait for stop before killing it 在docker stop命令执行的时候,会先向容器中PID为1的进程发送系统信号SIGTERM,然后等待容器中的应用程序终止执行,如果等待时间达到设定的超时时间,或者默认的10秒,会继续发送SIGKILL的系统信号强行kill掉进程。在容器中的应用程序,可以选择忽略和不处理SIGTERM信号,不过一旦达到超时时间,程序就会被系统强行kill掉,因为SIGKILL信号是直接发往系统内核的,应用程序没有机会去处理它。在使用docker stop命令的时候,我们唯一能控制的是超时时间,比如设置为20秒超时: ...

January 1, 2018 · 1 min

SSD 4k对齐问题

版权声明 本站原创文章 由 萌叔 发表 转载请注明 萌叔 | http://vearne.cc 因为知识有限,如果文章中有错误,请指出,谢谢。 起因: 我们生产环境的一台机器,使用的是SSD硬盘,但是测试的结果,读写速度只能到200MB/s, 而按照网上提供给的数据,SSD至少能够达到500MB/s, 顺序读写 会不会我对SSD的设置有问题 1. 文件大小和文件占用空间 在操作系统中,文件大小和文件占用空间大小是2个不同的概念 文件大小可以理解为文件实际大小,比如字节数 文件占用空间大小是为了存储这个文件所分配的硬盘空间的大小 文件 xxx.log 文件的大小仅有7个字节,而实际占用了512 * 8 = 4k个字节 文件 xxx2.log [root@xxx tmp]#stat /tmp/xxx2.log File: `/tmp/xxx2.log' Size: 38890 Blocks: 80 IO Block: 4096 regular file Device: fc01h/64513d Inode: 814342 Links: 1 Access: (0644/-rw-r--r--) Uid: ( 0/ root) Gid: ( 0/ root) Access: 2017-11-13 12:24:42.966209408 +0800 Modify: 2017-11-13 12:24:42.971209436 +0800 Change: 2017-11-13 12:24:42.971209436 +0800 细心的朋友会发现,文件空间总是大于文件大小,而且Blocks恰好为8的整数倍,这是因为操作系统为了和内存分页大小保持一致,便于数据从硬盘加载到内存中,以及便于从内存将文件回写到硬盘上,所以所做的妥协。 内存页大小 ...

January 1, 2018 · 4 min

saltstack 常用命令总结(持续更新)

版权声明 本站原创文章 由 萌叔 发表 转载请注明 萌叔 | http://vearne.cc 起因: 工作中经常要用到,就列在这儿,方便查看。 1. file server 1.1 更新state文件(针对master) fileserver.update backend=roots,git 1.2 清除本地state文件(针对master) salt-run fileserver.clear_cache 1.3 列出fileserver目录(针对master) 列出文件夹 salt-run fileserver.dir_list 列出文件 salt-run fileserver.file_list 2. Pillar 2.1 更新pillar 如果你设定git作为external pillar salt-run git_pillar.update branch='branch'repo='https://foo.com/bar.git' 2.2 查看pillar 查看特定 salt "*" pillar.get disk_type 查看所有 salt "*" pillar.items 2.3 刷新目标机器的pillar salt '*' saltutil.refresh_pillar 3. grains 3.1 查看grains 查看特定 salt '*' grains.item os osrelease oscodename 查看所有 salt '*' grains.items 3.2 同步自定义的grains 脚本放在salt://_grains 目录中 Sync grains modules from salt://_grains to the minion ...

January 1, 2018 · 1 min

SaltStack 重要配置

版权声明 本站原创文章 由 萌叔 发表 转载请注明 萌叔 | http://vearne.cc 当整个saltstack的负载比较高的时候需要修改如果配置参数 1. Minion By default, the Salt fileserver recurses fully into all defined environments to attempt to find files. To limit this behavior so that the fileserver only traverses directories with SLS files and special Salt directories like _modules, enable the option below. This might be useful for installations where a file root has a very large number of files and performance is negatively impacted. Default is False. ...

January 1, 2018 · 1 min

Redis 关于大量1级key的测试

版权声明 本站原创文章 由 萌叔 发表 转载请注明 萌叔 | http://vearne.cc 起因:有文章提到Redis的1级key数量不应该超过100w 我十分怀疑这个结论是怎么得到的。我们知道在Redis中一个DB中的所有key维护在一个HashMap中,较多的key当然会导致,key的移动更加困难,当然由于HashMap的原因,在rehash时,可能消耗更多的时间;另外内存可能有少部分浪费。可是key的数量增大到100w以上,是否真的会带来其它问题吗 1. 测试验证 1.1 测试方法 使用string 类型,不断的插入新key,为了保证key仅可能不重复,且长度一致 使用自增变量 i 的md5值 每写入10w个key记录一下当前的内存值,已经插入这10w个key所消耗的时间 import json import redis import random import time import hashlib r = redis.Redis(host='localhost',port=6379,db=5) SIZE = 100000 fp = open('result.txt', 'w') counter = 0 for i in xrange(0, 100): t1 = time.time() for j in xrange(0, SIZE): counter += 1 print 'counter', counter m = hashlib.md5() m.update(str(i * SIZE + j)) key = m.hexdigest() r.set(key, 1) t2 = time.time() margin = t2 - t1 info = r.info() #print info ll = [] ll.append( str((i + 1) * SIZE) ) ll.append(str(margin)) ll.append(str(info['used_memory'])) fp.write(','.join(ll) + '\n') fp.flush() print (i + 1) * SIZE, margin, info['used_memory'] fp.close() 1.2 测试数据 测试总计写入1000w个key,耗时大概在半小时 图1 ...

January 1, 2018 · 1 min

golang中可变长参数的使用

版权声明 本站原创文章 由 萌叔 发表 转载请注明 萌叔 | http://vearne.cc 起因: 使用的Redis的时候,需要使用LPUSH 往一个key中一次写入多个value 我使用的是garyburd/redigo 这个库 函数定义如下 // Do sends a command to the server and returns the received reply. func Do(commandName string, args ...interface{}) (reply interface{}, err error) 显然函数是可变长参数 解决方法 1. 列表 package main import ( "fmt" "github.com/garyburd/redigo/redis" ) func main() { dialOption1 := redis.DialDatabase(0) dialOption2 := redis.DialPassword("xxxx") rs, err := redis.Dial("tcp", "127.0.0.1:6379", dialOption1, dialOption2) if err != nil { fmt.Println(err) } // redis的key是 "mykey" args := []interface{}{"mykey"} args = append(args, 10, 20) args = append(args, 30) count, err := redis.Int(rs.Do("LPUSH", args ...)) fmt.Println("count:", count) } 2. 字典 package main import ( "fmt" "github.com/garyburd/redigo/redis" ) func main() { dialOption1 := redis.DialDatabase(0) dialOption2 := redis.DialPassword("xxxx") rs, err := redis.Dial("tcp", "127.0.0.1:6379", dialOption1, dialOption2) if err != nil { fmt.Println(err) } test_map := make(map[string]int) test_map["zhangsan"] = 1 test_map["lisi"] = 2 test_map["wangwu"] = 3 // redis的key是 "my_hash" args := []interface{}{"my_hash"} for f, v := range test_map { args = append(args, f, v) } str, err := redis.String(rs.Do("HMSET", args ...)) fmt.Println(str) } 参考资料 How do I call a command with a variable number of arguments Go实例学:可变长参数函数

December 31, 2017 · 1 min

业务日志收集方案

版权声明 本站原创文章 由 萌叔 发表 转载请注明 萌叔 | http://vearne.cc 起因: 我们线上的业务通常会部署到10几台或者几十台机器上,线上的日志如果用salt执行命令远程的grep已经是越来越不方便了,所以我们决定对日志进行统一收集,管理 1. 选择方案 我们业务日志不算特别的多,因此不想方案过于复杂,并且公司内部已经有ES和kafaka集群 因此可以选方案有 1) rsyslog + kafka + elasticsearch 2)fluentd + kafka + elasticsearch 我最终选择了方案1: a) 由于公司的服务器主要是centos, 默认已经安装了rsyslog b) Fluentd是JRuby开发的,而rsyslog是二进制程序 以前有过logstash的使用经历,当日志量较大时,logstash会把CPU打的很高 感受:rsyslog的功能其实非常强大, 它所有配置都是从某个input获取数据再发送到output(和logstask很像) 支持: 1) 文件 –> kafka 2) 文件 –> elasticsearch 3) tcp/udp –> 文件 4)文件 –> 其它主机(TCP/UDP) input 和 output 是可以任意组合的 如果你不想搭建Elasticsearch和Kafka,完全可以把所有日志收集到某个文件服务器 然后在这台文件服务器上再使用logrotate,完全可以满足日常的开销 kafka只是用来做缓冲的,如果日志没有明显的波峰,可以不使用kafka 2. 实施 2.1 统一日志字段 我们多个业务项目,并且有Golang、Python等多种语言,为了保证,入ES的数据格式一致,我们统一了日志的字段,如下 所有字段都是比选的,如果没有请留成空字符串* 字段 类型 是否必填 说明 备注 service string 是 业务标识 使用英文字符和下划线,中划线 name string 是 logger名称 level string 是 日志级别 ERROR/INFO/DEBUG/WARNING pathname string 是 文件全路径 lineno int 是 在文件中的行号 如果没有, 给默认值-1 msg string 是 消息体 task_id string 是 任务ID log_date string 是 日志时间 ES上的字段类型为datetime 2017-01-01T00:00:00+0800 不同的业务和项目之间通过service字段区分 ...

December 31, 2017 · 1 min

Elasticsearch经验总结(持续补充)

版权声明 本站原创文章 由 萌叔 发表 转载请注明 萌叔 | http://vearne.cc 起因: ES在笔者所在的公司使用也有3年多了,集群的规模达到上百台,期间也有很多的经验,我这里总结出来分享给大家,技术水平有限,如有错误请指正。 事项: 这些事项,我把它们以问题的形式列出,并会持续补充 1. 关于shard大小的分配 ES的shard是在index创建好时,就已经分配了,所以shard数量的选择非常重要,根据经验shard的大小在10GB ~ 20GB 较为合适。选择这个大小的原因如下 1)ES是通过移动shard来实现负载均衡,如果shard过大移动会非常缓慢 2)另外每个shard相当于一个lucene实例,lucene实例也对应着一组Java线程,所以shard数也不应该过多 2. 关于index的命名设计 如果数据是随着时间增长的,可以选择按月,或者按天分库 index的命名可以是 index_201701、index_201702、index_201703 或 index_20170301、index_20170302、index_20170303 然后可以为他们指定别名index_2017,这样可以直接使用这个别名查询所有index库 另外ES的库是可以关闭的,关闭以后,不占内存空间,只消耗硬盘空间 3. SSD OR 机械硬盘? Elasticsearch的速度有赖于索引,大量的索引是以文件的形式存储在硬盘上的,如果你的数据量较大,且单次的查询或聚合量较大,那么应该使用SSD,据我们的测试表明,再查询的数据量较大的情况下, 使用SSD的ES速度是机械硬盘的ES速度的10倍, 官方说法在正确配置的情况下,SSD的写入速度是机械硬盘的500倍 给一个参考值 数据单条记录1kB 操作系统Centos 6.7 内存64G ES版本2.3 ,堆内存31GB 单个ES data node处理能力 机械硬盘 SSD 1w/min 10w/min 见参考资料[1] If you are using SSDs, make sure your OS I/O scheduler is configured correctly. When you write data to disk, the I/O scheduler decides when that data is actually sent to the disk. The default under most *nix distributions is a scheduler called cfq (Completely Fair Queuing). ...

December 31, 2017 · 3 min

我看过的好书推荐

版权声明 本站原创文章 由 萌叔 发表 转载请注明 萌叔 | http://vearne.cc 起因:以前一直想有人能给我介绍下有哪些好的计算机方面的书,却也一直没怎么得到高人的点拨,现在自己跌跌撞撞的走过10年的职场生活,也算读了几本书,跟大家分享一下。 我尽量按照体系或者编程语言分类: 公共篇: 书名: 《携程架构实践》 推荐理由:对大型互联网的架构和重要组件都有涉及,基本属于点到为止。 但是萌叔仍然推荐阅读一下。 1)此书中提到的很多解决方案是携程内部现在正在使用的,具有很高的参考价值。 2)对特定领域问题的解决方案的演进和思考,对未来的架构发展方向有指引作用。 3)经常搬砖的朋友,可以提高一下自己的格局。 书名: 《构建高性能web站点》 推荐理由: 跟web站点性能调优的常用思路和方法都能在这里找到。 书名:《数学之美》 推荐理由: 能使你建立起框架性的,提纲挈领的书。 书名:《编写可读代码的艺术》 推荐理由: 代码规范引导。任何外来强加的代码规范,都不及发自内心的想写更好,更可读代码的愿望。另外就是多读一些开源项目的代码,对写好代码有很大的帮助,有一天你会突然明白,原来还能这么写。 书名:《Linux/Unix设计思想》 推荐理由: 从哲学方面探讨了linux和unix的设计思想,可以用来开脑洞。 书名:《白帽子讲web安全》 推荐理由: web安全方面的入门好书,XSS和CSRF都有涉及 书名:《lucene实战》第二版 推荐理由: lucene核心开发者编著。lucene是solr和elasticsearch的底层。要想把solr和elasticsearch弄明白,这本书必须得看。 书名:《Elasticsearch源码解析与优化实战》 推荐理由:基于6.1.2源码的深度解读,相关原理和软件配置参数讲解的也很详细,对Elasticsearch的深入学习大有益处。 书名:《python绝技:运用python成为顶级黑客》 推荐理由: 不要被这本书的名字给唬住了,其实这本书的英文名称叫《Violent Python》主要是讲使用Python来进行安全方面的实践,100%的实操,而不是空洞的理论,涉及网络和安全相关知识 书名:《Unix环境高级编程》 推荐理由: 任何一门编程语言都需要把自己的程序转换为对操作系统接口的调用。所以了解系统API是非常重要的。读完这本书再去看本门语言中对线程和进程的使用会感到非常的熟悉。但是读本书的时候最好有C语言基础,否则肯定读不懂。 书名:《linux内核设计与实现》 推荐理由: 标题特别唬人,但其实里面真正设计到编程的部分并不多,很大部门都是在阐释设计思想,建议看英文版,中文版有缺失,导致无法看懂。看中文版最好玩的地方在于,每当你看中文版看不懂的时候,一看英文版就明白了 书名:《图灵程序设计丛书:Linux Shell脚本攻略》 推荐理由: 这本阿三写的神书,确实比《shell高级编程》读起来舒服多了,不过这本书里写的都是常用命令和常用参数,比较简单。 书名:《Redis设计与实现》 推荐理由: 这本书的作者,功力绝对不一般。读完这本书我认识了跳跃表,并且redis为了实现低内存开销和高性能所采用的方法也让人有眼前一亮的感觉。 书名:《MySQL是怎样运行的-从根儿上理解MySQL》 推荐理由:直接深入实现细节,包括索引结构,查询流程。更难能可贵的是本书有非常丰富的彩色图表,让人一目了然。豆瓣评分高达9.5分。萌叔强烈推荐。在此感谢作者,也感谢给我推荐这本书的峰云大神。 书名:《SRE-Google运维解密》 推荐理由:本书介绍了google内部生产实践中遇到的一些问题,并且他们对于这些问题的思考和解决方案。 对于规模较大的公司,有一定的借鉴意义。 站在巨人的肩膀上,你能看得更远。 书名:《深入理解linux网络》 推荐理由:豆瓣评分高达9.5分。 深入linux内核源码,了解数据包发送和接收细节、epoll的底层工作原理。 本书对应对面试和日常服务性能优化都有帮助。另外本书配有大量彩色图表,表述调理清晰。 提示:本书不适合初学者。 书名:《Apache APISIX实战》 推荐理由: APISIX项目官方团队编写,对于理解网关设计理念,工作原理,插件扩展有一定的帮助。 ...

December 31, 2017 · 1 min