第一个dubbo程序

第一个dubbo程序

Dubbo是阿里SOA服务化治理方案的核心框架,它提供了注册中心机制,解耦了消费方和服务方动态发现的问题,并提供高可靠能力,大量采用为内核+富插件设计思想,包括框架自身核心特性都作为扩展点实现,提供灵活的可扩展能力。

Dubbo架构

上图是Dubbo的架构图,其中Provider在启动时会向注册中心把自己的元数据注册上去(比如服务IP和端口等),Consumer在启动时从注册中心订阅(第一次订阅会拉取全量数据)服务提供方的元数据,注册中心发生数据变更会推送给订阅的Consumer。在获取服务元数据后,Consumer可以发起RPC调用,在RPC调用前后会向监控中心上报统计信息(比如并发数和调用的接口)。

下面我们就使用Dubbo搭建一个简单的Demo。

安装Zookeeper

从Zookeeper的官网下载Zookeeper的安装包,解压到任意目录,作为安装目录install_directory

新建环境变量ZK_HOME,指向${install_directory}/

将${ZK_HOME}/bin路径,添加到可执行路径

在${ZK_HOME}/conf路径下复制一份配置文件zoo_sample.cfg,并重命名为zoo.cfg

在终端执行zkServer.sh start即可,默认会监听2181端口。

第一个dubbo程序

新建一个Maven项目,依赖为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<dependencies>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.6.3</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo-rpc-rest</artifactId>
<version>2.6.3</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>2.12.0</version>
</dependency>
</dependencies>

然后新建三个子模块:

  • first-dubbo-service:对外暴露的服务,所有对外暴露的接口,都在这边
  • first-dubbo-server:first-dubbo-service的实现方,实现了first-dubbo-service暴露的接口
  • first-dubbo-client:服务调用方

基于XML配置实现

first-dubbo-service

首先声明一个HelloService接口,提供一个hello方法

1
2
3
4
public interface HelloService {

public String hello(String name);
}

first-dubbo-server

定义一个HelloService的实现类,实现了HelloService的hello方法

1
2
3
4
5
6
7
public class HelloServiceImpl implements HelloService {
public String hello(String name) {
String now = new SimpleDateFormat("HH:mm:ss").format(new Date());
return "Hello, " + name + ", now is " + now + ", request from " + RpcContext.getContext().getRemoteAddressString();
}
}

接着编写一个启动类,它做的主要是从指定的XML配置文件中读取配置,并启动

1
2
3
4
5
6
7
8
9
public class HelloServerApplication {

public static void main(String[] args) throws Exception {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"spring/hello-server.xml"});
context.start();
System.in.read();
}

}

spring/hello-server.xml配置文件内容为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd">

<!-- 服务提供方应用名称, 方便用于依赖跟踪 -->
<dubbo:application name="hello-server"/>

<!-- 使用本地zookeeper作为注册中心 -->
<dubbo:registry address="zookeeper://127.0.0.1:2181"/>

<!-- 只用Dubbo协议并且指定监听端口 20880 -->
<dubbo:protocol name="dubbo" port="20880"/>

<!-- 通过xml方式配置为bean, 让spring托管和实例化 -->
<bean id="helloService" class="com.dubbo.service.impl.HelloServiceImpl"/>

<!-- 声明服务暴露的接口,并暴露服务 -->
<dubbo:service interface="com.dubbo.service.HelloService" ref="helloService"/>

</beans>

启动完成之后,打开XShell,执行命令telnet localhost 20880连接上dubbo。

telnet连接

然后输入invoke com.dubbo.service.HelloService.hello("huhansan")发起调用,调用的格式为invoke [接口.fangfa ]

invoke调用接口方法

上图为调用成功,标明Server服务成功启动,并且成功响应了调用。

first-dubbo-client

client的启动代码如下:

1
2
3
4
5
6
7
8
9
public class HelloClientApplication {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"spring/hello-client.xml"});
context.start();
HelloService helloService = (HelloService) context.getBean("helloService");
String result = helloService.hello("huhansan");
System.out.println("Call hello result is " + result);
}
}

其中spring/hello-client.xml配置为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<?xml version="1.0" encoding="UTF-8"?>
<!--
~
~ Licensed to the Apache Software Foundation (ASF) under one or more
~ contributor license agreements. See the NOTICE file distributed with
~ this work for additional information regarding copyright ownership.
~ The ASF licenses this file to You under the Apache License, Version 2.0
~ (the "License"); you may not use this file except in compliance with
~ the License. You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
~
-->

<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd">

<!-- 服务消费方应用名称, 方便用于依赖跟踪 -->
<dubbo:application name="hello-client"/>

<!-- 使用本地zookeeper作为注册中心 -->
<dubbo:registry address="zookeeper://127.0.0.1:2181"/>

<!-- 声明服务暴露的接口,并暴露服务 -->
<dubbo:reference id="helloService" check="false" interface="com.dubbo.service.HelloService"/>

</beans>

运行消费方的方法可得结果:

Client调用结果

基于注解实现

所有依赖保持不变。

first-dubbo-server

HelloService实现类修改为:

1
2
3
4
5
6
7
8
@Service
public class HelloServiceAnnotationImpl implements HelloService {
public String hello(String name) {
String now = new SimpleDateFormat("HH:mm:ss").format(new Date());
return "Hello, " + name + ", now is " + now + ", request from " + RpcContext.getContext().getRemoteAddressString();
}
}

在类上使用注解@Service标记

HelloServerApplication修改为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
public class HelloServerAnnotationApplication {

public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(HelloServerConfig.class);
}

@Configuration
// 指定扫描服务所在的包的路径
@EnableDubbo(scanBasePackages = "com.dubbo.service")
static class HelloServerConfig {

@Bean
public ProviderConfig providerConfig() {
return providerConfig();
}

@Bean
public ApplicationConfig applicationConfig() {
ApplicationConfig config = new ApplicationConfig();
config.setName("hello-client");
return config;
}

@Bean
public RegistryConfig registryConfig() {
RegistryConfig registryConfig = new RegistryConfig();
// 使用Zookeeper的注册中心,同时给出注册中心的IP和端口
registryConfig.setProtocol("zookeeper");
registryConfig.setAddress("localhost");
registryConfig.setPort(2181);
return registryConfig;
}

public ProtocolConfig protocolConfig() {
ProtocolConfig protocolConfig = new ProtocolConfig();
// 默认使用Dubbo服务,在20880端口监听服务
protocolConfig.setName("dubbo");
protocolConfig.setPort(20880);
return protocolConfig;
}
}

}

first-dubbo-client

HelloClientApplication修改为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
public class HelloClientAnnotationApplication {

public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(HelloClientConfig.class);
context.start();
HelloClientAnnotation helloService = context.getBean(HelloClientAnnotation.class);
String result = helloService.hello("huhansi");
System.out.println("Result is " + result);
}

@Configuration
@EnableDubbo(scanBasePackages = "com.dubbo.service")
@ComponentScan(value = {"com.dubbo.client"})
static class HelloClientConfig {
@Bean
public ApplicationConfig applicationConfig() {
ApplicationConfig config = new ApplicationConfig();
config.setName("hello-client");
return config;
}

@Bean
public ConsumerConfig consumerConfig() {
return new ConsumerConfig();
}

@Bean
public RegistryConfig registryConfig() {
RegistryConfig registryConfig = new RegistryConfig();
registryConfig.setProtocol("zookeeper");
registryConfig.setAddress("localhost");
registryConfig.setPort(2181);
return registryConfig;
}

}

}

新增一个HelloClientAnnotation类:

1
2
3
4
5
6
7
8
9
10
@Component
public class HelloClientAnnotation {
@Reference
private HelloService helloService;

public String hello(String name) {
return helloService.hello(name);
}
}

通过注解消费服务时,只需要@Reference注解标注,该注解适用于对象字段和方法中。因此需要做一下特殊的包装。

基于代码实现

所有依赖保持不变

first-dubbo-server

HelloServerApplication修改为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class HelloServerApiApplication {

public static void main(String[] args) throws Exception {
ServiceConfig<HelloService> service = new ServiceConfig<HelloService>();
service.setApplication(new ApplicationConfig("hello-server"));
service.setRegistry(new RegistryConfig("zookeeper://127.0.0.1:2181"));
service.setInterface(HelloService.class);
service.setRef(new HelloServiceImpl());
service.export();
System.out.println("Hello Server is running.");
System.in.read();
}

}

first-dubbo-client

HelloClientApplication修改为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class HelloClientApiApplication {

public static void main(String[] args) {
ReferenceConfig<HelloService> reference = new ReferenceConfig<HelloService>();
reference.setApplication(new ApplicationConfig("hello-client"));
reference.setRegistry(new RegistryConfig("zookeeper://127.0.0.1:2181"));
reference.setInterface(HelloService.class);
HelloService helloService = reference.get();
String result = helloService.hello("huhanwu");
System.out.println("Result is " + result);
}

}

0%