除了Java、Python和JavaScript之外,如果要開始學(xué)習(xí)一門新語言的話,我想應(yīng)該是Go!
目前創(chuàng)新互聯(lián)建站已為1000多家的企業(yè)提供了網(wǎng)站建設(shè)、域名、網(wǎng)絡(luò)空間、網(wǎng)站托管、服務(wù)器租用、企業(yè)網(wǎng)站設(shè)計(jì)、南澗網(wǎng)站維護(hù)等服務(wù),公司將堅(jiān)持客戶導(dǎo)向、應(yīng)用為本的策略,正道將秉承"和諧、參與、激情"的文化,與客戶和合作伙伴齊心協(xié)力一起成長(zhǎng),共同發(fā)展。
Go語言正在被越來越多的公司使用。我們公司的后端服務(wù)已經(jīng)全面采用Go語言實(shí)現(xiàn)了。
最開始接觸Go語言是去年將一份Go代碼“翻譯”成Python并集成到測(cè)試平臺(tái)上,說來也挺神奇,我從來沒學(xué)過Go卻完成了這個(gè)工作,這也側(cè)面反應(yīng)了Go的語法還是很平易近人的。
今年,在海翔飛調(diào)崗之后已經(jīng)沒有太多時(shí)間寫代碼了,但如果要開始學(xué)習(xí)一個(gè)新的語言或技術(shù)的話,我最想學(xué)的是Go!
目前來看,Go似乎還并沒有太多測(cè)試人員使用的場(chǎng)景,不過,我之前介紹過的BDD行為驅(qū)動(dòng)框架gauge是由Go開發(fā)的,當(dāng)然,它也支持使用Go來編寫B(tài)DD測(cè)試代碼。
對(duì)于,已經(jīng)有一定開發(fā)經(jīng)驗(yàn)的同學(xué),如何快速的開始學(xué)習(xí)Go語言呢?我這里給一些思路。
#### 第一步:下載和安裝
在配置環(huán)境的時(shí)候你需要重點(diǎn)了解GOROOT、GOPATH的作用。
你還要準(zhǔn)備一款稱手的編輯器,如果你像我一樣,一直都在使用VS Code的話,那么就它就可以了。
#### 第二步:從hello world開始
先運(yùn)行一個(gè)hello world程序,認(rèn)識(shí)Go語言的語法。
package main
import ( ? ?"fmt")
func main(){
fmt.Println("helloworld!")
}
#### 第三步:熟悉Go的語法
接下來,你可能要花一周左右的時(shí)間熟悉Go語言的語法。比如,變量定義、if/for、函數(shù)、Map、跨文件的程序調(diào)用…等,當(dāng)然,還有一些Go特有的知識(shí)。
當(dāng)然,我更喜歡看視頻教程,雖然質(zhì)量參差不齊,但我仍然覺得看視頻比我自己看書更有效率。
熟悉一段Go代碼:
package main
import"fmt"
func myFunc() {
i := 0
Here: ? //這行的第一個(gè)詞,以冒號(hào)結(jié)束作為標(biāo)簽
fmt.Println(i)
i++ ? ?if i 10{ ? ? ? ?goto Here ? //跳轉(zhuǎn)到Here去
}
}func main() { ? ?//調(diào)用函數(shù)
myFunc()
}
#### 第四步:Go如何做單元測(cè)試
針對(duì)Go做測(cè)試也非常簡(jiǎn)單。比如,這是一個(gè)被測(cè)試文件:add.go。
package test_demofunc Add(a int, b int) int{ ? ?return a + b
}
下面針對(duì)Add()函數(shù)編寫測(cè)試用例,test_add.go
package test_demo
import ( ? ?"testing")
func TestAdd1(t *testing.T){
r:= Add(1, 2) ? ?if r !=3{
t.Errorf("Add(1, 2)failed. Got %d, expected 3.", r)
}
}
func TestAdd2(t *testing.T){
r:= Add(2, 2) ? ?if r !=4{
t.Errorf("Add(2, 2)failed. Got %d, expected 4.", r)
}
}
你只需要執(zhí)行?go test?命令就可以運(yùn)行上面的測(cè)試了。
#### 第五步:從哪兒找第三方庫(kù)
當(dāng)然,你只學(xué)習(xí)go語言本身,基本是做不了什么事的,必須要使用第三方擴(kuò)展庫(kù)。
這里羅列了Go語言的第三方庫(kù),通過這些第三方庫(kù)的介紹,我們也可以大概知道Go可以用來干什么。
如果你知道庫(kù)的名字的話,也可以在這個(gè)網(wǎng)站上搜索。
據(jù)我了解,Go的第三方庫(kù)大多都在GitHub上面。
#### 第六步:用Go做Web開發(fā)
Go是靜態(tài)語言,而且支持并發(fā)編程,所以,他有天然的性能優(yōu)勢(shì),大多公司主要使用Go也是開發(fā)后端服務(wù)(即API)。
終于到了實(shí)戰(zhàn)階段,如果我們真的要掌握一門語言,那么一定要用它來開發(fā)一個(gè)項(xiàng)目出來。這個(gè)過程大概需要一個(gè)月。
Beego是Go下在主流的Web開發(fā)框架,資料相對(duì)比較豐富,而且有完善的文檔。你可為此制定一個(gè)目標(biāo),比如用它來開發(fā)一個(gè)Blog,為此,你需要詳細(xì)閱讀Beego文檔,以及學(xué)習(xí)相關(guān)的Web開發(fā)技術(shù)。
等你完成這個(gè)項(xiàng)目的時(shí)候,我想你已經(jīng)會(huì)使用Go語言了。
和大部分知名開源軟件誕生在歐美國(guó)家不同,OpenResty自身和依賴的主要組件都是金磚國(guó)家的開發(fā)者發(fā)明的,這點(diǎn)還挺有意思。
Nginx是俄羅斯人發(fā)明的,Lua是巴西幾個(gè)教授發(fā)明的,中國(guó)人章亦春把LuaJITVM嵌入到Nginx中,實(shí)現(xiàn)了OpenResty這個(gè)高性能服務(wù)端解決方案。
通過OpenResty,你可以把nginx的各種功能進(jìn)行自由拼接,更重要的是,開發(fā)門檻并不高,這一切都是用強(qiáng)大輕巧的Lua語言來操控。
它主要的使用場(chǎng)景主要是:
在Lua中揉和和處理各種不同的nginx上游輸出(Proxy,Postgres,Redis,Memcached等)
在請(qǐng)求真正到達(dá)上游服務(wù)之前,Lua可以隨心所欲的做復(fù)雜的訪問控制和安全檢測(cè)
隨心所欲的操控響應(yīng)頭里面的信息
從外部存儲(chǔ)服務(wù)(比如Redis,Memcached,MySQL,Postgres)中獲取后端信息,并用這些信息來實(shí)時(shí)選擇哪一個(gè)后端來完成業(yè)務(wù)訪問
在內(nèi)容handler中隨意編寫復(fù)雜的Web應(yīng)用,使用同步但依然非阻塞的方式,訪問后端數(shù)據(jù)庫(kù)和其他存儲(chǔ)
在rewrite階段,通過Lua完成非常復(fù)雜的URLdispatch
用Lua可以為nginx子請(qǐng)求和任意location,實(shí)現(xiàn)高級(jí)緩存機(jī)制
組織OpenResty技術(shù)大會(huì)之前,我一直認(rèn)為自己是一個(gè)孤獨(dú)的OpenResty使用者,覺得自己在使用一個(gè)冷門的技術(shù)。
雖然大家都聽說過OpenResty或者ngx_lua,但感覺用在生產(chǎn)環(huán)境中使用的卻少之又少,除了幾個(gè)CDN公司外,好像沒有聽說過哪家知名互聯(lián)網(wǎng)公司在使用。而CDN行業(yè)之所以使用,很多是受到cloudflare技術(shù)棧的影響,OpenResty的作者也在國(guó)外這家CDN公司。
但辦完這個(gè)大會(huì),我發(fā)現(xiàn)使用者真的挺多,奇虎360的所有服務(wù)端團(tuán)隊(duì)都在使用,京東、百度、魅族、知乎、優(yōu)酷、新浪這些互聯(lián)網(wǎng)公司都在使用。有用來寫WAF、有做CDN調(diào)度、有做廣告系統(tǒng)、消息推送系統(tǒng),還有像我們部門一樣,用作APIserver的。有些還用在非常關(guān)鍵的業(yè)務(wù)上,比如開濤在高可用架構(gòu)分享的京東商品詳情頁(yè),是我知道的ngx_lua最大規(guī)模的應(yīng)用。
2.奇虎企業(yè)安全服務(wù)端技術(shù)選型的標(biāo)準(zhǔn)
先說下3年多前做架構(gòu)選型的時(shí)候,我為什么會(huì)選擇OpenResty?
其實(shí)架構(gòu)如何設(shè)計(jì)并不重要,因?yàn)槊考夜?,每個(gè)團(tuán)隊(duì),他們的公司文化和技術(shù)背景各不相同,生搬硬套會(huì)適得其反。重要的是當(dāng)初為什么這么選擇,中途為什么調(diào)整。
我們的產(chǎn)品要求單機(jī)上面,服務(wù)端提供高性能的API接口,QPS至少過萬,未來需要支撐到10萬。我們并沒有急于去使用PHP、Python或者其他的語言來實(shí)現(xiàn)功能,而是先勾勒出一個(gè)理想化的技術(shù)模型。
這個(gè)模型應(yīng)該具備:
非阻塞的訪問網(wǎng)絡(luò)IO。在連接MySQL、Redis和發(fā)起HTTP請(qǐng)求時(shí),工作進(jìn)程不能傻傻的等待網(wǎng)絡(luò)IO的返回,而是需要支持事件驅(qū)動(dòng),用協(xié)程的方式讓CPU資源更有效的去處理其他請(qǐng)求。很多語言并不具備這樣的能力和周邊庫(kù)。
有完備的緩存機(jī)制。不僅需要支持Redis、Memcached等外部緩存,也應(yīng)該在自己的進(jìn)程內(nèi)有緩存系統(tǒng)。我們希望大部分的請(qǐng)求都能在一個(gè)進(jìn)程中得到數(shù)據(jù)并返回,這樣是最高效的方法,一旦有了網(wǎng)絡(luò)IO和進(jìn)程間的交互,性能就會(huì)受到很大影響。
同步的寫代碼邏輯,不要讓開發(fā)者感知到回調(diào)和異步。這個(gè)也很重要,程序員也是人,代碼應(yīng)該更符合人的思維習(xí)慣,顯式的回調(diào)和異步關(guān)鍵字,會(huì)打斷思路,也給調(diào)試帶來困難。
最好是站在巨人肩上,基于成熟的技術(shù)上搭建。采用一門全新誕生的語言和技術(shù),需要經(jīng)歷語言自身發(fā)展期頻繁調(diào)整的陣痛,還可能站錯(cuò)隊(duì)。
不僅支持Linux平臺(tái),還需要支持Windows平臺(tái),這個(gè)是我們產(chǎn)品很特別的需求,很多中小企業(yè)用戶還是習(xí)慣Windows的操作,不具備Linux的維護(hù)能力。
基于以上幾點(diǎn)的考慮,考察了當(dāng)時(shí)的一些方案,選擇了OpenResty。
首先,它最大的特點(diǎn)就是用同步的代碼邏輯實(shí)現(xiàn)非阻塞的調(diào)用,其次它有單進(jìn)程內(nèi)的LRUcache和進(jìn)程間的shareDICTcache,而且它是揉合nginx和LuaJIT而產(chǎn)生的。而且nginx有Windows版本,雖然有非常多的限制,但這些限制都是可以解決的,nginx官方Windows版本中不支持的特性,我們開源出來的版本都解決了。
第一次看到這樣的方案,我覺得它肯定會(huì)顛覆高性能服務(wù)端的開發(fā)。為什么呢?在我之前的公司里,每天會(huì)有近百億次的查詢請(qǐng)求,而服務(wù)器只用了十臺(tái)。
我們采用了nginxC模塊+內(nèi)置在nginx中的K-V數(shù)據(jù)庫(kù)(自己開發(fā)的),來實(shí)現(xiàn)所有的業(yè)務(wù)邏輯,達(dá)到這個(gè)目標(biāo)。聽上去很簡(jiǎn)單,但是過程非常艱辛,兩三個(gè)十幾年工作經(jīng)驗(yàn)的大牛做了一年多才穩(wěn)定下來。絕大部分開發(fā)能力不足,只能望塵莫及。而且后續(xù)的調(diào)試和維護(hù),也會(huì)花費(fèi)不少精力。
但是OpenResty的出現(xiàn)改變了這一切,OpenResty非常的pythonic,適合人類的正常思維。新手經(jīng)過一兩個(gè)月的學(xué)習(xí),做出來的API,就可以達(dá)到nginxC模塊的性能,而且代碼量大大減少,也方便調(diào)試。
3.以奇虎和新浪為例,如何在項(xiàng)目中引入新技術(shù)
技術(shù)選型只是第一步,如何才能在一個(gè)產(chǎn)品或者項(xiàng)目中引入OpenResty這個(gè)新的技術(shù)呢?我拿奇虎企業(yè)安全和新浪移動(dòng)這兩家公司真實(shí)發(fā)生的案例給大家看看。我和新浪移動(dòng)的周晶,都是在一個(gè)有成熟產(chǎn)品的部門,用一兩個(gè)人的力量,把一個(gè)新技術(shù),替換掉了原有的技術(shù)架構(gòu)。但由于企業(yè)產(chǎn)品和個(gè)人產(chǎn)品的不同,方法有很大的不一樣。
先說我所在奇虎企業(yè)安全。我在2012年初加入這個(gè)部門,當(dāng)時(shí)產(chǎn)品主打免費(fèi),目標(biāo)用戶是小企業(yè)。所以架構(gòu)設(shè)計(jì)上面,只考慮了幾十點(diǎn)、幾百點(diǎn)的終端請(qǐng)求,使用了非常強(qiáng)綁定的Windows平臺(tái)技術(shù),而且傾向于不用開源軟件,自己新做一個(gè)更適合自己的框架。包括自己用C++開發(fā)的Webserver,自己寫的PHP路由和框架,數(shù)據(jù)存儲(chǔ)在sqlite里面。
我?guī)兔π薷牧藘蓚€(gè)月PHP的bug,看明白了技術(shù)架構(gòu)的思路之后,就去新開的一個(gè)產(chǎn)品線了。這是一個(gè)實(shí)驗(yàn)性的產(chǎn)品,主要面對(duì)央企和專用網(wǎng),一個(gè)網(wǎng)絡(luò)中有上百萬的終端。
剛開始沒有什么人關(guān)注,我就直接采用了Linux+OpenResty+Redis+Postgres的開源組件,性能測(cè)試甩之前的N條街。后面這個(gè)實(shí)驗(yàn)性的產(chǎn)品,和之前的產(chǎn)品,合并為一個(gè)產(chǎn)品,技術(shù)上面就割裂為兩套架構(gòu)。老功能用老架構(gòu),新功能用新架構(gòu)。
隨著越來越多大用戶的增加,原有的技術(shù)架構(gòu)開始捉襟見肘,技術(shù)債務(wù)越積壓越多。隨著用戶的抱怨,sqlite被拋棄,全面換成Postgres。但對(duì)于自己開發(fā)的框架還是有些敝帚自珍。
期間通過對(duì)比測(cè)試、OpenResty培訓(xùn)還有多次用戶性能問題排查,讓開發(fā)同學(xué)們都知道這門技術(shù)的優(yōu)勢(shì)??毂患影鄩嚎宓拈_發(fā)同學(xué),逐漸開始選擇使用OpenResty而不是自研的框架,來進(jìn)行新功能的開發(fā),以及舊功能的遷移,來避免加班。
在產(chǎn)品重構(gòu)的時(shí)候,之前自研的服務(wù)端框架被完全拋棄,服務(wù)端開發(fā)的同學(xué)從8、9個(gè)人減少到3個(gè)人。在新技術(shù)的引入過程中,我們沒有采用強(qiáng)制的舉措,因?yàn)槠髽I(yè)產(chǎn)品需要穩(wěn)定,用戶處部署的版本更新很慢。
而新浪移動(dòng)周晶的實(shí)踐,對(duì)大家更有參考意義。新浪移動(dòng)最開始是基于Apache,用PHP來處理用戶請(qǐng)求。Apache是同步多進(jìn)程模型,在并發(fā)請(qǐng)求不多的情況下沒有問題。
但是總是會(huì)有突發(fā)新聞,比如馬航失聯(lián)、文章出軌等,突發(fā)的高流量把后臺(tái)壓垮了幾次。而且可以預(yù)見世界杯的流量也會(huì)很大,所以周晶花幾個(gè)月時(shí)間,用nginx替換了Apache,使用nginx的fast_cgi_cache,QPS提升了一個(gè)數(shù)量級(jí)。
新浪移動(dòng)后臺(tái)的接口都是使用PHP來實(shí)現(xiàn)的,在高并發(fā)下有些力不從心。而nginx簡(jiǎn)單的緩存雖然能滿足性能,但不能滿足業(yè)務(wù)精細(xì)化和數(shù)據(jù)一致性的要求,需要找PHP之外的解決方案,前提是讓PHP的開發(fā)能夠舒適的使用。node.js的回調(diào)地獄、Go的調(diào)試不方便,都是一個(gè)阻礙。
他們最后選擇了OpenResty,而且基于OpenResty開源了一個(gè)Web框架Vanilla(香草),模仿了Yaf的使用習(xí)慣,讓PHP的開發(fā)更容易接受和上手。Vanilla已經(jīng)在新浪移動(dòng)開始使用,一些核心業(yè)務(wù),比如高清圖和體育直播,正在向這個(gè)框架遷移中。
4.入門痛點(diǎn),以及學(xué)習(xí)的正確方法
我和周晶的入門,都是自己摸著石頭過河。當(dāng)時(shí)除了Python社區(qū)「大媽」的那篇使用文章外,找不到其他的資料。
奇虎和新浪都用OpenResty成功替換了之前的技術(shù),但問題還是挺明顯,就是大家都認(rèn)為自己是孤獨(dú)的使用者,同事中基本沒有人認(rèn)同。在關(guān)鍵和支撐業(yè)務(wù)上,使用OpenResty有些不放心,都會(huì)在邊緣業(yè)務(wù)上先做嘗試和驗(yàn)證。
雖然OpenResty的性能做的很棒,比肩或者超過其他所有的高性能解決方案,但是擔(dān)心沒有學(xué)習(xí)資料、擔(dān)心招不到人、擔(dān)心沒人交流,可能還擔(dān)心作者章亦春哪天撂挑子不干了,這個(gè)項(xiàng)目就黃了。
高可用架構(gòu)群里的各位都是架構(gòu)師,是技術(shù)決策者,在引入一門新技術(shù)的時(shí)候,肯定會(huì)考慮到這些風(fēng)險(xiǎn)。比如小米科技馬利超在高可用架構(gòu)的分享,他們?cè)趽屬?gòu)系統(tǒng)中曾經(jīng)使用過ngx_lua,雖然性能滿足需求,但是團(tuán)隊(duì)里面熟悉的人少,最后還是改成了Go語言實(shí)現(xiàn)。
如何解決這些擔(dān)憂?社區(qū)是有過思考和討論的,我們放在分享最后講。先從一個(gè)嘗試使用這門技術(shù)的開發(fā)者的角度看,OpenResty不少基礎(chǔ)工作沒有完善,友好程度不夠:
只能從源碼安裝,沒有apt-get、brew等軟件倉(cāng)庫(kù)安裝方法;安裝第三方庫(kù)沒有PIP、NPM之類的包管理工具,需要去先谷歌,然后拷貝代碼文件到指定的目錄下,才能require使用。
代碼編寫需要修改nginx.conf和對(duì)應(yīng)的lua代碼,即使是helloworld也是如此。當(dāng)然你可以把代碼寫在nginx的配置文件里面,但是生產(chǎn)環(huán)境肯定是要分離的。這種編寫代碼的方式,不像是一個(gè)編程語言,和常規(guī)的編程方式不同。
有獨(dú)特的執(zhí)行階段概念,因?yàn)镺penResty是基于nginx的,所以也繼承它的這種概念。你的代碼邏輯,可能需要放在不同的階段里面運(yùn)行,才能獲取你想要的預(yù)期。而這些階段間信息如何傳遞,以及哪些API不能在某些階段使用,就會(huì)經(jīng)常攔住新手。
遇到問題只有郵件列表這一種方式來溝通,而郵件列表是被墻的。文檔也只有英文版本,導(dǎo)致很多新手的問題無法被解決。
沒有系統(tǒng)學(xué)習(xí)OpenResty的手段,大都是業(yè)務(wù)需要實(shí)現(xiàn)什么功能,就去文檔和API里面去找。至于方式對(duì)不對(duì),能不能優(yōu)化,就不知道了。
官方下載第三方庫(kù)并解壓包,將解壓包放入安裝目錄,電腦開始菜單,運(yùn)行。
第三方庫(kù)是一種為了方便編寫出程序或者方便辦公的一種外來安裝的庫(kù),不同于本地庫(kù),因此需要安裝才可以使用。
1、在cmd命令行直接使用pip install 包名命令安裝
示例:
注意:安裝成功會(huì)顯示Successfully installed keras,如果出現(xiàn)黃色字體警告,是由于pip庫(kù)包不是最新的,但keras庫(kù)已成功安裝,可隨后對(duì)pip包進(jìn)行更新,更新命令:python -m pip install --upgrade pip。
2、手動(dòng)下載第三方庫(kù),然后在cmd命令行使用pip install 下載文件名命令安裝下載的第三方庫(kù)()
更多Python知識(shí)請(qǐng)關(guān)注Python自學(xué)網(wǎng)