您可以捐助,支持我们的公益事业。

1元 10元 50元





认证码:  验证码,看不清楚?请点击刷新验证码 必填



  求知 文章 文库 Lib 视频 iPerson 课程 认证 咨询 工具 讲座 Modeler   Code  
会员   
 
   
 
 
     
   
 订阅
  捐助
dubbo高级配置学习(下)
 
作者:wanglei0622 来源:CSDN 发布于 2015-9-10
   次浏览      
 

结果缓存

结果缓存,用于加速热门数据的访问速度,Dubbo提供声明式缓存,以减少用户加缓存的工作量。

2.1.0以上版本支持

示例代码:https://github.com/alibaba/dubbo/tree/master/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/cache

lru 基于最近最少使用原则删除多余缓存,保持最热的数据被缓存。

threadlocal 当前线程缓存,比如一个页面渲染,用到很多portal,每个portal都要去查用户信息,通过线程缓存,可以减少这种多余访问。

jcache 与JSR107集成,可以桥接各种缓存实现。

缓存类型可扩展,参见:CacheFactory扩展点

配置如:

<dubbo:reference

interface="com.foo.BarService"

cache="lru"

/>

或:

<dubbo:reference

interface="com.foo.BarService">
<dubbo:method

name="findBar"

cache="lru"

/>
</dubbo:reference>

泛化引用

泛接口调用方式主要用于客户端没有API接口及模型类元的情况,参数及返回值中的所有POJO均用Map表示,通常用于框架集成,比如:实现一个通用的服务测试框架,可通过GenericService调用所有服务实现。

<dubbo:reference

id="barService"

interface="com.foo.BarService"

generic="true"

/>



GenericService
barService = (GenericService) applicationContext.getBean("barService");
Object
result = barService.$invoke("sayHello",
new

String[] { "java.lang.String"

}, new

Object[] { "World"

});

 

import

com.alibaba.dubbo.rpc.service.GenericService;

//
引用远程服务
ReferenceConfig<GenericService>
reference = new

ReferenceConfig<GenericService>(); //
该实例很重量,里面封装了所有与注册中心及服务提供方连接,请缓存
reference.setInterface("com.xxx.XxxService");
//
弱类型接口名
reference.setVersion("1.0.0");
reference.setGeneric(true);
//
声明为泛化接口
GenericService
genericService = reference.get(); //
用com.alibaba.dubbo.rpc.service.GenericService可以替代所有接口引用
//
基本类型以及Date,List,Map等不需要转换,直接调用
Object
result = genericService.$invoke("sayHello",
new

String[] {"java.lang.String"},
new

Object[] {"world"});
//
用Map表示POJO参数,如果返回值为POJO也将自动转成Map
Map<String,
Object> person = new

HashMap<String, Object>();
person.put("name",
"xxx");
person.put("password",
"yyy");
Object
result = genericService.$invoke("findPerson",
new

String[]{"com.xxx.Person"},
new

Object[]{person}); //
如果返回POJO将自动转成Map

假设存在POJO如:

package

com.xxx;
public

class
PersonImpl implements

Person {
private

String name;
private

String password;
public

String getName() {
return

name;
}
public

void
setName(String name) {
this.name
= name;
}
public

String getPassword() {
return

password;
}
public

void
setPassword(String password) {
this.password=
password;
}
}

则POJO数据:


Person
person = new

PersonImpl();
person.setName("xxx");
person.setPassword("yyy");

可用下面Map表示:

Map<String,
Object> map = new

HashMap<String, Object>();
map.put("class",
"com.xxx.PersonImpl");
//
注意:如果参数类型是接口,或者List等丢失泛型,可通过class属性指定类型。
map.put("name",
"xxx");
map.put("password",
"yyy");

泛化实现

泛接口实现方式主要用于服务器端没有API接口及模型类元的情况,参数及返回值中的所有POJO均用Map表示,通常用于框架集成,比如:实现一个通用的远程服务Mock框架,可通过实现GenericService接口处理所有服务请求。

<bean

id="genericService"

class="com.foo.MyGenericService"

/>
<dubbo:service

interface="com.foo.BarService"

ref="genericService"

/>


package

com.foo;
public

class
MyGenericService implements

GenericService {
public

Object $invoke(String methodName, String[] parameterTypes, Object[] args)
throws

GenericException {
if

("sayHello".equals(methodName))
{
return

"Welcome "
+ args[0];
}
}
}


...

GenericService
xxxService = new

XxxGenericService(); //
用com.alibaba.dubbo.rpc.service.GenericService可以替代所有接口实现
ServiceConfig<GenericService>
service = new

ServiceConfig<GenericService>(); //
该实例很重量,里面封装了所有与注册中心及服务提供方连接,请缓存
service.setInterface("com.xxx.XxxService");
//
弱类型接口名
service.setVersion("1.0.0");
service.setRef(xxxService);
//
指向一个通用服务实现
//
暴露及注册服务
service.export();

回声测试

回声测试用于检测服务是否可用,回声测试按照正常请求流程执行,能够测试整个调用是否通畅,可用于监控。

所有服务自动实现EchoService接口,只需将任意服务引用强制转型为EchoService,即可使用。

<dubbo:reference

id="memberService"

interface="com.xxx.MemberService"

/>



MemberService
memberService = ctx.getBean("memberService");
//
远程服务引用
EchoService
echoService = (EchoService) memberService; //
强制转型为EchoService
String
status = echoService.$echo("OK");
//
回声测试可用性
assert(status.equals("OK"))

上下文信息

上下文中存放的是当前调用过程中所需的环境信息。

所有配置信息都将转换为URL的参数,参见《配置项一览表》中的“对应URL参数”一列。

注意

RpcContext是一个ThreadLocal的临时状态记录器,当接收到RPC请求,或发起RPC请求时,RpcContext的状态都会变化。

比如:A调B,B再调C,则B机器上,在B调C之前,RpcContext记录的是A调B的信息,在B调C之后,RpcContext记录的是B调C的信息。

(1) 服务消费方

xxxService.xxx();
//
远程调用

boolean

isConsumerSide = RpcContext.getContext().isConsumerSide(); //
本端是否为消费端,这里会返回true
String
serverIP = RpcContext.getContext().getRemoteHost(); //
获取最后一次调用的提供方IP地址
String
application = RpcContext.getContext().getUrl().getParameter("application");
//
获取当前服务配置信息,所有配置信息都将转换为URL的参数
//
...
yyyService.yyy();
//
注意:每发起RPC调用,上下文状态会变化
//
...

(2) 服务提供方

public

class
XxxServiceImpl implements

XxxService {
public

void
xxx() { //
服务方法实现
boolean

isProviderSide = RpcContext.getContext().isProviderSide(); //
本端是否为提供端,这里会返回true
String
clientIP = RpcContext.getContext().getRemoteHost(); //
获取调用方IP地址
String
application = RpcContext.getContext().getUrl().getParameter("application");
//
获取当前服务配置信息,所有配置信息都将转换为URL的参数
//
...
yyyService.yyy();
//
注意:每发起RPC调用,上下文状态会变化
boolean

isProviderSide = RpcContext.getContext().isProviderSide(); //
此时本端变成消费端,这里会返回false
//
...
}
}

隐式传参

注:path,group,version,dubbo,token,timeout几个key有特殊处理,请使用其它key值。

(1) 服务消费方

RpcContext.getContext().setAttachment("index",
"1");
//
隐式传参,后面的远程调用都会隐式将这些参数发送到服务器端, 类似cookie,用于框架集成,不建议常规业务使用

xxxService.xxx();
//
远程调用


//
...

【注】 setAttachment设置的KV,在完成下面一次远程调用会被清空。即多次远程调用要多次设置。

(2) 服务提供方

public

class
XxxServiceImpl implements

XxxService {
public

void
xxx() { //
服务方法实现
String
index = RpcContext.getContext().getAttachment("index");
//
获取客户端隐式传入的参数,用于框架集成,不建议常规业务使用
//
...
}
}

异步调用

基于NIO的非阻塞实现并行调用,客户端不需要启动多线程即可完成并行调用多个远程服务,相对多线程开销较小。

2.0.6及其以上版本支持

配置声明:

consumer.xml

<dubbo:reference

id="fooService"

interface="com.alibaba.foo.FooService">


<dubbo:method

name="findFoo"

async="true"

/>


</dubbo:reference>


<dubbo:reference

id="barService"

interface="com.alibaba.bar.BarService">


<dubbo:method

name="findBar"

async="true"

/>


</dubbo:reference>

调用代码:

fooService.findFoo(fooId);
//
此调用会立即返回null


Future<Foo>
fooFuture = RpcContext.getContext().getFuture(); //
拿到调用的Future引用,当结果返回后,会被通知和设置到此Future。



barService.findBar(barId);
//
此调用会立即返回null


Future<Bar>
barFuture = RpcContext.getContext().getFuture(); //
拿到调用的Future引用,当结果返回后,会被通知和设置到此Future。



//
此时findFoo和findBar的请求同时在执行,客户端不需要启动多线程来支持并行,而是借助NIO的非阻塞完成。



Foo
foo = fooFuture.get(); //
如果foo已返回,直接拿到返回值,否则线程wait住,等待foo返回后,线程会被notify唤醒。


Bar
bar = barFuture.get(); //
同理等待bar返回。



//
如果foo需要5秒返回,bar需要6秒返回,实际只需等6秒,即可获取到foo和bar,进行接下来的处理。

你也可以设置是否等待消息发出:(异步总是不等待返回)

sent="true" 等待消息发出,消息发送失败将抛出异常。

sent="false" 不等待消息发出,将消息放入IO队列,即刻返回。

<dubbo:method

name="findFoo"

async="true"

sent="true"

/>

如果你只是想异步,完全忽略返回值,可以配置return="false",以减少Future对象的创建和管理成本:


<dubbo:method

name="findFoo"

async="true"

return="false"

/>

本地调用

本地调用,使用了Injvm协议,是一个伪协议,它不开启端口,不发起远程调用,只在JVM内直接关联,但执行Dubbo的Filter链。

Define injvm protocol:

<dubbo:protocol

name="injvm"

/>

<dubbo:provider

protocol="injvm"

/>

Set service protocol:


<dubbo:service

protocol="injvm"

/>

Use injvm first:

<dubbo:consumer

injvm="true"

.../>
<dubbo:provider

injvm="true"

.../>

<dubbo:reference

injvm="true"

.../>
<dubbo:service

injvm="true"

.../>

注意:服务暴露与服务引用都需要声明injvm="true"

自动暴露、引用本地服务

从 dubbo 2.2.0 开始,每个服务默认都会在本地暴露;在引用服务的时候,默认优先引用本地服务;如果希望引用远程服务可以使用一下配置强制引用远程服务。

<dubbo:reference

... scope="remote"

/>

参数回调

参数回调方式与调用本地callback或listener相同,只需要在Spring的配置文件中声明哪个参数是callback类型即可,Dubbo将基于长连接生成反向代理,这样就可以从服务器端调用客户端逻辑。

2.0.6及其以上版本支持

代码参见:https://github.com/alibaba/dubbo/tree/master/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/callback

(1) 共享服务接口:

服务接口示例:

CallbackService.java

package

com.callback;
public

interface
CallbackService {
void

addListener(String key, CallbackListener listener);
}

CallbackListener.java

package

com.callback;
public

interface
CallbackListener {
void

changed(String msg);
}

(2) 服务提供者:

服务提供者接口实现示例:

CallbackServiceImpl.java

package

com.callback.impl;
import

java.text.SimpleDateFormat;
import

java.util.Date;
import

java.util.Map;
import

java.util.concurrent.ConcurrentHashMap;
import

com.callback.CallbackListener;
import

com.callback.CallbackService;
public

class
CallbackServiceImpl implements

CallbackService {
private

final
Map<String, CallbackListener> listeners = new

ConcurrentHashMap<String, CallbackListener>();
public

CallbackServiceImpl() {
Thread
t = new

Thread(new

Runnable() {
public

void
run() {
while(true)
{
try

{
for(Map.Entry<String,
CallbackListener> entry : listeners.entrySet()){
try

{
entry.getValue().changed(getChanged(entry.getKey()));
}
catch

(Throwable t) {
listeners.remove(entry.getKey());
}
}
Thread.sleep(5000);
//
定时触发变更通知
}
catch

(Throwable t) { //
防御容错
t.printStackTrace();
}
}
}
});
t.setDaemon(true);
t.start();
}
public

void
addListener(String key, CallbackListener listener) {
listeners.put(key,
listener);
listener.changed(getChanged(key));
//
发送变更通知
}
private

String getChanged(String key) {
return

"Changed: "
+ new

SimpleDateFormat("yyyy-MM-dd
HH:mm:ss").format(new

Date());
}
}

服务提供者配置示例:

<bean

id="callbackService"

class="com.callback.impl.CallbackServiceImpl"

/>
<dubbo:service

interface="com.callback.CallbackService"

ref="callbackService"

connections="1"

callbacks="1000">
<dubbo:method

name="addListener">
<dubbo:argument

index="1"

callback="true"

/>
<!--也可以通过指定类型的方式-->
<!--<dubbo:argument
type="com.demo.CallbackListener" callback="true" />-->
</dubbo:method>
</dubbo:service>

(3) 服务消费者:

服务消费者配置示例:

consumer.xml


<dubbo:reference

id="callbackService"

interface="com.callback.CallbackService"

/>

 

服务消费者调用示例:

ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:consumer.xml");
context.start();

CallbackService callbackService = (CallbackService) context.getBean("callbackService");

callbackService.addListener("http://10.20.160.198/wiki/display/dubbo/foo.bar", new CallbackListener(){
public void changed(String msg) {
System.out.println("callback1:" + msg);
}
});

事件通知

在调用之前,调用之后,出现异常时,会触发oninvoke, onreturn, onthrow三个事件,可以配置当事件发生时,通知哪个类的哪个方法。

支持版本:2.0.7之后

(1) 服务提供者与消费者共享服务接口:

IDemoService.java

interface

IDemoService {
public

Person get(int

id);
}

(2) 服务提供者实现:

DemoServiceImpl.java

class

NormalDemoService implements

IDemoService {
public

Person get(int

id) {
return

new
Person(id, "charles`son",
4);
}
}

(3) 服务提供者配置:

provider.xml

<dubbo:application name="rpc-callback-demo" />

<dubbo:registry address="http://10.20.160.198/wiki/display/dubbo/10.20.153.186" />

<bean id="demoService" class="com.alibaba.dubbo.callback.implicit.NormalDemoService" />

<dubbo:service interface="com.alibaba.dubbo.callback.implicit.IDemoService" ref="demoService" version="1.0.0" group="cn"/>

(4) 服务消费者Callback接口及实现:

Nofify.java

interface

Nofify {
public

void
onreturn(Person msg, Integer id);
public

void
onthrow(Throwable ex, Integer id);
}


class

NofifyImpl implements

Nofify {
public

Map<Integer, Person> ret = new

HashMap<Integer, Person>();
public

Map<Integer, Throwable> errors = new

HashMap<Integer, Throwable>();
public

void
onreturn(Person msg, Integer id) {
System.out.println("onreturn:"

+ msg);
ret.put(id,
msg);
}
public

void
onthrow(Throwable ex, Integer id) {
errors.put(id,
ex);
}
}

(5) 服务消费者Callback接口及实现:

consumer.xml

注:

callback与async功能正交分解:

async=true,表示结果是否马上返回.

onreturn 表示是否需要回调.

组合情况:(async=false 默认)

异步回调模式:async=true onreturn="xxx"

同步回调模式:async=false onreturn="xxx"

异步无回调 :async=true

同步无回调 :async=false

(6) TEST CASE:

Test.java

<bean

id
="demoCallback"

class
= "com.alibaba.dubbo.callback.implicit.NofifyImpl"

/>
<dubbo:reference

id="demoService"

interface="com.alibaba.dubbo.callback.implicit.IDemoService"

version="1.0.0"

group="cn"

>
<dubbo:method

name="get"

async="true"

onreturn
= "demoCallback.onreturn"

onthrow="demoCallback.onthrow"

/>
</dubbo:reference>

 
   
次浏览       
相关文章

企业架构、TOGAF与ArchiMate概览
架构师之路-如何做好业务建模?
大型网站电商网站架构案例和技术架构的示例
完整的Archimate视点指南(包括示例)
相关文档

数据中台技术架构方法论与实践
适用ArchiMate、EA 和 iSpace进行企业架构建模
Zachman企业架构框架简介
企业架构让SOA落地
相关课程

云平台与微服务架构设计
中台战略、中台建设与数字商业
亿级用户高并发、高可用系统架构
高可用分布式架构设计与实践
最新活动计划
LLM大模型应用与项目构建 12-26[特惠]
QT应用开发 11-21[线上]
C++高级编程 11-27[北京]
业务建模&领域驱动设计 11-15[北京]
用户研究与用户建模 11-21[北京]
SysML和EA进行系统设计建模 11-28[北京]

专家视角看IT与架构
软件架构设计
面向服务体系架构和业务组件
人人网移动开发架构
架构腐化之谜
谈平台即服务PaaS

面向应用的架构设计实践
单元测试+重构+设计模式
软件架构师—高级实践
软件架构设计方法、案例与实践
嵌入式软件架构设计—高级实践
SOA体系结构实践

锐安科技 软件架构设计方法
成都 嵌入式软件架构设计
上海汽车 嵌入式软件架构设计
北京 软件架构设计
上海 软件架构设计案例与实践
北京 架构设计方法案例与实践
深圳 架构设计方法案例与实践
嵌入式软件架构设计—高级实践
更多...