新聞中心
建行到家rpc連接超時
系統(tǒng)沒有及時升級。
創(chuàng)新互聯(lián)公司長期為上1000+客戶提供的網(wǎng)站建設(shè)服務(wù),團(tuán)隊從業(yè)經(jīng)驗(yàn)10年,關(guān)注不同地域、不同群體,并針對不同對象提供差異化的產(chǎn)品和服務(wù);打造開放共贏平臺,與合作伙伴共同營造健康的互聯(lián)網(wǎng)生態(tài)環(huán)境。為水城企業(yè)提供專業(yè)的成都做網(wǎng)站、網(wǎng)站建設(shè),水城網(wǎng)站改版等技術(shù)服務(wù)。擁有十余年豐富建站經(jīng)驗(yàn)和眾多成功案例,為您定制開發(fā)。
建行到家rpc顯示請求超時,主要原因就是系統(tǒng)沒有及時升級,部分組件沒有響應(yīng),必須更新。
rpc(RemoteProcedureCall)是遠(yuǎn)程過程調(diào)用,它是一種通過網(wǎng)絡(luò)從遠(yuǎn)程計算機(jī)程序上請求服務(wù),而不需要了解底層網(wǎng)絡(luò)技術(shù)的協(xié)議。
GRPC負(fù)載均衡
負(fù)載均衡是高可用網(wǎng)絡(luò)基礎(chǔ)架構(gòu)的關(guān)鍵組件,通常用于將工作負(fù)載分布到多個服務(wù)器來提高應(yīng)用的性能和可靠性。
關(guān)于GRPC的負(fù)載均衡,我們選擇NGINX來進(jìn)行反向代理。NGINX在1.13.9版本已經(jīng)開始支持GRPC代理。有了對 GRPC 的支持,NGINX 就可以代理 GRPC TCP 連接,還可以終止、檢查和跟蹤 GRPC 的方法調(diào)用。
在nginx的配置文件中配置GRPC代理即可。
通過grpc 調(diào)用代理端口
觀察NGINX的access.log,可以看到相應(yīng)的代理記錄
首先GRPC是建立在HTTP2.0的基礎(chǔ)上進(jìn)行數(shù)據(jù)傳輸,HTTP2.0的優(yōu)勢就不用多說了。因此NGINX負(fù)載均衡同樣也是建立在HTTP2.0的基礎(chǔ)之上。并且NGINX新增了GRPC模塊。用于負(fù)載GRPC請求。
需要注意以下幾個NGINX的參數(shù)配置:
nginx_http2模塊
http2_max_requests:在一個tcp連接上默認(rèn)通過的最大數(shù)據(jù)包數(shù),默認(rèn)1000個
http2_max_concurrent_streams:在一個tcp連接上默認(rèn)最大并發(fā)流,默認(rèn)128個
nginx_grpc模塊
grpc_send_timeout:將請求傳輸?shù)絞RPC服務(wù)器的超時時間,如果超過這個時間,NGINX會斷開連接。
grpc_read_timeout:接收gRPC服務(wù)器數(shù)據(jù)的超時時間,如果超過這個時間,NGINX會斷開連接。
grpc_socket_keepalive:NGINX與gRPC服務(wù)器長連接配置設(shè)置。
四、HBase客戶端
1、通過Configuration初始化集群Connection
1.1、Connction維持了客戶端到整個HBase集群的鏈接,如一個HBase集群有2個Master、5個RegionServer,那么一般來說整個Connection會維持一個到Active Master的TCP連接和5個到ReginonServer的TCP鏈接。
1.2、通常一個進(jìn)程只需要為一個獨(dú)立的集群建立一個Connection即可,并不需要建立連接池。
1.3、Connection還緩存了訪問的Meta信息,后續(xù)的大部分請求都可以通過緩存的Meta信息定位到對應(yīng)的Region Server。
2、通過Connection初始化Table
2.1、Table是一個非常輕量級的對象,它所使用的連接資源、配置信息、線程池、Meta緩存等都來自于Connection。
2.2、由同一個Connection創(chuàng)建的多個Table,都會共享連接、配置信息、線程池、Meta緩存這些資源
2.3、在branch-1以及之前的版本中,Table并不是線程安全的類,所以不建議在多個線程中使用同一個Table實(shí)例。在HBase 2.00及之后,Table已經(jīng)實(shí)現(xiàn)了線程安全。
2.4、由于Table是一個非常輕量級的對象,所以可以通過Connection為每個請求創(chuàng)建一個Table,但是記住,在該請求執(zhí)行完畢之后需要關(guān)閉Table資源。
3、hbase:meta
3.1、hbase:meta用來保存整個集群的region信息
3.2、hbase:meta在HBase中保證始終只有一個Region,這是為了確保meta表多次操作的原子性,因?yàn)镠Base本質(zhì)上只支持Region級別的事務(wù)所謂Region級別的事務(wù)是指:當(dāng)多個操作落在同一個Region內(nèi)時,HBase能保證這一批操作執(zhí)行的原子性。如果多個操作分散在不同的Region,則無法保證這批操作的原子性
3.3、hbase:meta的一行就對應(yīng)一個Region. 它的rowkey主要由TableName、StartRow、TimeStamp、EncodeName、標(biāo)識這個Region是屬于哪個表,表Rowkey的起始行以及Region的創(chuàng)建時間戳
3.4、hbase:meta只有一個列簇info他有4列,info:regioninfo、info:seqnumDuringOpen、info:server、info:serverstartcode,表示這個表rowkey的起始位置,region落在哪個RegionServer上以及所在RegionServer的啟動時間戳
4、HBase超時參數(shù)設(shè)置
hbase.rpc.timeout:表示單次RPC請求的超時時間,默認(rèn)是60 000ms。
hbase.clinet.retries.number:最多允許發(fā)生多少次RPC重試操作默認(rèn)是35次。
hbase.clinet.pause:表示連續(xù)兩次RPC重試之間的休眠時間,默認(rèn)是100ms。重試休眠時間是按照隨機(jī)退避算法設(shè)計的。也就是重試次數(shù)越多,休眠間隔時間就會越來越長。按照默認(rèn)的重試次數(shù)35,則可能長期卡在休眠和重試兩個步驟中
hbase.clinet.operation.timeout:表示單次API的超時時間,默認(rèn)值為1 200 000ms.一次API可能會有多次RPC重試,這個參數(shù)是API操作的總超時。
5、CAScheckAndPut、inCrementColumnValue操作是Region級別串行執(zhí)行的,吞吐受限,在HBase 2.x版本已調(diào)整設(shè)計,對于同一個Region內(nèi)部的不同行可以并行執(zhí)行CAS,這樣大大提交了Region內(nèi)部的CAS吞吐
6、Filter使用避坑指南
6.1、PrefixFilter 前綴過濾
低效使用方式:
Scan scan = new Scan();
scan.setFilter(new PrefixFillter(Bytes.toBytes("def")));
這個Scan雖然能得到預(yù)期的效果,但是并不高效,因?yàn)閷τ趓owKey在區(qū)間(-∞,def)的數(shù)據(jù),會一條條掃描,發(fā)現(xiàn)前綴不為def,就讀下一行,直到找到第一個rowkey為def的行為止
高效使用方式:
Scan scan = new Scan();
scan.setStartRow(Bytes.toBytes("def"));
scan.setFilter(new PrefixFillter(Bytes.toBytes("def")));
增加了一個startRow。RegionServer發(fā)現(xiàn)Scan設(shè)置了startRow,首先會尋址定位到startRow。這樣就跳過了大量的(-∞,def)的數(shù)據(jù)。
最高效的使用方式:
Scan scan = new Scan();
scan.setStartRow(Bytes.toBytes("def"));
scan.setStopRow(Bytes.toBytes("deg"));
將PrefixFilter直接展開,掃描[def,deg)區(qū)間的數(shù)據(jù),這樣效率是最高的。
6.2、PageFilter:表有5個Region起始key為(-∞,1)、[1,2)、[2,3)、[3,4)、[4,+∞)每個Region 都有超過100條數(shù)據(jù)
錯誤的使用方式:
Scan scan = new Scan();
scan.setStartRow(Bytes.toBytes("1"));
scan.setStopRow(Bytes.toBytes("3"));
scan.setFilter(new PageFilter(100))
這樣寫得出來的分頁每頁數(shù)據(jù)就會有200 條。但是明明設(shè)置了分頁每頁條數(shù)是100。原因是,它需要scan 2個Region.scan從一個region切換到另一個region之前的那個Filter的內(nèi)部狀態(tài)就無效了,新的region內(nèi)部用的是一個全新的Filter.Filter計數(shù)器被清零。Filter不是全局的, 所以它分別從2個region各查了100 條,總共200 條返回。
正確的使用方式:
如果想實(shí)現(xiàn)分頁功能,可以不通過Filter而直接通過limit來實(shí)現(xiàn)。
Scan scan = new Scan();
scan.setStartRow(Bytes.toBytes("1"));
scan.setStopRow(Bytes.toBytes("3"));
scan.setLimit(100);
所以對于用戶來說,正常情況下PageFilter并沒有太多的存在價值
6.3、SingleColumnValueFilter
使用方式:
Scan scan = new Scan();
SingleColumnValueFilter scvf = new? SingleColumnValueFilter(Bytes.toBytes("family"),Bytes.toBytes("qualifier"),
CompareOp.EQUAL,Bytes.toBytes("value"));
scan.setFilter(scvf);
表面上是將列簇為family,列為qualifier,值為value的cell返回給用戶,但事實(shí)上那些不包含family:qualifier的行也會默認(rèn)返回給用戶,如果用戶不希望讀取那些不包含family:qualifier的數(shù)據(jù),需要設(shè)計如下scan
Scan scan = new Scan();
SingleColumnValueFilter scvf = new? SingleColumnValueFilter(Bytes.toBytes("family"),Bytes.toBytes("qualifier"),
CompareOp.EQUAL,Bytes.toBytes("value"));
scvf.setFiterIfMisssing(true);
scan.setFilter(scvf);
另外當(dāng)SingleColumnValueFilter設(shè)置為filterIfMisssing為true時,和其他Filter組合成FilterList時可能導(dǎo)致返回的結(jié)果不正確。建議是不要使用SingleColumnValueFilter與其他Filter組合成FilterList。 直接指定列,通過ValueFilter替換掉SingleColumnValueFilter
Scan scan = new Scan();
ValueFilter vf = new ValueFilter(CompareOf.EQUAL,new BinaryComparatoe(Bytes.toBytes("value")));
scan.addColum(Bytes.toBytes("family"),Bytes.toBytes("qualifier"));
scan.setFilter(vf);
7、HBase寫入方式對比
7.1、table.put(Put):
每次執(zhí)行都會執(zhí)行一次RPC和磁盤持久化,寫入吞吐受限于磁盤帶寬、網(wǎng)絡(luò)帶寬,不會有數(shù)據(jù)丟失能保證put操作的原子性。
7.2、table.put(ListPut):
客戶端打包一批put提交,執(zhí)行一次RPC,一次WAL。相比第一種省略了多次往返的RPC和磁盤持久化。但是時間會變長。如果打包的put分布在多個Region。則不能保證這一批put的原子性,應(yīng)為HBase不支持跨Region的多行事務(wù),失敗的put會經(jīng)歷若干次重試。
7.3、bulk load:
將待寫入的數(shù)據(jù)生成HFile,然后采用bulk load方式將HFile直接加載到對于的Region的CF內(nèi)。這是一種完全離線的快速寫入方式。它應(yīng)該是最快的批量寫入手段,同時不會對線上的集群產(chǎn)生巨大壓力,在load完HFile之后,CF內(nèi)部會進(jìn)行Compaction,但是Compaction是異步的且可以限速,所以bulk load對線上集群非常友好。
使用場景舉例:
7.3.1、兩個集群互為主備,其中一個集群由存在數(shù)據(jù)丟失,想通過另一備份集群的數(shù)據(jù)來修復(fù)異常集群。最快的方式是:把備份集群的數(shù)據(jù)導(dǎo)一個快照拷貝到異常集群,然后通過copyTable工具掃快照生成HFile,然后bulk load 到異常集群,完成數(shù)據(jù)的修復(fù)。
7.3.2、當(dāng)用戶寫入大量數(shù)據(jù)后,發(fā)現(xiàn)選擇的split keys不合適,想重新選擇split keys見表,這時也可以通過 snapshort生成HFile再bulk load的方式生成新表。
gohttp只獲取header斷開
考慮基于HTTP的RPC,或者HTTP服務(wù)器主動通知客戶端的機(jī)制,就是HTTP Long-Polling,意思就是客戶端發(fā)起一個長連接,服務(wù)器阻塞忍住不響應(yīng)直到:
超時,比如5秒后,我們給客戶端響應(yīng)一個keepalive,意思是現(xiàn)在還沒有啥事,請繼續(xù)polling。
拿到結(jié)果,這個可能是任何時候,比如300毫秒、1100毫秒、2300毫秒拿到一個事件,響應(yīng)給客戶端,實(shí)現(xiàn)了有事件異步通知。
這樣客戶端和服務(wù)器之間RPC的效率就非常高,只有在有事件時才會通知。但是,實(shí)際上還有一種情況需要處理:
當(dāng)客戶端斷開連接,比如客戶端設(shè)置了3秒鐘TCP請求超時,或者因?yàn)榭蛻舳薈rash時OS回收了FD等等,這個時候服務(wù)器應(yīng)該要終止polling事務(wù),停止獲取事件。因?yàn)槿绻@個時候獲取了事件,那么如何處理這個事件?只能丟棄,如果客戶端再次發(fā)起請求,就拿不到這個事件了。
問題就來了,如何在HTTP Handler中探測客戶端斷開?例如:
網(wǎng)站標(biāo)題:go語言rpc超時時間 go實(shí)現(xiàn)rpc
本文URL:http://www.ef60e0e.cn/article/doieheo.html