一些更新说明:


2016-12-01:

  1. 更新了使用nginx_upstream_check_module时, 当backend web server为IIS时, 原有的配置会导致upstream check module无法判断后端server是否alive的问题.
  2. nginx configure添加了http_stub_status_module, 用于监控基本的访问量信息.
  3. 添加了重新编译nginx之后, 替换原有部署的可执行文件的具体操作步骤.

环境介绍:


  • OS: 阿里云/CentOS 7/3.10.0-123.9.3.el7.x86_64.
  • 硬件配置: 2台ECS(web01, web02), 4 core, 16GB memeory, 100GB disk size.
  • 原有程序的部署介绍(基于node.js)
    • port 9000: 部署了PC网站, 域名为: *.example.com, www.example.com
    • port 9001: 部署了m站点, 域名为: m.example.com
    • port 9002: 部署了app web api, 域名为: api.example.com

总体思路:


  1. nginx部署在2台ECS server(web01, web02)的443端口.
  2. 利用nginx的反向代理, 将请求按照domain name将请求分别转发至对应的node.js application port.
  3. nginx upstream配置健康检查, 监测web01和web02上的node.js application是否alive.

编译安装nginx:


重要说明:

nginx以及所有的第三方包的源代码都统一放到/usr/local/src目录.目录结构如下:

1
2
3
4
5
6
7
8
9
└── src
├── ct-submit-1.0.0
├── libbrotli
├── nginx-1.11.5
├── nginx-ct-1.3.1
├── nginx_upstream_check_module
├── ngx_brotli
├── openssl
└── sslconfig

如果你之前已经安装过nginx的基础上, 需要更新patch或者添加第三方module, 请在make完成了之后不要执行make install. 正确的处理方式为:

  • 先将原有的nginx二进制文件备份, 并备份其所有的conf文件. 完成了备份之后, 在将make生成的二进制文件手动copy到/usr/local/nginx/sbin/目录下:
1
sudo cp /usr/local/src/nginx-1.11.5/objs/nginx /usr/local/nginx/sbin/
  • copy完成了之后, 可能需要调整conf的相关配置, 请记得一定要使用nginx -t测试配置文件的正确性
1
sudo /usr/local/nginx/sbin/nginx -t
  • 测试成功了之后, 请执行:
1
sudo /usr/local/nginx/sbin/nginx -s reload
阅读全文 »

上一篇文章当中, 我们介绍了SSL证书的类型, 如何选择和购买等. 本篇文章我们开始进入实践环节, 讨论如何部署SSL证书.

我们应用程序的整体架构:


arch

上述架构只列出了和讨论https相关的部分.

SSL证书放在哪里进行管理?


对于静态资源请求, 由于存储在阿里云OSS上, 并在最前端使用了阿里云CDN, 因此将SSL证书的相关信息在阿里云CDN上配置一下就好了.

对于动态资源的请求, 最前端是使用SLB, 理论上来说, 处理方式可以和上述CDN的方式保持一致, 即将SSL证书放在SLB上进行管理, 但是这样做有以下的缺点:

  • 我们需要支持将http请求强制跳转至https, 毕竟用户在浏览器当中输入地址时, 几乎没有用户会主动在浏览器地址栏当中输入: https://. 目前阿里云的SLB并不支持redirect强制跳转的功能,因此我们需要在SLB背后在架设一个nginx, 通过配置server listen 80来做强制跳转.
1
2
3
4
5
server {
listen 80;
server_name .example.com;
return 301 https://$host$request_uri;
}

同时, nginx还可以很方便做很多扩展功能, 例如http/2的支持, TCP优化等.

基于上述原因, 我们决定在SLB背后的web server上部署nginx, 并将SSL证书放在nginx上进行管理.

调整之后的架构如下:
arch2

Q: 上述架构中nginx是否会有单点失败的问题?
A: 不会, 基于成本的考虑, 我们并没有在使用单独的ECS Server部署nginx, 而是将nginx直接部署到了原来的那2台web server上, SLB上的健康检查也调整为check对应的nginx端口是否alive. 具体的设置方式会在下文当中进行介绍.

阅读全文 »

一些重要的互联网资源参考:


强烈建议通读一下Jerry Qu的关于https, http/2, nginx的blog, 这是我目前发现的在国内的技术文章中, 关于上述的几个知识点讲解的最为全面透彻的文章.

传送门: https://imququ.com/

为什么我们需要实现全站https?


目前主流大厂的网站和服务都已经实现了全站https, 例如: baidu, taobao, jd等.
关于这方面的好处和优势, 互联网上太多文章在进行介绍. 例如: 为什么我们应该尽快升级到 HTTPS?
对于一般的创业型公司, 迫切需要实现全站https的理由:

  1. 苹果要求所有iOS应用在年底前默认使用HTTPS连接
  2. 微信小程序的开发, 要求必须使用https通信
  3. HTTP/2的支持

HTTP2.0其实可以支持非HTTPS的,但是现在主流的浏览器chrome,firefox表示还是只支持基于TLS部署的HTTP2.0协议,所以要想升级成HTTP2.0还是先升级HTTPS为好.

升级之前的准备工作.


SSL的证书类型?

  • DV (Domain Validation): 面向个体用户,安全体系相对较弱,验证方式就是向 whois 信息中的邮箱发送邮件,按照邮件内容进行验证即可通过.
  • OV (Organization Validation): 面向企业用户,证书在DV证书验证的基础上,还需要公司的授权,CA通过拨打信息库中公司的电话来确认.
  • EV (Extended Validation): 在浏览器URL地址栏当中,展示了注册公司的信息,这会让用户产生更大的信任,这类证书的申请除了以上两个确认外,还需要公司提供金融机构的开户许可证,要求十分严格.

需要强调的是,不论是 DV、OV 还是 EV 证书,其加密效果都是一样的!

重要的区别:

  1. DV证书的审核速度较快, 由程序完成审核, 一般申请了之后马上就能够完成证书颁发; OV和EV证书审核较慢, 由人工审核, 一般需要数天的时间.
  2. EV证书会在浏览器当中显示公司的信息, 通常被称为绿色地址栏, 以增加用户的信任感. 参考如下访问github时, chrome浏览器的显示方式:
    EV证书示例
  3. EV证书不支持单个泛域名(.example.com)或者多个泛域名(.example1.com, *.example2.com), OV和DV证书则支持.

如何选择?
通常的情况下, 一个处于初创阶段的互联网公司有多少个子系统是很难在前期就界定出来的. 因此, 如果能够无法明确规划出未来有多少个子系统, 需要使用多少个二级域名, 最好购买支持单个或者多个泛域名的证书. 至于是DV还是OV, 我个人觉得不是那么重要.

一些经验总结:
HTTPS网页中加载的HTTP资源被称之为Mixed Content, 不同的浏览器有不同的block http资源的策略, 因此最好提前整理出你的程序依赖的内部http资源, 和外部http资源(统计资源[GA, CNZZ, 百度统计], 第三方分享, 第三方地图服务等). 尤其是外部的http资源, 需要评估是否提供了https的服务.

阅读全文 »

命令行常用快捷键:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
空格键: 预览
cmd + ,: 设置
cmd + -/=: 缩小/放大
ctrl + u: 删除到行首(与zsh冲突, zsh中是删除整行)
ctrl + k: 删除到行尾
ctrl + p/n: 上/下移动一行或者前/后一个命令
ctrl + b/f: 光标前/后移char
esc + b/f: 光标前/后移word(蛋疼不能连续work)
ctrl + a/e: 到行首/行尾
ctrl + h/d: 删前/后字符
ctrl + y: 粘贴
ctrl + w: 删除前一个单词
esc + d: 删后一个单词
ctrl + _: undo
ctrl + r: bck-i-search/reverse-i-search, 输入关键字搜索历史命令

学习网站:


Learn X in Y minutes: 快速学习各种相关知识的网站. 强调在几分钟之内对该技术能够有大概的了解和认识.
实验楼: 提供学习该项技术的实验环境(虚拟机环境), 部分课程需要收费, 会员也需要收费.
慕课网: 课程很丰富, 最大的靓点是全免费.
菜鸟网: 文档教学类网站, 优点是涉及的技术知识非常全面, 很适合入门学习.

优秀的个人技术Blog:


后端技术杂谈: 后端技术Java, 架构.
iMysql: Mysql层面有一些比较深入的文章.
火丁笔记: 有一些非常有技术含量的后端技术文章.

Linux:


bash man: 简洁的Linux bash shell帮助文档, 以命令或者分类的方式搜索, 并提供较为详细的示例.

the geek stuff: linux学习的网站, 示例非常简洁, 清晰. 比较好的文章包括:

view large file: 查看大文件.

du & df: 查看磁盘空间.

centos rpm 安装相关: 尤其是如下这条, 在服务器上通过yum install安装, 但是镜像源下载rpm包超级慢的情况, 可以找一台网络比较好的PC, 用迅雷等下载软件加速下载, 再copy到服务器上之后进行安装, 此时,可能会使用到:

1
2
# 用 yum 去安装本地组件,并自动地检查/满足依赖性
yum --nogpgcheck localinstall packagename.arch.rpm

Linux各个版本的源代码在线阅读

阅读全文 »

关于本系列文章


开篇里的说明

网络测试环境搭建和说明


参考这里

TCP协议的特点


面向连接:
使用TCP协议通信的双方必须先建立连接, 然后才能开始数据的读写.双方都必须为该连接分配必要的内核资源, 以管理连接的状态和连接上数据的传输.TCP连接是全双工的, 即双方的数据读写可以通过一个连接进行.完成数据交换之后, 通信双方都必须断开连接以释放系统资源.

正因为其面向链接, 并且连接是1对1的, 因此TCP协议不适用于广播和多播(其特点是, 目的地对应多个IP地址)的应用. 而无链接协议UDP则非常适合于多播和广播.

基于字节流:
基于字节流的服务(TCP)与基于数据报的服务(UDP)的区别是, 从实际编码的角度上来对比, 体现为通信双方是否必须执行相同次数的读、写操作(当然, 这只是表现形式).

当发送端应用程序连续执行多次写操作时, TCP模块先将这些数据放入TCP发送缓冲区中.当TCP模块真正开始发送数据时, 发送缓冲区中这些等待发送的数据可能被封装成一个或多个TCP报文段发出.因此, TCP模块发送出的TCP报文段的个数和应用程序执行的写操作次数之间没有固定的数量关系.

当接收端收到一个或多个TCP报文段后, TCP模块将它们携带的应用程序数据按照TCP报文段的序号(见后文)依次放入TCP接收缓冲区中, 并通知应用程序读取数据.接收端应用程序可以一次性将TCP接收缓冲区中的数据全部读出, 也可以分多次读取, 这取决于用户指定的应用程序读缓冲区的大小.因此, 应用程序执行的读操作次数和TCP模块接收到的TCP报文段个数之间也没有固定的数量关系.

综上所述, 发送端执行的写操作次数和接收端执行的读操作次数之间没有任何数量关系, 这就是字节流的概念:应用程序对数据的发送和接收是没有边界限制的.UDP则不然.发送端应用程序每执行一次写操作, UDP模块就将其封装成一个UDP数据报并发送之.接收端必须及时针对每一个UDP数据报执行读操作(通过recvfrom系统调用), 否则就会丢包(这经常发生在较慢的服务器上).并且, 如果用户没有指定足够的应用程序缓冲区来读取UDP数据, 则UDP数据将被截断.

下面的2个图示说明了基于数据流的TCP协议与基于数据报的UDP协议的具体区别:
tcp-baseon-stream
udp-baseon-datagram

传输的可靠性:

  1. TCP协议采用发送应答机制, 即发送端发送的每个TCP报文段都必须得到接收方的应答, 才认为这个TCP报文段传输成功.
  2. TCP协议采用超时重传机制, 发送端在发送出一个TCP报文段之后启动定时器, 如果在定时时间内未收到应答, 它将重发该报文段.
  3. 因为TCP报文段最终是以IP数据报发送的, 而IP数据报到达接收端可能乱序、重复, 所以TCP协议还会对接收到的TCP报文段重排、整理, 再交付给应用层.

与TCP协议对比, UDP协议则和IP协议一样, 提供不可靠服务.它们都需要上层协议来处理数据确认和超时重传.

阅读全文 »

关于本系列文章


开篇里的说明

网络测试环境搭建和说明


参考这里

概述


定义/职责: IP协议是上层协议的基础(TCP, UDP), 它为上层协议提供无状态, 无连接, 不可靠的服务

无状态:
定义: 无状态(stateless)是指IP通信双方不同步传输数据的状态信息, 所有数据报的发送, 传输, 接收都是相互独立并且没有上下文关系的.
优点: 简单/高效, 不需要为了保持通信状态而使用额外的内核资源, 也不需要在数据报当中包含额外的状态信息, 从而减少了包的大小.
缺点: 无状态会导致数据报的乱序和重复发送. 例如第N个IP数据报会比N+1个IP数据报后到达接收端, 或者同一个IP数据报会多次到达同一个接收端.

  • 传输层的TCP协议是有状态/面向连接的协议, 它能够自己来处理乱序的, 重复的IP数据报, 以确保传输的内容是绝对有序和可靠的.
  • IP数据报头部提供了一个标识字段用以唯一标识一个IP数据报, 但它是被用来处理IP分片和重组的, 而不是用来指示接收顺序的.
    常见的无状态网络协议: UDP, Http.

无连接:
定义: 无连接(connectionless)是指IP通信双方都不长久地维持对方的任何信息. 基于IP协议的上层协议在每次发送数据时, 都必须明确地给出对方的IP地址.

不可靠:
定义: IP协议不能保证IP数据报准确地到达接收端, 它只是承诺尽最大努力(best effort).
导致IP数据报无法到达接收端的原因/场景:

  • 中转路由器发现IP数据报的TTL为0, 会直接丢弃掉, 并返回一个ICMP的错误消息(超时错误)给发送端.
  • 接收端发现IP数据报的内容不正确(通过CRC校验机制), 会直接丢弃掉, 并返回一个ICMP的错误消息(IP头部参数错误)给发送端.
    发送端的IP模块一旦检测到IP数据报发送失败, 就通知上层协议发送失败,而不会试图重传.因此,使用IP服务的上层协议(比如TCP协议)需要自己实现数据确认, 超时重传等机制以达到可靠传输的目的.
    阅读全文 »

关于本系列文章


开篇里的说明

网络测试环境搭建和说明


参考这里

概述


定义/职责: 将域名转换为IP地址.

浏览器中输入一个域名之后:

  1. 获取输入URL的域名地址, 例如:www.google.com.
  2. 向DNS服务器发送DNS查询请求, DNS服务器在网络连接的属性里面配置, 或者使用自动获取的.
  3. 接收DNS服务器返回的响应报文, 并解析获得IP地址.

DNS查询和应答报文详解


dns数据报格式

DNS header:

  • 16 bit标识字段: 用于标识一组DNS查询和应答, 以区分哪一个DNS应答是哪一个DNS查询的回应.
  • 16 bit标记字段: 用于协商具体的通信方式和反馈通信状态, 具体参考下图:
    dns标识字段

    • QR: 0表示查询, 1标识应答.
    • opcode: 定义查询和应答的类型, 0–标准查询, 1–反向查询(通过IP获得主机名), 2–请求服务器状态.
    • AA: 占1位, 授权应答(Authoritative Answer) – 这个比特位在应答的时候才有意义, 指出给出应答的服务器是查询域名的授权解析服务器.
    • TC: 截断标志, 仅当DNS报文使用UDP服务时使用. 因为UDP数据报有长度限制, 所以过长的DNS报文将被截断. 1表示DNS报文超过512字节,并被截断.
    • RC: 递归查询标志. 1表示执行递归查询, 即如果目标DNS服务器无法解析某个主机名, 则它将向其他DNS服务器继续查询, 如此递归, 直到获得结果并把该结果返回给客户端. 0表示执行迭代查询, 即如果目标DNS服务器无法解析某个主机名, 则它将自己知道的其他DNS服务器的IP地址返回给客户端, 以供客户端参考.
    • RA: 允许递归标志. 仅由应答报文使用, 1表示DNS服务器支持递归查询.
    • zero: 未使用, 必须都社会为0.
    • rcode: 4位返回码, 表示应答的状态. 常用值有0–无错误, 3–域名不存在.
  • 16 bit查询问题个数–QDCOUNT: 指明报文请求段中的问题记录数.

  • 16 bit回答问题个数–ANCOUNT: 指明报文回答段中的回答记录数.
  • 16 bit授权问题个数–NSCOUNT: 指明报文授权段中的授权记录数.
  • 16 bit额外资源问题个数–ARCOUNT: 指明报文附加段中的附加记录数.

对于上述4个字段, 查询报文和回答报文的值分别如下:

请求类型 QDCOUNT ANCOUNT NSCOUNT ARCOUNT
查询报文 1 0 0 0
回答报文 0 1 1 or 0 1 or 0
阅读全文 »

关于本系列文章


开篇里的说明

网络测试环境搭建和说明


  • mac os x上使用parallels desktop搭建虚拟机.
  • mac os x, IP: 10.211.55.2
  • linux centos 7 VM, IP: 10.211.55.4
  • windows 7 VM, IP: 10.211.55.3

概述


定义/职责: ARP协议能实现任意网络层地址到任意物理地址的转换. 这里重点讨论的是: 将网络层的IP Datagram Header中的IP Address, 解析为物理链路层frame Header中的mac address.

原理: 主机向自己所在的网络广播一个ARP请求,该请求包含目标机器的网络地址。此网络上的其他机器都将收到这个请求,但只有被请求的目标机器会回应一个ARP应答,其中包含自己的物理地址.

报文详解


ARP报文格式

  • 硬件类型字段定义物理地址的类型,它的值为1表示MAC地址。
  • 协议类型字段表示要映射的协议地址类型,它的值为0x800,表示IP地址。
  • 硬件地址长度字段和协议地址长度字段,顾名思义,其单位是字节。对MAC地址来说,其长度为6;对IP(v4)地址来说,其长度为4。
  • 操作字段指出4种操作类型:ARP请求(值为1)、ARP应答(值为2)、RARP请求(值为3)和RARP应答(值为4)。
  • 最后4个字段指定通信双方的以太网地址和IP地址。发送端填充除目的端以太网地址外的其他3个字段,以构建ARP请求并发送之。接收端发现该请求的目的端IP地址是自己,就把自己的以太网地址填进去,然后交换两个目的端地址和两个发送端地址,以构建ARP应答并返回之(当然,如前所述,操作字段需要设置为2)。
    阅读全文 »

What and Why?


我们经常在ssh连接到VPS上之后, 由于某种原因长时间没有进行任何SSH操作之后, 你会发现当前的ssh终端hang在那里, 没有任何反应, 提示如下:

1
packet_write_wait: Connection to xx.xx.xx.xx: Broken pipe

我猜这个应该是由于ssh协议的某种保护机制, 当client长时间没有发送任何请求时, 强行断开连接, 以避免连接数过多的时候占用更多服务器端资源. 这个保护机制对于VPS来说(只有个人使用, 一般只会开几个ssh终端进行操作), 显然用户体验不是太好.

修改SSH Clinet配置


我们可以设置每间隔多少秒, 让ssh client发出NULL packet数据包给服务器端, 以保持连接会话.

1
2
3
4
5
sudo vi /etc/ssh/ssh_config #全局
or
sudo vi ~/.ssh/config #本用户

添加以下的内容:

Host *
ServerAliveInterval 100

如果只是临时使用, 不想修改配置文件, 可以使用以下方式:

1
ssh -o ServerAliveInterval=100 user@example.com

修改SSH Server配置


1
sudo vi /etc/ssh/sshd_config

添加以下的内容:

ClientAliveInterval 60
TCPKeepAlive yes
ClientAliveCountMax 100

ClientAliveInterval: 服务器端每间隔60秒发出NULL packet至客户端, 以保持连接会话.
TCPKeepAlive: 防止被防火墙drop掉idle连接.
ClientAliveCountMax: 允许最大的客户端连接数量.

设置好了之后, 需要restart sshd service.

1
sudo systemctl restart sshd

Ref


https://docs.oseems.com/general/application/ssh/disable-timeout
http://unix.stackexchange.com/questions/200239/how-can-i-keep-my-ssh-sessions-from-freezing

关于本系列文章


我在学习TCP/IP协议以及Linux服务器端编程时, 原本打算学习和参考三本经典书籍:

  1. TCP/IP详解 卷1:协议
    TCP/IP详解 卷1:协议
  2. UNIX环境高级编程(第3版)
    UNIX环境高级编程(第3版)
  3. UNIX网络编程 卷1:套接字联网API
    UNIX网络编程 卷1:套接字联网API

在经过阅读了之后, 发现这三本书不是那么容易入门, 书也太厚了, 不方便阅读. 偶然的机会, 我在多看上发现了一本还算不错的入门书籍:
Linux高性能服务器编程
Linux高性能服务器编程

这本书有以下几个特点:

  • 书比较薄, 并涵盖了我想了解和学习的知识点, 很适合入门.
  • 有很多需要实际动手的Demo, 能够帮助读者理解.
  • 有电子版, 随时都能阅读: 豆瓣电子版 多看电子版 PS: 多看电子版的代码排版有点问题, 希望多看能够早点修复.

这个系列的文章是我阅读Linux高性能服务器编程的读书笔记, 并对需要深入学习的部分加入了一些自己的理解和认识, 以及额外的参考资料. 如果你认为本系列对你的学习能够有所帮助, 希望能够购买原版图书.

RFC文档

What is RFC?

A Request for Comments (RFC) is a formal document from the Internet Engineering Task Force ( IETF ) that is the result of committee drafting and subsequent review by interested parties. Some RFCs are informational in nature.

当你对某个TCP/IP的问题搞不明白时, 最好去查看的RFC文档, 这才是最权威的解释.

TCP/IP协议族体系结构以及主要协议


四层:

  • 链路层
  • 网络层
  • 传输层
  • 应用层

NOTE: 链路层, 网络层, 传输层由于需要稳定而可靠的服务, 都在内核空间当中实现. 只有应用层是交给用户空间实现.
tcp/ip协议体系结构图

阅读全文 »