【置顶】个人阶段性学习和规划总结(技能树)

  专注后台服务端开发也好久了,自我感觉经验增加了很多,接触到的东西确实不少,博文也批量更新了很多。表面看似很多很杂,但个人心中思路计划感觉还是比较明确的,此处做一阶段性整理和总结吧。
  其实不仅仅是后台服务端开发,就整个软件开发的知识构成也是有所层次的。个人毕竟不是正规计算机科班出身,也就是大家所说的半路出道的野程序员,很多时候感觉自己的知识构成还是有所缺陷。长痛不如短痛,晚补不如早补,该学的终究跑不掉!

【置顶】博客资源收录大全

  虽然当下微信公众号席卷自媒体之势如火如荼,但是文章展示个人还是偏向于独立博客的方式,主要是因为个人可以控制的东西比较多。我想,对于我来说,这个时代没有什么比个性和自由更为重要的了吧。
  下面是一些网络知名人士的博客,以及在搜索资料过程中遇到的好站点。除了不感兴趣的前端、移动端外,过于Java/Nodejs等语言化的博客也被KO了,希望平时没事多看看吧!

CMake工具使用手册

  之前自己的小项目都是直接手动人肉Makefile,因为项目的文件不是很多,发现以前写的那个Makefile模板增增改改还是挺够用的。但现在发现CMake真是越来越流行了,不知道是不是借着QT/KDE等项目的东风,越来越多的C++开源项目开始使用CMake工具来用作管理项目了。此外,著名IDE Clion和CMake也集成的很好,只不过我现在已经不用IDE进行调试了,因为命令行的GDB更方便。
cmake
  这次在一个项目中使用了CMake,简单直白的几行命令,就可以快速生成Makefile,相比Makefile晦涩的语法和隐暗的规则,可以说是懒人(对我来说主要是弱鸡)用的Makefile。除了辅助生成编译用的Makefile,CMake还集成安装、测试、打包等功能,同时跟Boost库的单元测试框架也很好的集成,Bingo!
  注意:CMake工具的实现主要是由一系列的命令构成,同时还有大量的预定义变量,正是他们的存在使得用户可以用极少的语句生成功能丰富的Makefile文件。现在CMake官方最新发布版本是v3.8,但是在CentOS-7系列的机器上最新的CMake版本仍然是v2.8分支,由于代码的部署环境所限,本篇文档还是针对CMake v2.8.12老版本操作实验的结果,有时候同最新CMake可能会有所差异,建议查看查看老版本的文档。
  CMake中有很多涉及到文件、目录的相关命令或者变量,在作为参数的时候有时可以使用相对路径,有时可以使用绝对路径;在使用相对路径的时候,有时候是相对于项目的源代码路径,有时候是相对于编译路径,还有些时候相对路径参考于某些预制变量,这些东西如果被搞糊涂了还是建议查看相关文档。
  本文档不求最全,够用即可!

一、起步

  凡是手动安装过CMake管理的软件的同学,都知道CMake的用法。通常会在项目路径下面建立一个build目录,然后进入build目录使用➜ build git:(master) ✗ cmake ../ 命令就可以生成Makefile文件,接下来的操作想必大家就都知道了。额外创建build路径进行项目外编译,就是可以保护你的源代码路径整洁干净。
  所以开发者就是要编写这个CMakeLists.txt文件,方便自己的同时也方便了用户。

后台开发那些常用技术再次小结(三):存储部分

  原书对于存储模块,主要就是描述的数据库的设计和优化,和我通常想到的文件系统的存储有点差异,其实数据库的底层还是放在文件系统上面的(原谅我又不禁想到了GitLab删库事件),只不过随着数据量增加数据库文件的尺寸会不断的变大(在mysql中查找datadir的变量就可以看见数据文件的位置)。
  互联网公司很多数据都塞在数据库中的,而且数据库这一模块的使用和优化经验也比较的丰富,更加有文章可做吧!

一、文件存储

  在绝大多数情况下磁盘一直都被诟病是拖慢整个系统的罪魁祸首,现在看来网络速度都会比磁盘要快得多。
  如果是自己的服务器托管,建议尽可能的增加物理内存(云主机就算了,增加内存配置价格贼贵),因为操作系统的缓存机制,较大的物理内存能减少IO操作,从而改善文件系统访问性能。
  现在优化磁盘效率的方法除了操作系统和文件系统的参数调优之外,最直接的方法就是上SSD。想到前些年很多人对SSD还是持观望态度,时常会有SSD无故掉盘、数据无法恢复的情况,不过从这些年看来随着SSD技术的完善,各大厂商和数据中心都以SSD硬盘作为主机的卖点了,可见SSD还是接受住了现实的考验了(虽然现在随着工艺水平的提高和TLC的推广,据称SSD的寿命甚至还不如之前),工业上通过SSD将业务性能提高几倍甚至几十倍的案例数见不鲜。一方面来说,可以将SSD作为一个缓存介质可以大大增加IO密集型应用效率,这样即使出故障也对业务没有什么影响;二则现实世界没有什么硬件是绝对可靠的,所谓的可靠性缺陷可以用软件来弥补。想当初我在2012年花了六百多大洋买了Crucial 64GB m-sata接口的固态硬盘,该硬盘作为系统盘现在仍然工作的杠杠地,所以增加内存和上固态硬盘是任何工作或者生产机器实现“垂直扩展“的最佳捷径了。对于固态硬盘如果是SATA3接口,其最高速率是6Gbps,而现在很多SSD的传输速度已经受限于该接口速率了,那么你可以考虑采用PCI-E接口的SSD存储来获取更高的性能了。
  RAID(独立冗余磁盘阵列)算是一个历史悠久但却极为有用的存储技术了,通过多个廉价独立的磁盘进行组合达到多种组合,将IO操作分散到多个物理磁盘上去,同时具有增加副本备份恢复的功能,就可以让整个存储系统在可靠性、性能、成本之间做出权衡,RAID技术算是最底层硬件层次上所做出的备份和优化操作。RAID10算是比较流行的,虽然需要的磁盘比较多(磁盘利用率低),但是大家觉得在可靠性和性能都能达到较好的效果(也不一定,工业上不都是认为3-5份的数据备份才是比较安全的嘛)。

后台开发那些常用技术再次小结(二):Web服务层

  Web服务部分应当算是整个服务端开发中最重要、最复杂、同时也最具可玩性的部分了。业务逻辑的处理主要分布在Web服务层,这样一方面可以让其上层展示层不必关心业务逻辑,只专心负责展示和用户输入部分(也让其具有强大的伸缩性),而Web服务层本身也可以通过功能分割(增加副本、功能分割和数据分片是实现伸缩性的三大利器),以及单个服务自身的伸缩设计,最终构建一个功能强大的Web服务层。
  Web服务层采用一定的设计模式为上层提供调用接口,同时这些年来,跟随者移动互联网和与计算的大潮,各大厂商也喜欢将自己的服务通过接口的方式免费或者收费的形式提供给第三方使用,这也就是所谓的Web服务和前端应用平行部署的现象,在这种环境下的服务接口设计就显得会比以往更加的重要,当时那种裸socket之上自定义数据帧的时代显然是跟不上了。尤其这些年来,关于RESTful接口设计风格可谓是如日中天,无论是Google、Amazon这些互联网大佬,还是几个人组成的互联网创业公司,都号称自己开放的服务是符合RESTful风格的接口,但是正如我在V2ex论坛上看到大家所争论(《 RESTful 有用吗? HTTP 有 GET POST 就足够了?》)的一样:绝对纯正的RESTful风格接口的设计和实现在当下是不可能实现的,大家开放出来的接口要么就是根据实践情况有所妥协,要么就是封装了一个简易外壳的“伪RESTful接口”而已。
  这里看到一本《服务设计模式》,虽然后面的内容看的不是很明白,但是前面对于服务设计的总结还是不错的,在此进行归纳总结!归咎来说,Web服务主要是为集成不同的系统提供相应地方法,并通过HTTP来输出可重用业务功能,他们或者将HTTP作为一种简单的信息传输工具来承载数据传输(比如SOAP/WSDL服务),或者将HTTP作为一种完整的应用控制协议,将HTTP协议的内容定义服务的各种行为和语义(RESTful服务),前者被定义为以功能为中心的服务,后者被定义为以资源为中心的服务。
  以功能为中心的服务:该种风格的服务是指能够调用远程机器上的功能或者对象方法,而无需知道这些功能或者对象是如果实现的,因此这种框架技术需要处理跨编程语言、跨CPU构架、跨运行时环境的问题,同时对调用参数的约定、变量转换、错误处理还必须进行明确的规范。以功能为中心的服务现在基本是SOAP一枝独秀,其基本使用XML作为服务描述和消息编码方式,通过HTTP在客户端和服务端之间传递请求和响应。

后台开发那些常用技术再次小结(一):前端部分

  回家的路途上看了一下《互联网创业核心技术:构建可伸缩的web应用》这本书,该书是使用开发者头条积分兑换的第二本书,而且出版的时间还比较新。看了之后感觉还是比较有收的,至少感觉有了这个视野之后,再观网上那些所谓的高并发、高性能、高扩展性的网站架构,会有一种豁然开朗的感觉。其实怎么说呢,现在强调的高性能、可扩展系统的各套花样本质上也就那么几种模式,大家都是在实际项目中根据自身的业务规模、业务特点做相应的选型、裁剪、适配、调优而已。
  想想其实也不难理解,毕竟我们已经进入后互联网时代这么久了,大规模互联网系统开发中的各种问题、各种坑点想必大家都遇到过了,解决方案也十分成熟可靠,甚至各大云平台都把你所考虑的东西都帮你做完了,你只需要专注自己的业务开发和运维就可以了!或许真如之前别人所对我所说:这些互联网时代听起来高大上的技术,如果不是作为专家深入研究,而是仅仅当做一个现成的组件使用,那么你所“了解”的这些技术,充其量就是跟别人之间多出来的那几分谈资而已,任何一个程序员在对应的环境下都可以快速掌握的。说说也是,毕竟上面说的那本书俺一天不到的时间就看完了,这么看来,感觉操作系统、数据结构和算法、计算机网络、软件调试和优化等看似不起眼的东西,此时便显得更为地重要!
  不过话又说回来,上面的意思并不是说这类知识不重要,即使你不去做他,但是对他的全局观的理解和把控也会影响到自身的业务设计和实现。于是后面将根据书中内容的主线,总体描述现在互联网系统的开发过程中,为了达到构建高性能、可扩展的架构,从前端层、Web应用层、Web服务层、数据存储层部分,配合缓存、异步这些组件进行设计和实现的相关事项,同时配合其他文献分类别进行整理归纳和扩充,算是做一个自我普及的作用吧。
struct

2017年春节返途中的两三思考

  2017年是中国传统农历上的鸡年,而对我来说也是注定不平凡的一年:全家终于搬迁进了久等三年的安置新房,算是终于住上一个看起来像样一点的房子了;这是我结婚后的第一个年头,名义上正式步入人生中新的阶段;这年是我老爸的本命年,我爸六十了,而我也已经三十而立了!
  这是在和老婆走完娘家从汉中回深圳途中立下的提纲,这是一个没有空客320/波音737,也没有时速三百公里和谐号的旅途,我们搭乘的,是从所有南下陕西人记忆中磨灭不掉的K768。我是无座票在这人山人海中度过了漫长的28个小时(当然还是要感谢黄牛帮老婆抢了张卧铺),那种人山人海、水泄不通、吵杂闷浊的环境实在是种炼狱的感觉,而唯一带来的好处就是,没有在安然舒适的环境中看电影、耍手机来消磨时光,而是给了我多些回忆、思考的机会和生活的种种感触(悲剧是吸了好多二手烟,这点确实比较惨)!
2017-ticket

父母和亲人老了
  年底在老家办了一场简单的婚礼,算是所有的亲戚都到场了,本身我爸妈都是排行最小的,所以到场的长辈都是老头、老太级别的状态了,最长的姑妈已经84岁高龄了。虽是一眼望去满是凋零,但是堂、表兄弟姐妹的小孩很多,活蹦乱跳的小精灵为整个场地增加了不少生命的气息。在所有我这一辈的亲戚中,我是最后完婚的,不过作为我这代人婚事的收官之作,虽然简陋但也凭空流露出那么一些自豪感。
  让我感到欣慰的是,全家早年虽然多灾多难、命运多舛,而且爸妈也都接近60岁高龄,但是总体来说二老的身体和精神面貌还挺不错的。自从03年上大学直到现在工作,一直未有机会在家尽孝,这点是一直让我心中愧疚不已的,自己是家中的独子,必须承担起这份义不容辞的责任。结婚本是件幸福无比的事情,但是婚后直接面临的就是孩子、房子等各种问题,身边跟我类似情况的朋友还有很多,有时候想想我们这代人活得真是无比的辛苦。

GNU GDB调试手册

  人家都说Windows平台下的程序员是幸福的,因为Visual Studio实在是太好用了。
  我想一听到上面这句话,绝大多数Linux平台C/C++程序员都将会沉默,至少网上搜Linux平台下C/C++开发调试,很大一部分文章都是介绍搭建IDE的,这也侧面说明了Linux平台下没有一个占绝对主流地位好用的IDE。自己平时写程序是用的SlickEdit,这个IDE很贵,支持代码补全和跳转,调试过程也支持断点、Watch等特性,但是使用过程中还是有这样那样的小问题(比如非英文字串显式、速度比较慢),但是总体比较而言还是比较优秀的跨平台C/C++ IDE。虽然线下编码调试使用这货当然可以,然则线上环境就无能为力了,再加上自己之前对gdb也只是了解个表明,这次就顺着gdb的文档深挖一下!
  真是一看吓一跳,gdb的命令行调试要远比IDE的功能高级的多,如果只是通常的设置断点,监测变量什么的可能IDE比较方便,但是一旦上升到高级点的调试技巧,反而gdb在命令行的模式下更为的方便和高效。
  前方预警:这将会是一篇很长很长的文档摘读

一、开始使用gdb

1.1 启动gdb

1
2
3
4
➜ ~ gdb program [core|pid]
➜ ~ gdb --args g++ -O2 -o main main.cpp
(gdb) shell echo $SHELL
(gdb) set logging on

  gdb接需要调试的程序可执行文件,后面可以附加core文件或者pid进程号(调试正在运行的进程),如果有第三个参数gdb总是先尝试解释他为core文件,然后才是进程号。第二种格式采用–args,待调试的程序执行的时候需要额外的参数,此时可执行程序后面的参数不再被gdb解释。
  组合键Ctrl-D或者输入quit可以退出调试状态,如果之前attach到一个进程上面去了,可以用detach命令释放进程,如果quit有表达式那么表达式就作为gdb的退出状态,否则是被调试的子进程的退出状态。gdb中使用Ctrl-C不会终止gdb,而是会终止gdb正在运行的调试指令返回到gdb命令状态。
  在gdb中可以使用shell或者!做前导来执行shell中的命令而不用退出gdb(gdb的退出和重启动的代价是很大的),make命令可以用来重新编译程序而不用先导shell|!符号,而gdb自动重新加载符号。
  通过set logging on可以打开日志功能,默认会将日志输出追加到当前目录的gdb.txt文件中。

1.2 gdb中的命令

  gdb是很智能的,所有的命令都可以使用TAB、TAB-TAB进行补齐或者提示,不输入任何命令的空换行(在可能的情况下)表示重新执行前一条指令,这节省了重复输入step|list等指令的劳动。gdb允许指令和参数的缩减输入,没有歧义的时候会运行,而在遇到歧义的时候起会提示出各个歧义的命令列表供参考。
  有些命令参数中可能含有特殊的符号(比如括号),尤其在C++允许函数重载的时候需要使用参数类型来进行区分,此时参数需要使用 ‘ 单引号来包围,而且在需要的时候gdb也会自动帮你包围并给出候选列表的。

1.3 gdb帮助

  gdb本身附带了很多帮助命令,比如:
  help command:显示名的帮助信息
  apropos args:会在命令名、文档中搜索指定的表达式
  info args|registers|breakpoints|…:可以显示很多状态信息,具体可以查看help info
  set var val:设置环境变量
  show var:显示环境变量的值

1.4 调试执行程序

  对于待调试程序编译时候,总应该使用-g选项生成调试信息。

HTTPS原理简单介绍

  HTTPS在今后的互联网中必将扮演者越来越重要的角色了,国外互联网大佬对https部署也是竭力鼓吹呐喊,HTTP/2协议的推广更是逼着你不上也得上!在HTTPS普及化过程中,必然会损害某些集团的利益,但是这是互联网的趋势,历史的洪流是谁也阻挡不了的!
  这篇文章就是对HTTPS的大概做一个了解,力图宏观上掌握其基本原理和流程,而其中涉及到的具体加密算法的细节之流就留给那些博士title的人研究去吧!
  还是一样,要用Wireshark抓取和分析SSL/TLS的数据包,需要设置电脑的SSLKEYLOGFILE环境变量才可以。在Windows上面搞了好久,发现抓到的数据包还是不能解密,最后在Ubuntu下一次就完成了,看来搞开发的话还要Linux算是神器啊!抓取的数据包和Master-Secret也打包共享给大家了。此外为了简单起见,客户端请求禁用了Diffie Hellman支持,这个算法是为了提高安全性考虑的,好处就是密钥可以独立于服务器的私钥,所以历史数据即使在私钥被窃取的情况下,会话的内容也无法被破解。
https
  上面展现的客户端和服务器整个通信过程尽收眼底:首先三次握手建立TCP连接,然后客户端发起HTTP请求并得到302跳转,客户端进行ACK确认后,转而向443端口进行TCP三次握手连接,接下来就是TLS协商,加密信道建立后采用加密方式进行数据的传输。流程中夹杂着TLS和TCP的数据包,这一点也不奇怪,因为ACK是TCP协议的特性哦!

RPC设计和使用中的一些杂谈

  RPC当前在大公司的开发中越来越流行了,各大厂的开源RPC框架也呈百花开放的状态。在通过前面的文章做了一个对Google出品之gRPC的使用手册,也算是在使用方面有了一个基本的了解。恰巧最近逛别人博客的时候,看到几篇关于RPC原理和设计方面的文章,觉得十分不错,于是这里就将这些文章进行整理,对RPC设计、使用和实现中的那些乱七八糟的问题进行一个归纳总结。

一、RPC的原理和关键点

1.1 RPC的原理

rpc
  RPC的原理可以说是再简单不过了,一张图足以说明问题,总体来说会经历以下的步骤:
  (1). client代码像普通函数调用一样调用client stub函数,这个调用是本地调用,调用参数会和平常函数调用一样进行返回地址和调用参数压栈操作;
  (2). client stub会把调用参数和其它信息(比如调用方法名、调用属性等,可以称为metadata)进行打包封装成message,然后通过系统调用发送该message,这个打包的过程是个序列化的过程;
  (3). client寻求到服务端的地址,然后通过本地操作系统经由某种协议,将上述message发送给server端;
  (4). server端的操作系统接收message后将其传递给server stub;