Dubbo本地调用
本地調(diào)用介紹
當(dāng)一個應(yīng)用既是一個服務(wù)的提供者,同時也是這個服務(wù)的消費者的時候,可以直接對本機提供的服務(wù)發(fā)起本地調(diào)用。從?2.2.0?版本開始,Dubbo 默認在本地以?injvm?的方式暴露服務(wù),這樣的話,在同一個進程里對這個服務(wù)的調(diào)用會優(yōu)先走本地調(diào)用。
與本地對象上方法調(diào)用不同的是,Dubbo 本地調(diào)用會經(jīng)過 Filter 鏈,其中包括了 Consumer 端的 Filter 鏈以及 Provider 端的 Filter 鏈。通過這樣的機制,本地消費者和其他消費者都是統(tǒng)一對待,統(tǒng)一監(jiān)控,服務(wù)統(tǒng)一進行治理。
同時,相比于遠程調(diào)用來說,Dubbo 本地調(diào)用性能較優(yōu),省去了請求、響應(yīng)的編解碼及網(wǎng)絡(luò)傳輸?shù)倪^程。
要使用 Dubbo 本地調(diào)用不需做特殊配置,按正常 Dubbo 服務(wù)暴露服務(wù)即可。任一服務(wù)在暴露遠程服務(wù)的同時,也會同時以?injvm?的協(xié)議暴露本地服務(wù)。injvm?是一個偽協(xié)議,不會像其他協(xié)議那樣對外開啟端口,只用于本地調(diào)用的目的。
以下面的 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"/>這里同時配置了同一服務(wù)?DemoService?的提供者以及消費者。在這種情況下,該應(yīng)用中的?DemoService的消費方會優(yōu)先使用?injvm?協(xié)議進行本地調(diào)用。上述的例子可以在 dubbo-samples 工程中找到源碼:https://github.com/apache/dubbo-samples/blob/master/dubbo-samples-local
細粒度控制本地調(diào)用
本地調(diào)用是可以顯示關(guān)閉的,通過這種方式,服務(wù)提供者可以做到對遠端服務(wù)消費者和本地消費者一視同仁。具體做法是通過?scope="remote"?來關(guān)閉?injvm?協(xié)議的暴露,這樣,即使是本地調(diào)用者,也需要從注冊中心上獲取服務(wù)地址列表,然后才能發(fā)起調(diào)用,而這個時候的調(diào)用過程,與遠端的服務(wù)消費者的過程是一致的。
<bean id="target" class="org.apache.dubbo.samples.local.impl.DemoServiceImpl"/> <!-- 服務(wù)提供者指定 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"/>同樣的,服務(wù)消費者也支持通過?scope?來限定發(fā)起調(diào)用優(yōu)先走本地,還是只走遠程。比如,可以通過以下的方式強制消費端通過遠程調(diào)用的方式來發(fā)起 dubbo 調(diào)用:
<!-- 服務(wù)消費者指定 scope="remote" --> <dubbo:reference id="demoService" interface="org.apache.dubbo.samples.local.api.DemoService" scope="remote"/>如果同時服務(wù)提供方限定了?scope="local"?的話,
<!-- 服務(wù)提供者指定 scope="remote" --> <dubbo:service interface="org.apache.dubbo.samples.local.api.DemoService" ref="target" scope="remote"/> <!-- 服務(wù)消費者指定 scope="local" --> <dubbo:reference id="demoService" interface="org.apache.dubbo.samples.local.api.DemoService" scope="local"/>那么該程序中的 dubbo 調(diào)用將會失敗,原因是服務(wù)提供方只暴露了遠程服務(wù)到注冊中心上,并沒有暴露injvm?協(xié)議的服務(wù),而出于同一個進程中的服務(wù)消費者查找不到?injvm?協(xié)議的服務(wù),也不會去遠程的注冊中心上訂閱服務(wù)地址。同樣的,當(dāng)服務(wù)提供者限定?scope="local"?而服務(wù)消費者限定?scope="remote"?也會因為相同的原因?qū)е抡{(diào)用失敗。出錯信息如下:
[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何時無法使用本地調(diào)用
默認情況下,本地調(diào)用是自動開啟的,不需要做額外的配置。只有當(dāng)需要關(guān)閉的時候,才需要通過?scope的配置來顯式的關(guān)閉。
但是,特別需要指出的是,在下面的幾種情況下,本地調(diào)用是無法使用的:
第一,泛化調(diào)用的時候無法使用本地調(diào)用。
第二,消費者明確指定 URL 發(fā)起直連調(diào)用。當(dāng)然,如果消費者指定的是?injvm?的 URL,最終的調(diào)用也是走本地調(diào)用的,比如:
<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"/>強制打開本地調(diào)用
除了通過?scope?來控制本地調(diào)用的行為之外,也可以通過?injvm?這個配置來強制打開或者禁用本地調(diào)用。
<dubbo:consumer injvm="false" .../> <dubbo:provider injvm="true" .../>但是通過?injvm?來配置本地調(diào)用的方式已經(jīng)被廢棄。通過?scope?的方式來控制是官方推薦的。
總結(jié)
本文介紹了本地調(diào)用的概念以及帶來的好處,并進一步的揭示了 dubbo 本地調(diào)用實際上是在當(dāng)前進程中暴露了?injvm?的協(xié)議,而該協(xié)議并不會對外暴露端口,然后討論了如何通過?scope?來細粒度的控制本地調(diào)用的行為,并強調(diào)了通過?invjm?來配置的方式已經(jīng)被廢棄,在未來版本中可能會被刪除。
原文:http://dubbo.apache.org/zh-cn/blog/dubbo-local-call.html
總結(jié)
- 上一篇: spring-boot 中实现标准 re
- 下一篇: 使用axios时遇到的Request M