网站一屏做多大,寻找电销团队合作,wordpress 资料导出,网站买空间我们已经介绍了Dubbo在服务治理方面提供的特性#xff0c;今天我们一起来看看Dubbo在其它方面提供的特性。同服务治理篇一样#xff0c;本文的目的在于学会使用Dubbo在服务管控方面提供的特性#xff0c;依旧不涉及任何实现原理。
工程结构
嗯~~
是这样的#xff0c;因为…
我们已经介绍了Dubbo在服务治理方面提供的特性今天我们一起来看看Dubbo在其它方面提供的特性。同服务治理篇一样本文的目的在于学会使用Dubbo在服务管控方面提供的特性依旧不涉及任何实现原理。
工程结构
嗯~~
是这样的因为电脑过于拉胯而且IDEA着实有些吃内存了所有我将测试工程按照子项目合并到一起了目前我使用的工程结构是这样的 子模块名由两部分组成配置方式功能如XMLProvider表示以XML配置方式为主的服务提供方。
TipsIDEA快要追上“内存雄狮”CLionl了。
本地存根Stub
使用Dubbo时服务使用方只集成了接口所有的实现全都在服务提供方但部分场景中我们希望服务使用方完成一些逻辑的处理以此来减少RPC交互带来的性能消耗例如将参数校验放在服务使用方去做减少一次与服务调用方的网络交互。 这种场景中我们可以使用Dubbo提供的本地存根特性。我们有如下的服务提供方的工程结构 xml-provider-api模块中定义了对外提供服务的接口XMLProviderService代码如下
public interface XMLProviderService {String say(String message);
}
以及接口存根XMLProviderServiceStub代码如下
public class XMLProviderServiceStub implements XMLProviderService {private final XMLProviderService xmlProviderService;public XMLProviderServiceStub(XMLProviderService xmlProviderService) {this.xmlProviderService xmlProviderService;}Overridepublic String say(String message) {if (StringUtils.isBlank(message)) {return message不能为空;}try {return this.xmlProviderService.say(message);} catch (Exception e) {return 远程调用失败: e.getMessage();}}
}
接着我们在服务使用方的工程中配置接口存根
dubbo:reference idxmlProviderService interfacecom.wyz.api.XMLProviderService stubcom.wyz.api.stub.XMLProviderServiceStub/
Tips使用本地存根要求存根的实现类必须有传入Proxy实例服务使用方提生成的Proxy实例的构造函数。
本地伪装Mock
本地伪装即我们在《Dubbo的高级特性服务治理篇》中提到的服务降级我们今天再稍微做一个补充。本地伪装是本地存根的一个子集本地存根可以处理RPC调用环节中各种各样的错误和异常而本地伪装则专注于处理RpcException如网络失败响应超时等这种需要容错处理的异常。
我们为XMLProviderService添加一个本地伪装服务XMLProviderServiceMock工程结构如下 XMLProviderServiceMock的代码如下
public class XMLProviderServiceMock implements XMLProviderService {Overridepublic String say(String message) {return 服务出错了;}
}
配置文件可以按如下方式配置
dubbo:reference idxmlProviderService interfacecom.wyz.api.XMLProviderService mocktrue/
这种配置中要求Mock的实现必须按照“接口名Mock后缀”的方式进行命名如果不想使用这种命名方式可以使用全限名
dubbo:reference idxmlProviderService interfacecom.wyz.api.XMLProviderService mockcom.wyz.api.mock.XMLProviderServiceMock/
Tips再“重复”一遍Mock的原因是上一篇中出了一点错误本应在dubbo:reference标签中做的配置我写到了dubbo:service标签中产生错误的原因还是没有动手在项目中写一写哎真应了那句“纸上得来终觉浅绝知此事要躬行”。
参数回调
Dubbo支持参数回调功能使服务提供方可以“反向”调用服务使用方该功能是基于长链接生成的反向代理实现的效果类似于异步调用。我们举个支付的例子
XMLProvider工程的xml-provider-api模块中添加PaymentService接口同时添加PaymentNotifyService用于通知PaymentService的结果
public interface PaymentService {void payment(String cardNo, PaymentNotifyService paymentNotifyService);
}public interface PaymentNotifyService {void paymentNotify(String message);
}
XMLProvider工程的xml-provider-service模块中实现PaymentService接口
public class PaymentServiceImpl implements PaymentService {Overridepublic void payment(String cardNo, PaymentNotifyService paymentNotifyService) {System.out.println(向卡号[ cardNo ]付钱);// 业务逻辑paymentNotifyService.paymentNotify(付款成功);}
}
执行PaymentService#payment方法并调用PaymentNotifyService#paymentNotify方法通知服务调用方执行结果。
XMLConsumer工程中实现PaymentNotifyService接口
public class PaymentNotifyServiceImpl implements PaymentNotifyService {Overridepublic void paymentNotify(String message) {System.out.println(支付结果 message);}
}
来看一下此时的工程结构 接下来是XML的配置参数回调中我们需要关注的是服务提供方XMLProvider工程的xml-provider-service模块的配置
bean idpaymentServiceImpl classcom.wyz.service.impl.PaymentServiceImpl/
dubbo:service interfacecom.wyz.api.PaymentService refpaymentServiceImpl callbacks10dubbo:method namepaymentdubbo:argument index1 callbacktrue//dubbo:method
/dubbo:service
配置通过第4行的dubbo:argument index1 callbacktrue/来确定PaymentService#payment方法中第2个index从0开始参数是回调参数callbacks限制了同一个长链接下回调的次数而不是总共回调的次数。
Tips在实际的支付业务场景中更倾向于异步处理比如服务提供方在接收到支付请求是启动新线程处理支付业务并调用通知接口主线程返回成功接收支付请求。
异步调用
异步调用允许服务提供方立即返回响应同时后台继续执行请求处理当服务使用方请求响应结果时服务提供方将结果返回。 DUbbo支持两种异步调用方式
使用CompletableFuture接口使用RpcContext
DUbbo 2.7之后DUbbo以CompletableFuture接口为异步编程的基础。
使用CompletableFuture实现异步调用
我们先来看如何使用CompletableFuture实现异步调用声明CompletableFutureAsyncService接口
public interface CompletableFutureAsyncService {CompletableFutureString async(String message);
}
接着是接口实现
public class CompletableFutureAsyncServiceImpl implements CompletableFutureAsyncService {Overridepublic CompletableFutureString async(String message) {return CompletableFuture.supplyAsync(() - {System.out.println(Thread.currentThread().getName() say : message);try {TimeUnit.SECONDS.sleep(10);} catch (InterruptedException e) {throw new RuntimeException(e);}return 异步调用成功;});}
}
XML配置与普通的DubboRPC接口配置相同xml-provider-service模块的配置
bean idcompletableFutureAsyncServiceImpl classcom.wyz.service.impl.CompletableFutureAsyncServiceImpl /
dubbo:service interfacecom.wyz.api.CompletableFutureAsyncService refcompletableFutureAsyncServiceImpl /
XMLConsumer模块的配置
dubbo:reference idcompletableFutureAsyncService interfacecom.wyz.api.CompletableFutureAsyncService/
使用方式也非常简单
CompletableFutureString completableFuture completableFutureAsyncService.async(Hello);
System.out.println(completableFuture.get());
Tips
Dubbo中使用CompletableFuture与单独使用CompletableFuture并无什么差异~~CompletableFutureAsyncServiceImpl的实现中打印接口名称的目的是为了清晰的展示出异步调用的效果CompletableFuture#supplyAsync(SupplierU supplier)默认使用ForkJoinPool#commonPool()重载方法CompletableFuture#supplyAsync(SupplierU supplier, Executor executor)允许使用自定义线程池。
使用AsyncContext实现异步调用
除了使用CompletableFuture外还可以通过Dubbo定义的AsyncContext实现异步调用。先来编写接口和接口实现
public interface RpcContextAsyncService {String async(String message);
}public class RpcContextAsyncServiceImpl implements RpcContextAsyncService {Overridepublic String async(String message) {final AsyncContext asyncContext RpcContext.startAsync();new Thread(() - {asyncContext.signalContextSwitch();asyncContext.write(Thread.currentThread().getName() say : message);}).start();// 异步调用中这个返回值完全没有意义return null;}
}
服务提供方的配置与其它Dubbo接口的配置并无不同
bean idrpcContextAsyncServiceImpl classcom.wyz.service.impl.RpcContextAsyncServiceImpl/
dubbo:service interfacecom.wyz.api.RpcContextAsyncService refrpcContextAsyncServiceImpl/
接着是服务使用方的配置需要添加async参数
dubbo:reference idrpcContextAsyncService interfacecom.wyz.api.RpcContextAsyncService asynctrue/
最后是在服务使用方中调用RPC接口
rpcContextAsyncService.async(Thanks);FutureString future RpcContext.getServiceContext().getFuture();
System.out.println(future.get());
泛化调用
Dubbo的泛化调用提供了一种不依赖服务提供方APISDK的而调用服务的实现方式。主要场景在于网关平台的实现通常网关的实现不应该依赖于其他服务的APISDK。
Dubbo官方提供了3种泛化调用的方式
通过API使用泛化调用通过Spring使用泛化调用XML形式Protobuf对象泛化调用
这里我们介绍以XML的形式配置泛化调用的方式。
准备工作
首先我们再准备一个服务提供的工程GenericProvider工程结构如下 工程中定义了接口即实现类GenericProviderService和GenericProviderServiceImpl代码如下
public interface GenericProviderService {String say(String message);
}public class GenericProviderServiceImpl implements GenericProviderService {Overridepublic String say(String message) {return GenericProvider say: message;}
}
generic-dubbo-provider.xml中只需要正常配置GenericProvider提供的服务即可
bean idgenericProviderServiceImpl classcom.wyz.service.impl.GenericProviderServiceImpl/
dubbo:service interfacecom.wyz.service.api.GenericProviderService refgenericProviderServiceImpl generictrue/
application.yml文件的配置我们就不多赘述了。
服务使用方的配置
回到XMLConsumer工程中先配置Dubbo服务引用xml-dubbo-consumer.xml中添加如下内容
dubbo:reference idgenericProviderService generictrue interfacecom.wyz.service.api.GenericProviderService/
参数generic声明这是一个泛化调用的服务。此时IDEA会将interfacecom.wyz.service.api.GenericProviderService标红提示“Cannot resolve class GenericProviderService”这个我们不需要关注因为com.wyz.service.api包下确实不存在GenericProviderService接口。
接着我们来使用GenericProviderService接口
ApplicationContext context SpringContextUtils.getApplicationContext();
// genericProviderService是XML中定义的服务id
GenericService genericService (GenericService) context.getBean(genericProviderService);// $invoke的3个参数分别为方法名参数类型参数
Object result genericService.$invoke(say, new String[]{java.lang.String}, new Object[]{wyz});
System.out.println(result);
这样我们就可以通过ApplicationContext获取到GenericProviderService接口提供的服务了。
TipsSpringContextUtils用于获取ApplicationContext代码如下
Component
public class SpringContextUtils implements ApplicationContextAware {private static ApplicationContext applicationContext null;public static ApplicationContext getApplicationContext() {return SpringContextUtils.applicationContext;}Overridepublic void setApplicationContext(Nonnull ApplicationContext applicationContext) throws BeansException {SpringContextUtils.applicationContext applicationContext;}
}
结语
好了到目前为止我们已经一起认识并学习了Dubbo中常用特性的配置与使用当然了经历了多年的发展Dubbo的提供的特性远不止于此如果想要了解更多内容可以查看阿里巴巴提供的文档《Apache Dubbo微服务框架从入门到精通》。
下一篇我们从服务注册部分正式开启对Dubbo实现原理的探索。 如果本文对你有帮助的话还请多多点赞支持。如果文章中出现任何错误还请批评指正。最后欢迎大家关注分享硬核Java技术的金融摸鱼侠王有志我们下次再见