FPs

2016年总结

离开北京前,和妹子一起去了次故宫,妹子拍的天安门

tiaanmen

2015年3月初来到北京,2017年1月底离开,在第一家公司,从实习到入职转正,再到离职。
16年,五一有九天假,去了长沙岳麓书院,回了学校,再去了佛山。最重大的变化都发生在下半年,六一时和妹子在一起,八月份一起出游去了泰国。
Continue ->


Salt Minion ID 變爲FQDN 記錄的問題

最近在一臺外網機器上起了salt minion ,但是同事發現/etc/salt/minion_id 不對,之前自動生成的minion_id 都是機器的/etc/hostname,這回變成了一個奇怪的域名:cncXXXX.XXX.ln.cn,並且這個域名和使用 hostname --all-fqdns 返回的結果相同。先查下minion_id 是怎麼生成的。

Github:saltstack/salt/doc/topics/tutorials/walkthrough.rst:

When the minion is started, it will generate an id value, unless it has been generated on a previous run and cached (in /etc/salt/minion_id by default). This is the name by which the minion will attempt to authenticate to the master. The following steps are attempted, in order to try to find a value that is not localhost:

  1. The Python function socket.getfqdn() is run
  2. /etc/hostname is checked (non-Windows only)
  3. /etc/hosts (%WINDIR%\system32\drivers\etc\hosts on Windows hosts) is checked for hostnames that map to anything within 127.0.0.0/8.

If none of the above are able to produce an id which is not localhost, then a sorted list of IP addresses on the minion (excluding any within 127.0.0.0/8) is inspected. The first publicly-routable IP address is used, if there is one. Otherwise, the first privately-routable IP address is used.

If all else fails, then localhost is used as a fallback.

應該是第一點,通過socket.getfqdn 拿到的結果,也驗證了和上文提到的hostname --all-fqdns 拿到的結果一樣。

FQDN是什麼?

Continue ->

HAProxy 最佳實踐筆記

haproxy_best_practice

這篇筆記內容主要來自Haproxy官方團隊分享的一個幻燈片:《Haproxy best practice》,介紹了一些常規的配置方式和優化手段。

不要盲目使用文中出現的所有技巧。

Haproxy 是如何工作的

關於Haproxy 團隊介紹,以及一些特性介紹直接看前面幾張幻燈片即可。 Haproxy 的主要用作代理請求,工作流程如下:
haproxy_proxy_mode

client 和Haproxy 建立連接,Haproxy 再和對應的後端server 建立連接,然後作爲中間人,轉發請求。 在Haproxy 配置中,對一個代理,會劃分爲2層,frontend(前端) 和backend(後端),這和上文說的Haproxy 的工作流程也是對應的。
Continue ->


高流量負載下Nginx 調優

  • 原文地址: Martin Fjordvald
  • 已獲得原文作者翻譯許可,本文遵循原文許可協議
  • 原文發表時間:April 27,2011

我曾經討論過一些Nginx 最常見的問題,毫無疑問,其中一個問題就是關於如何優化nginx 獲得高性能。不必驚訝,因爲大多數nginx 新用戶都是從Apache 遷移過來,所以他們習慣於調整配置和使用巫術來盡可能讓服務器達到最佳性能。

恩,我得告訴你一些壞消息,你並不能真的顯著優化nginx。沒有什麼配置能讓你的負載降低一半,或讓PHP 運行速度快2 倍。謝天謝地,好消息是nginx 不需要任何調優,因爲直接使用它時就已經被優化過了。最大的優化發生在當你決定運行通過ape-get install ,yum install 或 make install 安裝的nginx。(請注意這些倉庫內容常常過期。Wiki 的安裝頁面上通常有最新的倉庫。)

也就是說,有很多選項會影響nginx 的行爲,但是這些選項的默認值並不全都爲高流量的情況優化過。另外我們也需要考慮nginx 運行的平臺,優化我們的操作系統,因爲它們某些地方也會有瓶頸。

總之,我們沒法優化單個連接的加載時間,但是可以確保nginx 處理高流量的情況時有優化過的理想的環境。當然,我所說的高流量是指每秒幾百個請求,絕大多數人不需要爲這種情況費心思,不過如果你有興趣或者準備處理這種情況,請繼續往下讀吧。

Continue ->

關閉HPKP 和HSTS的方法

大家對於HSTS 一般都比較熟悉了,對HPKP 可能比較陌生,簡單來說由於CA 的工作模式,導致別人有可能通過其他CA 簽發你網站的證書,這個時候你就需要有一條頭信息聲明你網站的證書的指紋是什麼。
關於HSTS 和HPKP 的介紹可以查看Jerry Qu 的這2篇文章:

HSTS 和HPKP 都是通過頭信息傳遞給瀏覽器,瀏覽器都會根據max-age 緩存起來,所以在添加了HSTS 和HPKP 了之後,想要回滾,就沒有在服務端回滾程序那麼方便了。

有以下幾種情況會遇到要關閉/移除:

HSTS: 運維同學在剛剛做HTTPS 的時候,開啓了HSTS,甚至加了includeSubDomains,某些老客戶端訪問HTTP的接口的時候跳到HTTS,由於SNI、加密套件兼容性等問題出現故障;

HPKP: 無論是用根證書、中間證書還是站點證書簽發了指紋,虽然HPKP有备份方案,即发送多个pin-sha,但是还是需要准备证书出现故障,要关闭HPKP。另外要记得添加report-uri,这样出错时,服务端能主动的发现上报的信息。

個人覺得HPKP 和HSTS 在設計上實在太像了,如下例子:

HSTS:

Strict-Transport-Security: max-age=31536000; includeSubDomains

HPKP:

Public-Key-Pins:
      pin-sha256="d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM=";
      pin-sha256="E9CZ9INDbd+2eRQozYqqbQ2yXLVKB9+xcprMF+44U1g=";
      pin-sha256="LPJNul+wow4m6DsqxbninhsWHlwfp0JecwQzYpOLmCQ=";
      max-age=10000; includeSubDomains

所以在關閉,或者說移除HSTS或HPKP的方式上也是一樣的。

即max-age 字段指定为0

看下RFC:

HTST(RFC6797):

The max-age value is essentially a "time to live" value relative
to the reception time of the STS header field.

If the max-age header field value token has a value of zero, the
UA MUST remove its cached HSTS Policy information (including the
includeSubDomains directive, if asserted) if the HSTS Host is
known, or the UA MUST NOT note this HSTS Host if it is not yet
known.

HPKP(RFC7469):

The max-age value is essentially a "time to live" value relative to
the time of the most recent observation of the PKP header field.  If
the max-age header field value token has a value of 0, the UA MUST
remove its cached Pinning Policy information (including the
includeSubDomains directive, if asserted) if the Pinned Host is
Known, or, MUST NOT note this Pinned Host if it is not yet Known.

果然很像。。。居然照抄。
另外includeSubdomains 两者的定义也是一样的。


一個改良的Ping

Ping 是一個非常常用的命令,有2種情況會使用它:
一是會從瀏覽器的地址欄或者其他人發給我的網址,複製,然後進行ping,帶着協議以及一堆uri和args,
例如: https://accounts.google.com/AddSession?hl=en...
二從Linux 系統的網絡地址複製過來IP,進行Ping,帶着掩碼位數,
例如:192.168.1.1/32

以上2種情況,如果直接複製內容到終端,然後ping,會提示:

ping: cannot resolve ....: Unknown host

很惱人,寫一個簡單的腳本:

#!/usr/bin/env bash
#author: fangpeishi@gmail.com
#issues:
#  - http(s)://xxx.xx/xxx/xx?xxx
#  - 192.168.1.1/32

new_args=`echo $@ |sed  's/http.*\:\/\///' |sed 's/\/[^ ]*//'`
#echo ${new_args}
ping ${new_args}

把這個腳本命名爲pin, 放到 /bin 之類的目錄下面即可(本來想做成alias,沒成功),最終效果如下:
pin


寫一個Pelican 插件:Read More Link

another_read_more_link_demo

之前用Octopress 搭建博客的時候,用過一個很酷的功能,在文章中插入<!-- more -->之後,首頁的文章列表只會顯示這個標記之前的內容,然後添加一個類似繼續閱讀的鏈接。後來有一段時間切到Wordpress,也有類似的功能,但是在Pelican 上沒見到。

Continue ->

《Web 性能權威指南》讀書筆記

bookcover

《Web 性能權威指南》的起因是在看《HTTPS 權威指南》的時候,看到優化相關的,然後就延伸到想看一下這本書。
這本書,作者提供了免費的在線英文版,建議還是看英文的,中文翻譯版有些地方略生硬。

TCP 優化

這部分從協議出發,講解了優化的要點。

三次握手帶來的延遲使得創建每創建一個新的TCP連接都要付出很大的代價。而這也決定了提高TCP應用性能的關鍵,在於想辦法重用連接。

可以看到重用連接在後續的HTTP 優化都是重點。
第二章分內容和《HTTPS 權威指南》的9.1 有重合,可以都看下。

把服務器內核升級到最新版本(Linux: 3.2+)

新內核能獲得更好的性能,例如採用了PRR,比例降速算法。

Continue ->

Nginx 加載配置的順序分析

問題背景

在部署HTTPS 的時候,2台Nginx 下都部署了多個域名的證書,即NginxA 部署了證書a.com 和b.com 的證書,NginxB 也部署了證書a.com 和b.com ,域名a.com 指向NginxA,域名b.com 指向NginxB。
在用SSL LABS 檢測的時候,發現b.com 會出現“This site works only in browsers with SNI support.”,而a.com 不會。
SNI

SNI 介紹

關於SNI 的簡單介紹:

在 Nginx 中可以通过指定不同的 server_name 来配置多个站点。HTTP/1.1 协议请求头中的 Host 字段可以标识出当前请求属于哪个站点。但是对于 HTTPS 网站来说,要想发送 HTTP 数据,必须等待 SSL 握手完成,而在握手阶段服务端就必须提供网站证书。对于在同一个 IP 部署不同 HTTPS 站点,并且还使用了不同证书的情况下,服务端怎么知道该发送哪个证书?
Server Name Indication,简称为 SNI,是 TLS 的一个扩展,为解决这个问题应运而生。有了 SNI,服务端可以通过 Client Hello 中的 SNI 扩展拿到用户要访问网站的 Server Name,进而发送与之匹配的证书,顺利完成 SSL 握手。

引用來源:关于启用 HTTPS 的一些经验分享(二)

使用OpenSSL 測試NginxA,NginxB,不指定Host 頭,NginxA 返回的是a.com 的證書,NginxB 返回的也是a.com 的證書。

openssl s_client -connect nginx_ip:443 -showcerts < /dev/null 

Nginx 源碼分析

基本確定是配置加載的順序問題。在NginxA 和NginxB 中先加載的都是a.com。 在nginx.conf 中,我用 include 指令 引入了 某目錄下的所有conf 結尾的配置:

include /home/xxxxx/*.conf;

懷疑Nginx include 是按照字典順序,即a-z 的順序。看下源代碼,參考的Nginx 代碼版本是1.11.0。
先找到include 指定相關的函數:
Continue ->