开发更高质量的服务

版权声明 本站原创文章 由 萌叔 发表 转载请注明 萌叔 | http://vearne.cc 1.引言 产品要求的功能都都开发完了,但这并不是终结。怎么样做才能让我们的服务具有更好的质量。 笔者结合自己的遇到的问题和工作中的经验,并以提问的方式,给读者一点点建议 2. 提问 重要性不分先后 2.1 如果服务器重启,服务是否能自动拉起? 2.2 如果程序异常退出,服务是否能够自动拉起? 2.3 如果程序异常退出,能够自动拉起,那么你怎么知道服务是否发生了重启? 2.4 如果是web服务,QPS是多少?每个URL的QPS是多少? 峰值是多少?一般在什么时间点触发? 每种URL的请求量是否合理? 2.5 如果是web服务,每个请求的响应时间是多少?TP90?TP99分别是多少? 2.6 异常请求(比如HTTP非200的比例是多少?)什么样的比例是合理的?为什么? 2.7 如果是多实例部署,那么整个系统的承载极限是多少?如果达到了极限,瓶颈在哪儿(木桶原理中所谓的短板) 2.8 服务都有哪些依赖项(微服务/数据库/文件系统) 其中哪些是无状态的,哪些是弱状态的,哪些是强状态的。这些外部服务和系统,是否已经做到高可用?能否做到快速扩容? 2.9 服务消耗的带宽多少?是否有可能达到带宽上限 如果是面向公网的服务,请求是否已经进行了压缩? 2.10 服务在部署上,是否已经做到了二地三机房 每个地区的网络线路,是否能做到2套或2套以上 (防止光纤被挖断的情况) 2.11 DNS服务是否能够对后端服务进行探活,自动修改域名的解析列表 2.12 部署是否实现了自动化 如果服务需要紧急扩容,该怎么做? 基于docker的容器化方案,还是ansible脚本? 2.13 文档是否完整,文档是否能与代码保持一致 2.14 如果是比较复杂的业务系统,是否有完整的自动化测试脚本 2.15 如果使用了数据库,比如用到了Redis/MySQL Redis连接池和MySQL连接池,是否已经打满(达到最大的poolSize) 打满之后,程序是会等待,还是报错? 2.16 如果使用了Redis,每次Redis操作的耗时是多少?TP90?TP99? 有没有慢查询?这些慢查询是否合理? 2.17 如果使用了MySQL,SQL是否做过审核 哪些表的操作频率最高?那种类型的操作最多? 有没有慢查询?这些慢查询是否合理? 有没有联表过多的查询? 2.18 如果使用了cache,cache的命中率是多少?cache容量是否达到上限? cache会不会与数据库存储不一致,不一致是否可以容许 cache的容量是否达到上限,是否已经触发了LRU 2.19 如果使用了负载均衡,负载均衡与服务之间是长连接吗? 如果服务和其它服务有交互,他们之间是长连接吗? 2.20 服务所在机器CPU负载怎么样?连接数高吗? 是否有大量的TIME_WAIT和CLOSE_WAIT ...

July 2, 2019 · 1 min

机械键盘换轴记

版权声明 本站原创文章 由 萌叔 发表 转载请注明 萌叔 | http://vearne.cc 1. 引言 我买的雷蛇的机械键盘,采用了1年半,坏了,先坏了F键,又坏了空格键和回车键,果然便宜没好货啊。买了几个cherry的轴体,本着人道主义精神再最后挽救一下。 2. 准备工作 2.1 cherry轴体 某宝上就有卖,红轴、茶轴、青轴3元/个,绿轴6元/个。 从阻尼的感受来看,从轻到重分别是红、棕、青(图上蓝色的那个)、绿 亲身的体验还是很重要的,可以各买1个试试,或者直接购买试轴器 轴体拆开了,就是下图这么个样子,外壳、铜片、弹簧、塑料的按键 不包含任何芯片,看起来原理也简单,但却真正考验配件的质量 2.2 电洛铁套装 2.3 螺丝刀套装 只用到一字和十字螺丝刀 2.4 拔轴器 因为笔者没有购买,这里直接用网上的图 3. 动手 3.1 拆除前置面板 注意 前置面板上有大量的卡扣,拆的时候要有耐心,用一字螺丝刀,一点点的撬开。 3.2 拆除后面板 注意 有几颗螺丝其实是隐藏在键盘的胶皮垫子下方,拆除时,不要忘了。 3.3 拆除原来的轴体 拆除轴体需要注意的以下事项 电洛铁加热到足够温度,首先沾少量的松香,再融开焊点的锡 此处松香作为助焊剂,沾松香可以使电洛铁更好的吸附焊点的锡,俗称挂锡。 2)待焊点的锡清除的差不多时,一边融开焊点的锡,一边可以使用拔轴器摁住轴体的卡扣(一字螺丝刀按住卡扣慢慢撬也可),向外慢慢的拔 注意 轴体有两侧有卡扣不能硬拔,否则可能损坏PCB板 小技巧 如果旧轴体已经拔出,但是PCB板的孔洞没有露出,可以一边用电洛铁融开焊点,一边用细铁丝(曲别针即可)插入小孔反复抽插。这样可以使孔洞露出。 3)插入新的cherry轴体,重新焊接好即可 4. 意外的惊喜 即使不小心电洛铁烫坏了PCB板的触点,键盘也未必完全报废 笔者在拆除旧的轴体时烫坏了一个触点(下图C位置)。通过万用表测量发现A、B、D均有4v左右的电压,唯独C点没有电压。初步揣测,键盘内部可能是并联电路,所以尝试在B和C之间用导线连接。经过测试,C位置的按键功能恢复。 最后来一张轴体安装完毕的图 请我喝瓶饮料

September 24, 2018 · 1 min

身在互联网圈的一些感受

版权声明 本站原创文章 由 萌叔 发表 转载请注明 萌叔 | http://vearne.cc 絮絮叨叨 自从把我的博客从CSDN迁出,独立成站以后,就很少在微信上发技术文章了, 主要是2个原因: 阅读微信的都是碎片时间, 而技术文章很多都需要深度的思考,不少还需要动手实际操作 在微信上粘贴代码太不放方便了 最后 欢迎访问我的个人博客 萌叔 今天来聊点最近的一些感受。 1. 中国崛起 我曾经跟我的同事们开玩笑,我说以后外国程序员,都必须要学中文,不然他们就看不到第一手的技术资料。 这几年中国程序员在世界上的影响力越来越大,这可能得益于中国有最大的互联网消费群体。 举几个例子 中国有世界上最大的redis使用平台,据新浪公布的资料,他们的redis平台有500+server,2000+的实例,不过这个应该不是单个集群的规模。 golang虽然是Google开发的语言,但是最大golang社区在中国,从几届gopher china大会的热闹程度,就可以看出golang在中国的火热程度 在前端领域巨牛的开源JavaScript项目VUE.js,为Github有史以来星标数第10多的项目,其作者是中国的尤雨溪 2. 处理能力压倒实际需求 曾经和一个美发行业的朋友聊过天,他所在的公司是一家有将近10余家分店的连锁企业,可是每天产生的订单数不超过1000单。 所以我的感觉是对绝大数领域,社区存在的解决方案的处理能力足够满足需要,数据库、或者某些框架只需要做简单的配置,就能够满足他们的日常需要了。二次开发,尤其是性能领域的二次开发的重要性变得相对较低。 3. 成熟的解决方案层出不穷 在10年前,甚至是几年前,技术资料非常难找。很多问题都没有很好解决方案,问都不知道该问谁。而现在各种社区里有各种乐于回答问题的好心人。各种开源或者收费云服务的解决方案满大街都是。 举几个例子 电商你可以用ShopsN 日志收集可以用ELK(elasticsearch + logstash + kibana) 监控你可以用zabbix或者open-falcon 这些方案很多都是开箱即用,就像使用yum或者apt-get一样简单。 而且应对绝大多数场景,已经绰绰有余。真正需要进行二次开发的只剩下扳着指头都能数出来的寥寥几家。 我不禁有些担忧,我们这些程序员的出路在哪儿。 总结 絮絮叨叨的说点心里话吧,也想听听大家的吐槽。 请我喝瓶饮料

June 1, 2018 · 1 min

如何生成全局唯一ID

版权声明 本站原创文章 由 萌叔 发表 转载请注明 萌叔 | http://vearne.cc 前言 在分布式环境中,生成全局唯一ID是非常需求。本文将介绍几种常见生成方法,并对它们的优缺点做出点评。 0. 8个字节 语言或数据库 内建类型 Golang uint64 Java long Python int MySQL bigint unsigned 2 ^ 32(4个字节)最多只有40多亿,对于高并发的系统,肯定不是够的。 以新浪微博为例,每天的新增的微博量都过亿,所以考虑到ID的容量,这个ID的长度至少是8个字节 1. UUID 长度: 为16 bytes, 128 bits 44e91a8a58d111e8ae84784f43a6cab8 见参考资料1: 5种版本 时间的版本 DCE Security MD5哈希 (伪)随机数 SHA-1哈希 以Version 1为例子 time_inc + clk_seq + node points time_inc时间精度为100 ns 即使在100ns以内,2次生成的time_inc也不会重复,因为会自动加1 clk_seq 为2个bytes一般是随机数(2 ^ 16 为65536) 协议文档中写明,此字段可以用来防止时钟回拨,但是在高并发情况下,也很难保证不出现冲突。 node取mac地址 下面是python的uuid库生成的一组ID a7748921-58d9-11e8-a727-784f43a6cab8 a70b016e-58d9-11e8-8a8c-784f43a6cab8 a6991957-58d9-11e8-8874-784f43a6cab8 a5b143ba-58d9-11e8-9600-784f43a6cab8 2. snowflake 长度: 8 bytes ...

May 16, 2018 · 2 min

查看网站或域名价值的小工具

版权声明 本站原创文章 由 萌叔 发表 转载请注明 萌叔 | http://vearne.cc 做了一个小工具,方便查看网站或域名价值,大家都来试下吧 点击链接 请我喝瓶饮料

January 10, 2018 · 1 min

做了个工具类的小网站---tool.vearne.cc

版权声明 本站原创文章 由 萌叔 发表 转载请注明 萌叔 | http://vearne.cc 欢迎大家使用 http://tool.vearne.cc/ 大家有什么工具类的需要,也可以给我评论,我会抽空往上加

January 1, 2018 · 1 min

《人月神话》读书总结

版权声明 本站原创文章 由 萌叔 发表 转载请注明 萌叔 | http://vearne.cc 人月神话的说明,为落后项目增加人手,会导致额外的任务分配开销,协作开发的沟通成本。新分配的人员还需要重新熟悉项目。这就像5核CPU,并不能是5倍的单核CPU的性能。(资源竞争,互斥等等引起的) 同样有2年经验且受同样培训的情况下,优秀的专业程序员可以是较差程序员的10倍。 概念完整性是系统设计中最重要的考虑因素。要形成整个系统的概念完整性,就必须实施贵族式的专制。设计工作职能由一个或者具有共识的小型团队来完成 功能数量和理解上的复杂程度的比值可以作为衡量系统易用性的一种指标 对于大型项目,系统结构设计和具体实现相分离是获得概念完整性的强有力的方法。系统结构设计可以理解为,定义不同功能模块的职责划分,模块之间的接口规范。系统结构设计是针对系统的高度抽象,有点像java中的中的接口和实现类。(比如,只定义,这里需要一个数据库,至于数据库的选型,可以在实现阶段再考虑 牢记开发人员承担创造性的实现责任,架构师只能提出建议 团队组织的目标是为了减少必要的交流和协作量 传统的树状组织反映了权力的结构原理–不允许双重领导 在大型团队中,各个小组倾向于不断的局部化,以满足自己的目标,而较少考虑对用户的整体影响。这种方向性的问题是大型项目的主要危险 从系统整体出发以及面向用户的态度是软件编程管理人员最重要的职能。 构建独立小型程序的数据(开发时间)不适用大型系统项目。程序开发时间随程序规模的增长,呈指数增长。一般为指数约为1.5,大量时间消耗在集成测试中。 从文档层面来讲,我倾向于同时有设计文档和用户使用文档 设计文档针对开发人员,用户使用文档针对用户(客户) 最好的方式是,在代码中嵌入注释,然后自动生成文档

January 1, 2018 · 1 min

火车票购票问题2

版权声明 本站原创文章 由 萌叔 发表 转载请注明 萌叔 | http://vearne.cc 看过火车票购票问题1 的朋友可能已经发现,还有可以优化的方案 方案1: 在处理购票请求的后期,某些站点区间可用的票数已经为0, 那么后续再有类似请求时,可以直接返回失败 这里的特殊情况是,如果有人退票,则某个站点区间又会有可卖的票,可以通过在购票高峰期限制退票来排除这个特殊情况。 对应文件 sell2.py # -*- coding: utf-8 -*- ############################################################ # 假定站点编号从 1 ~ 10 # 共20节车厢, 每个车厢20排 # 编号形如 # 1A 1B 1C 1D 1F # 2A 2B 2C 2D 2F # ... # 20A 20B 20C 20D 20F # 20 * 5 * 20 = 2000个座位 # 其实座位编号完全可以从 0 ~ 1999, 并不影响我们对问题本身的分析 ############################################################ import time MAX_CARRIAGE_NUM = 20 MAX_ROW_NUM = 20 MAX_SITE_INDEX = 10 class Seg(object): def __init__(self, carriage_no, seat_no, start_site, end_site): # 车厢编号 self.carriage_no = carriage_no # 座位编号 self.seat_no = seat_no # 完整编号 self.no = str(carriage_no) + '-' + seat_no # 能够售卖的开始站序号 int self.start_site = start_site # 能够售卖的终点站序号 int self.end_site = end_site def __str__(self): return str((self.no, self.start_site, self.end_site)) def init(): ticket_dict = {} for i in range(1, MAX_SITE_INDEX): for j in range(i + 1, MAX_SITE_INDEX + 1): ticket_dict[(i, j)] = [] for i in range(1, MAX_CARRIAGE_NUM + 1): for row in range(1, MAX_ROW_NUM + 1): for col in ['A', 'B', 'C', 'D', 'F']: # 每个座位都可以出售从s1 到 s10的车票 key = (1, 10) # print Seg(i, str(row) + col, 1, 10) ticket_dict[key].append(Seg(i, str(row) + col, 1, 10)) return ticket_dict def sell(ticket_dict, start, end, sellout_dict): ''' :param ticket_dict: :param start: 购票的起始站 :param end: 购票的终点站 :return: ''' if sellout_dict.get((start, end), False): return None # 需要找到一个有票的站点区间覆盖目标站点区间 # 所有可能的起始站 site_start = [] x = 1 while x <= start: site_start.append(x) x += 1 site_start.reverse() # 所有可能的终点站 site_end = [] y = end while y <= MAX_SITE_INDEX: site_end.append(y) y += 1 ticket = None for x in site_start: for y in site_end: if len(ticket_dict[(x, y)]) > 0: ticket = ticket_dict[(x, y)].pop() if ticket: # 判断一下这个座位的站点区间是否被完全用完了 # 如果没有还需要把新生成的余票间存回去 if start > x: temp = Seg(ticket.carriage_no, ticket.seat_no, x, start) ticket_dict[(x, start)].append(temp) if y > end: temp = Seg(ticket.carriage_no, ticket.seat_no, end, y) ticket_dict[(end, y)].append(temp) return Seg(ticket.carriage_no, ticket.seat_no, start, end) # 对于(start, end), 没有可以卖的票 # 那说明所有覆盖 (start, end) 的站点区间都没有票了 for x in site_start: for y in site_end: sellout_dict[(x, y)] = True return None def print_residual(ticket_dict): print '------------余票情况-------------' for key in ticket_dict: if ticket_dict[key]: print key, len(ticket_dict[key]) if __name__ == '__main__': ticket_dict = init() sellout_dict = {} t1 = time.time() with open('req.csv') as fp: for line in fp: ll = line.split(',') user = ll[0] start = int(ll[1]) end = int(ll[2]) ticket = sell(ticket_dict, start, end, sellout_dict) print '#' * 100 print line.strip() if ticket: print user, "bought", ticket print_residual(ticket_dict) # time.sleep(2) t2 = time.time() print t2 - t1 经过测试,速度又提升了20% ,处理10w请求只用了1秒多 ...

January 1, 2018 · 2 min

火车票购票问题1

版权声明 本站原创文章 由 萌叔 发表 转载请注明 萌叔 | http://vearne.cc 前段时间看了知乎的一篇文章 12306 外包给阿里巴巴、IBM 等大企业做是否可行? 李爱吉对于买票问题的优化算法,给了我非常大的启示,我决定实现出来,以享众人。 1.火车票购票问题描述 假定该车次有s1、s2、s3 … 到s6个站点,共6个站点 对于任意一个座位,初始时它可以出售的有效区间都是从首站s1到末站sN, 但是如果该座位某一段被售出,能出售有效区间就变化了。 如果上图所示: 红色的区段表示已经售出,该座位的情况是 站点2 -> 站点4 的票已经被售出 站点1 -> 站点2 的票仍可售卖 站点4 -> 站点6 的票仍可售卖 以某趟车次的车票出售为例,假定该车次有20节车厢,每节车厢有100个座位,那么共有座位 100 * 20 = 2000座位 那么在购票时(从站点x到站点y),都必须遍历这2000个座位,以找到一个合适的座位,由于有的座位的某些区段已经被售出,实际遍历的查询次数肯定大于2000次 这里把座位数记为m 查询n次的时间复杂度就是O(mn) 2. 查询优化 假定某趟车次共有10个站点,那么根据排列组合,能够售出车票,出发站、到达站的组合只能有 10 *(10 - 1) / 2 = 45 种 优化方法: 由于组合是有限的,我们可以把每个座位可以售卖的站点区间索引起来,当一个购票请求(x,y)从站点x到站点y 到达时,首先去查询 对应站点区间是否有票,如果没有就尝试在能够覆盖(x,y) 的站点区间的索引中去寻找。 # -*- coding: utf-8 -*- ############################################################ # 假定站点编号从 1 ~ 10 # 共20节车厢, 每个车厢20排 # 编号形如 # 1A 1B 1C 1D 1F # 2A 2B 2C 2D 2F # ... # 20A 20B 20C 20D 20F # 20 * 5 * 20 = 2000个座位 # 其实座位编号完全可以从 0 ~ 1999, 并不影响我们对问题本身的分析 ############################################################ import time MAX_CARRIAGE_NUM = 20 MAX_ROW_NUM = 20 MAX_SITE_INDEX = 10 class Seg(object): def __init__(self, carriage_no, seat_no, start_site, end_site): # 车厢编号 self.carriage_no = carriage_no # 座位编号 self.seat_no = seat_no # 完整编号 self.no = str(carriage_no) + '-' + seat_no # 能够售卖的开始站序号 int self.start_site = start_site # 能够售卖的终点站序号 int self.end_site = end_site def __str__(self): return str((self.no, self.start_site, self.end_site)) def init(): ticket_dict = {} for i in range(1, MAX_SITE_INDEX): for j in range(i + 1, MAX_SITE_INDEX + 1): ticket_dict[(i, j)] = [] for i in range(1, MAX_CARRIAGE_NUM + 1): for row in range(1, MAX_ROW_NUM + 1): for col in ['A', 'B', 'C', 'D', 'F']: # 每个座位都可以出售从s1 到 s10的车票 key = (1, 10) # print Seg(i, str(row) + col, 1, 10) ticket_dict[key].append(Seg(i, str(row) + col, 1, 10)) return ticket_dict def sell(ticket_dict, start, end): ''' :param ticket_dict: :param start: 购票的起始站 :param end: 购票的终点站 :return: ''' # 需要找到一个有票的站点区间覆盖目标站点区间 # 所有可能的起始站 site_start = [] x = 1 while x <= start: site_start.append(x) x += 1 site_start.reverse() # 所有可能的终点站 site_end = [] y = end while y <= MAX_SITE_INDEX: site_end.append(y) y += 1 # print 'site_start', site_start # print 'site_end', site_end for x in site_start: for y in site_end: ticket = None if len(ticket_dict[(x, y)]) > 0: ticket = ticket_dict[(x, y)].pop() if ticket: # 判断一下这个座位的站点区间是否被完全用完了 # 如果没有还需要把新生成的余票间存回去 if start > x: temp = Seg(ticket.carriage_no, ticket.seat_no, x, start) ticket_dict[(x, start)].append(temp) if y > end: temp = Seg(ticket.carriage_no, ticket.seat_no, end, y) ticket_dict[(end, y)].append(temp) return Seg(ticket.carriage_no, ticket.seat_no, start, end) return None def print_residual(ticket_dict): print '------------余票情况-------------' for key in ticket_dict: if ticket_dict[key]: print key, len(ticket_dict[key]) if __name__ == '__main__': ticket_dict = init() t1 = time.time() with open('req.csv') as fp: for line in fp: ll = line.split(',') user = ll[0] start = int(ll[1]) end = int(ll[2]) ticket = sell(ticket_dict, start, end) if ticket: print '#' * 100 print line.strip() print user, "bought", ticket print_residual(ticket_dict) # time.sleep(2) t2 = time.time() print t2 - t1 我随机生成了一个测试文件req.csv 来模拟用户的购票行为, 测试结果表明, 及时在单线程的情况下,只用了不到2秒就处理完了10w 个请求。这个速度已经足够快了,下一次我们再来对程序进行优化。 ...

January 1, 2018 · 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