我今天了解一下dubbo的用法,虽然多,但是我只想了解注解的用法(毕竟之前都主要是注解)。
然后再dubbo-samples下面有个dubbo-samples-annotation目录。给的示例是使用zookeeper作为注册中心,要实现的就是架构图而已,主要是先了解registry,provider,和consumer的用法:
看示例是使用zookeeper作为注册中心。所以下了一个zookeeper。
思路流程1、首先肯定是启动zookeeper,然后看下初始有什么目录。
2、再启动provider,启动完毕后观察zookeeper多了什么东西,然后根据内容猜测含义。
3、再启动consumer,再观察zookeeper有什么变化。
刚开始的zookeeper肯定是这样的:
然后启动org.apache.dubbo.samples.annotation.AnnotationProviderBootstrap,多了两个目录:
dubbo和service。
猜测字面意思dubbo就存放于dubbo相关的信息,service就存放于服务相关的信息。
验证首先看dubbo
依次有config, mapping, metadata, org.apache.dubbo.samples.annotation.api.GreetingService, org.apache.dubbo.samples.annotation.api.HelloService。
config, mapping, metadata根据字面意思就是配置信息,映射信息和元数据信息。
后面两个应该就是暴露的服务api。
大概找了一找前三个重复度相对高一点,主要是还是对外暴露的api(猜测可能是api可以取别名之类的,默认一致),应该是用的时候需要拿值。所以前三个先不管。
还是看看后面两个。因为做事情是一致的 所以就用其中一个就行了。
这个基本应该都猜得到 configurators应该是保存配置信息的。providers就是服务提供方(微服务下可能服务有多个)。
configurators没有值。看providers。
dubbo%3A%2F%2F192.168.2.49%3A20880%2Forg.apache.dubbo.samples.annotation.api.HelloService%3Fanyhost%3Dtrue%26application%3Dsamples-annotation-provider%26deprecated%3Dfalse%26dubbo%3D2.0.2%26dynamic%3Dtrue%26generic%3Dfalse%26interface%3Dorg.apache.dubbo.samples.annotation.api.HelloService%26metadata-type%3Dremote%26methods%3DsayHello%2CsayGoodbye%26pid%3D12444%26release%3D3.0.2.1%26revision%3D1.0.0_annotation%26sayGoodbye.retries%3D0%26sayGoodbye.return%3Dtrue%26sayGoodbye.sent%3Dtrue%26sayGoodbye.timeout%3D250%26service-name-mapping%3Dtrue%26side%3Dprovider%26timeout%3D1000%26timestamp%3D1640077451474%26token%3D27c2a162-5a0e-4150-a1ad-b4806548e250%26version%3D1.0.0_annotation
这个应该就是所谓的dubbo协议。
比如首先出现的dubbo表示是dubbo协议,后面的ip是我网卡的地址,在后面是api调用路径等等等。
再看一下services节点
感觉像是dubbo应用名。然后我就改了一下这个重启
所以应该是这个控制了。
再看看节点下的东西。
就是暴露服务的ip和端口。
接下来就是consumer了。理论上应该类似:
原本我以为/services应该会有个consumer的服务,但是没有。应该是调用就结束了,所以没有必要单独存个服务名。
主要是这个地方有变化:
看看之前的:
多了router,consumer两个。
字面意思router就是路由的,consumer就是消费方。
不知为何没有数据,先就这样,整体很乱,我整理一张图出来试试。
应用例子其实看了一看,也没有什么好说的。
provider:简单带过就是借助spring的容器配置好bean,然后根据配置文件配置服务提供的一些信息。扫描对应的类将接口调用注册到zookeeper中。
实际流程:
1、AnnotationProviderBootstrap:启动spring容器加载并配置ProviderConfiguration类。
2、ProviderConfiguration:通过加载dubbo-provider.properties配置属性,加载对应的接口实现类调用实际的方法。然后生产一个ProviderConfig类并对外提供api。
public class AnnotationProviderBootstrap {
public static void main(String[] args) throws Exception {
new EmbeddedZooKeeper(2181, false).start();
//使用spring环境,在ProviderConfiguration类中申明并注册接口和相关配置
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ProviderConfiguration.class);
//容器环境启动
context.start();
System.out.println("dubbo service started.");
new CountDownLatch(1).await();
}
}
@Configuration
@EnableDubbo(scanbasePackages = "org.apache.dubbo.samples.annotation.impl")
@PropertySource("classpath:/spring/dubbo-provider.properties")
public class ProviderConfiguration {
@Bean
public ProviderConfig providerConfig() {
ProviderConfig providerConfig = new ProviderConfig();
providerConfig.setTimeout(1000);
return providerConfig;
}
}
@DubboService(version = AnnotationConstants.VERSION, methods = {@Method(name = "sayGoodbye", timeout = 250, retries = 0)})
public class AnnotationHelloServiceImpl implements HelloService {
@Override
public String sayHello(String name) {
System.out.println("provider received invoke of sayHello: " + name);
sleepWhile();
return "Annotation, hello " + name;
}
public String sayGoodbye(String name) {
System.out.println("provider received invoke of sayGoodbye: " + name);
sleepWhile();
return "Goodbye, " + name;
}
private void sleepWhile() {
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
dubbo.application.name=samples-annotation-provider
dubbo.registry.address=zookeeper://${zookeeper.address:127.0.0.1}:2181
dubbo.protocol.name=dubbo
dubbo.protocol.port=20880
dubbo.provider.token=true
consumer:与provider类似,都是要指定一些信息和属性,但不同的是作为调用方。需要知道调用provider的哪个接口的哪个方法。
实际流程:
1、AnnotationConsumerBootstrap:启动spring容器加载并配置ConsumerConfiguration类,然后从spring容器中拿到bean,再调用对应的方法。
2、ConsumerConfiguration:通过加载dubbo-consumer.properties配置属性,加载对应的接口实现类调用实际的方法。
3、AnnotationAction:通过@DubboReference绑定接口,并配置属性(如版本、超时时间等),方便使用接口调用provider提供的方法。
public class AnnotationConsumerBootstrap {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ConsumerConfiguration.class);
context.start();
final AnnotationAction annotationAction = (AnnotationAction) context.getBean("annotationAction");
System.out.println("hello : " + annotationAction.doSayHello("world"));
System.out.println("goodbye : " + annotationAction.doSayGoodbye("world"));
System.out.println("greeting : " + annotationAction.doGreeting("world"));
System.out.println("reply : " + annotationAction.replyGreeting("world"));
}
}
@Configuration
@EnableDubbo(scanbasePackages = "org.apache.dubbo.samples.annotation.action")
@PropertySource("classpath:/spring/dubbo-consumer.properties")
@ComponentScan(value = {"org.apache.dubbo.samples.annotation.action"})
public class ConsumerConfiguration {
}
dubbo.application.name=samples-annotation-consumer
dubbo.registry.address=zookeeper://${zookeeper.address:127.0.0.1}:2181
@Component("annotationAction")
public class AnnotationAction {
@DubboReference(interfaceClass = HelloService.class, version = AnnotationConstants.VERSION
)
private HelloService helloService;
@DubboReference(interfaceClass = GreetingService.class,
version = AnnotationConstants.VERSION,
timeout = 1000,
methods = {@Method(name = "greeting", timeout = 3000, retries = 1)})
private GreetingService greetingService;
public String doSayHello(String name) {
try {
return helloService.sayHello(name);
} catch (Exception e) {
e.printStackTrace();
return "Throw Exception";
}
}
public String doSayGoodbye(String name) {
try {
return helloService.sayGoodbye(name);
} catch (Exception e) {
e.printStackTrace();
return "Throw Exception";
}
}
public String doGreeting(String name) {
try {
return greetingService.greeting(name);
} catch (Exception e) {
e.printStackTrace();
return "Throw Exception";
}
}
public String replyGreeting(String name) {
try {
return greetingService.replyGreeting(name);
} catch (Exception e) {
e.printStackTrace();
return "Throw Exception";
}
}
}
总结:从上面可以看出来。要实现调用,要统一好接口。即不管是provider还是consumer,api的接口应该都一致,所以一般来说微服务的接口调用都会在父项目上写一个公共的api接口,这样就避免了接口不一致出现问题。总体过程感觉好像完全理解了调用,但是让我叙述一遍似乎又没什么好说的,可能还是没有实际运用过吧



