Demo结构介绍

Demo使用Maven聚合功能,里面有三个模块,目录如下:

  • 其中Consumer模块为服务消费者,里面TestConsumer和consumer.xml组成了基于Spring配置方式的服务调用,TestConsumerApi是基于Dubbo API方式的服务调用,TestConsumerApiGeneric是泛化方式的服务调用,TestConsumerAsync是异步调用的方式。
  • 其中Provider模块为服务提供者,里面TestProvider和provider.xml组成了基于Spring配置方式的服务提供,TestProviderApi是基于Dubbo API的服务提供,UserServiceImpl为服务实现类。
  • 其中SDK模块是一个二方包,用来存放服务提供者所有的接口,是为了代码复用使用,在服务提供者和消费者的模块里面都需要引入这个二方包。

其中SDK里面的接口定义源码如下:

public interface UserServiceBo {
String sayHello(String name);
String testPojo(Person person);
}
public interface Person {
}

在SDK模块执行 mvn clean install 命令会安装该模块的jar到本地仓库,要想在其他模块引入该jar,必须要先执行这个安装步骤。

基于Spring配置的服务提供方与消费方搭建

Provider模块为服务提供者,作用是提供的服务到Zookeeper,并使用Netty服务监听服务消费端的链接。里面TestProvider和provider.xml组成了基于XML方式的服务提供,UserServiceImpl为服务实现类。

首先需要在Provider模块里面引入SDK模块,因为Provider模块需要用到UserServiceBo接口(需要在SDK模块执行 mvn clean install 命令,会安装该模块的jar到本地仓库)。

然后实现UserServiceBo接口为UserServiceImpl,代码如下:

public class UserServiceImpl implements UserServiceBo{

    @Override
public String sayHello(String name) {
//让当前当前线程休眠2s
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
} return name;
} @Override
public String sayHello2(String name) {
//让当前当前线程休眠2s
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
} return name;
}
@Override
public String testPojo(Person person) {
return JSON.toJSONString(person);
}
}

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:context="http://www.springframework.org/schema/context"
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://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://code.alibabatech.com/schema/dubbo
http://code.alibabatech.com/schema/dubbo/dubbo.xsd"> <!-- 提供方应用信息,用于计算依赖关系 -->
<dubbo:application name="dubboProvider" /> <!-- 使用zookeeper注册中心暴露服务地址 -->
<dubbo:registry address="zookeeper://127.0.0.1:2181" /> <!-- 用dubbo协议在20880端口暴露服务 -->
<dubbo:protocol name="dubbo" port="20880" />
<!-- 启用monitor模块 -->
<dubbo:monitor protocol="registry" /> <bean id="userService" class="com.test.UserServiceImpl" /> <!-- 声明需要暴露的服务接口 -->
<dubbo:service interface="com.test.UserServiceBo" ref="userService"
group="dubbo" version="1.0.0" timeout="3000"/> </beans>

日志文件log4j.properties内容如下:

log4j.rootLogger=INFO,A1
log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.PatternLayout

然后,编写服务发布测试类TestProvider,代码如下:

public class TestProvider {   

    public static void main(String[] arg) throws InterruptedException {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:provider.xml"); //挂起当前线程,如果没有改行代码,服务提供者进程会消亡,服务消费者就发现不了提供者了
Thread.currentThread().join();
}
}

最后,运行TestProvider类,输出如下:

说明当前服务已经注册了Zookeeper。

基于Spring配置的服务消费方搭建

Consumer模块为服务消费方,服务消费端主要是从Zookeeper获取自己需要的服务提供者的ip列表,然后根据路由规则选择一个ip进行远程调用。里面TestConsumer和consumer.xml组成了基于xml方式的服务调用。

首先需要在Consumer模块中引入SDK模块,因为Consumer模块需要用到UserServiceBo接口(泛化调用时候不需要这个步骤)。

consumer.xml内容如下:

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
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://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://code.alibabatech.com/schema/dubbo
http://code.alibabatech.com/schema/dubbo/dubbo.xsd"> <!-- 消费方应用名,用于计算依赖关系,不是匹配条件,不要与提供方一样 -->
<dubbo:application name="dubboConsumer" /> <!-- 使用multicast广播注册中心暴露发现服务地址 -->
<dubbo:registry protocol="zookeeper" address="zookeeper://127.0.0.1:2181" />
<!-- 启动monitor-->
<dubbo:monitor protocol="registry" />
<!-- 生成远程服务代理,可以和本地bean一样使用demoService -->
<dubbo:reference id="userService" interface="com.test.UserServiceBo" group="dubbo" version="1.0.0" timeout="3000"/> </beans>

测试服务消费类TestConsumer代码如下:

public class TestConsumer {

    public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
new String[] { "classpath:consumer.xml" }); final UserServiceBo demoService = (UserServiceBo) context.getBean("userService"); System.out.println(demoService.sayHello("哈哈哈"));
}
}

最后运行TestConsumer,会输出:

说明服务消费端已经正常调用了服务提供方的服务了。

注:至此一个经典的含有服务提供者/服务消费者/服务注册中心的简单分布式系统搭建完毕了。

基于Dubbo API方式的服务提供方与消费方搭建

基于Dubbo API方式的服务提供方搭建

其中Provider模块为服务提供者,里面TestProviderApi是基于Dubbo Api的服务提供,UserServiceImpl为服务实现类。

首先需要在Provider模块里面引入SDK模块,这个不变。

然后实现UserServiceBo接口为UserServiceImpl,这个也不变。

再接着编写Dubbo Api服务提供测试代码TestProviderApi,代码如下:

public class TestProviderApi {

    public static void main(String[] arg) throws InterruptedException {

        //(4.3.1-1)等价于  <bean id="userService" class="com.test.UserServiceImpl" />
UserServiceBo userService = new UserServiceImpl();
//(4.3.1-2)等价于 <dubbo:application name="dubboProvider" />
ApplicationConfig application = new ApplicationConfig();
application.setName("dubboProvider"); //(4.3.1-3)等价于 <dubbo:registry address="zookeeper://127.0.0.1:2181" />
RegistryConfig registry = new RegistryConfig();
registry.setAddress("127.0.0.1:2181");
registry.setProtocol("zookeeper"); // (4.3.1-4)等价于 <dubbo:protocol name="dubbo" port="20880" />
ProtocolConfig protocol = new ProtocolConfig();
protocol.setName("dubbo");
protocol.setPort(20880); //4.3.1-5)等价于 <dubbo:monitor protocol="registry" />
MonitorConfig monitorConfig = new MonitorConfig();
monitorConfig.setProtocol("registry"); //4.3.1-6)等价于 <dubbo:service interface="com.test.UserServiceBo" ref="userService"
//group="dubbo" version="1.0.0" timeout="3000"/>
ServiceConfig<UserServiceBo> service = new ServiceConfig<UserServiceBo>(); // 此实例很重,封装了与注册中心的连接,请自行缓存,否则可能造成内存和连接泄漏
service.setApplication(application);
service.setMonitor(monitorConfig);
service.setRegistry(registry); // 多个注册中心可以用setRegistries()
service.setProtocol(protocol); // 多个协议可以用setProtocols()
service.setInterface(UserServiceBo.class);
service.setRef(userService);
service.setVersion("1.0.0");
service.setGroup("dubbo");
service.setTimeout(3000);
service.export(); //4.3.1-8) 挂起当前线程
Thread.currentThread().join();
}
}

基于dubbo-spring-boot-starter使用SpringBoot搭建一个简单的服务提供者服务应用,这里重新打包一个SDK,内容如下:

服务提供方搭建

服务提供方应用结构如下:

其中ProviderApp为SpringBoot的启动类,代码如下:

@SpringBootApplication
@EnableDubboConfiguration
@RestController
@ComponentScan(basePackages = { "com.gitchat.demo.provider.service" })
public class ProviderApp { @RequestMapping("/")
String home() {
return "Hello Demo!";
}
public static void main(String[] args) {
SpringApplication.run(ProviderApp.class, args);
}
}

@ComponentScan(basePackages={"com.gitchat.demo.provider.service"})说明扫描com.gitchat.demo.provider.service包下的@Component注解的类到Spring容器。

UserServiceImpl为服务实现类,代码如下:

@Service(interfaceClass = UserServiceBo.class,group="dubbo",version="1.0.0")
@Component
public class UserServiceBoImpl implements UserServiceBo{ @Override
public String sayHello(String name) {
return "hello:" + name;
} @Override
public String testPojo(Person person) {
return person.toString();
} }

@Service(interfaceClass=UserServiceBo.class,group="dubbo",version="1.0.0")标示UserServiceBoImpl会作为服务提供出去,dubbo-start会扫描到这个注解,并创建一个ServiceConfig对象,然后调用ServiceConfig的export方法发布服务到Zookeeper。使用dubbo-starter后,你只需要在需要发布的服务的实现类上添加@Service注解就可以了,无须在显示创建ServiceConfig对象。

配置文件application.properties内容如下:

server.port=7003
management.port=7004
spring.application.name=demo-provider spring.dubbo.server=true
spring.dubbo.registry=zookeeper://127.0.0.1:2181

其中server.port为内嵌Tomcat容器监听端口,management.port为健康检查端口,spring.application.name为应用的名称,spring.dubbo.server=true说明开启Dubbo服务,spring.dubbo.registry为服务注册中心地址。

日志配置文件log4j.properties内容如下:

log4j.rootLogger=INFO,A1
log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.PatternLayout

pom.xml里面需要配置内容如下,首先由于是SpringBoot应用所以需要如下引入:

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.1.RELEASE</version>
</parent>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

还需要引入dubbo-spring-boot-starter,这个starter里面包含了Dubbo需要的东西:

    <dependency>
<groupId>com.alibaba.spring.boot</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>2.0.0</version>
</dependency>

然后引入Zookeeper包,和依赖的SDK:

        <dependency>
<groupId>com.101tec</groupId>
<artifactId>zkclient</artifactId>
<version>0.10</version>
<exclusions>
<exclusion>
<artifactId>slf4j-log4j12</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
</exclusions>
</dependency>

最后需要引入spring-boot-maven插件,以便打包为可执行的jar文件:

<build>
<finalName>demo-provider</finalName> <plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<executable>false</executable>
<excludeDevtools>true</excludeDevtools>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>

上面配置完毕后,执行ProviderApp的main函数输出如下,可知服务注册到Zookeeper了:

服务消费方搭建

服务消费方应用结构如下:

其中ConsumerApp为SpringBoot启动的入口,代码如下:

@SpringBootApplication
@EnableDubboConfiguration
@RestController
@ComponentScan(basePackages = { "com.gitchat.demo.consumer.service" })
public class ConsumerApp { @Autowired
private ConsumerService consumerService; @RequestMapping(value = "/testSayHello", method = RequestMethod.GET)
String testSayHello(@RequestParam(value = "name", required = true) String name) {
return consumerService.sayHello(name);
} @RequestMapping("/")
String home() {
return "Hello Demo!";
} public static void main(String[] args) {
SpringApplication.run(ConsumerApp.class, args); }
}

可知注入了ConsumerService的一个实例到Spring容器,然后testSayHello方法内部调用了ConsumerService实例的sayHello方法,这个controller是为了测试服务消费的,下面我们看看ConsumerService的实现:

@Component
public class ConsumerService { @Reference(group="dubbo",interfaceClass=UserServiceBo.class,version="1.0.0")
private UserServiceBo userServiceBo; public String sayHello(String name){
return userServiceBo.sayHello(name);
}
}

注解@Reference标示当前要消费UserServiceBo接口的服务,并通过注解说明要消费服务的接口,版本和分组信息,dubbo-starter会自动扫描这个注解然后生成一个ReferenceConfig对象,然后调用ReferenceConfig的get()方法获取远程调用实例的代理类,并设置到userServiceBo变量。ConsumerService的sayHello方法则是调用远程服务userServiceBo的sayHello方法。

配置文件application.properties内容如下:

server.port=7001
management.port=7002
spring.application.name=demo-consumer spring.dubbo.server=true
spring.dubbo.registry=zookeeper://127.0.0.1:2181

pom文件和日志文件与服务提供者类似,不再赘述。

Dubbo学习笔记2:Dubbo服务提供端与消费端应用的搭建的更多相关文章

  1. Dubbo学习笔记4:服务消费端泛化调用与异步调用

    本文借用dubbo.learn的Dubbo API方式来解释原理. 服务消费端泛化调用 前面我们讲解到,基于Spring和基于Dubbo API方式搭建简单的分布式系统时,服务消费端引入了一个SDK二 ...

  2. dubbo学习笔记二(服务调用)

    项目结构 代码示例 由于之前的IEchoService 的一个方法只是在服务端控制台打印,不便在浏览器测试,所以新添加的方法 api和服务端代码变更 public interface IEchoSer ...

  3. dubbo学习笔记一(服务注册)

    相关的资料 官方文档 官方博客 项目结构 项目说明 [lesson1-config-api] 是一个接口工程,编译后是jar包,被其他工程依赖 [lesson1-config-2-properties ...

  4. dubbo学习笔记(二)dubbo中的filter

    转:https://www.cnblogs.com/cdfive2018/p/10219730.html dubbo框架提供了filter机制的扩展点(本文基于dubbo2.6.0版本). 扩展接口 ...

  5. Dubbo学习笔记(二) Dubbo的基本配置

    Check启动检查 根据之前的学习,我们简单理解的Dubbo远程调用的基本流程,服务提供者注册到注册中心,然后服务消费者通过监听注册中心达到远程调用的目的,那么如果注册中心中没有消费者对应的接口会怎么 ...

  6. Dubbo 学习(二)服务注册与发现

    在上一篇中我们提到,dubbo官网上推荐使用ZooKeeper作为注册中心.那么今天我们就通过代码来实践一番,看看一个dubbo的服务消费者如果找到通过ZooKeeper暴露自己的dubbo服务提供者 ...

  7. 并发编程学习笔记(4)----jdk5中提供的原子类及Lock使用及原理

    (1)jdk中原子类的使用: jdk5中提供了很多原子类,它会使变量的操作变成原子性的. 原子性:原子性指的是一个操作是不可中断的,即使是在多个线程一起操作的情况下,一个操作一旦开始,就不会被其他线程 ...

  8. # go微服务框架kratos学习笔记六(kratos 服务发现 discovery)

    目录 go微服务框架kratos学习笔记六(kratos 服务发现 discovery) http api register 服务注册 fetch 获取实例 fetchs 批量获取实例 polls 批 ...

  9. Dubbo学习笔记10:Dubbo服务消费方启动流程源码分析

    同理我们看下服务消费端启动流程时序图: 在<Dubbo整体架构分析>一文中,我们提到服务消费方需要使用ReferenceConfig API来消费服务,具体是调用代码(1)get()方法来 ...

随机推荐

  1. eg_5

    问题描述:输入两个字符串,从第一字符串中删除第二个字符串中所有的字符. 例如,输入”They are students.”和”aeiou”,则删除之后的第一个字符串变成”Thy r stdnts.” ...

  2. 团队作业之404 Note Found Team

    如果记忆是一个罐头的话,我希望这一罐罐头不会过期----<重庆森林> 404 Note Found Team 如果记忆是一个备忘录的话,别说了,它不会过期----<404 Note ...

  3. Rsyslog日志服务搭建

    rsyslog是比syslog功能更强大的日志记录系统,可以将日志输出到文件,数据库和其它程序.Centos 6.x默认的rsyslog版本是5.x. 网上关于rsyslog的安装配置文档倒是不少,但 ...

  4. 关于对i++,++i的理解

    i++,代表 先赋值,在加:++i,代表先自加再赋值:后台console例子中可以看到第一个例子:var a= i++;  i是等于1的:先赋值,所以打印出a =1的:而i++后为2:所以打印出a = ...

  5. 深度学习:卷积神经网络(convolution neural network)

    (一)卷积神经网络 卷积神经网络最早是由Lecun在1998年提出的. 卷积神经网络通畅使用的三个基本概念为: 1.局部视觉域: 2.权值共享: 3.池化操作. 在卷积神经网络中,局部接受域表明输入图 ...

  6. BZOJ5102 POI2018Prawnicy(堆)

    考虑固定右端点,使左端点最小.那么按右端点排序后查询前缀这些区间的左端点第k小即可.然而写了一个treap一个线段树都T飞了,感觉惨爆.事实上可以用堆求第k小,维护一个大根堆保证堆中元素不超过k个即可 ...

  7. MT【155】单调有界必有极限

    (清华2017.4.29标准学术能力测试20) 已知数列$\{a_n\}$,其中$a_1=a$,$a_2=b$,$a_{n+2}=a_n-\dfrac 7{a_{n+1}}$,则_______ A.$ ...

  8. 【刷题】BZOJ 2157 旅游

    Description Ray 乐忠于旅游,这次他来到了T 城.T 城是一个水上城市,一共有 N 个景点,有些景点之间会用一座桥连接.为了方便游客到达每个景点但又为了节约成本,T 城的任意两个景点之间 ...

  9. [AT2268] [agc008_f] Black Radius

    题目链接 AtCoder:https://agc008.contest.atcoder.jp/tasks/agc008_f 洛谷:https://www.luogu.org/problemnew/sh ...

  10. 51nod 1293 球与切换器 | DP

    51nod 1293 球与切换器 | DP 题面 有N行M列的正方形盒子.每个盒子有三种状态0, -1, +1.球从盒子上边或左边进入盒子,从下边或右边离开盒子.规则: 如果盒子的模式是-1,则进入它 ...