dubbo服務(wù)使用redis注冊(cè)中心的系列異常解決
前言
dubbo支持zookeeper,reids,multicast等注冊(cè)中心注冊(cè)服務(wù)信息,使用redis作為注冊(cè)中心時(shí),因?yàn)閞eids作為注冊(cè)中心使用并不廣泛,早期reids由于定位內(nèi)網(wǎng)訪問,使用密碼驗(yàn)證也不怎么重視,導(dǎo)致框架本身設(shè)計(jì)缺陷,會(huì)有很多坑,如1.沒有考慮到帶密碼驗(yàn)證的redis,2.集群容錯(cuò)模式判斷錯(cuò)誤 3.不可以設(shè)置redisdbindex等。其中部分問題,博主已經(jīng)提交給dubbo官方倉(cāng)庫(kù)了,但是還沒有完全解決掉,其實(shí)這些問題無需等官方修復(fù),對(duì)源碼稍加改造就ok了。
1.不支持帶密碼,設(shè)置indexdb的reids
2.5.6以及以前的會(huì)有這個(gè)問題,最新的版本已經(jīng)解決了這個(gè)問題了,但是還是存在一個(gè)坑,就是必須得設(shè)置用戶名(大家都知道redis驗(yàn)證不需要用戶名),如URL的構(gòu)造方法有如下判斷
這會(huì)導(dǎo)致,如果只設(shè)置了密碼,沒有設(shè)置用戶名,就會(huì)拋Invalid url, password without username的異常。
解決方法:
1.打開RedisRegistry.java,設(shè)置jedispool時(shí)判斷下,如果設(shè)置密碼,使用帶密碼,indexdb入?yún)⒌臉?gòu)造方法,具體如下:
if(StringUtils.isEmpty(url.getPassword())){ this.jedisPools.put(address, new JedisPool(config, host, port, url.getParameter(Constants.TIMEOUT_KEY, Constants.DEFAULT_TIMEOUT),null,url.getParameter("db.index",0))); }else { this.jedisPools.put(address, new JedisPool(config, host, port, url.getParameter(Constants.TIMEOUT_KEY, Constants.DEFAULT_TIMEOUT),url.getPassword(),url.getParameter("db.index",0))); }
2.配置注冊(cè)中心的時(shí)候得把username加上,如:
二,集群容錯(cuò)模式異常
這個(gè)問題,不開啟服務(wù)監(jiān)控不會(huì)有問題,在開啟dubbo服務(wù)監(jiān)控后,就會(huì)拋異常:Unsupported redis cluster: Failsafe. The redis cluster only supported failover or replicate,問題是由如下圖紅框內(nèi)的if判斷造成的,因?yàn)楸O(jiān)控模塊服務(wù)默認(rèn)的集群容錯(cuò)模式為Failsafe,而且寫死了,不可通過配置更改,如圖:
如下圖箭頭所指為添加了排除監(jiān)控中心的if判斷邏輯:
三,jedis連接池連接的坑
在修改了dubbo后,由于沒有更新到修改后本地打包的dubbo依賴,一度報(bào)如下異常:
at java.lang.Thread.run(Thread.java:748) Caused by: redis.clients.jedis.exceptions.JedisException: Could not get a resource from the pool at redis.clients.util.Pool.getResource(Pool.java:51) at redis.clients.jedis.JedisPool.getResource(JedisPool.java:226) at com.alibaba.dubbo.registry.redis.RedisRegistry.doSubscribe(RedisRegistry.java:342) ... 43 more Caused by: java.util.NoSuchElementException: Unable to validate object at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:506) at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:363) at redis.clients.util.Pool.getResource(Pool.java:49) ... 45 more
Unable to validate object的問題網(wǎng)上有各種說法,博主也找了好久的問題,最終通過猜想+讀jedis源碼+本地debug調(diào)試才解決的問題。其實(shí)網(wǎng)上的說法都正確,原因是jedis內(nèi)一段代碼導(dǎo)致的,dubbo默認(rèn)設(shè)置了連接池的test.on.borrow為true,所有在拿連接前都會(huì)驗(yàn)證一遍,驗(yàn)證的邏輯如下:
如上圖,前面兩個(gè)判斷100%不會(huì)有問題,網(wǎng)上大多是因?yàn)閞edis服務(wù)本身出問題了,ping的時(shí)候沒有返回PONG。博主這邊是以為jedis.isConnected()報(bào)錯(cuò)了,但是jedis是個(gè)坑,雖然返回了false,但是具體的異常信息并沒有拋出來,其實(shí)這個(gè)地方,具體的異常:redis.clients.jedis.exceptions.JedisDataException: NOAUTH Authentication required.。很明顯是reids密碼驗(yàn)證失敗了。因?yàn)橐婚_始修改的dubbo密碼設(shè)置沒有依賴到
四,服務(wù)超過8個(gè)應(yīng)用啟動(dòng)卡死
這個(gè)最終的問題還是jedis導(dǎo)致的,dubbo默認(rèn)初始化的jedis連接池,最大鏈接數(shù)是8個(gè),然后默認(rèn)的從連接池里拿連接的超時(shí)時(shí)間為-1,又因?yàn)槭褂胷edis作為注冊(cè)中心時(shí),通過訂閱暴露的service 的變更來做服務(wù)治理的,而jedis里的服務(wù)訂閱是阻塞占用連接的,也就是說有多少個(gè)服務(wù),就會(huì)被占用多少個(gè)鏈接。這就導(dǎo)致了,當(dāng)暴露的服務(wù)數(shù)量大于8個(gè)時(shí),從連接池中獲取不到資源,又永不超時(shí),造成應(yīng)用啟動(dòng)卡死的現(xiàn)象
解決方案:手動(dòng)設(shè)置jedis的最大連接數(shù),如:
spring.dubbo.registry.parameters.max.total = 200
文末結(jié)語(yǔ)
使用開源的產(chǎn)品,還是要多讀讀開源產(chǎn)品代碼,至少架構(gòu)設(shè)計(jì),模塊劃分要了解,這樣遇到啥問題,才不會(huì)手足無措,才能舉一反三。bug或異常一點(diǎn)都不可怕,遇到異常,解決異常就問兩個(gè)問題。1.在哪里拋出的異常(找到拋異常的代碼),2.為什么拋這個(gè)異常(找出拋異常的原因,一般有邏輯,如if判斷等,沒有的邏輯的異常一般都是系統(tǒng)級(jí)別的),然后通讀下異常周邊代碼,基本上問題就搞定了
以上就是dubbo服務(wù)使用redis注冊(cè)中心的系列異常解決的詳細(xì)內(nèi)容,更多關(guān)于dubbo使用redis注冊(cè)中心系列異常的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
- 解決dubbo啟動(dòng)報(bào)服務(wù)注冊(cè)失敗Failed?to?register?dubbo
- springboot發(fā)布dubbo服務(wù)注冊(cè)到nacos實(shí)現(xiàn)方式
- springboot整合Dubbo與Feign的實(shí)現(xiàn)?(無注冊(cè)中心)
- 升級(jí)dubbo2.7.4.1版本平滑遷移到注冊(cè)中心nacos
- dubbo服務(wù)注冊(cè)到nacos的過程剖析
- Dubbo無法訪問遠(yuǎn)程Zookeeper已注冊(cè)服務(wù)的問題解決方案
- 從dubbo zookeeper注冊(cè)地址提取出zookeeper地址的方法
- 解決Dubbo應(yīng)用啟動(dòng)注冊(cè)ZK獲取IP慢的原因之一
相關(guān)文章
Redis?Lua腳本實(shí)現(xiàn)ip限流示例
這篇文章主要介紹了Redis?Lua腳本實(shí)現(xiàn)ip限流示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-07-07redis 限制內(nèi)存使用大小的實(shí)現(xiàn)
這篇文章主要介紹了redis 限制內(nèi)存使用大小的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-05-05淺談內(nèi)存耗盡后Redis會(huì)發(fā)生什么
這篇文章主要介紹了淺談內(nèi)存耗盡后Redis會(huì)發(fā)生什么,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03