BlockChain技術系列(三)- fabric協議介紹
fabric的點對點(peer-to-peer)通訊是建立在允許雙向的基於流的訊息gRPC上的。它使用Protocol Buffers來序列化peer之間傳輸的資料結構。Protocol buffers 是語言無關,平臺無關並具有可擴充套件機制來序列化結構化的資料的技術。資料結構,訊息和服務是使用 proto3 language註釋來描述的。
3.1 訊息
訊息在節點之間通過Message
proto 結構封裝來傳遞的,可以分為 4 種類型:發現(Discovery), 交易(Transaction), 同步(Synchronization)和共識(Consensus)。每種型別在payload
message Message { enum Type { UNDEFINED = 0; DISC_HELLO = 1; DISC_DISCONNECT = 2; DISC_GET_PEERS = 3; DISC_PEERS = 4; DISC_NEWMSG = 5; CHAIN_STATUS = 6; CHAIN_TRANSACTION = 7; CHAIN_GET_TRANSACTIONS = 8; CHAIN_QUERY = 9; SYNC_GET_BLOCKS = 11; SYNC_BLOCKS = 12; SYNC_BLOCK_ADDED = 13; SYNC_STATE_GET_SNAPSHOT = 14; SYNC_STATE_SNAPSHOT = 15; SYNC_STATE_GET_DELTAS = 16; SYNC_STATE_DELTAS = 17; RESPONSE = 20; CONSENSUS = 21; } Type type = 1; bytes payload = 2; google.protobuf.Timestamp timestamp = 3; }
payload
是由不同的訊息型別所包含的不同的像Transaction
或Response
這樣的物件的不透明的位元組陣列。例如:type
為CHAIN_TRANSACTION
那麼payload
就是一個Transaction
物件。
3.1.1 發現訊息
在啟動時,如果CORE_PEER_DISCOVERY_ROOTNODE
被指定,那麼 peer 就會執行發現協議。CORE_PEER_DISCOVERY_ROOTNODE
是網路(任意peer)中扮演用來發現所有 peer 的起點角色的另一個 peer 的 IP 地址。協議序列以payload
是一個包含:
message HelloMessage { PeerEndpoint peerEndpoint = 1; uint64 blockNumber = 2; } message PeerEndpoint { PeerID ID = 1; string address = 2; enum Type { UNDEFINED = 0; VALIDATOR = 1; NON_VALIDATOR = 2; } Type type = 3; bytes pkiID = 4; } message PeerID { string name = 1; }
這樣的端點的HelloMessage
物件的DISC_HELLO
訊息開始的。
域的定義:
PeerID
是在啟動時或配置檔案中定義的 peer 的任意名字PeerEndpoint
描述了端點和它是驗證還是非驗證 peerpkiID
是 peer 的加密IDaddress
以ip:port
這樣的格式表示的 peer 的主機名或IP和埠blockNumber
是 peer 的區塊鏈的當前的高度
如果收到的DISC_HELLO
訊息的塊的高度比當前 peer 的塊的高度高,那麼它馬上初始化同步協議來追上當前的網路。
DISC_HELLO
之後,peer 會週期性的傳送DISC_GET_PEERS
來發現任意想要加入網路的 peer。收到DISC_GET_PEERS
後,peer 會發送payload
包含PeerEndpoint
的陣列的DISC_PEERS
作為響應。這是不會使用其它的發現訊息型別。
3.1.2 交易訊息
有三種不同的交易型別:部署(Deploy),呼叫(Invoke)和查詢(Query)。部署交易向鏈上安裝指定的鏈碼,呼叫和查詢交易會呼叫部署號的鏈碼。另一種需要考慮的型別是建立(Create)交易,其中部署好的鏈碼是可以在鏈上例項化並定址的。這種型別在寫這份文件時還沒有被實現。
3.1.2.1 交易的資料結構
CHAIN_TRANSACTION
和CHAIN_QUERY
型別的訊息會在payload
帶有Transaction
物件:
message Transaction {
enum Type {
UNDEFINED = 0;
CHAINCODE_DEPLOY = 1;
CHAINCODE_INVOKE = 2;
CHAINCODE_QUERY = 3;
CHAINCODE_TERMINATE = 4;
}
Type type = 1;
string uuid = 5;
bytes chaincodeID = 2;
bytes payloadHash = 3;
ConfidentialityLevel confidentialityLevel = 7;
bytes nonce = 8;
bytes cert = 9;
bytes signature = 10;
bytes metadata = 4;
google.protobuf.Timestamp timestamp = 6;
}
message TransactionPayload {
bytes payload = 1;
}
enum ConfidentialityLevel {
PUBLIC = 0;
CONFIDENTIAL = 1;
}
域的定義:
type
- 交易的型別, 為1時表示:UNDEFINED
- 為未來的使用所保留.CHAINCODE_DEPLOY
- 代表部署新的鏈碼.CHAINCODE_INVOKE
- 代表一個鏈碼函式被執行並修改了世界狀態CHAINCODE_QUERY
- 代表一個鏈碼函式被執行並可能只讀取了世界狀態CHAINCODE_TERMINATE
- 標記的鏈碼不可用,所以鏈碼中的函式將不能被呼叫
chaincodeID
- 鏈碼原始碼,路徑,建構函式和引數雜湊所得到的IDpayloadHash
-TransactionPayload.payload
所定義的雜湊位元組.metadata
- 應用可能使用的,由自己定義的任意交易相關的元資料uuid
- 交易的唯一IDtimestamp
- peer 收到交易時的時間戳confidentialityLevel
- 資料保密的級別。當前有兩個級別。未來可能會有多個級別。nonce
- 為安全而使用cert
- 交易者的證書signature
- 交易者的簽名TransactionPayload.payload
- 交易的payload所定義的位元組。由於payload可以很大,所以交易訊息只包含payload的雜湊
交易安全的詳細資訊可以在第四節找到
3.1.2.2 交易規範
一個交易通常會關聯鏈碼定義及其執行環境(像語言和安全上下文)的鏈碼規範。現在,有一個使用Go語言來編寫鏈碼的實現。將來可能會新增新的語言。
message ChaincodeSpec {
enum Type {
UNDEFINED = 0;
GOLANG = 1;
NODE = 2;
}
Type type = 1;
ChaincodeID chaincodeID = 2;
ChaincodeInput ctorMsg = 3;
int32 timeout = 4;
string secureContext = 5;
ConfidentialityLevel confidentialityLevel = 6;
bytes metadata = 7;
}
message ChaincodeID {
string path = 1;
string name = 2;
}
message ChaincodeInput {
string function = 1;
repeated string args = 2;
}
域的定義:
chaincodeID
- 鏈碼原始碼的路徑和名字ctorMsg
- 呼叫的函式名及引數timeout
- 執行交易所需的時間(以毫秒錶示)confidentialityLevel
- 這個交易的保密級別secureContext
- 交易者的安全上下文metadata
- 應用想要傳遞下去的任何資料
當 peer 收到chaincodeSpec
後以合適的交易訊息包裝它並廣播到網路
3.1.2.3 部署交易
部署交易的型別是CHAINCODE_DEPLOY
,且它的payload包含ChaincodeDeploymentSpec
物件。
message ChaincodeDeploymentSpec {
ChaincodeSpec chaincodeSpec = 1;
google.protobuf.Timestamp effectiveDate = 2;
bytes codePackage = 3;
}
域的定義:
chaincodeSpec
- 參看上面的3.1.2.2節.effectiveDate
- 鏈碼準備好可被呼叫的時間codePackage
- 鏈碼原始碼的gzip
當驗證 peer 部署鏈碼時,它通常會校驗codePackage
的雜湊來保證交易被部署到網路後沒有被篡改。
3.1.2.4 呼叫交易
呼叫交易的型別是CHAINCODE_DEPLOY
,且它的payload包含ChaincodeInvocationSpec
物件。
message ChaincodeInvocationSpec {
ChaincodeSpec chaincodeSpec = 1;
}
3.1.2.5 查詢交易
查詢交易除了訊息型別是CHAINCODE_QUERY
其它和呼叫交易一樣
3.1.3 同步訊息
同步協議以3.1.1節描述的,當 peer 知道它自己的區塊落後於其它 peer 或和它們不一樣後所發起的。peer 廣播SYNC_GET_BLOCKS
,SYNC_STATE_GET_SNAPSHOT
或SYNC_STATE_GET_DELTAS
並分別接收SYNC_BLOCKS
, SYNC_STATE_SNAPSHOT
或SYNC_STATE_DELTAS
。
安裝的共識外掛(如:pbft)決定同步協議是如何被應用的。每個小時是針對具體的狀態來設計的:
SYNC_GET_BLOCKS 是一個SyncBlockRange
物件,包含一個連續區塊的範圍的payload
的請求。
message SyncBlockRange {
uint64 start = 1;
uint64 end = 2;
uint64 end = 3;
}
接收peer使用包含 SyncBlocks
物件的payload
的SYNC_BLOCKS
資訊來響應
message SyncBlocks {
SyncBlockRange range = 1;
repeated Block blocks = 2;
}
start
和end
標識包含的區塊的開始和結束,返回區塊的順序由start
和end
的值定義。如:當start
=3,end
=5時區塊的順序將會是3,4,5。當start
=5,end
=3時區塊的順序將會是5,4,3。
SYNC_STATE_GET_SNAPSHOT 請求當前世界狀態的快照。 payload
是一個SyncStateSnapshotRequest
物件
message SyncStateSnapshotRequest {
uint64 correlationId = 1;
}
correlationId
是請求 peer 用來追蹤響應訊息的。接受 peer 回覆payload
為SyncStateSnapshot
例項的SYNC_STATE_SNAPSHOT
資訊
message SyncStateSnapshot {
bytes delta = 1;
uint64 sequence = 2;
uint64 blockNumber = 3;
SyncStateSnapshotRequest request = 4;
}
這條訊息包含快照或以0開始的快照流序列中的一塊。終止訊息是len(delta) == 0的塊
SYNC_STATE_GET_DELTAS 請求連續區塊的狀態變化。預設情況下總賬維護500筆交易變化。 delta(j)是block(i)和block(j)之間的狀態轉變,其中i=j-1。 payload
包含SyncStateDeltasRequest
例項
message SyncStateDeltasRequest {
SyncBlockRange range = 1;
}
接收 peer 使用包含 SyncStateDeltas
例項的payload
的SYNC_STATE_DELTAS
資訊來響應
message SyncStateDeltas {
SyncBlockRange range = 1;
repeated bytes deltas = 2;
}
delta可能以順序(從i到j)或倒序(從j到i)來表示狀態轉變
3.1.4 共識訊息
共識處理交易,一個CONSENSUS
訊息是由共識框架接收到CHAIN_TRANSACTION
訊息時在內部初始化的。框架把CHAIN_TRANSACTION
轉換為 CONSENSUS
然後以相同的payload
廣播到驗證 peer。共識外掛接收這條訊息並根據內部演算法來處理。外掛可能建立自定義的子型別來管理共識有窮狀態機。3.4節會介紹詳細資訊。
3.2 總賬
總賬由兩個主要的部分組成,一個是區塊鏈,一個是世界狀態。區塊鏈是在總賬中的一系列連線好的用來記錄交易的區塊。世界狀態是一個用來儲存交易執行狀態的鍵-值(key-value)資料庫
3.2.1 區塊鏈
3.2.1.1 區塊
區塊鏈是由一個區塊連結串列定義的,每個區塊包含它在鏈中前一個區塊的雜湊。區塊包含的另外兩個重要資訊是它包含區塊執行所有交易後的交易列表和世界狀態的雜湊
message Block {
version = 1;
google.protobuf.Timestamp timestamp = 2;
bytes transactionsHash = 3;
bytes stateHash = 4;
bytes previousBlockHash = 5;
bytes consensusMetadata = 6;
NonHashData nonHashData = 7;
}
message BlockTransactions {
repeated Transaction transactions = 1;
}
域的定義:
version
- 用來追蹤協議變化的版本號timestamp
- 由區塊提議者填充的時間戳transactionsHash
- 區塊中交易的merkle root hashstateHash
- 世界狀態的merkle root hashpreviousBlockHash
- 前一個區塊的hashconsensusMetadata
- 共識可能會引入的一些可選的元資料nonHashData
-NonHashData
訊息會在計算區塊的雜湊前設定為nil,但是在資料庫中儲存為區塊的一部分BlockTransactions.transactions
- 交易訊息的陣列,由於交易的大小,它們不會被直接包含在區塊中
3.2.1.2 區塊雜湊
-
previousBlockHash
雜湊是通過下面演算法計算的-
使用protocol buffer庫把區塊訊息序列化為位元組碼
-
使用FIPS 202描述的SHA3 SHAKE256演算法來對序列化後的區塊訊息計算大小為512位的雜湊值
-
-
transactionHash
是交易merkle樹的根。定義merkle tree實現是一個代辦 -
stateHash
在3.2.2.1節中定義.
3.2.1.3 非雜湊資料(NonHashData)
NonHashData訊息是用來儲存不需要所有 peer 都具有相同值的塊元資料。他們是建議值。
message NonHashData {
google.protobuf.Timestamp localLedgerCommitTimestamp = 1;
repeated TransactionResult transactionResults = 2;
}
message TransactionResult {
string uuid = 1;
bytes result = 2;
uint32 errorCode = 3;
string error = 4;
}
-
localLedgerCommitTimestamp
- 標識區塊提交到本地總賬的時間戳 -
TransactionResult
- 交易結果的陣列 -
TransactionResult.uuid
- 交易的ID -
TransactionResult.result
- 交易的返回值 -
TransactionResult.errorCode
- 可以用來記錄關聯交易的錯誤資訊的程式碼 -
TransactionResult.error
- 用來記錄關聯交易的錯誤資訊的字串
3.2.1.4 交易執行
一個交易定義了它們部署或執行的鏈碼。區塊中的所有交易都可以在記錄到總賬中的區塊之前執行。當鏈碼執行時,他們可能會改變世界狀態。之後世界狀態的雜湊會被記錄在區塊中。
3.2.2 世界狀態
peer 的世界狀態涉及到所有被部署的鏈碼的狀態集合。進一步說,鏈碼的狀態由鍵值對集合來表示。所以,邏輯上說,peer 的世界狀態也是鍵值對的集合,其中鍵有元組{chaincodeID, ckey}
組成。這裡我們使用術語key
來標識世界狀態的鍵,如:元組{chaincodeID, ckey}
,而且我們使用cKey
來標識鏈碼中的唯一鍵。
為了下面描述的目的,假定chaincodeID
是有效的utf8字串,且ckey
和value
是一個或多個任意的位元組的序列
3.2.2.1 世界狀態的雜湊
當網路活動時,很多像交易提交和同步 peer 這樣的場合可能需要計算 peer 觀察到的世界狀態的加密-雜湊。例如,共識協議可能需要保證網路中最小數量的 peer 觀察到同樣的世界狀態。
應為計算世界狀態的加密-雜湊是一個非常昂貴的操作,組織世界狀態來使得當它改變時能高效效的計算加密-雜湊是非常可取的。將來,可以根據不同的負載條件來設計不同的組織形式。
由於fabric是被期望在不同的負載條件下都能正常工作,所以需要一個可拔插的機制來支援世界狀態的組織。
3.2.2.1.1 Bucket-tree
Bucket-tree 是世界狀態的組織方式的實現。為了下面描述的目的,世界狀態的鍵被表示成兩個元件(chaincodeID
and ckey
) 的通過nil位元組的級聯,如:key
= chaincodeID
+nil
+cKey
。
這個方法的模型是一個merkle-tree在hash table桶的頂部來計算世界狀態的加密-雜湊
這個方法的核心是世界狀態的key-values被假定儲存在由預先決定的桶的數量(numBuckets
)所組成的雜湊表中。一個雜湊函式(hashFunction
) 被用來確定包含給定鍵的桶數量。注意hashFunction
不代表SHA3這樣的加密-雜湊方法,而是決定給定的鍵的桶的數量的正規的程式語言雜湊函式。
為了對 merkle-tree建模,有序桶扮演了樹上的葉子節點-編號最低的桶是樹中的最左邊的葉子節點。為了構造樹的最後第二層,葉子節點的預定義數量 (maxGroupingAtEachLevel
),從左邊開始把每個這樣的分組組合在一起,一個節點被當作組中所有葉子節點的共同父節點來插入到最後第二層中。注意最後的父節點的數量可能會少於maxGroupingAtEachLevel
這個構造方式繼續使用在更高的層級上直到樹的根節點被構造。
下面這個表展示的在{numBuckets=10009 and maxGroupingAtEachLevel=10}
的配置下會得到的樹在不同層級上的節點數。
Level | Number of nodes |
---|---|
0 | 1 |
1 | 2 |
2 | 11 |
3 | 101 |
4 | 1001 |
5 | 10009 |
為了計算世界狀態的加密-雜湊,需要計算每個桶的加密-雜湊,並假設它們是merkle-tree的葉子節點的加密-雜湊。為了計算桶的加密-雜湊,儲存在桶中的鍵值對首先被序列化為位元組碼並在其上應用加密-雜湊函式。為了序列化桶的鍵值對,所有具有公共chaincodeID字首的鍵值對分別序列化並以chaincodeID的升序的方式追加在一起。為了序列化一個chaincodeID的鍵值對,會涉及到下面的資訊:
- chaincodeID的長度(chaincodeID的位元組數)
- chaincodeID的utf8位元組碼
- chaincodeID的鍵值對數量
- 對於每個鍵值對(以ckey排序)
- ckey的長度
- ckey的位元組碼
- 值的長度
- 值的位元組碼
對於上面列表的所有數值型別項(如:chaincodeID的長度),使用protobuf的變體編碼方式。上面這種編碼方式的目的是為了桶中的鍵值對的位元組表示方式不會被任意其他鍵值對的組合所產生,並減少了序列化位元組碼的總體大小。
例如:考慮具有chaincodeID1_key1:value1, chaincodeID1_key2:value2, 和 chaincodeID2_key1:value1
這樣名字的鍵值對的桶。序列化後的桶看上去會像:12 + chaincodeID1 + 2 + 4 + key1 + 6 + value1 + 4 + key2 + 6 + value2 + 12 + chaincodeID2 + 1 + 4 + key1 + 6 + value1
如果桶中沒有鍵值對,那麼加密-雜湊為nil
。
中間節點和根節點的加密-雜湊與標準merkle-tree的計算方法一樣,即:應用加密-雜湊函式到所有子節點的加密-雜湊從左到右級聯後得到的位元組碼。進一步說,如果一個子節點的加密-雜湊為nil
,那麼這個子節點的加密-雜湊在級聯子節點的加密-雜湊是就被省略。如果它只有一個子節點,那麼它的加密-雜湊就是子節點的加密-雜湊。最後,根節點的加密-雜湊就是世界狀態的加密-雜湊。
上面這種方法在狀態中少數鍵值對改變時計算加密-雜湊是有效能優勢的。主要的優勢包括:
- 那些沒有變化的桶的計算會被跳過
- merkle-tree的寬度和深度可以通過配置
numBuckets
和相關推薦
BlockChain技術系列(三)- fabric協議介紹
fabric的點對點(peer-to-peer)通訊是建立在允許雙向的基於流的訊息gRPC上的。它使用Protocol Buffers來序列化peer之間傳輸的資料結構。Protocol buffers 是語言無關,平臺無關並具有可擴充套件機制來序列化結構化的資料的技術。資料結構,訊息和服務是
BlockChain技術系列(四)- fabric安全介紹
這一節將討論下面的圖所展示的設定描述。特別的,系統是由下面這些實體構成的:成員管理基礎架構,如從一個實體集合中區分出不同使用者身份的職責(使用系統中任意形式的標識,如:信用卡,身份證),為這個使用者註冊開戶,並生成必要的證書以便通過fabric成功的建立交易,部署或呼叫鏈碼。
BlockChain技術系列(二)- fabric架構介紹
fabric是由下面這個小節所描述的核心元件所組成的。 2.1 架構 這個架構參考關注在三個類別中:會員(Membership),區塊鏈(Blockchan)和鏈碼(chaincode)。這些類別是邏輯結構,而不是物理上的把不同的元件分割到獨立的程序,地址空間,(虛擬)機器中。
BlockChain技術系列(一)- fabric介紹
1. 介紹 這份文件規範了適用於工業界的區塊鏈的概念,架構和協議。 1.1 什麼是 fabric? fabric 是在系統中數字事件,交易呼叫,不同參與者共享的總賬。總賬只能通過共識的參與者來更新,而且一旦被記錄,資訊永遠不能被修改。每一個記錄的事件都可以根據參與者的協議進行
dubbo系列三、架構介紹及調用過程解析
使用 wid mes info 註冊中心 response sources zh-cn 組裝 一、整體設計 圖例說明: 圖中左邊淡藍背景的為服務消費方使用的接口,右邊淡綠色背景的為服務提供方使用的接口,位於中軸線上的為雙方都用到的接口。 圖中從下至上分為十層,
BlockChain技術系列(七)- 應用程式設計介面
一個遵循MVC-B架構的應用– Model, View, Control, BlockChain. VIEW LOGIC – 與控制邏輯整合的移動或WEB 使用者介面。 CONTROL LOGIC – 協調使用者介面、
BlockChain技術系列(六)- 應用程式設計介面
fabric的主要介面是REST API。 REST API允許應用註冊使用者,查詢區塊鏈,併發布交易。 CLI為了開發,同樣提供有效API的子集。CLI允許開發人員能夠快速測試鏈碼或查詢交易狀態。 應用程式通過REST API與非驗證的 peer 節點,這將需要某種形式的認證,以確保實
BlockChain技術系列(五)- 拜占庭共識
obcpbft包是PBFT共識協議[1]的實現,其中提供了驗證器之間的共識,雖然驗證器的閾作為Byzantine,即,惡意的或不可預測的方式失敗。在預設的配置中,PBFT容忍t<n/3的拜占庭驗證器。 處理提供PBFT共識協議的參考實現,obcpbft 外掛還包含了新穎的
Hadoop學習系列(2.Hadoop框架介紹與搜索技術體系介紹)
消息 監控系統 mapreduce spa 文件系統 sql 平時 偽分布式 自己 第一天2.Hadoop框架介紹與搜索技術體系介紹1.大數據典型特性與分布式開發難點2.Hadoop框架介紹與搜索技術體系介紹3.Hadoop版本與特性介紹4.Hadoop核心模塊之HDFS分
【OCR技術系列之三】大批量生成文字訓練集
9.png false per store else value 隨機 %d alt 放假了,終於可以繼續可以靜下心寫一寫OCR方面的東西。上次談到文字的切割,今天打算總結一下我們怎麽得到用於訓練的文字數據集。如果是想訓練一個手寫體識別的模型,用一些前人收集好的手寫文字集就
區塊鏈技術系列(3)- Fabric基礎架構原理
多看 技術分享 發的 size 開源項目 初始 排序。 創建 生成 前言 對於區塊鏈方面多技術,我還是建議大家多看英文文檔,多利用Google來搜索技術文章。 怎麽搭建自己專屬V-P-N來訪問Google,請看我之前發的文章: 新人如何快速搭建自己的個人網站以及自己專屬
ROS系列三:ROS檔案系統介紹
轉自:http://wiki.ros.org/cn/ROS/Tutorials/NavigatingTheFilesystem 目錄 預備工作 快速瞭解檔案系統概念 檔案系統工具 回顧 預備工作 本教程中我們將會用到ros-
呼叫鏈系列三:解讀UAVStack中的呼叫鏈技術
本專題前幾篇文章主要從架構層面介紹瞭如何實現分散式呼叫追蹤系統。這篇文章我們不談架構,就其中的一項關鍵技術實現進行深入探討:如何從超文字傳輸協議(HTTP)中獲取request和response的body和header。 在Java中,HTTP協議的請求/響應模型是由Servlet規範+Servlet容
CLANG技術分享系列三:API有效性檢查
CLANG技術分享系列三:API有效性檢查 01 NOV 2016 . CATEGORY: TECH . COMMENTS #CLANG 問題背景 iOS API(Class/Protocol的Interface,Pr
cas系列-cas REST協議(三)
cas的rest協議 cas還支援rest協議方式進行訪問,格式和引數如下: 1. 獲取TGT 請求方式,路徑,http協議及請求引數: POST /cas/v1/tickets HTTP/1.0 username=battags&password=pas
企業路由技術協議介紹
將企業路由技術中出現的英文字母總結了一下並註明瞭解釋 一.RIP:是一種基於距離向量( Distance Vector)演算法的協議,它使用跳數( Hop Count)作為度量值來衡 量到達目的地址的距離。在RIP網路中,預設情況下,裝置到與它直接相連網路的跳數為0,通過
【原創】技術系列之 記憶體管理(三)
作者:CppExplore 地址:http://www.cppblog.com/CppExplore/(2)boost::pool系列。boost的記憶體池最低層是simple_segregated_storage,類似於Loki中的chunk,在其中申請釋放block(boost中把block稱為c
理解PHP依賴注入容器(dependency injection container)系列(三) Symfony服務容器介紹
到現在,我們談論了一些基本概念,前兩篇中的例子對於我們理解依賴注入的實現很有幫助,現在我們將深入 Symfony 2服務容器的實現。 Symfony中的依賴注入容器是一個名叫sfServiceContainer的類來管理的 按照Symfony的設計思路,
keystone系列三:閘道器協議
一 靜態頁面和動態頁面 在瞭解了http協議後,我們知曉,一個web server的本質就是 瀏覽器傳送一個HTTP請求; 伺服器收到請求,生成一個HTML文件; 伺服器把HTML文件作為HTTP響應的Body傳送給瀏覽器; 瀏覽器收到HTTP響應,從HTTP Bod
技術系列之 記憶體管理(三)
(2)boost::pool系列。boost的記憶體池最低層是simple_segregated_storage,類似於Loki中的chunk,在其中申請釋放block(boost中把block稱為chunk,暈死,這裡還是稱其為block)採用了和loki的chunk中同樣