[TOC]
代碼
import java.util.List;
public abstract interface DemoService {
public abstract String build(String name) throws Exception;
String sayHello(String name);
List getUsers();
}
import java.util.ArrayList;
import java.util.List;
public class DemoServiceImpl implements DemoService {
public String sayHello(String name) {
return "Hello " + name;
}
public List getUsers() {
List list = new ArrayList();
User u1 = new User();
u1.setName("jack");
u1.setAge(20);
u1.setSex("男");
list.add(u1);
return list;
}
public String build(String name) throws Exception {
return null;
}
}
import java.io.Serializable;
//必須實現(xiàn)Serializable接口
public class User implements Serializable {
private static final long serialVersionUID = -2814022769568306965L;
private String name;
private Integer age;
private String sex;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
@Override
public String toString() {
return "User{" + "name='" + name + '\'' + ", age=" + age + ", sex='" + sex + '\'' + '}';
}
}
dubbo-provider.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://code.alibabatech.com/schema/dubbo
http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
<!-- 提供方應用信息河爹,用于計算依賴關系 -->
<dubbo:application name = "hello-world-app-provider" />
<!--zookeeper注冊中心 -->
<dubbo:registry protocol="zookeeper" address="vimda.vimda:2181" />
<!-- 用dubbo協(xié)議在20880端口暴露服務 -->
<dubbo:protocol name="dubbo" port="20880" />
<!-- 具體的實現(xiàn)bean -->
<bean id="demoProvideService" class="dubboxTs.DemoServiceImpl" />
<!-- 暴露的服務接口 -->
<dubbo:service interface="dubboxTs.DemoService" ref="demoProvideService"/>
</beans>
bean指定id塞栅,此id可用于其他bean或者dubbo:service引用;同時指明實現(xiàn)類dubboxTs.DemoServiceImpl 启泣。
dubbo:service interface指定服務接口類,ref引用上述已定義的服務bean ID。
dubbo:registry 指明通信協(xié)議和zookeeper地址纬黎。
dubbo-consumer.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://code.alibabatech.com/schema/dubbo
http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
<!-- 消費方應用名,用于計算依賴關系劫窒,不是匹配條件本今,不要與提供方一樣 -->
<dubbo:application name="hello-world-app-consumer"/>
<!-- 使用zookeeper注冊中心暴露服務地址 -->
<dubbo:registry protocol="zookeeper" address="vimda.vimda:2181"/>
<!-- 增加引用遠程服務配置 -->
<dubbo:reference id="demoConsumeService" interface="dubboxTs.DemoService"/>
</beans>
consumer先使用<
dubbo:registry>引用zookeeper。
其次使用dubbo:reference 引用已注冊在zookeeper中心的provide(demoConsumeService),并指出demoConsumeService的實現(xiàn)接口烛亦。
log4j.properties
log4j.rootLogger=debug,A1,DRF
# A1 is set to be a ConsoleAppender.
log4j.appender.A1=org.apache.log4j.ConsoleAppender
# A1 uses PatternLayout.
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=[%-5p][%d{yyyyMMdd HH:mm:ss,SSS}] [THREAD ID=%t] [%C{1}:%L] %m%n
#DRF
log4j.appender.DRF=org.apache.log4j.DailyRollingFileAppender
log4j.appender.DRF.Threshold=${log4j.leve}
log4j.appender.DRF.DatePattern='.'yyyy-MM-dd
log4j.appender.DRF.File=./log/monitor.log
#log4j.appender.DRF.File=../log/monitor.log
log4j.appender.DRF.Append=true
log4j.appender.DRF.layout=org.apache.log4j.PatternLayout
log4j.appender.DRF.layout.ConversionPattern=[%-5p][%d{yyyyMMdd HH:mm:ss,SSS}] [THREAD ID=%t] [%C{1}:%L] %m%n
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import dubboxTs.DemoService;
public class ConsumerTs {
@Test
public void startConsumer() {
try {
String configLocation = "dubbo-consumer.xml";
ApplicationContext context = new ClassPathXmlApplicationContext(configLocation);
String[] names = context.getBeanDefinitionNames();
System.out.print("Beans:");
for (String string : names) {
System.out.print(string);
System.out.print(",");
}
System.out.println();
DemoService ds = (DemoService) context.getBean("demoConsumeService");
System.out.println(ds.sayHello("hehe"));
System.out.println(ds.getUsers());
Thread.sleep(Long.MAX_VALUE);
} catch (Exception e) {
e.printStackTrace();
}
}
}
import java.io.IOException;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class ProviderTs {
@Test
public void startProvider(){
String configLocation = "dubbo-provider.xml";
ApplicationContext context = new ClassPathXmlApplicationContext(configLocation);
String[] names = context.getBeanDefinitionNames();
System.out.print("Beans:");
System.out.println();
for (String string : names){
System.out.print(string + ";");
}
try {
System.in.read();
} catch (IOException e) {
e.printStackTrace();
}
}
}
先啟動ProviderTs诈泼,后啟動ConsumerTs
provider控制臺
property source. Returning [null]
Beans:
hello-world-app-provider;com.alibaba.dubbo.config.RegistryConfig;dubbo;demoProvideService;dubboxTs.DemoService;
consumer控制臺
property source. Returning [null]
Beans:
hello-world-app-provider;com.alibaba.dubbo.config.RegistryConfig;dubbo;demoProvideService;dubboxTs.DemoService;[DEBUG][20170115 00:41:36,583]
講解
流程如下圖所示:
節(jié)點角色說明:
Provider: 暴露服務的服務提供方。
Consumer: 調(diào)用遠程服務的服務消費方煤禽。
Registry: 服務注冊與發(fā)現(xiàn)的注冊中心铐达。
Monitor: 統(tǒng)計服務的調(diào)用次調(diào)和調(diào)用時間的監(jiān)控中心。
Container: 服務運行容器檬果。
調(diào)用關系說明:
- 服務容器負責啟動瓮孙,加載唐断,運行服務提供者。
- 服務提供者在啟動時杭抠,向注冊中心注冊自己提供的服務脸甘。
- 服務消費者在啟動時,向注冊中心訂閱自己所需的服務偏灿。
- 注冊中心返回服務提供者地址列表給消費者丹诀,如果有變更,注冊中心將基于長連接推送變更數(shù)據(jù)給消費者翁垂。
- 服務消費者铆遭,從提供者地址列表中,基于軟負載均衡算法沿猜,選一臺提供者進行調(diào)用枚荣,如果調(diào)用失敗,再選另一臺調(diào)用啼肩。
- 服務消費者和提供者橄妆,在內(nèi)存中累計調(diào)用次數(shù)和調(diào)用時間,定時每分鐘發(fā)送一次統(tǒng)計數(shù)據(jù)到監(jiān)控中心祈坠。
窺看dubbo調(diào)用過程
問題
consumer如何找到消費者
consumer如何調(diào)用消費者的方法
provider如何接受消費者的請求和參數(shù),并如何調(diào)用對應方法
provider如何返回調(diào)用結(jié)果
首次調(diào)用
首先在ReferenceConfig的createProxy()等到invoker
interface DemoService -> zookeeper://192.168.91.25:2181/com.alibaba.dubbo.registry.RegistryService?anyhost=true&application=hello-world-app-consumer&check=false&dubbo=2.5.3&interface=DemoService&methods=sayHello,build,getUsers&pid=13388&side=consumer×tamp=1489659254215
我的zookeeper IP 端口為192.168.91.25:2181.
如下圖,未執(zhí)行ds.sayHello("hehe")前,消費者仍未知 提供者的具體"位置".
在 MockClusterInvoker處, result = this.invoker.invoke(invocation);進入AbstractClusterInvoker
public Result invoke(Invocation invocation) throws RpcException {Result result = null;String value = directory.getUrl().getMethodParameter(invocation.getMethodName(), Constants.MOCK_KEY, Boolean.FALSE.toString()).trim();if (value.length() == 0 || value.equalsIgnoreCase("false")){//no mock result = this.invoker.invoke(invocation);} else if (value.startsWith("force")) {if (logger.isWarnEnabled()) {logger.info("force-mock: " + invocation.getMethodName() + " force-mock enabled , url : " + directory.getUrl());}//force:direct mock result = doMockInvoke(invocation, null);} else {//fail-mock try {result = this.invoker.invoke(invocation);}catch (RpcException e) {if (e.isBiz()) {throw e;} else {if (logger.isWarnEnabled()) {logger.info("fail-mock: " + invocation.getMethodName() + " fail-mock enabled , url : " + directory.getUrl(), e);}result = doMockInvoke(invocation, e);}}}return result;}
在AbstractClusterInvoker 226行處獲得invokers的ip,端口,服務.
public Result invoke(final Invocation invocation) throws RpcException {
checkWheatherDestoried();
LoadBalance loadbalance;
List<Invoker<T>> invokers = list(invocation);
if (invokers != null && invokers.size() > 0) {
loadbalance = ExtensionLoader.getExtensionLoader(LoadBalance.class).getExtension(invokers.get(0).getUrl()
.getMethodParameter(invocation.getMethodName(),Constants.LOADBALANCE_KEY, Constants.DEFAULT_LOADBALANCE));
} else {
loadbalance = ExtensionLoader.getExtensionLoader(LoadBalance.class).getExtension(Constants.DEFAULT_LOADBALANCE);
}
RpcUtils.attachInvocationIdIfAsync(getUrl(), invocation);
return doInvoke(invocation, invokers, loadbalance);
}
227行調(diào)用遠程方法并返回調(diào)用結(jié)果.
provider方面
參考:
http://blog.csdn.net/a258831020/article/details/48011777
希望你能指出文章寫得不好之處,感激不盡.