Dubbo本地调用
本地調用介紹
當一個應用既是一個服務的提供者,同時也是這個服務的消費者的時候,可以直接對本機提供的服務發起本地調用。從?2.2.0?版本開始,Dubbo 默認在本地以?injvm?的方式暴露服務,這樣的話,在同一個進程里對這個服務的調用會優先走本地調用。
與本地對象上方法調用不同的是,Dubbo 本地調用會經過 Filter 鏈,其中包括了 Consumer 端的 Filter 鏈以及 Provider 端的 Filter 鏈。通過這樣的機制,本地消費者和其他消費者都是統一對待,統一監控,服務統一進行治理。
同時,相比于遠程調用來說,Dubbo 本地調用性能較優,省去了請求、響應的編解碼及網絡傳輸的過程。
要使用 Dubbo 本地調用不需做特殊配置,按正常 Dubbo 服務暴露服務即可。任一服務在暴露遠程服務的同時,也會同時以?injvm?的協議暴露本地服務。injvm?是一個偽協議,不會像其他協議那樣對外開啟端口,只用于本地調用的目的。
以下面的 XML 配置為例:
<dubbo:registry address="zookeeper://127.0.0.1:2181"/> <dubbo:protocol name="dubbo" port="20800"/><bean id="demoServiceTarget" class="org.apache.dubbo.samples.local.impl.DemoServiceImpl"/><dubbo:service interface="org.apache.dubbo.samples.local.api.DemoService" ref="demoServiceTarget"/> <dubbo:reference id="demoService" interface="org.apache.dubbo.samples.local.api.DemoService"/>這里同時配置了同一服務?DemoService?的提供者以及消費者。在這種情況下,該應用中的?DemoService的消費方會優先使用?injvm?協議進行本地調用。上述的例子可以在 dubbo-samples 工程中找到源碼:https://github.com/apache/dubbo-samples/blob/master/dubbo-samples-local
細粒度控制本地調用
本地調用是可以顯示關閉的,通過這種方式,服務提供者可以做到對遠端服務消費者和本地消費者一視同仁。具體做法是通過?scope="remote"?來關閉?injvm?協議的暴露,這樣,即使是本地調用者,也需要從注冊中心上獲取服務地址列表,然后才能發起調用,而這個時候的調用過程,與遠端的服務消費者的過程是一致的。
<bean id="target" class="org.apache.dubbo.samples.local.impl.DemoServiceImpl"/> <!-- 服務提供者指定 scope="remote" --> <dubbo:service interface="org.apache.dubbo.samples.local.api.DemoService" ref="target" scope="remote"/> <dubbo:reference id="demoService" interface="org.apache.dubbo.samples.local.api.DemoService"/>同樣的,服務消費者也支持通過?scope?來限定發起調用優先走本地,還是只走遠程。比如,可以通過以下的方式強制消費端通過遠程調用的方式來發起 dubbo 調用:
<!-- 服務消費者指定 scope="remote" --> <dubbo:reference id="demoService" interface="org.apache.dubbo.samples.local.api.DemoService" scope="remote"/>如果同時服務提供方限定了?scope="local"?的話,
<!-- 服務提供者指定 scope="remote" --> <dubbo:service interface="org.apache.dubbo.samples.local.api.DemoService" ref="target" scope="remote"/> <!-- 服務消費者指定 scope="local" --> <dubbo:reference id="demoService" interface="org.apache.dubbo.samples.local.api.DemoService" scope="local"/>那么該程序中的 dubbo 調用將會失敗,原因是服務提供方只暴露了遠程服務到注冊中心上,并沒有暴露injvm?協議的服務,而出于同一個進程中的服務消費者查找不到?injvm?協議的服務,也不會去遠程的注冊中心上訂閱服務地址。同樣的,當服務提供者限定?scope="local"?而服務消費者限定?scope="remote"?也會因為相同的原因導致調用失敗。出錯信息如下:
[20/03/19 05:03:18:018 CST] main INFO config.AbstractConfig: [DUBBO] Using injvm service org.apache.dubbo.samples.local.api.DemoService, dubbo version: 2.7.1, current host: 169.254.146.168 Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'demoService': FactoryBean threw exception on object creation; nested exception is java.lang.IllegalStateException: Failed to check the status of the service org.apache.dubbo.samples.local.api.DemoService. No provider available for the service org.apache.dubbo.samples.local.api.DemoService from the url injvm://127.0.0.1/org.apache.dubbo.samples.local.api.DemoService?application=demo-provider&default.lazy=false&default.sticky=false&dubbo=2.0.2&interface=org.apache.dubbo.samples.local.api.DemoService&lazy=false&methods=sayHello&pid=76198®ister.ip=169.254.146.168&release=2.7.1-SNAPSHOT&scope=local&side=consumer&sticky=false×tamp=1553072598838 to the consumer 169.254.146.168 use dubbo version 2.7.1何時無法使用本地調用
默認情況下,本地調用是自動開啟的,不需要做額外的配置。只有當需要關閉的時候,才需要通過?scope的配置來顯式的關閉。
但是,特別需要指出的是,在下面的幾種情況下,本地調用是無法使用的:
第一,泛化調用的時候無法使用本地調用。
第二,消費者明確指定 URL 發起直連調用。當然,如果消費者指定的是?injvm?的 URL,最終的調用也是走本地調用的,比如:
<dubbo:reference id="demoService" interface="org.apache.dubbo.samples.local.api.DemoService" url="injvm://127.0.0.1/org.apache.dubbo.samples.local.api.DemoService"/>強制打開本地調用
除了通過?scope?來控制本地調用的行為之外,也可以通過?injvm?這個配置來強制打開或者禁用本地調用。
<dubbo:consumer injvm="false" .../> <dubbo:provider injvm="true" .../>但是通過?injvm?來配置本地調用的方式已經被廢棄。通過?scope?的方式來控制是官方推薦的。
總結
本文介紹了本地調用的概念以及帶來的好處,并進一步的揭示了 dubbo 本地調用實際上是在當前進程中暴露了?injvm?的協議,而該協議并不會對外暴露端口,然后討論了如何通過?scope?來細粒度的控制本地調用的行為,并強調了通過?invjm?來配置的方式已經被廢棄,在未來版本中可能會被刪除。
原文:http://dubbo.apache.org/zh-cn/blog/dubbo-local-call.html
總結
- 上一篇: spring-boot 中实现标准 re
- 下一篇: 使用axios时遇到的Request M