項目地址:https://github.com/SpringCloud/spring-cloud-dubbo 歡迎star财搁、fork
spring-cloud-dubbo
spring/spring cloud的設計理念是integrate everything泥技。充分利用現有開源組件陪拘,在他們之上設計一套統(tǒng)一規(guī)范/接口使他們能夠接入spring cloud體系并且能夠無縫切換底層實現裳涛,使他們能夠集成到一起良好運作咐吼。最典型的例子就是DiscoveryClient,只要實現DiscoveryClient相關接口咳蔚,spring cloud的底層注冊中心可以隨意更換豪嚎,dubbo的注冊中心也有SPI規(guī)范進行替換。
本項目的目標是將dubbo融入到spring cloud生態(tài)中谈火,使微服務之間的調用同時具備restful和dubbo調用的能力侈询。做到對業(yè)務代碼無侵入,無感知:引入jar包則微服務間調用使用dubbo糯耍,去掉jar包則使用默認的restful扔字。
設計思路
之前因為工作需要增強過feign,feign的設計思路就是提供一套API温技,底層契約隨意更換啦租,參照feign的SpringMvcContract類。與項目理念非常相似荒揣,所以我們也使用feign作為統(tǒng)一接口篷角,spring cloud下feign默認使用restful方式調用,我們只需要擴展feign系任,提供dubbo方式調用就行了恳蹲。
服務提供方
服務提供方提供service(restful服務)和api(sdk開發(fā)工具)虐块。服務消費方使用api來調用服務(方便提供方升級增加服務提供方可控性)。
api中定義FeignClient接口(spring-cloud-dubbo-demo-provider-api):
@FeignClient("provider")
public interface ProviderService {
@GetMapping("/hello")
String hello();
}
service中實現該接口(spring-cloud-dubbo-demo-provider-service):
@RestController
public class ProviderServiceImpl implements ProviderService {
@Override
public String hello() {
return "Hello " + System.currentTimeMillis();
}
}
上述代碼是一個典型的spring cloud restful api嘉蕾。在服務提供方我們要做的就是:引入dubbo贺奠,掃描含有@FeignClient注解的類并且提供dubbo訪問即可(FeignClientToDubboProviderBeanPostProcessor)。關鍵代碼片段:
private void registerServiceBeans(Set<String> packagesToScan, BeanDefinitionRegistry registry) {
...
scanner.addIncludeFilter(new AnnotationTypeFilter(FeignClient.class, true, true));
for (String packageToScan : packagesToScan) {
// Registers @Service Bean first
scanner.scan(packageToScan);
...
}
服務消費方
引入spring-cloud-dubbo-demo-provider-api依賴错忱,并直接使用@Autowire使用相關api:
@RestController
public class TestService {
@Autowired
private ProviderService providerService;
@GetMapping("/test")
public String test() {
return "Test " + providerService.hello();
}
}
上述代碼是一個典型的spring cloud feign使用儡率。我們只需要替換feign的實現:產生ProviderService接口proxy bean時,使用dubbo產生的bean替換默認的feign產生的restful調用的bean即可(DubboFeignBuilder)以清。關鍵代碼片段:
@Override
public <T> T target(Target<T> target) {
ReferenceBeanBuilder beanBuilder = ReferenceBeanBuilder
.create(defaultReference, target.getClass().getClassLoader(), applicationContext)
.interfaceClass(target.type());
try {
T object = (T) beanBuilder.build().getObject();
return object;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
如何使用
參考spring-cloud-dubbo-demo
先建立一組標準的spring cloud restful工程儿普,注意feign client接口由服務提供方提供。然后接入spring-cloud-dubbo給項目提供dubbo調用能力掷倔。
引入依賴:
<dependency>
<groupId>cn.springcloud.dubbo</groupId>
<artifactId>spring-cloud-dubbo-starter</artifactId>
</dependency>
使用 https://github.com/apache/incubator-dubbo-spring-boot-project 0.2.0版本眉孩,目前還未發(fā)布maven中央倉庫,需要本地編譯安裝勒葱,spring-boot與dubbo集成和配置均安裝此項目說明文檔
服務提供方配置:
dubbo.application.name=provider
dubbo.registry.address=eureka://127.0.0.1:8761
dubbo.scan.basePackages=cn.springcloud.dubbo.demo.provider.service
為了減少依賴浪汪,快速體驗,并且作為將dubbo完全融入spring cloud后續(xù)計劃的POC凛虽。我們按照dubbo SPI擴展規(guī)范 http://dubbo.apache.org/books/dubbo-dev-book/impls/registry.html 死遭,提供了一個實驗性質的dubbo eureka注冊中心(dubbo eureka配置中心的ip和端口可以隨便填,我們并不會用到這里的配置凯旋,我們用的是spring cloud的配置殃姓,dubbo擴展規(guī)范要求 eureka:// 后面必須要跟ip和端口而已)。如果要在生產環(huán)境使用瓦阐,目前還是建議采用dubbo自帶的zookeeper注冊中心,只需將上面注冊中心配置改為:
dubbo.registry.address=zookeeper://127.0.0.1:2181
服務消費方配置:
dubbo.application.name=consumer
dubbo.registry.address=eureka://127.0.0.1:8761
dubbo.scan.basePackages=cn.springcloud.dubbo.demo.consumer.service
開啟eureka
開啟provider
開啟consumer
訪問 view-source:http://localhost:8761/eureka/apps/CONSUMER metadata確認含有如下dubbo注冊信息:
<metadata>
<providers>["dubbo://172.24.223.241:30880/cn.springcloud.dubbo.demo.consumer.service.BarService?anyhost=true&application=consumer&dubbo=2.6.2&generic=false&interface=cn.springcloud.dubbo.demo.consumer.service.BarService&methods=bar&pid=9268&side=provider&timestamp=1528524172162"]</providers>
<consumers>["consumer://172.24.223.241/cn.springcloud.dubbo.demo.provider.service.FooService?application=consumer&category=consumers&check=false&dubbo=2.6.2&interface=cn.springcloud.dubbo.demo.provider.service.FooService&methods=foo&pid=9268&qos.enable=false&side=consumer&timestamp=1528524172906","consumer://172.24.223.241/cn.springcloud.dubbo.demo.provider.service.ProviderService?application=consumer&category=consumers&check=false&dubbo=2.6.2&interface=cn.springcloud.dubbo.demo.provider.service.ProviderService&methods=hello&pid=9268&qos.enable=false&side=consumer&timestamp=1528524172823"]</consumers>
</metadata>
在服務消費方TestService打上斷點篷牌,訪問 http://localhost:28080/test 可以看到ProviderService的實現類proxy為dubbo睡蟋,采用dubbo進行服務間調用
服務消費方使用restful調用,只需將dubbo相關依賴排除即可:
<dependency>
<groupId>cn.springcloud.dubbo</groupId>
<artifactId>spring-cloud-dubbo-starter</artifactId>
<exclusions>
<exclusion>
<groupId>com.alibaba.boot</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
</exclusion>
</exclusions>
</dependency>
在服務消費方TestService打上斷點枷颊,訪問 http://localhost:28080/test 可以看到ProviderService的實現類proxy為feign戳杀,采用restful進行服務間調用
FAQ
如何使用更加細致的dubbo配置?
我們的工程融合了spring cloud和dubbo夭苗,只是將feign底層實現替換為dubbo而已信卡,因此所有dubbo標準用法均支持。服務提供方可以使用標準dubbo @Service注解進行細致配置:
@Service(group = "testGroup")
@RestController
public class ProviderServiceImpl implements ProviderService {
}
服務消費方可以使用標準dubbo @Reference注解進行細致配置:
// @Autowired
@Reference(group = "testGroup")
private ProviderService providerService;
作者:Charles_He
鏈接:http://www.reibang.com/p/0368dc1e9357
來源:簡書