1. 分布式系統(tǒng)核心問題
參考書籍:《區(qū)塊鏈原理蹭秋、設計與應用》
-
一致性問題
例子:兩個不同的電影院買同一種電影票,如何避免超售仇祭?如何保持兩個電影院數據一致澡屡?
挑戰(zhàn)
- 節(jié)點之間的網絡通訊是不可靠的炼蛤,包括任意延遲和內容故障补疑;
- 節(jié)點的處理可能是錯誤的恩静,甚至節(jié)點自身隨時可能宕機轰驳;
- 同步調用會讓系統(tǒng)變得不具備可擴展性。
要求
可終止性(Termination):一致的結果在有限時間內能完成绿聘;
-
共識性(Consensus):不同節(jié)點最終完成決策的結果應該相同;
eg:現在就剩一張票了次舌,兩個電影院也分別剛確認過這張票的存在熄攘,然后兩個電影院同時來了一個顧客要買票,從各自“觀察”看來彼念,自己的顧客都是第一個到的……怎么能達成結果的共識呢挪圾?記住我們的唯一秘訣:核心在于需要把兩件事情進行排序,而且這個順序還得是大家都認可的逐沙。
合法性(Validity):決策的結果必須是其它進程提出的提案哲思。
-
共識算法
保障分布式系統(tǒng)的一致性,需要通過共識算法來實現吩案。
簡述:對某個提案棚赔,大家達成一致的過程。
-
FLP 不可能性原理
FLP 不可能原理:在網絡可靠务热,存在節(jié)點失效(即便只有一個)的最小化異步模型系統(tǒng)中忆嗜,不存在一個可以解決一致性問題的確定性算法己儒。
eg: 三個人在不同房間崎岂,進行投票(投票結果是 0 或者 1)。三個人彼此可以通過電話進行溝通闪湾,但經常會有人時不時地睡著冲甘。比如某個時候,A 投票 0途样,B 投票 1江醇,C 收到了兩人的投票,然后 C 睡著了何暇。A 和 B 則永遠無法在有限時間內獲知最終的結果陶夜。
FLP原理只是最壞的情況下,但是我們可以付出一些代價來提高成功的概率裆站。
-
CAP 原理
分布式計算系統(tǒng)不可能同時確保一致性(Consistency)条辟、可用性(Availablity)和分區(qū)容忍性(Partition),設計中往往需要弱化對某個特性的保證宏胯。
一致性(Consistency):任何操作應該都是原子的羽嫡,發(fā)生在后面的事件能看到前面事件發(fā)生導致的結果,注意這里指的是強一致性肩袍;
可用性(Availablity):在有限時間內杭棵,任何非失敗節(jié)點都能應答請求;
-
分區(qū)容忍性(Partition):集群中的某些節(jié)點在無法聯(lián)系后氛赐,集群整體是否還能繼續(xù)進行服務魂爪。
分隔容忍(Partition tolerance) (系統(tǒng)中任意信息的丟失或失敗不會影響系統(tǒng)的繼續(xù)運作)
應用:
網絡中會經常會出現延遲丟包等問題先舷,所以分區(qū)容忍性一般不會弱化。
-
弱化一致性
對結果一致性不敏感的應用滓侍,可以允許在新版本上線后過一段時間才更新成功密浑,期間不保證一致性。
-
弱化可用性
對結果一致性很敏感的應用粗井,例如銀行取款機尔破,當系統(tǒng)故障時候會拒絕服務。
-
ACID 原則
ACID 原則描述了對分布式數據庫的一致性需求浇衬,同時付出了可用性的代價懒构。
- 原子性(Atomicity):每次操作是原子的,要么成功耘擂,要么不執(zhí)行胆剧;
- 一致性(Consistency):數據庫的狀態(tài)是一致的,無中間狀態(tài)醉冤;
- 隔離性(Isolation):各種操作彼此互相不影響秩霍;
- 持久性(Durability):狀態(tài)的改變是持久的,不會失效蚁阳。
一個與之相對的原則是 BASE(Basically Available(基本可用)铃绒、Soft state(軟狀態(tài))和Eventually consistent(最終一致性)),犧牲掉對一致性的約束(最終一致性)螺捐,來換取一定的可用性颠悬。
-
Paxos 與 Raft
-
Paxos
問題背景:古希臘 Paxon 島上的多個法官在一個大廳內對一個議案進行表決,如何達成統(tǒng)一的結果定血。他們之間通過服務人員來傳遞紙條赔癌,但法官可能離開或進入大廳,服務人員可能偷懶去睡覺澜沟。
算法中將節(jié)點分為三種類型:
- proposer:提出一個提案灾票,等待大家批準為結案。往往是客戶端擔任該角色茫虽;
- acceptor:負責對提案進行投票刊苍。往往是服務端擔任該角色;
- learner:被告知結案結果席噩,并與之統(tǒng)一班缰,不參與投票過程〉渴啵可能為客戶端或服務端埠忘。
算法需要滿足 safety 和 liveness 兩方面的約束要求:
- safety:保證決議結果是對的,無歧義的,不會出現錯誤情況莹妒。
- 決議(value)只有在被 proposers 提出的 proposal 才能被最終批準名船;
- 在一次執(zhí)行實例中,只批準(chosen)一個最終決議旨怠,意味著多數接受(accept)的結果能成為決議渠驼;
- liveness:保證決議過程能在有限時間內完成。
- 決議總會產生鉴腻,并且 learners 能獲得被批準(chosen)的決議迷扇。
基本過程包括 proposer 提出提案,先爭取大多數 acceptor 的支持爽哎,超過一半支持時蜓席,則發(fā)送結案結果給所有人進行確認。一個潛在的問題是 proposer 在此過程中出現故障课锌,可以通過超時機制來解決厨内。極為湊巧的情況下,每次新的一輪提案的 proposer 都恰好故障渺贤,系統(tǒng)則永遠無法達成一致(概率很谐浮)。
Paxos 能保證在超過的正常節(jié)點存在時志鞍,系統(tǒng)能達成共識瞭亮。
-
Raft
Raft 算法是Paxos 算法的一種簡化實現。
包括三種角色:leader述雾、candidate 和 follower街州,其基本過程為:
- Leader 選舉:每個 candidate 隨機經過一定時間都會提出選舉方案兼丰,最近階段中得票最多者被選為 leader玻孟;
- 同步事件記錄 log:leader 會找到系統(tǒng)中 log 最新的記錄,并強制所有的 follower 來刷新到這個記錄鳍征。
-
-
拜占庭問題
拜占庭是古代東羅馬帝國的首都黍翎,由于地域寬廣,守衛(wèi)邊境的多個將軍(系統(tǒng)中的多個節(jié)點)需要通過信使來傳遞消息艳丛,達成某些一致的決定匣掸。但由于將軍中可能存在叛徒(系統(tǒng)中節(jié)點出錯),這些叛徒將努力向不同的將軍發(fā)送不同的消息氮双,試圖會干擾一致性的達成碰酝。
拜占庭問題即為在此情況下,如何讓忠誠的將軍們能達成行動的一致?
Byzantine Fault Tolerant (BFT) 算法
? BFT算法保證所有正常的replicas節(jié)點執(zhí)行相同序列的操作戴差。因為所有的replicas節(jié)點都是deterministic送爸,而且初始狀態(tài)都相同,根據狀態(tài)機原理(state machine replication),這些replicas會產生相同的結果狀態(tài)袭厂。當Client收到f+1個replicas節(jié)點返回的結果時墨吓,如果這些結果都一樣,因為BFT算法確保了最多有f個replicas出現問題纹磺,所以至少有一個replicas是正確的帖烘,那么Client收到的這些結果都是正確的。
其他解決思路:
問題由來:系統(tǒng)存在多個提案橄杨,一致確認困難
PoW(Proof of Work) 算法思路:
- 增加提案成本(限制了提案數量)
- 放寬對最終一致性確認的需求秘症,約定好大家都確認并沿著已知最長的鏈進行拓寬。
注:系統(tǒng)的最終確認是概率意義上的存在式矫。這樣历极,即便有人試圖惡意破壞,也會付出很大的經濟代價(付出超過系統(tǒng)一半的算力)衷佃。
-
可靠性指標
下表給出不同指標下趟卸,每年允許服務出現不可用時間的參考值。
指標 概率可靠性 每年允許不可用時間 典型場景 一個九 90% 1.2 個月 不可用 二個九 99% 3.6 天 普通單點 三個九 99.9% 8.6 小時 普通企業(yè) 四個九 99.99% 51.6 分鐘 高可用 五個九 99.999% 5 分鐘 電信級 六個九 99.9999% 31 秒 極高要求 七個九 99.99999% 3 秒 N/A 八個九 99.999999% 0.3 秒 N/A 九個九 99.9999999% 30 毫秒 N/A
2. Raft算法
參考學習鏈接:
Raft 算法實現推薦:
其他:狀態(tài)機
1. 概述
Raft 是一種為了管理復制日志的一致性算法氏义。它提供了和 Paxos 算法相同的功能和性能锄列,但是它的算法結構和 Paxos 不同,使得 Raft 算法更加容易理解并且更容易構建實際的系統(tǒng)惯悠。Raft 將一致性算法分解成了幾個關鍵模塊邻邮,例如 領導人選舉、日志復制和安全性 克婶。
2. Raft基礎
服務器節(jié)點的三種狀態(tài):
-
Leader(領導人)
通常情況下筒严,系統(tǒng)中只有一個領導人,其他節(jié)點都是跟隨者情萤。領導人處理所有的客戶端請求(如果一個客戶端和跟隨者聯(lián)系鸭蛙,那么跟隨者會把請求重定向給領導人)。
-
Follower(跟隨者)
跟隨者不會發(fā)送任何請求筋岛,只是簡單的響應來自領導者或者候選人的請求娶视。如果跟隨者接收不到消息,那么他就會變成候選人并發(fā)起一次選舉睁宰。
-
Candidate(候選人)
獲得集群中大多數選票的候選人將成為領導者肪获。
下面是這三種狀態(tài)的轉化過程:
跟隨者只響應來自其他服務器的請求。如果跟隨者接收不到消息柒傻,那么他就會變成候選人并發(fā)起一次選舉孝赫。獲得集群中大多數選票的候選人將成為領導者。在一個任期內,領導人一直都會是領導人直到自己宕機了红符。
3. 領導人選舉
-
觸發(fā)選舉
Raft 使用一種心跳機制來觸發(fā)領導人選舉青柄。觸發(fā)有兩種情況:
- 初始狀態(tài)時劫映,所有服務器節(jié)點都是跟隨者,并且隨機睡眠一段時間刹前,這個時間在0~1000ms之間泳赋。最先醒來的server A進入 Candidate 狀態(tài),觸發(fā)選舉喇喉。
- 領導者周期性的向所有跟隨者發(fā)送心跳包(即不包含日志項內容的附加日志項 RPCs)來維持自己的權威祖今。如果一個跟隨者在一段時間里沒有接收到任何消息,也就是選舉超時拣技,那么這時觸發(fā)選舉以選出新的領導者千诬。
-
選舉
要開始一次選舉過程,跟隨者先要增加自己的 當前任期號 并且轉換到候選人狀態(tài)膏斤。然后他會并行的向集群中的其他服務器節(jié)點發(fā)送請求投票的 RPCs 來給自己投票徐绑。當一個候選人從整個集群的大多數服務器節(jié)點(一半以上)獲得了針對同一個任期號的選票,那么他就贏得了這次選舉并成為領導人莫辨。每一個服務器最多會對一個任期號投出一張選票傲茄,按照先來先服務的原則。
在等待投票的時候沮榜,候選人可能會從其他的服務器接收到聲明它是領導人的附加日志項 RPC盘榨。如果這個領導人的任期號(包含在此次的 RPC中)不小于候選人當前的任期號,那么候選人會承認領導人合法并回到跟隨者狀態(tài)蟆融。 如果此次 RPC 中的任期號比自己小草巡,那么候選人就會拒絕這次的 RPC 并且繼續(xù)保持候選人狀態(tài)。
如果有多個跟隨者同時成為候選人型酥,那么選票可能會被瓜分以至于沒有候選人可以贏得大多數人的支持山憨。當這種情況發(fā)生的時候,每一個候選人都會超時弥喉,然后通過增加當前任期號來開始一輪新的選舉郁竟。
-
選舉之后
一旦候選人贏得選舉,他就立即成為領導人档桃。然后他會向其他的服務器發(fā)送心跳消息來建立自己的權威并且阻止新的領導人的產生枪孩。
4. 日志復制
-
復制過程
Leader選舉出來后,就可以開始處理客戶端請求藻肄。Leader收到客戶端請求后,將請求內容作為一條log日志添加到自己的log記錄中拒担,并向其它server發(fā)送RPCs(添加日志)請求嘹屯。其它server收到請求后,如果滿足條件就將其添加到本地的log中从撼,并給Leader發(fā)送添加成功的response州弟。Leader在收到大多數server添加成功的response后钧栖,就將該條log正式提交到狀態(tài)機中。
-
一致性保持
當一個領導人剛獲得權力的時候婆翔,他初始化所有的 nextIndex 值為自己的最后一條日志的index(索引)加1拯杠。如果一個跟隨者的日志和領導人不一致,那么在下一次的附加日志 RPC 時的一致性檢查就會失敗啃奴。在被跟隨者拒絕之后潭陪,領導人就會減小 nextIndex 值并進行重試。最終 nextIndex 會在某個位置使得領導人和跟隨者的日志達成一致最蕾。當這種情況發(fā)生依溯,附加日志 RPC 就會成功,這時就會把跟隨者沖突的日志條目全部刪除并且加上領導人的日志瘟则。一旦附加日志 RPC 成功黎炉,那么跟隨者的日志就會和領導人保持一致,并且在接下來的任期里一直繼續(xù)保持醋拧。
5. 安全性
-
選舉限制
候選人為了贏得選舉必須聯(lián)系集群中的大部分節(jié)點慷嗜,這意味著每一個已經提交的日志條目在這些服務器節(jié)點中肯定存在于至少一個節(jié)點上。如果候選人的日志至少和大多數的服務器節(jié)點一樣新丹壕,那么他一定持有了所有已經提交的日志條目洪添。請求投票 RPC 實現了這樣的限制: RPC 中包含了候選人的日志信息,然后投票人會拒絕掉那些日志沒有自己新的投票請求雀费。
Raft 通過比較兩份日志中最后一條日志條目的索引值和任期號定義誰的日志比較新干奢。如果兩份日志最后的條目的任期號不同,那么任期號大的日志更加新盏袄。如果兩份日志最后的條目任期號相同忿峻,那么日志比較長的那個就更加新。
-
提交之前任期內的日志條目
領導人知道一條當前任期內的日志記錄是可以被提交的辕羽,只要它被存儲到了大多數的服務器上逛尚。如果一個領導人在提交日志條目之前崩潰了,未來后續(xù)的領導人會繼續(xù)嘗試復制這條日志記錄刁愿。然而绰寞,一個領導人不能斷定一個之前任期里的日志條目被保存到大多數服務器上的時候就一定已經提交了。圖 8 展示了一種情況铣口,一條已經被存儲到大多數節(jié)點上的老日志條目滤钱,也依然有可能會被未來的領導人覆蓋掉。
圖 8:如圖的時間序列展示了為什么領導人無法通過老的日志的任期號來判斷其提交狀態(tài)脑题。在 (a) 中件缸,S1 是領導者,部分的復制了索引位置 2 的日志條目叔遂。在 (b) 中他炊,S1 崩潰了争剿,然后 S5 在任期 3 里通過 S3、S4 和自己的選票贏得選舉痊末,然后從客戶端接收了一條不一樣的日志條目放在了索引 2 處蚕苇。然后到 (c),S5 又崩潰了凿叠;S1 重新啟動涩笤,選舉成功,開始復制日志幔嫂。在這時辆它,來自任期 2 的那條日志已經被復制到了集群中的大多數機器上,但是還沒有被提交履恩。如果 S1 在 (d) 中又崩潰了锰茉,S5 可以重新被選舉成功(通過來自 S2,S3 和 S4 的選票)切心,然后覆蓋了他們在索引 2 處的日志飒筑。但是,在崩潰之前绽昏,如果 S1 在自己的任期里復制了日志條目到大多數機器上协屡,如 (e) 中,然后這個條目就會被提交(S5 就不可能選舉成功)全谤。 在這個時候肤晓,之前的所有日志就會被正常提交處理。
為了消除圖 8 里描述的情況认然,Raft 永遠不會通過計算副本數目的方式去提交一個之前任期內的日志條目补憾。只有領導人當前任期里的日志條目通過計算副本數目可以被提交;一旦當前任期的日志條目以這種方式被提交卷员,那么由于日志匹配特性盈匾,之前的日志條目也都會被間接的提交。在某些情況下毕骡,領導人可以安全的知道一個老的日志條目是否已經被提交(例如削饵,該條目是否存儲到所有服務器上),但是 Raft 為了簡化問題使用一種更加保守的方法未巫。
當領導人復制之前任期里的日志時窿撬,Raft 會為所有日志保留原始的任期號, 這在提交規(guī)則上產生了額外的復雜性。在其他的一致性算法中,如果一個新的領導人要重新復制之前的任期里的日志時思犁,它必須使用當前新的任期號。Raft 使用的方法更加容易辨別出日志喧枷,因為它可以隨著時間和日志的變化對日志維護著同一個任期編號。另外轮傍,和其他的算法相比,Raft 中的新領導人只需要發(fā)送更少日志條目。
6. Raft 算法實現指導
狀態(tài):
狀態(tài) | 所有服務器上持久存在的 |
---|---|
currentTerm | 服務器最后一次知道的任期號(初始化為 0赡模,持續(xù)遞增) |
votedFor | 在當前獲得選票的候選人的 Id |
log[] | 日志條目集;每一個條目包含一個用戶狀態(tài)機執(zhí)行的指令师抄,和收到時的任期號 |
狀態(tài) | 所有服務器上經常變的 |
---|---|
commitIndex | 已知的最大的已經被提交的日志條目的索引值 |
lastApplied | 最后被應用到狀態(tài)機的日志條目索引值(初始化為 0漓柑,持續(xù)遞增) |
狀態(tài) | 在領導人里經常改變的 (選舉后重新初始化) |
---|---|
nextIndex[] | 對于每一個服務器,需要發(fā)送給他的下一個日志條目的索引值(初始化為領導人最后索引值加一) |
matchIndex[] | 對于每一個服務器叨吮,已經復制給他的日志的最高索引值 |
附加日志 RPC:
由領導人負責調用來復制日志指令辆布;也會用作heartbeat
參數 | 解釋 |
---|---|
term | 領導人的任期號 |
leaderId | 領導人的 Id,以便于跟隨者重定向請求 |
prevLogIndex | 新的日志條目緊隨之前的索引值 |
prevLogTerm | prevLogIndex 條目的任期號 |
entries[] | 準備存儲的日志條目(表示心跳時為空茶鉴;一次性發(fā)送多個是為了提高效率) |
leaderCommit | 領導人已經提交的日志的索引值 |
返回值 | 解釋 |
---|---|
term | 當前的任期號锋玲,用于領導人去更新自己 |
success | 跟隨者包含了匹配上 prevLogIndex 和 prevLogTerm 的日志時為真 |
接收者實現:
- 如果
term < currentTerm
就返回 false (5.1 節(jié)) - 如果日志在 prevLogIndex 位置處的日志條目的任期號和 prevLogTerm 不匹配,則返回 false (5.3 節(jié))
- 如果已經存在的日志條目和新的產生沖突(索引值相同但是任期號不同)涵叮,刪除這一條和之后所有的 (5.3 節(jié))
- 附加任何在已有的日志中不存在的條目
- 如果
leaderCommit > commitIndex
惭蹂,令 commitIndex 等于 leaderCommit 和 新日志條目索引值中較小的一個
請求投票 RPC:
由候選人負責調用用來征集選票(5.2 節(jié))
參數 | 解釋 |
---|---|
term | 候選人的任期號 |
candidateId | 請求選票的候選人的 Id |
lastLogIndex | 候選人的最后日志條目的索引值 |
lastLogTerm | 候選人最后日志條目的任期號 |
返回值 | 解釋 |
---|---|
term | 當前任期號,以便于候選人去更新自己的任期號 |
voteGranted | 候選人贏得了此張選票時為真 |
接收者實現:
- 如果
term < currentTerm
返回 false (5.2 節(jié)) - 如果 votedFor 為空或者就是 candidateId割粮,并且候選人的日志至少和自己一樣新盾碗,那么就投票給他(5.2 節(jié),5.4 節(jié))
所有服務器需遵守的規(guī)則:
所有服務器:
- 如果
commitIndex > lastApplied
舀瓢,那么就 lastApplied 加一廷雅,并把log[lastApplied]
應用到狀態(tài)機中(5.3 節(jié)) - 如果接收到的 RPC 請求或響應中,任期號
T > currentTerm
京髓,那么就令 currentTerm 等于 T航缀,并切換狀態(tài)為跟隨者(5.1 節(jié))
跟隨者(5.2 節(jié)):
- 響應來自候選人和領導者的請求
- 如果在超過選舉超時時間的情況之前都沒有收到領導人的心跳,或者是候選人請求投票的朵锣,就自己變成候選人
候選人(5.2 節(jié)):
- 在轉變成候選人后就立即開始選舉過程
- 自增當前的任期號(currentTerm)
- 給自己投票
- 重置選舉超時計時器
- 發(fā)送請求投票的 RPC 給其他所有服務器
- 如果接收到大多數服務器的選票谬盐,那么就變成領導人
- 如果接收到來自新的領導人的附加日志 RPC,轉變成跟隨者
- 如果選舉過程超時诚些,再次發(fā)起一輪選舉
領導人:
- 一旦成為領導人:發(fā)送空的附加日志 RPC(心跳)給其他所有的服務器飞傀;在一定的空余時間之后不停的重復發(fā)送,以阻止跟隨者超時(5.2 節(jié))
- 如果接收到來自客戶端的請求:附加條目到本地日志中诬烹,在條目被應用到狀態(tài)機后響應客戶端(5.3 節(jié))
- 如果對于一個跟隨者砸烦,最后日志條目的索引值大于等于 nextIndex,那么:發(fā)送從 nextIndex 開始的所有日志條目:
- 如果成功:更新相應跟隨者的 nextIndex 和 matchIndex
- 如果因為日志不一致而失敗绞吁,減少 nextIndex 重試
- 如果存在一個滿足
N > commitIndex
的 N幢痘,并且大多數的matchIndex[i] ≥ N
成立,并且log[N].term == currentTerm
成立家破,那么令 commitIndex 等于這個 N
3. 常識
-
ftp/http/https/http 2.0
-
通俗解釋
ftp: 文件傳輸的協(xié)議
http: 網絡交流的基礎颜说,凡是網絡都需要它
https: 安全的http
http 2.0: http1.0 和 http 1.1 的升級版购岗,反正就是解決了 前代 http 的一些問題
-
專業(yè)解釋
ftp: FTP 是 File Transfer Protocol(文件傳輸協(xié)議)的英文簡稱,用于控制文件在不同計算機之間的雙向傳輸门粪,如下載和上傳喊积,顧名思義 下載就是從遠程服務器將文件copy到自己的本地,上傳就是把本地文件copy到遠程服務器上玄妈。
http: 超文本傳輸協(xié)議(HTTP)是一種應用協(xié)議用于分布式乾吻,協(xié)作和超媒體信息系統(tǒng),主要是一種請求 - 響應 協(xié)議拟蜻。如: 瀏覽器的客戶端向服務器提交HTTP 請求 消息绎签,服務器接到請求之后響應HTML文件和其他內容等資源。響應包含有關請求的完成狀態(tài)信息酝锅,并且可能還包含消息正文中的請求內容等诡必。
https: HTTP的改進,用于通過計算機網絡進行安全通信屈张。在HTTPS擒权,該通信協(xié)議被加密的傳輸層安全性(TLS),或以前阁谆,它的前身碳抄,安全套接字層(SSL)。HTTP沒有加密场绿,容易受到中間人和竊聽攻擊剖效,攻擊者可以竊取網站賬戶等敏感信息等。HTTPS旨在抵御此類攻擊焰盗。
http 2.0: HTTP / 2 是 HTTP 1.1 以來的第一個新版本璧尸。旨在解決 http 1.0 和 1.1 的一些問題。
? http 1.0 和 1.1 的一些問題:
? 1熬拒、 單連接多資源的方式爷光,減少服務端的鏈接壓力,內存占用更少,連接吞吐量更大。
? 2澎粟、不支持首部壓縮
? http 2.0 優(yōu)點:
? 1蛀序、 多路復用允許同時通過單一的 HTTP/2 連接發(fā)起多重的請求-響應消息,不用依賴建立多個 TCP 連接活烙。HTTP/2 把 HTTP 協(xié)議通信的基本單位縮小為一個一個的幀徐裸,這些幀對應著邏輯流中的消息。并行地在同一個 TCP 連接上雙向交換消息啸盏。從而是的擁塞狀況得到改善重贺。
? 2、首部壓縮,減少了數據大小
? 3气笙、在 HTTP/2 中次企,服務器可以對客戶端的一個請求發(fā)送多個響應。
-
-
tcp/ip
-
通俗解釋
TCP負責保證數據安全正確地傳輸到目的地健民。而IP是每一臺聯(lián)網設備的一個唯一的地址抒巢。
-
專業(yè)解釋
TCP/IP 是供已連接因特網的計算機進行通信的通信協(xié)議贫贝, 定義了電子設備如何連入因特網秉犹,以及數據如何在它們之間傳輸的標準。
該協(xié)議包含 TCP稚晚、UDP崇堵、IP、ICMP客燕、DHCP等一系列協(xié)議鸳劳。
TCP是面向連接的通信協(xié)議,通過三次握手建立連接也搓,四次揮手拆除連接赏廓。
ip: Internet的網絡地址是指連入Internet網絡的計算機的地址編號。所以傍妒,在Internet網絡中幔摸,網絡地址唯一地標識一臺計算機,如:123.37.0.200颤练。
-
-
gzip壓縮
通俗解釋:把文件壓縮為 .gz 格式既忆,或者解壓文件
-
專業(yè)解釋
語法:gzip [option] filename
option:
? -c 將輸出寫到標準輸出上,并保留原有文件嗦玖。
? -d 將壓縮文件解壓患雇。
? -l 對每個壓縮文件,顯示字段(不解壓):壓縮文件的大小宇挫、未壓縮文件的大小苛吱、壓縮比、未壓縮文件的名字
? -r 遞歸式地查找指定目錄并壓縮其中的所有文件或者是解壓縮器瘪。
? -t 測試翠储,檢查壓縮文件是否完整。
? -v 對每一個壓縮和解壓的文件娱局,顯示文件名和壓縮比彰亥。
? -num 用指定的數字num調整壓縮的速度,-1或--fast表示最快壓縮方法(低壓縮比)衰齐,-9或--best表示最慢壓縮方法(高壓縮比)任斋。系統(tǒng)缺省值為6。注:gzip不能壓縮整個目錄》峡幔可以使用tar先打包瘟檩,再壓縮
eg:
tar cf test.tar test/ gzip test.tar
-
nginx/cgi/uWSGI/php-fpm/fastcgi
-
通俗解釋
nginx: 一個性能很高的服務器
uWSGI: 一個web服務器
cgi: 寫Web程序的標準
php-fpm: 用與處理PHP請求的東西
-
專業(yè)解釋
nginx: 一個高性能的占有內存少,并發(fā)能力強的(反向)代理服務器
uWSGI: uWSGI是一個Web服務器澈蟆,它實現了WSGI協(xié)議墨辛、uwsgi、http等協(xié)議趴俘。WSGI是一種Web服務器網關接口睹簇。它是一個Web服務器與web應用通信的一種規(guī)范。
cgi: 一個通用的web標準寥闪。
fastcgi: Web服務器和語言解釋器(eg:uWsgi)兩者底層的通信協(xié)議的規(guī)范太惠,是對CGI的開放的擴展。
php-fpm: 全稱是php fastcgi process manager即php fastcgi進程管理器疲憋,相比fastcgi靜態(tài)的喚起cgi凿渊,fpm能根據訪問的壓力動態(tài)的喚起cgi進程和銷毀以到達動態(tài)的調整cgi數量,這樣可以有效的使用內存缚柳。其他優(yōu)點:fpm還可以平滑的重載php配置埃脏;不用再配置cgi端口;有更好的狀態(tài)輸出和slowlog日志秋忙,502的時候能給出更多的錯誤細節(jié)彩掐。
-
-
高階函數/函數柯里化
-
通俗解釋
高階函數:從一個函數映射到另一個函數
函數柯里化:多參數的函數簡化為單參數的函數的過程
-
專業(yè)解釋
高階函數:滿足下列一個或者兩個條件的函數:
- 接受一個或多個函數作為輸入
- 輸出一個函數
函數柯里化:柯里化(Currying)指的是將原來接受多個參數的函數變成新的接受一個參數的函數的過程。
eg:
function add(a, b) { return a + b; } add(1, 2) // 柯里化 var addCurry = curry(add) addCurry(1)(2)
-
-
函數式編程
通俗解釋:是一種編寫程序的方法論翰绊,也就是教我們怎么寫程序的
專業(yè)解釋:一種 編程范式 佩谷,屬于一種 結構化編程
思想:把運算過程寫成一系列嵌套的函數調用
eg:
? 數學表達式 :
(1 + 2) * 3 - 4
? 傳統(tǒng)寫法:
a := 1 + 2 b := a * 3 c := b - 4
? 函數式編程寫法:
result := subtract(multiply(add(1,2), 3), 4)
五大特點:
-
函數是"第一等公民"
函數與其他數據類型擁有同樣的地位和功能,如:可以賦值給其他變量监嗜,也可以作為參數谐檀,傳入另一個函數,或者作為別的函數的返回值裁奇。
-
只用"表達式"桐猬,不用"語句"
"表達式"是一個單純的運算過程,有返回值刽肠;"語句"是執(zhí)行某種操作溃肪,沒有返回值音五。只使用表達式惫撰,不使用語句就是每一步都是單純的運算過程,都有返回值躺涝。
-
沒有"副作用"
函數是獨立的厨钻,返回的值是一個新的值,不得修改外部變量的值。
-
不修改狀態(tài)
函數式編程使用參數保存狀態(tài)夯膀,而不保存在變量中诗充,例如遞歸。
-
引用透明
函數獨立诱建,不依賴于外部變量或"狀態(tài)"蝴蜓,只依賴于輸入的參數,任何時候只要參數相同俺猿,引用函數所得到的返回值總是相同的茎匠。
好處:
- 代碼簡潔,開發(fā)快速
- 接近自然語言辜荠,易于理解
- 更方便的代碼管理
- 易于"并發(fā)編程"
- 代碼的熱升級
-
-
前置條件/后置條件/循環(huán)不變量/代碼正確性證明
前置條件:指函數履行其契約所必須滿足的條件汽抚,即此函數可以執(zhí)行的必須滿足的條件。
后置條件:指函數執(zhí)行完畢后伯病,返回之前哪些條件是調用者可以期望的。
eg:
func test(a, b int) int { return a + b }
注:前置條件:函數的兩個參數 a, b且為 int 型
? 后置條件:返回值必須為 int 型
循環(huán)不變量:循環(huán)過程中算法的固有性質否过。如:隊列出棧的時候一定是最前面的節(jié)點出棧午笛,不會是其他點。
代碼正確性證明:
? 選取一個布爾函數 F(V)苗桂,在整個循環(huán)過程(起始和進行中)药磺,F(V)為真,當循環(huán)結束后煤伟,F(V)可以說明函數的正確性癌佩。
-
hash函數/慢哈希/加密算法
通俗解釋:都是一些加密算法,即讓你的信息需要一定的秘鑰或者其他什么東西才能看的一種手段
-
專業(yè)解釋
hash函數:散列函數便锨,一個偽隨機數生成器围辙,著名的 hash 算法 MD4,MD5放案,SHA1
-
慢哈希
定義:指執(zhí)行這個哈希函數非常慢姚建,這樣暴力破解需要枚舉遍歷所有可能結果時,就需要花上非常非常長的時間吱殉。
最簡單的方法就是對 Hash 后的結果再 Hash掸冤。
缺點:慢,消耗計算資源
-
加密算法
定義:對原來為明文的文件或數據按某種算法進行處理友雳,使其成為不可讀的一段代碼稿湿,通常稱為“密文”,使其只能在輸入相應的密鑰之后才能顯示出本來內容押赊,通過這樣的途徑來達到保護數據不被非法人竊取饺藤、閱讀的目的。
分類:對稱加密和非對稱加密
常見算法:
對稱加密算法:DES和3DES、RC2和RC4策精、AES
非對稱加密算法:RSA舰始、DSA、ECC
-
線程/進程/協(xié)程/并行算法
-
通俗解釋
進程:你運行的程序的實例
線程:輕量級進程
并行算法:幾個人一起解決一個問題
-
專業(yè)解釋
進程:是一個具有一定獨立功能的程序關于某個數據集合的一次運行活動咽袜。它是操作系統(tǒng)動態(tài)執(zhí)行的基本單元丸卷,在傳統(tǒng)的操作系統(tǒng)中,進程既是基本的分配單元询刹,也是基本的執(zhí)行單元谜嫉。
線程:是程序中一個單一的順序控制流程。在單個程序中同時運行多個線程完成不同的工作凹联,稱為多線程沐兰。
并行算法:使用多個進程或者線程同時求解同一個問題,進程或者線程之間相互協(xié)調統(tǒng)一蔽挠,最終得到結果住闯。
-
-
文件系統(tǒng)
通俗解釋:幫助傻瓜用戶管理文件的系統(tǒng)
-
專業(yè)解釋
定義:文件系統(tǒng)(file system)是命名文件及放置文件的邏輯存儲和恢復的系統(tǒng)。
用處:將不美的操作轉化為美的接口澳淑,即將底層的操作進行抽象比原,方便用戶。
常見的文件系統(tǒng):FAT杠巡、NTFS量窘、exFAT、Ext氢拥、Btrfs
-
html/css/js
通俗解釋: 用來做我們看到的網頁的語言
-
專業(yè)解釋
-
HTML
定義:超文本標記語言 (Hyper Text Markup Language)
eg:
<!DOCTYPE html> <html> <head> <title>hello</title> </head> <body> <p>hello world</p> </body> </html>
-
CSS
定義:層疊樣式表 (Cascading Style Sheets)
用處:渲染 HTML蚌铜,讓HTML更漂亮
body{ background-color: #eef5fd; }
-
JS
定義:JavaScript 是一個高層次,動態(tài)嫩海,弱類型冬殃,基于原型的,多范式出革,并且解釋 的編程語言
用處:對事件響應造壮,動態(tài)網頁制作等
document.write("<h1>Hello world</h1>")
-
-
bcd/mit licenses
-
通俗解釋
MIT License:相對較為寬松的授權條款
BCD License:比GPL許可證和MPL許可證寬松,比MIT嚴格一點
-
專業(yè)解釋
MIT License:MIT許可是一個寬容的自由軟件許可證起源于美國麻省理工學院(MIT)骂束。它只對重用限制非常有限耳璧,MIT許可證允許在私有軟件中重復使用,前提是許可軟件的所有副本均包含MIT許可條款和版權聲明的副本展箱。
BCD License:對使用和重新分配涵蓋的軟件施加最小的限制旨枯,BSD由于允許使用者修改和重新發(fā)布代碼,也允許使用或在BSD代碼上開發(fā)商業(yè)軟件發(fā)布和銷售混驰,因此是對商業(yè)集成很友好的協(xié)議攀隔。但前提是1皂贩、如果再發(fā)布的產品中包含源代碼,則在源代碼中必須帶有原來代碼中的BSD協(xié)議昆汹。
2明刷、如果再發(fā)布的只是二進制類庫/軟件,則需要在類庫/軟件的文檔和版權聲明中包含原來代碼中的BSD協(xié)議满粗。
3辈末、不可以用開源代碼的作者/機構名字和原來產品的名字做市場推廣。
-
-
cocoa
通俗解釋:蘋果的一套用來寫Mac OS X應用程序的面向對象的框架
專業(yè)解釋:Cocoa是蘋果公司為Mac OS X所創(chuàng)建的原生面向對象的API
用于蘋果設備的應用程序
主要開發(fā)工具:XCode 和 Interface Builder
-
mvc模式
-
通俗解釋
Model(模型)映皆、View(視圖)和 Controller(控制器)
-
專業(yè)解釋
Model(模型)表示應用程序核心(比如數據庫記錄列表)
View(視圖)顯示數據(數據庫記錄)
Controller(控制器)處理輸入(寫入數據庫記錄)流程:用戶通過視圖層進行相關操作挤聘,引發(fā)相應的事件傳到控制層,控制層處理響應捅彻,并返回相應的值或者通過其他方式傳值组去。
-
-
裝飾者/裝飾器模式
通俗解釋:包裝,給一個對象在外部添加一些功能
專業(yè)解釋:動態(tài)的為對象添加功能步淹,即從一個對象外部來給對象添加功能从隆。它不必改變原類文件,動態(tài)的擴展一個對象的功能贤旷,主要是通過創(chuàng)建一個裝飾器來包裝對象广料。
eg:
def login_required(func): @wraps(func) def wrapper(*args, **kw): token = request.headers.get('Authorization') try: payload = jwt.decode(token, config.SECRET, algorithms=[config.JWT_ALGORITHM]) return func(payload, *args, **kw) except Exception, e: logging.warn('login error: ' + e.message) return jsonify({'successful': False, 'error': 'Unauthorized!'}) return wrapper
-
socket/websocket
-
通俗解釋
socket: 網絡數據交換的接口
websocket: 單個TCP連接雙向通信
-
專業(yè)解釋
socket: 網絡上的兩個程序通過一個雙向的通信連接實現數據的交換,這個連接的一端稱為一個socket幼驶。socket本質是編程接口(API),對TCP/IP的封裝韧衣,TCP/IP也要提供可供程序員做網絡開發(fā)所用的接口盅藻,這就是Socket編程接口;HTTP是轎車畅铭,提供了封裝或者顯示數據的具體形式氏淑;Socket是發(fā)動機,提供了網絡通信的能力硕噩。
websocket: WebSocket協(xié)議是基于TCP的一種新的網絡協(xié)議假残。它實現了瀏覽器與服務器全雙工(full-duplex)通信——允許服務器主動發(fā)送信息給客戶端。
-
-
opengl/opencv
-
通俗解釋
**OpenGL: ** 主要是一個3D 圖像庫(2D 也能寫)
**OpenCV: ** 跨平臺計算機視覺庫
-
專業(yè)解釋
**OpenGL: **OpenGL(全寫Open Graphics Library)是指定義了一個跨編程語言炉擅、跨平臺的編程接口規(guī)格的專業(yè)的圖形程序接口辉懒。它用于三維圖像(二維的亦可),是一個功能強大谍失,調用方便的底層圖形庫眶俩。
OpenCV: 由一系列 C 函數和少量 C++ 類構成,同時提供了Python快鱼、Ruby颠印、MATLAB等語言的接口纲岭,實現了圖像處理和計算機視覺方面的很多通用算法,還涉及一些機器學習的算法线罕。
Opencv是從圖像到數據止潮,OpenGL是從數據到圖像
-
-
多態(tài)
通俗解釋:同樣的事件在不同對象上產生不同效果,如你去打NBA和科比去打NBA钞楼,雖然都是去打比賽喇闸,但是就是不一樣的結果。
專業(yè)解釋:指允許不同類的對象對同一消息做出響應窿凤。即同一消息可以根據發(fā)送對象的不同而采用多種不同的行為方式仅偎。
eg:
class A ...{ public String show(D obj)...{ return ("A and D"); } public String show(A obj)...{ return ("A and A"); } } class B extends A...{ public String show(B obj)...{ return ("B and B"); } public String show(A obj)...{ return ("B and A"); } } class C extends B...{} class D extends B...{}
main 函數如下:
public void main(String[] args) { A a1 = new A(); A a2 = new B(); B b = new B(); C c = new C(); D d = new D(); System.out.println(a1.show(b)); // ① System.out.println(a1.show(c)); // ② System.out.println(a1.show(d)); // ③ System.out.println(a2.show(b)); // ④ System.out.println(a2.show(c)); // ⑤ System.out.println(a2.show(d)); // ⑥ }
輸出:
① A and A ② A and A ③ A and D ④ B and A ⑤ B and A ⑥ A and D
-
像素/尺寸/px/分辨率/ppi
像素:是指在由一個數字序列表示的圖像中的一個最小單位,稱為像素雳殊。
尺寸:屏幕對角線的長度
px: 像素單位
分辨率:如 1080 * 1920橘沥,就是高是1080px,寬是1920px夯秃,即整個屏幕可以用1080 × 1920 個格子劃分座咆,每個格子代表一個像素
ppi:屏幕像素密度(PPI)就是每英寸屏幕所擁有的像素數
注:這個英寸是指對角線的長度
-
如何計算sin(1), e^x, log(x), sqrt(x)/快速/精確
-
sqrt(x)
0x5f3759df 取的真迷
float InvSqrt (float x) { float xhalf = 0.5f*x; int i = *(int*)&x; i = 0x5f3759df - (i >> 1); // 計算第一個近似根 x = *(float*)&i; x = x*(1.5f - xhalf*x*x); // 牛頓迭代法 return x; }
sin()
-
-
全加器/半加器/超前進位加法器
逐位進位加法器
簡介:在每一位的計算時,都在等待前一位的進位仓洼。
超前進位加法器:是對普通的全加器進行改良而設計成的并行加法器箕戳,主要是針對普通全加器串聯(lián)時互相進位產生的延遲進行了改良某残。
主要思想:1、由輸入的A陵吸,B算出每一位的G玻墅,P;2壮虫、由各位的G狈癞,P算出每一位的GN:0妄均,PN:0稽坤;3滨攻、由每一位的GN:0,PN:0與CIN算出每一位的COUT谆构,S裸扶。
-
編譯原理/代碼運行原理
編譯:把高級語言變成計算機能夠識別的機器語言
代碼運行原理:編譯 -> 執(zhí)行
-
mysql/mongodb/sql/NoSql
通俗解釋:各種數據庫
-
專業(yè)解釋:組織、存儲搬素、管理數據的倉庫
-
mysql
一種關系型數據庫
組成:
- 數據以表格的形式出現
- 表格中每行為各種數據
- 表格中每列為同一類型(名稱)的數據
- 許多的行和列組成一張表單
- 若干的表單組成database
-
mongodb
文檔型數據庫呵晨,主要應用于web應用
優(yōu)點:數據結構要求不嚴格魏保,表結構可變,擴展性高摸屠,不需要預先定義數據表結構
缺點:查詢性能不高谓罗,而且缺乏統(tǒng)一的查詢語法
-
sql
SQL 是用于訪問和處理數據庫的標準的計算機語言。
-
nosql
泛指非關系型數據庫季二,用于超大規(guī)模數據的存儲檩咱。
優(yōu)點:
- 沒有復雜的關系
- 擴展性高
- 成本低
- 靈活
- 采用分布式計算
-
-
cookie/session
-
通俗解釋
cookie: 存儲在本地的用來辨認用戶以及其狀態(tài)等信息的數據
session: 存儲在服務器上的用來辨認用戶、其狀態(tài)以及回話等信息的數據
-
專業(yè)解釋
cookie: 網站為了認證用戶存儲在本地的數據胯舷,存儲在客戶端刻蚯,但是不是很安全,別人可以分析存放在本地的 cookie 并進行 cookie 欺騙桑嘶。
session: 存儲客戶的信息并存儲在服務器上的炊汹,但是當訪問增多,會比較占用你服務器的性能逃顶。
-
-
git/svn/版本控制
-
專業(yè)解釋
git: 分布式版本控制系統(tǒng)讨便,沒有中心服務器,不同開發(fā)者都能管理項目代碼以政。
SVN: 集中式版本管理系統(tǒng)霸褒,即有一個中心倉庫,里面保存了項目代碼的不同版本盈蛮,開發(fā)人員在本地在只有這個倉庫中的一個版本废菱,如果想要其他版本,必須得到中心服務器授權才能獲得抖誉。
版本控制: 記錄倉庫各個組別的改動昙啄,并時不同人編輯的同一組別的內容得到更新
-
-
ssh (Secure Shell)
通俗解釋:一種安全的網絡協(xié)議
專業(yè)解釋:建立在應用層基礎上的安全協(xié)議,專為遠程登錄會話和其他網絡服務提供安全性的協(xié)議寸五,所有傳輸的數據都會被加密。
兩種級別的安全驗證:
-
基于口令的安全驗證
只要知道賬號和口令就可以登錄到遠程主機耿币,所以可能會有其他服務器冒充真正的服務器(中間人攻擊)
-
基于密鑰的安全驗證
你必須創(chuàng)建一對密匙梳杏,公鑰放在服務器上,這樣其他服務器就無法冒充真正的服務器淹接,但是登錄時間較慢十性。
過程:
- 客戶端向服務器發(fā)出請求,請求安全驗證塑悼。
- 服務器收到請求之后劲适,把服務器存儲的公鑰和你發(fā)送過來的公鑰進行比較。如果兩個密匙一致厢蒜,服務器就用公用密匙加密“質詢”并把它發(fā)送給客戶端軟件霞势。
- 客戶端軟件收到“質詢”之后用私匙解密再把它發(fā)送給服務器烹植。
-
-
php是世界上最好的語言/pythonic
PHP是世界上最好的語言:
由來:有些人認為PHP就是最簡單最完善最好的語言,并且熱衷于在各種論壇等地方與其他人進行爭辯愕贡。所謂一粉頂十黑草雕,“PHP是最好的語言”的梗即由此而來,其實它并不是諷刺PHP語言本身固以,而是在諷刺并不深入理解PHP的開發(fā)者墩虹。
PHP的優(yōu)點:
- 性能好
- 語法簡單,上手簡單
- 支持完整憨琳,有很多成熟的框架诫钓、社區(qū)等
PHP的缺點:
- 對多線程支持不太好
- 語法不嚴謹
- 每個PHP頁面被解釋執(zhí)行后,所有的相關資源都會被回收篙螟,無法在語言層面上讓對象常駐內存
pythonic:
-
通俗解釋
Python 的 區(qū)別于其他語言的優(yōu)雅寫法
-
專業(yè)解釋
? 如何寫出 pythonic : 閱讀 PEP 8菌湃,并遵守規(guī)范
? eg:
0 < a < 10 a, b = b, a
-
ORM
通俗解釋:數據庫的操作接口
專業(yè)解釋:Object-Relational Mapping(對象關系映射)
作用:在關系型數據庫和業(yè)務實體對象之間作一個映射,具體操作時只需簡單的操作對象的屬性和方法闲擦。
優(yōu)點:
- 操作簡單慢味,只用調接口,不用考慮SQL語句
- 固化數據結構變得簡單墅冷,不需要把每條數據轉化為一條一條的SQL語句
缺點:
- 性能差
- 靈活性不夠
4. golang 新手入門配置學習
bbs鏈接:https://newbbs.bingyan.net/topics/1111
Ubuntu下 golang 安裝與配置
-
安裝最新版本 golang 方法 (推薦)
解壓安裝包
tar -C /usr/local -xzf <安裝包>
(其中/usr/local
為 go 的解壓目錄即GOROOT纯路,也可以安裝到自己想要的位置,后面配置一下就行了)-
環(huán)境配置
-
在 ~/.bashrc 最后一行加上
export PATH=$PATH:/usr/local/go/bin
注:
:
為分隔符寞忿,即配置多個路徑時使用驰唬;/usr/local/go/bin
為 go 安裝位置下的 bin 目錄功效:用于 在bash 下使用命令
go
等命令(可看 bin 目錄下有哪些可執(zhí)行文件) -
之后 運行
source .bashrc
更新 PATH注:如果終端為 zsh, fish 命令
source
可能失效,這時需要輸入bash
進入 bash 執(zhí)行腔彰,但是當返回zsh 或者 fish等其他終端時可能還是無法使用 命令go
叫编,這是因為你的 zsh 或者 fish 有自己單獨的config 文件,你需要在那個文件最后一行加上相應代碼(由于不同終端配置語法不同霹抛,此處不做擴展)/etc/profile搓逾,/root/.bashrc
是系統(tǒng)全局環(huán)境變量設定
~/.profile,~/.bashrc
用戶家目錄下的私有環(huán)境變量設定?
當登入系統(tǒng)時候獲得一個shell進程時杯拐,其讀取環(huán)境設定檔有三步
- 首先讀入的是全局環(huán)境變量設定檔
/etc/profile
霞篡,然后根據其內容讀取額外的設定的文檔 - 然后根據不同使用者帳號,去其家目錄讀取
~/.profile
- 然后在根據用戶帳號讀取
~/.bashrc
?
~/.profile
與~/.bashrc
的區(qū)別
~/.profile
可以設定本用戶專有的路徑端逼,環(huán)境變量朗兵,等,它只能登入的時候執(zhí)行一次
~/.bashrc
也是某用戶專有設定文檔顶滩,可以設定路徑余掖,命令別名,每次shell script的執(zhí)行都會使用它一次 - 首先讀入的是全局環(huán)境變量設定檔
-
配置 GOPATH (可選)
- 在
~/.bashrc
或者~/.profile
最后一行加上export GOPATH=$HOME<你的工作目錄>
- 進入bash 執(zhí)行
source ~/.bashrc
或者~/.profile
礁鲁,如果此時沒有生效盐欺,可嘗試重啟或者注銷重新登錄
- 在
-
-
直接一鍵安裝赁豆,但是版本不一定是最新的
安裝命令:
sudo apt install golang-go
也可以在安裝之前通過
apt-cache search golang-go
搜索可見 golang-go 版本等- PATH 和 GOPATH 等見上文環(huán)境配置
-
golang 項目目錄結構
一個Go項目在GOPATH下,會有如下三個目錄:
- src存放源代碼 ( .go )
- pkg編譯后生成的文件
- bin編譯后生成的可執(zhí)行文件 ( .a )
?
<project> |--<bin> |--<pkg> |--<src> |--<a> |--<a1> |--al.go |--<a2> |--a2.go |--<b> |--b1.go |--b2.go
-
PATH GOPATH
等簡介-
GOROOT
GO 語言安裝的路徑找田,如我的 Ubuntu 下的是
/usr/local/go
歌憨,類似于JAVA中的JAVA_HOME -
GOPATH
GOPATH 表示代碼包或項目所在的地址,可以設置多個墩衙,不同地址之間使用
:
分隔假設:
GOPATH=~/project1:~/project2务嫡,GOROOT=/usr/local/go
,在代碼中引用了包:github.com/bitly/nsq/util
GO程序在編譯時會按先后次序到以下目錄中尋找源碼:
~/project1/github.com/bitly/nsq/util
~/project2/github.com/bitly/nsq/util
/usr/local/go/github.com/bitly/nsq/util
-
PATH
可執(zhí)行程序的路徑漆改,在命令行執(zhí)行命令時心铃,系統(tǒng)默認會在PATH中指定路徑里尋找。比如linux下我們用最常用的
cd
命令挫剑,執(zhí)行時我們并未指定cd
命令的路徑去扣,也沒有切換到cd
所在的目錄下去執(zhí)行該命令。這就是因為cd
命令的可執(zhí)行文件所在的目錄在PATH中錄入了樊破。go
安裝后愉棱,在GOROOT/bin目錄,如 Ubuntu 的/usr/local/go/bin
目錄下會有 go 哲戚、godoc奔滑、gofmt 三個可執(zhí)行命令。為了方便在編譯go項目時方便的使用go build顺少、go install
等命令朋其,需要將GOROOT/bin目錄加入到系統(tǒng)的PATH路徑下。 -
GOARCH
CPU 架構脆炎,如: amd64, 386
-
GOOS
操作系統(tǒng)梅猿,如:linux
-
GOBIN
工作目錄下的bin文件夾
-
GOEXE
生成的可執(zhí)行文件后綴
-
GOHOSTARCH
想要交叉編譯的CPU架構
-
GOHOSTOS
想要交叉編譯的操作系統(tǒng)
-
-
go 基本命令介紹
Go命令一般格式:
go command [arg]
其中,command是操作命令秒裕,arg是該命令的參數
常用命令介紹:
-
go get
用于動態(tài)獲取遠程代碼包袱蚓,如果是從GitHub上獲取,則需要現安裝git几蜻,如果是從Google Code上獲取癞松,則需要安裝hg。go get 獲取的遠程代碼包將被下載到
GOPATH
目錄下的src
文件夾中eg: go get -u github.com/nsf/gocode
-
go install
- 編譯導入的包文件入蛆,所有導入的包文件編譯完才會編譯主程序
- 將編譯后生成的可執(zhí)行文件放到bin目錄下(GOPATH/bin),編譯后的包文件放到pkg目錄下(GOPATH/pkg)
-
go run
用于編譯并直接運行程序硕勿,它會生成一個臨時文件(但不是一個標準的可執(zhí)行文件)哨毁,直接在命令行打印輸出程序執(zhí)行結果,方便用戶調試源武。
eg: go run main.go
-
go build
用于測試編譯包扼褪,可檢查是否存在編譯錯誤想幻,如果被編譯的是main包,會生成可執(zhí)行文件话浇。
#編譯 go build main.go #運行 ./main
-
go fmt
用于格式化源碼脏毯,有的IDE保存源碼時自動執(zhí)行該命令,比如subl幔崖,也可手動執(zhí)行它食店。
eg: go fmt main.go
-
go test
用于運行測試文件,該命令會自動讀取源碼目錄下的名為:*_test.go的文件赏寇,生成并運行測試用的可執(zhí)行文件吉嫩,測試成功會顯示“PASS”、“OK”等信息嗅定。
-
其他
- go clean:用來移除當前源碼包里面編譯生成的文件
- go env: 查看當前用戶的go環(huán)境變量
- go fix: 用來修復以前老版本的代碼到新版本
- go list: 列出當前全部安裝的packge
- go version: 查看當前go版本
hello world:
main.go 代碼:
package main import ( "fmt" ) func main() { fmt.Println("Hello World!") }
進入該文件所在目錄自娩,嘗試編譯運行:
go run main.go
終端會輸出 Hello World! ,則運行成功
-
-
sublime 配置 golang 環(huán)境
-
安裝 GoSublime
運行:Ctrl + B
個人 GoSublime 配置:
{ "env": { "PATH": "$PATH", // "GOPATH": "$HOME/Projects/Go/test", // "GOPATH": "$GOPATH:$GS_GOPATH", "GOPATH": "$GS_GOPATH" }, "comp_lint_enabled":true, "lint_enabled": true, "autocomplete_builtins": true, "fmt_cmd" :[ "goimports"], "snippets": [ { "match": {"global": true, "pkgname": "."}, "snippets": [ { "text":"type", "title":"type struct {}", "value":"type ${1:name} struct {\n\t$0\n}" },{ "text":"type", "title":"type interface {}", "value":"type ${1:name} interface {\n\t$0\n}" },{ "text":"var", "title":"var struct {}", "value":"var ${1:name} struct {\n\t$0\n}" },{ "text":"map", "title":"map[...]...", "value":"map[${1:string}]${2:interface{}}" },{ "text":"interface", "title":"interface{}", "value":"interface{}" },{ "text":"if", "title":"if err != nil {...}", "value":"if ${1:err} ${2:!=} ${3:nil} {\n\t$0\n}" },{ "text":"if", "title":"if ret,ok := func(); ok {...}", "value":"if ${1:ret,} ${2:ok} ${3::=} ${4:func()}; ${5:!ok} {\n\t$0\n}" },{ "text":"break", "title":"break", "value":"break" },{ "text":"continue", "title":"continue", "value":"continue" },{ "text":"defer", "title":"defer func()", "value":"defer ${0:func()}" },{ "text":"for", "title":"for k,v := range func() {...}", "value":"for ${1:k,}${2:v} := range ${3:func()} {\n\t$0\n}" },{ "text":"switch", "title":"switch ... {...}", "value":"switch ${1:name} {\ncase ${2:v}:\n\t$3\ndefault:\n\t$0\n}" } ] } ], }
注:
GS_GOPATH
is a pseudo-environment-variable. It's changed to match a possible GOPATH based on:- the current working directory, e.g.
~/go/src/pkg
then$GS_GOPATH
will be~/go/
- or the path the current
.go
file (or last activated.go
file if the current file is not.go
) e.g. if your file path is/tmp/go/src/hello/main.go
then it will be/tmp/go
簡單說就是 GS_GOPATH 是用來自動根據當前目錄設置 GOPATH 的
- the current working directory, e.g.
-
安裝 gocode
go get -u github.com/nsf/gocode go install github.com/nsf/gocode
安裝完成后渠退,我們可以在 $GOPATH/bin 目錄下忙迁,發(fā)現多出了個 gocode 文件
-
-
常用 tools
-
gocode 提供代碼補全
go get -u github.com/nsf/gocode
-
godef 代碼跳轉
go get -v code.google.com/p/rog-go/exp/cmd/godef go install -v code.google.com/p/rog-go/exp/cmd/godef
gofmt 自動代碼整理
-
golint 代碼語法檢查
go get github.com/golang/lint go install github.com/golang/lint
-
goimports 自動整理imports
go get golang.org/x/tools/cmd/goimports
-
-
安裝
echo
安裝:
go get -u github.com/labstack/echo/...
注:如果無法翻墻可能會報錯
package golang.org/x/crypto/acme/autocert: unrecognized import path "golang.org/x/crypto/acme/autocert"
解決方案:
分析錯誤,我們缺少crypto組件碎乃,需要下載姊扔,使用
go get golang.org/x/crypto/acme/autocert
來下載,但是 crypto 官方地址在外網好在 golang.org 在 github.com 上有備份倉庫荠锭,所以缺少的組件可以在 github 上下載
eg: 安裝 crypto 組件
github 地址: https://github.com/golang/crypto
過程:
mkdir -p /usr/local/go/src/golang.org/x/ git clone git@github.com:golang/crypto.git mv crypto /usr/local/go/golang.org/x/
**測試示例: **
main.go
package main import ( "net/http" "github.com/labstack/echo" ) func main() { e := echo.New() e.GET("/", func(c echo.Context) error { return c.String(http.StatusOK, "Hello, World!") }) e.Logger.Fatal(e.Start(":1323")) }
啟動:
go run server.go
Browse to http://localhost:1323 and you should see Hello, World! on the page.
更多echo 請參照學習官方教程:https://echo.labstack.com/guide