日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

阿里面试题:使用dubbo过程中遇到过哪些坑?

發布時間:2024/4/11 编程问答 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 阿里面试题:使用dubbo过程中遇到过哪些坑? 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

點擊上方“朱小廝的博客”,選擇“設為星標”

后臺回復”加群“加入公眾號專屬技術群

Dubbo[? |?d?b??| ,發音為`打波`] 穩如狗,哪有坑?

如果你用過Dubbo,但是沒碰到過什么坑,那只能說明你還沒有深交Dubbo,看看筆者那些年使用Dubbo踩過的坑!

父子類有相同屬性時值丟失

假設Provider提供的服務中某個服務的參數是WordDTO,并且WordDTO繼承自BaseDTO,兩個類的定義如下:

@Data public?class?BaseDTO?implements?Serializable?{private?Long?id; }@Data public?class?WordDTO?extends?BaseDTO?{private?Long?id;private?String?uuid;private?Long?timestamp;private?String?word; }

問題描述:在Consumer側給WordDTO賦的值,其id屬性的值無法在Provider側獲取到。假設Consumer傳的值是:{"id":68,"timestamp":1570928394380,"uuid":"f774f99f-987c-4506-8ab8-366cd619bb15","word":"hello world"},在Provider拿到的卻是:{"timestamp":1570928394380,"uuid":"f774f99f-987c-4506-8ab8-366cd619bb15","word":"hello world"}。

原因分析:dubbo默認采用的是hessian序列化&反序列化方式,JavaDeserializer在獲取fileds時,采用了Map去重。但是在讀取值時,根據serializer的順序,對于同名字段,子類的該字段值會被賦值兩次,總是被父類的值覆蓋,導致子類的字段值丟失。

解決方案

  • 更改序列化方式(不建議);

  • 刪掉子類中與父類同名屬性(建議);


  • 自定義異常被包裝成RuntimeException

    首先需要說明的是,出現這個問題有一定的條件。如果Provider中的api和自定義Exception定義都是在一個api.jar中,那么是不會有任何問題的。但是如果自定義Exception是在一個單獨的比如common.jar包中就會出現這個問題(此時api和model在另一個api.jar中)。

    下面是一段調用一個會拋出自定義異常的服務的代碼:

    try?{String?hello?=?demoService.saySomething(wordDTO);System.out.println(hello); }catch?(WrongArgumentException?e){System.err.println("wrong?argument?1:?"?+?e.getMessage()); }catch?(RuntimeException?e){System.err.println("wrong?argument?2:?"?+?e.getMessage()); }

    但是,調用的日志卻是如下所示,通過日志我們可以發現,在Consumer中并沒有捕獲到自定義的WrongArgumentException異常,只能捕獲到RuntimeException中的異常,且這個異常信息是封裝自定義的WrongArgumentException異常:

    wrong?argument?2:?com.afei.dev.maven.exception.WrongArgumentException:?word不允許為空 com.afei.dev.maven.exception.WrongArgumentException:?word不允許為空at?com.afei.test.dubbo.provider.facade.impl.DemoServiceImpl.saySomething(DemoServiceImpl.java:11)at?com.alibaba.dubbo.common.bytecode.Wrapper1.invokeMethod(Wrapper1.java)

    這是什么原因呢?這是因為dubbo Provider的ExceptionFilter.java對異常統一封裝導致的,其封裝的核心源碼我就不貼出來了,你如果有興趣可以自己下載查看。我這里只貼出它的處理邏輯,當碰到如下這些情況時,dubbo會直接拋出異常:

  • 如果是checked異常(不是RuntimeException但是是Exception.java類型的異常),直接拋出;

  • 在方法簽名上有聲明(例如String saySomething()throws MyException ),直接拋出;

  • 異常類和接口類在同一jar包里,直接拋出;

  • 是JDK自帶的異常(全類名以java或者javax開頭,例如java.lang.IllegalStateException),直接拋出;

  • 是Dubbo本身的異常RpcException,直接拋出;

  • 否則,Dubbo通過如下代碼將異常包裝成RuntimeException拋給客戶端:

    return?new?RpcResult(new?RuntimeException(StringUtils.toString(exception)));

    通過上面對ExceptionFilter的源碼分析可知,如果要讓Provider拋出自定義異常,有如下幾個解決辦法:

  • 將自定義異常和接口類放到一個包中即可(推薦);

  • 方法簽名上申明自定義異常;

  • 那么Dubbo為什么這樣設計?我相信沒有誰比Dubbo的作者梁飛更有發言權了!這里就引用Dubbo作者梁飛在Github上的原話(原話出處:https://github.com/apache/dubbo/issues/111):

    這個是為了防止服務提供方拋出了消費方沒有的異常,比如數據庫異常類,導致消費方反序列化失敗,使異常信息更奇怪,建議在業務接口上RuntimeException也聲明在throws中。


    IP暴露問題

    在某些復雜環境下,例如Docker、雙網卡、虛擬機等環境下,Dubbo默認綁定的IP可能并不是我們期望的正確IP,Dubbo綁定IP默認行為如下(核心源碼在NetUtils.java中):

  • 通過InetAddress.getLocalHost()獲取本機地址,如果本機地址有效則返回(有效地址需要滿足這幾點:1. 不能為空,2. 不是loopback地址(類似127.x.x.x),3. 不能是0.0.0.0,也不能是127.0.0.1);

  • 如果本機地址無效,那么再遍歷網卡地址,然后通過isValidAddress校驗ip是否正常并返回第一個有效的IP地址。這樣的話,Dubbo就不能保證返回的是內網IP還是外網IP。

  • 事實上,復雜環境下這個IP綁定問題不太好自動化解決,不過我們可以利用dubbo的擴展能力解決這些問題。

    • Docker環境

    如果你的dubbo部署在Docker上,那么需要注意了。我們需要解決Dubbo幾個特定參數來解決這個問題:

  • DUBBO_IP_TO_REGISTRY --- Registering to the IP address of the registration center

  • DUBBO_PORT_TO_REGISTRY --- Registering to the port of the registration center

  • DUBBO_IP_TO_BIND --- Listening IP addresses

  • DUBBO_PORT_TO_BIND --- Listening ports

  • 假設主機IP地址為30.5.97.6,docker啟動dubbo服務參考命令,啟動后,這個Provider服務注冊的地址就是30.5.97.6:20881,我們可以通過命令(telnet 30.5.97.6 20881,invoke org.apache.dubbo.test.docker.DemoService.hello("world"))檢查并調用Provider提供的服務:

    docker?run?-e?DUBBO_IP_TO_REGISTRY=30.5.97.6?-e?DUBBO_PORT_TO_REGISTRY=20881?-p?30.5.97.6:20881:20880?--link?zkserver:zkserver?-it?--rm?dubbo-docker-sample

    參考地址:https://github.com/apache/dubbo-samples/tree/master/dubbo-samples-docker。

    • 暴露外網IP

    如果你服務的調用方和消費方不在同一個內網中,那么就會希望Dubbo服務通過外網IP暴露。不過不好意思,dubbo默認的服務暴露行為搞不定,因為dubbo默認暴露的是內網IP地址。

    這個時候,我們就需要借助兩個參數:dubbo.protocol.host和dubbo.protocol.port,通過這兩個參數顯示申明我們暴露服務的IP和Port,這兩個參數即可以通過配置文件方式指定,也可以通過JVM參數方式指定,具體怎么使用,UP TO YOU!!!

    • 雙網卡問題

    當服務器上有多個網卡時,Dubbo服務提供者啟動時,會將錯誤的IP注冊到注冊中心,從而導致消費端連接不上。這種情況的筆者提供兩種解決辦法:

  • 配置dubbo.protocol.host=192.168.0.1

  • 配置/etc/hosts,例如afeiserver01 = 192.168.0.1,其中afeiserver01是機器名;


  • Data length too large

    這個異常的詳細堆棧信息如下所示:

    org.apache.dubbo.remoting.transport.ExceedPayloadLimitException: Data?length?too?large:?10356612,?max?payload:?8388608, channel:?NettyChannel?[channel=[id:?0xd36132c0,?L:/192.168.1.6:55078?-?R:/192.168.1.6:20880]]

    日志中提到max payload為8388608,等價于8 * 1024 * 1024,即8k。所以這個問題的原因非常清晰了,就是請求或者響應的報文體長度超過了8k。

    這個問題比較簡單,筆者在這里提供兩個解決方案:

  • 修改payload的值,將其調大,例如16777216,即16k,不推薦

  • 減少請求/響應報文長度。例如Provider提供的服務,最大批量限制為1000,比如最多只能批量查詢1000個用戶ID的用戶信息,推薦

  • 說明:

    dubbo在小報文的場景下表現最佳,所以,除非確實無法饒過。否則強烈不建議調大payload的值;


    線程耗盡

    dubbo服務Provider側如果線程耗盡,會跑出類似如下的異常信息:

    19-10-17?00:00:00.033?[New?I/O?server?worker?#1-6]?WARN??com.alibaba.dubbo.common.threadpool.support.AbortPolicyWithReport?-??[DUBBO]?Thread?pool?is?EXHAUSTED!?Thread?Name:?DubboServerHandler-10.0.0.77:20703,?Pool?Size:?200?(active:?200,?core:?200,?max:?200,?largest:?200),?Task:?5897697?(completed:?5897197),?Executor?status:(isShutdown:false,?isTerminated:false,?isTerminating:false),?in?dubbo://10.0.0.77:20703!,?dubbo?version:?2.5.3,?current?host:?127.0.0.1

    對dubbo有基本了解的都知道,Provider默認是fixed線程池,且線程數為200。那么什么時候會出現這種異常呢:

  • Provider側接口處理太慢。如果是這種原因的話,我們可以通過jstack命令,在線程棧中看到超過200個狀態為RUNNING、且命名為"DubboServerHandler-"的線程,通過線程棧我們大概知道是哪部分代碼引起的,然后優化問題代碼,提升處理能力從而解決這個問題;

  • Provider處理能力確實不夠。這個原因是指,Consumer可能會達到10000TPS,但是Provider單機處理能力可能只有1000TPS,如果沒有10臺以上的Provider服務實例,那么就確實需要擴容了。

  • Provier由于某些原因阻塞。這個原因一般是Provider側依賴的某些服務或者中間件出問題導致的;

  • 根據下面這段日志可知,Dubbo線程都阻塞在發送ActiveMQ消息的地方,我們可以通過異步發送MQ消息,或者檢查是不是ActiveMQ服務吞吐量不行并優化它的吞吐量等手段來解決:

    "DubboServerHandler-127.0.0.1:20880-thread-128"?daemon?prio=10?tid=0x00007fd574193811?nid=0x16cf1?waiting?for?monitor?entry?[0x00007fd691887000..0x00007fd691888810]java.lang.Thread.State:?BLOCKED?(on?object?monitor)at?org.apache.activemq.transport.MutexTransport.oneway(MutexTransport.java:40)-?waiting?to?lock?<0x00007fd6c9fa4ba8>?(a?java.lang.Object)at?org.apache.activemq.transport.ResponseCorrelator.oneway(ResponseCorrelator.java:60)at?org.apache.activemq.ActiveMQConnection.doAsyncSendPacket(ActiveMQConnection.java:1265)at?org.apache.activemq.ActiveMQConnection.asyncSendPacket(ActiveMQConnection.java:1259)

    服務調用失敗

    異常堆棧信息如下所示:

    Forbid?consumer?0?access?service?com.afei.dubbo.demo.api.QueryService?from?registry?127.0.0.1:2181?use?dubbo?version?2.5.3, Please?check?registry?access?list?(whitelist/blacklist)

    或者異常堆棧信息如下所示:

    org.apache.dubbo.rpc.RpcException: Failed?to?invoke?the?method?saySomething?in?the?service?com.afei.test.dubbo.provider.facade.DemoService. No?provider?available?for?the?service?com.afei.test.dubbo.provider.facade.DemoService:2.0.0 from?registry?224.5.6.7:1234

    我相信,每一個使用過dubbo服務的同學,肯定會碰到上面這兩個ERROR日志。這兩個問題一般有如下幾種原因:

  • Provider服務全部下線,即沒有一個存活的Provider服務進程。

  • 存在一個或多個Provider服務,但是version或者group不匹配。例如Consumer側申明version=1.0.0,而Provider側申明version=2.0.0,或者group不匹配,都會出現這個ERROR。

  • 暴露的IP有問題。例如暴露的是內網IP,但是調用卻是通過外網IP;

  • dubbo spring schema

    在dubbo進入apache之前,dubbo的spring schema申明如下:

    http://code.alibabatech.com/schema/dubbo

    當dubbo進入apache后,dubbo的spring schema能兼容兩種方式:

    http://dubbo.apache.org/schema/dubbo http://code.alibabatech.com/schema/dubbo

    這是由dubbo.jar中META-INF/spring.schemas文件決定的:

    http\://dubbo.apache.org/schema/dubbo/dubbo.xsd=META-INF/dubbo.xsd http\://code.alibabatech.com/schema/dubbo/dubbo.xsd=META-INF/compat/dubbo.xsd

    dubbo新版本是即能兼容http://dubbo.apache.org/schema/dubbo,也能兼容http://code.alibabatech.com/schema/dubbo。但是dubbo老版本只能兼容http://code.alibabatech.com/schema/dubbo。如果老版本也配置http://dubbo.apache.org/schema/dubbo,就會拋出如下日常:

    org.springframework.beans.factory.parsing.BeanDefinitionParsingException: Configuration?problem:?Unable?to?locate?Spring?NamespaceHandler?for?XML?schema?namespace?[http://dubbo.apache.org/schema/dubbo]

    想知道更多?描下面的二維碼關注我


    當當1024圖書優惠活動,疊加科技類圖書每滿100-50(活動時間10月22~24)。使用我的優惠嗎:2CGJZK,還可以享受:實付200-30(全場自營圖書可用,優惠券到期時間11-01),實際為花170買400元圖書。推薦書籍除了我的《深入理解Kafka》和《RabbitMQ實戰指南》之外,還推薦《數據密集型應用系統設計》、《SRE: Google運維解密》、《高性能MySQL》、《實現領域驅動設計》等。

    朕已閱?

    總結

    以上是生活随笔為你收集整理的阿里面试题:使用dubbo过程中遇到过哪些坑?的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。