在文章开始的时候先引入官网的架构图,

节点角色说明
| 节点 | 角色说明 |
|---|---|
Provider | 暴露服务的服务提供方 |
Consumer | 调用远程服务的服务消费方 |
Registry | 服务注册与发现的注册中心 |
Monitor | 统计服务的调用次数和调用时间的监控中心 |
Container | 服务运行容器 |
以上取自dubbo官网文档 http://dubbo.apache.org/zh-cn/docs/user/preface/architecture.html
dubbo干嘛的?一个分布式的RPC远程调用框架,可以使得调用远程服务如同调用本地服务一般的框架.具体介绍可以前往官网文档查看,这里不多加赘述,官网文档地址已在上文提及.
接下来看一个dubbo的样例.
先看一下整个样例的层级结构

api为公共组件,包括服务的接口规范
consumer为服务消费方,provider为服务提供方.
首先看api模块
代码如下:
public interface DoSomeDemo {
String doSome(String name);
}
pom文件配置如下
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>dubboDemo</artifactId>
<groupId>dubboDemo</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>api</artifactId>
<dependencies>
<dependency>
<groupId>dubboDemo</groupId>
<artifactId>api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.6.2</version>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.9</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>4.0.0</version>
</dependency>
</dependencies>
</project>
pom文件中引入了dubbo,zookeeper(注册中心)
接下来是consumer模块的代码

代码如下
public class Consumer {
public Object getRemoteCall(String url){
//创建一个远程服务代理
ReferenceConfig referenceConfig=new ReferenceConfig();
//配置当前应用信息
ApplicationConfig applicationConfig=new ApplicationConfig("consumer");
referenceConfig.setApplication(applicationConfig);
//选择远程服务
referenceConfig.setInterface(DoSomeDemo.class);
//直连的方式 无需注册中心,将url传入即可
//referenceConfig.setUrl(url);
//Multicast注册中心 不需要启动任何中心节点,只要广播地址一样,就可以互相发现
// RegistryConfig registryConfig=new RegistryConfig("multicast://224.1.1.1:111");
//zookeeper注册中心
RegistryConfig registryConfig=new RegistryConfig("zookeeper://127.0.0.1:2181");
referenceConfig.setRegistry(registryConfig);
//和本地bean一样使用xxxService,返回的就是拿到的远程服务对象(实际为一个代理对象)
return referenceConfig.get();
}
public static void main(String[] args) throws IOException {
Consumer consumer=new Consumer();
//如果使用直连方式则需要将整个url传入,本机的ip为10.111.23.237
//DoSomeDemo doSomeDemo = (DoSomeDemo) consumer.getRemoteCall("dubbo://10.111.23.237:20880/dubbo.service.DoSomeDemo");
DoSomeDemo doSomeDemo = (DoSomeDemo) consumer.getRemoteCall(null);
while (!"Q".equals(read())){
//调用远程服务
System.out.println(doSomeDemo.doSome("ok"));
}
}
//读取后台输入
private static String read(){
LineNumberReader lineNumberReader = new LineNumberReader(
new InputStreamReader(System.in));
try {
return lineNumberReader.readLine();
} catch (IOException e) {
e.printStackTrace();
}
return "";
}
}
代码中列出了三种注册中心的方式,直连(无注册中心),Multicast注册中心(不需要启动任何中心节点),zookeeper注册中心,这里采取zookeeper举例.
这里的配置只满足最简单的举例,详细的配置依赖关系如下:图片取自dubbo官网api
说回代码,consumer已经有了,接下来看看provider

dubbo.service目录底下为实现api接口的实现
public class DoSomeDemoImpl implements DoSomeDemo {
@Override
public String doSome(String name) {
return ("provider --- dubbo.service.DoSomeDemoImpl"+"------"+name+"---"+ RpcContext.getContext().getLocalAddressString());
}
}
打印出Rpc调用的端口及方法入参,便于之后查看对比结果
pom文件中引入api模块即可
<dependencies>
<dependency>
<groupId>dubboDemo</groupId>
<artifactId>api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
最为关键的Provider的实现代码如下
public class Provider {
public static void start(int port){
//服务提供者暴露服务配置
ServiceConfig serviceConfig=new ServiceConfig();
//服务config 相当于 <dubbo:application/>配置
ApplicationConfig applicationConfig=new ApplicationConfig("provider");
serviceConfig.setApplication(applicationConfig);
//服务提供者协议配置 协议config 相当于<dubbo:protocol/>配置
ProtocolConfig protocolConfig=new ProtocolConfig("dubbo",port);
serviceConfig.setProtocol(protocolConfig);
//直连 协议config
//RegistryConfig registryConfig=new RegistryConfig(RegistryConfig.NO_AVAILABLE);
//Multicast注册中心
//RegistryConfig registryConfig=new RegistryConfig("multicast://224.1.1.1:111");
RegistryConfig registryConfig=new RegistryConfig("zookeeper://127.0.0.1:2181");
serviceConfig.setRegistry(registryConfig);
//将服务的具体方法设置进去
serviceConfig.setInterface(DoSomeDemo.class);
serviceConfig.setRef(new DoSomeDemoImpl());
// 暴露及注册服务
serviceConfig.export();
//拿到当前服务的端口
port=((URL)serviceConfig.getExportedUrls().get(0)).getPort();
System.out.println("服务启动:"+port);
}
public static void main(String[] args) throws IOException {
Provider.start(-1);
System.in.read();
}
}
简言之,设置服务,选择协议,选择注册中心,将服务方法设入,全部放进服务配置中,然后暴露此服务
到这里,其实已经能够将Consumer与Provider启动,并且能够在Consumer中调用"DoSomeDemo"接口的实现方法了.
接下来看看Xml配置方式该如何设置

consumer.xml配置文件如下
<?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="consumerSpringXml"/>
<dubbo:reference interface="dubbo.service.DoSomeDemo" id="doSomeDemo"/>
<dubbo:registry address="zookeeper://127.0.0.1:2181"/>
</beans>
没错,和属性配置没什么区别,定义服务名称(consumerSpringXml),定义注册中心(zookeeper://127.0.0.1:2181),创建远程服务代理(dubbo.service.DoSomeDemo)
启动类代码如下
public class SpringConsumerXml {
public static void main(String[] args) throws IOException {
ApplicationContext context=new ClassPathXmlApplicationContext("consumer.xml");
((ClassPathXmlApplicationContext)context).start();
System.in.read();
DoSomeDemo doSomeDemo= (DoSomeDemo) context.getBean("doSomeDemo");
while (!"Q".equals(read())){
System.out.println(doSomeDemo.doSome("Xml"));
}
}
private static String read(){
LineNumberReader lineNumberReader = new LineNumberReader(
new InputStreamReader(System.in));
try {
return lineNumberReader.readLine();
} catch (IOException e) {
e.printStackTrace();
}
return "";
}
}
加载xml文件启动,拿到doSomeDemo对象,直接调用即可,与调用本地对象没有区别
接下来看看provider用xml配置的模块

provider.xml代码如下
<?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="providerSpringXml"/>
<dubbo:protocol port="-1" name="dubbo"/>
<dubbo:registry protocol="zookeeper" address="127.0.0.1:2181"/>
<dubbo:service interface="dubbo.service.DoSomeDemo" ref="doSomeDemoXml"/>
<!--将bean对象交给spring容器管理-->
<bean id="doSomeDemoXml" class="dubbo.service.DoSomeDemoXmlImpl"/>
</beans>
与consumer.xml不同的在于需要将提供的服务对象交给spring容器管理
启动类代码如下:
public class SpringProviderXml {
public static void main(String[] args) throws IOException {
ApplicationContext context=new ClassPathXmlApplicationContext("provider.xml");
((ClassPathXmlApplicationContext)context).start();
System.in.read();
}
}
单纯的加载xml文件,启动,System.in.read();是为了让服务不停止
最后看看使用注解的方式

注意,这里的DoService类
import com.alibaba.dubbo.config.annotation.Reference;
import dubbo.service.DoSomeDemo;
import org.springframework.stereotype.Service;
@Service
public class DoService {
@Reference
DoSomeDemo doSomeDemo;
public String doSome(String name){
return doSomeDemo.doSome(name);
}
}
@Reference为dubbo的注解,而@Service为spring的注解,为了将该对象交由spring容器管理
properties文件配置则更加简单
dubbo.application.name:consumerSpringProperties
dubbo.registry.address:zookeeper://127.0.0.1:2181
仅此而已
启动类则配置稍微多一些
@Configuration
@EnableDubbo(scanBasePackages = "service")
@PropertySource("consumer.properties")
@ComponentScan("service")
public class SpringConsumerProperties {
public static void main(String[] args) {
ApplicationContext context=new AnnotationConfigApplicationContext(SpringConsumerProperties.class);
((AnnotationConfigApplicationContext)context).start();
DoService doService= (DoService) context.getBean("doService");
while (!"Q".equals(read())){
System.out.println(doService.doSome("Properties"));
}
}
private static String read(){
LineNumberReader lineNumberReader = new LineNumberReader(
new InputStreamReader(System.in));
try {
return lineNumberReader.readLine();
} catch (IOException e) {
e.printStackTrace();
}
return "";
}
}
注解从上往下依次介绍,@Configuration为spring配置类注解,这里不再赘述,
@EnableDubbo(scanBasePackages = "service")
@ComponentScan("service")
这两个注解为开启dubbo 并设置注解的扫描范围,由于这里的样例将包名取为service且只有一层,所以容易引起误解,实际情况则需要将包名路径全部写入
@PropertySource("consumer.properties") 读取配置文件的注解,这里也不多介绍
最后再来看看Provider用注解的配置

properties文件
dubbo.application.name:providerSpringProvider
dubbo.protocol.name:dubbo
dubbo.protocol.port:-1
dubbo.registry.address:zookeeper://127.0.0.1:2181
暴露的服务方法
import com.alibaba.dubbo.config.annotation.Service;
@Service
public class DoSomeDemoPropertiesImpl implements DoSomeDemo {
@Override
public String doSome(String name) {
return ("provider --- dubbo.service.DoSomeDemoPropertiesImpl"+"------"+name+"---"+ RpcContext.getContext().getLocalAddressString());
}
}
而这里要注意的则是@Service注解为dubbo注解,不是spring的
启动类
@Configuration
@PropertySource("provider.properties")
@EnableDubbo(scanBasePackages = "dubbo.service")
public class SpringProviderProperties {
public static void main(String[] args) throws IOException {
ApplicationContext context=new AnnotationConfigApplicationContext(SpringProviderProperties.class);
((AnnotationConfigApplicationContext)context).start();
System.in.read();
}
}
大致与Consumer相似,这里不再赘述
本文介绍了Dubbo作为一个分布式RPC框架的基本概念和作用,并通过代码样例展示了如何搭建Dubbo服务,包括API、XML配置和注解方式的消费者与提供者实现。详细解释了各个模块的配置,如注册中心、服务暴露等。
372

被折叠的 条评论
为什么被折叠?



