dubbo初步认识
dubbo中文网站:http://dubbo.apache.org/zh-cn/
dubbo英文网站:http://dubbo.apache.org/en-us/
1.Apache Dubbo是一款高性能Java RPC框架
Apache Dubbo (incubating) |ˈdʌbəʊ| 是一款高性能、轻量级的开源Java RPC框架,它提供了三大核心能力:面向接口的远程方法调用,智能容错和负载均衡,以及服务自动注册和发现。
其结构图如下:
角色说明:
Provider 暴露服务的服务提供方
Consumer 调用远程服务的服务消费方
Registry 服务注册与发现的注册中心
Monitor 统计服务的调用次数和调用时间的监控中心
Container 服务运行容器
调用关系说明:
服务容器负责启动,加载,运行服务提供者。
服务提供者在启动时,向注册中心注册自己提供的服务。
服务消费者在启动时,向注册中心订阅自己所需的服务。
注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。
服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。
中文图:
RPC--远程过程调用协议:
RPC(Remote Procedure Call)—远程过程调用,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。RPC协议假定某些传输协议的存在,如TCP或UDP,为通信程序之间携带信息数据。在OSI网络通信模型中,RPC跨越了传输层和应用层。RPC使得开发包括网络分布式多程序在内的应用程序更加容易。
RPC采用客户机/服务器模式。请求程序就是一个客户机,而服务提供程序就是一个服务器。首先,客户机调用进程发送一个有进程参数的调用信息到服务进程,然后等待应答信息。在服务器端,进程保持睡眠状态直到调用信息的到达为止。当一个调用信息到达,服务器获得进程参数,计算结果,发送答复信息,然后等待下一个调用信息,最后,客户端调用进程接收答复信息,获得进程结果,然后调用执行继续进行
RPC类似于webservice,将服务发布为一个service。如果需要我们可以在普通的项目中使用RPC机制,RPC存在commons包中。
关于RPC的认识参考另一篇hadoop中的使用:https://www.cnblogs.com/qlqwjy/p/9087727.html
2、dubbo快速入门
一款dubbo管理项目(monitor管理器),基于web项目,部署在tomcat下面即可运行访问,默认用户名和密码都是root。https://github.com/qiao-zhi/springboot/blob/master/dubbo-admin-2.5.4.war
pom.xml
<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"> <modelVersion>4.0.0</modelVersion> <groupId>cn.qlq</groupId> <artifactId>zookeper</artifactId> <version>0.0.1-SNAPSHOT</version> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> <dependency> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> <version>3.4.8</version> </dependency> <dependency> <groupId>org.apache.curator</groupId> <artifactId>curator-framework</artifactId> <version>2.12.0</version> </dependency> <dependency> <groupId>org.apache.curator</groupId> <artifactId>curator-recipes</artifactId> <version>2.12.0</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>dubbo</artifactId> <version>2.5.5</version> </dependency> <dependency> <groupId>org.javassist</groupId> <artifactId>javassist</artifactId> <version>3.20.0-GA</version> </dependency> <dependency> <groupId>org.jboss.netty</groupId> <artifactId>netty</artifactId> <version>3.2.5.Final</version> </dependency> <dependency> <groupId>com.101tec</groupId> <artifactId>zkclient</artifactId> <version>0.2</version> </dependency> <dependency> <groupId>org.apache.curator</groupId> <artifactId>curator-framework</artifactId> <version>2.12.0</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.16</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.25</version> </dependency> </dependencies> <build> <!-- 配置了很多插件 --> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.5.1</version> <configuration> <source>1.7</source> <target>1.7</target> <encoding>UTF-8</encoding> </configuration> </plugin> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
1.基于XML的方式
1.1服务提供者
接口以及其实现
package dubbo; public interface DubboService { String sayHello(String name); }
package dubbo; public class DubboServiceImpl implements DubboService { public String sayHello(String name) { return "Hello " + name; } }
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" /> <!-- 使用multicast广播注册中心暴露服务地址,IP设置: 224.0.0.0 - 239.255.255.255 --> <dubbo:registry address="multicast://224.5.6.7:1234" /> <!-- 用dubbo协议在20880端口暴露服务 --> <dubbo:protocol name="dubbo" port="20880" /> <!-- 声明需要暴露的服务接口 --> <dubbo:service interface="dubbo.DubboService" ref="demoService" /> <!-- 和本地bean一样实现服务 --> <bean id="demoService" class="dubbo.DubboServiceImpl" /> </beans>
启动类:
package dubbo; import java.io.IOException; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Provider { public static void main(String[] args) throws IOException { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[] { "provider.xml" }); context.start(); System.in.read(); // 按任意键退出 } }
1.2服务消费者
接口同上:
package dubbo; public interface DubboService { String sayHello(String name); }
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="consumer-of-helloworld-app" /> <!-- 使用multicast广播注册中心暴露发现服务地址 --> <dubbo:registry address="multicast://224.5.6.7:1234" /> <!-- 生成远程服务代理,可以和本地bean一样使用demoService --> <dubbo:reference id="dubboService" interface="dubbo.DubboService" /> </beans>
启动类:
package dubbo; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Consumer { public static void main(String[] args) { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[] { "consumer.xml" }); context.start(); DubboService demoService = (DubboService) context.getBean("dubboService"); // 获取远程服务代理 String hello = demoService.sayHello("world"); // 执行远程方法 System.out.println(hello); // 显示调用结果 } }
结果:
Hello world
补充:当然可以基于zookeeper注册服务
将上面consumer.xml和provider.xml的注册地址改为zookeeper地址:(zookeeper要启动或者集群启动)
<dubbo:registry address="zookeeper://127.0.0.1:2181" />
zookeeper的节点信息如下:
发布到zookeeper之后查看从dubbo-admin项目查看生产者和消费者:
2.API实现
接口类还是上面的接口,服务提供者的实现类还是上面的实现类。
provider生产者:
package dubbo.api; import java.util.concurrent.CountDownLatch; import com.alibaba.dubbo.config.ApplicationConfig; import com.alibaba.dubbo.config.ProtocolConfig; import com.alibaba.dubbo.config.RegistryConfig; import com.alibaba.dubbo.config.ServiceConfig; import dubbo.DubboService; import dubbo.DubboServiceImpl; public class Provider { public static void main(String[] args) throws InterruptedException { CountDownLatch countDownLatch = new CountDownLatch(1); // 服务实现 DubboService dubboService = new DubboServiceImpl(); // 当前应用配置 ApplicationConfig application = new ApplicationConfig(); application.setName("provider"); // 连接注册中心配置 RegistryConfig registry = new RegistryConfig(); registry.setAddress("multicast://224.5.6.7:1234"); registry.setUsername("aaa"); registry.setPassword("bbb"); // 服务提供者协议配置 ProtocolConfig protocol = new ProtocolConfig(); protocol.setName("dubbo"); protocol.setPort(12345); protocol.setThreads(200); // 注意:ServiceConfig为重对象,内部封装了与注册中心的连接,以及开启服务端口 // 服务提供者暴露服务配置 ServiceConfig<DubboService> service = new ServiceConfig<DubboService>(); // 此实例很重,封装了与注册中心的连接,请自行缓存,否则可能造成内存和连接泄漏 service.setApplication(application); service.setRegistry(registry); // 多个注册中心可以用setRegistries() service.setProtocol(protocol); // 多个协议可以用setProtocols() service.setInterface(DubboService.class); service.setRef(dubboService); service.setVersion("1.0.0"); // 暴露及注册服务 service.export(); countDownLatch.await(); } }
consumer消费者:
package dubbo.api; import com.alibaba.dubbo.config.ApplicationConfig; import com.alibaba.dubbo.config.ReferenceConfig; import com.alibaba.dubbo.config.RegistryConfig; import dubbo.DubboService; public class Consumer { public static void main(String[] args) { // 当前应用配置 ApplicationConfig application = new ApplicationConfig(); application.setName("consumer"); // 连接注册中心配置 RegistryConfig registry = new RegistryConfig(); registry.setAddress("multicast://224.5.6.7:1234"); registry.setUsername("aaa"); registry.setPassword("bbb"); // 注意:ReferenceConfig为重对象,内部封装了与注册中心的连接,以及与服务提供方的连接 // 引用远程服务 ReferenceConfig<DubboService> reference = new ReferenceConfig<DubboService>(); // 此实例很重,封装了与注册中心的连接以及与提供者的连接,请自行缓存,否则可能造成内存和连接泄漏 reference.setApplication(application); reference.setRegistry(registry); // 多个注册中心可以用setRegistries() reference.setInterface(DubboService.class); reference.setVersion("1.0.0"); // 和本地bean一样使用xxxService DubboService dubboService = reference.get(); // 注意:此代理对象内部封装了所有通讯细节,对象较重,请缓存复用 System.out.println(dubboService.sayHello("china")); } }
3.基于spring的注解实现
参考:https://www.cnblogs.com/qlqwjy/p/10539824.html
不管基于何种方式,dubbo的生产者停掉之后消费者不能进行消费。
4.配置加载流程
Dubbo的配置读取总体上遵循了以下几个原则:
1.Dubbo支持了多层级的配置,并按预定优先级自动实现配置间的覆盖,最终所有配置汇总到数据总线URL后驱动后续的服务暴露、引用等流程。
2.ApplicationConfig、ServiceConfig、ReferenceConfig可以被理解成配置来源的一种,是直接面向用户编程的配置采集方式。
3.配置格式以Properties为主,在配置内容上遵循约定的path-based的命名
4.1配置来源
默认有四种配置来源:
JVM System Properties,-D参数
Externalized Configuration,外部化配置
ServiceConfig、ReferenceConfig等编程接口采集的配置
本地配置文件dubbo.properties
4.2覆盖关系
4.3配置格式
目前Dubbo支持的所有配置都是.properties格式的,包括-D、Externalized Configuration等,.properties中的所有配置项遵循一种path-based的配置格式:
# 应用级别
dubbo.{config-type}[.{config-id}].{config-item}={config-item-value}
# 服务级别
dubbo.service.{interface-name}[.{method-name}].{config-item}={config-item-value}
dubbo.reference.{interface-name}[.{method-name}].{config-item}={config-item-value}
# 多配置项
dubbo.{config-type}s.{config-id}.{config-item}={config-item-value}
- 应用级别
dubbo.application.name=demo-provider
dubbo.registry.address=zookeeper://127.0.0.1:2181
dubbo.protocol.port=-1
- 服务级别
dubbo.service.org.apache.dubbo.samples.api.DemoService.timeout=5000
dubbo.reference.org.apache.dubbo.samples.api.DemoService.tineout=6000
dubbo.reference.org.apache.dubbo.samples.api.DemoService.sayHello.timeout=7000
- 多配制项
dubbo.registries.unit1.address=zookeeper://127.0.0.1:2181
dubbo.registries.unit2.address=zookeeper://127.0.0.1:2182
dubbo.protocols.dubbo.name=dubbo
dubbo.protocols.dubbo.port=20880
dubbo.protocols.hessian.name=hessian
dubbo.protocols.hessian.port=8089
- 扩展配置
dubbo.application.parameters.item1=value1
dubbo.application.parameters.item2=value2
dubbo.registry.parameters.item3=value3
dubbo.reference.org.apache.dubbo.samples.api.DemoService.parameters.item4=value4
4.4几种配置格式
- xml配置
<!-- dubbo-provier.xml --> <dubbo:application name="demo-provider"/> <dubbo:config-center address="zookeeper://127.0.0.1:2181"/> <dubbo:registry address="zookeeper://127.0.0.1:2181" simplified="true"/> <dubbo:metadata-report address="redis://127.0.0.1:6379"/> <dubbo:protocol name="dubbo" port="20880"/> <bean id="demoService" class="org.apache.dubbo.samples.basic.impl.DemoServiceImpl"/> <dubbo:service interface="org.apache.dubbo.samples.basic.api.DemoService" ref="demoService"/>
- annotation
// AnnotationService服务实现 @Service public class AnnotationServiceImpl implements AnnotationService { @Override public String sayHello(String name) { System.out.println("async provider received: " + name); return "annotation: hello, " + name; } }
## dubbo.properties dubbo.application.name=annotation-provider dubbo.registry.address=zookeeper://127.0.0.1:2181 dubbo.protocol.name=dubbo dubbo.protocol.port=20880
- springboot
## application.properties
# Spring boot application
spring.application.name=dubbo-externalized-configuration-provider-sample
# Base packages to scan Dubbo Component: @com.alibaba.dubbo.config.annotation.Service
dubbo.scan.base-packages=com.alibaba.boot.dubbo.demo.provider.service
# Dubbo Application
## The default value of dubbo.application.name is ${spring.application.name}
## dubbo.application.name=${spring.application.name}
# Dubbo Protocol
dubbo.protocol.name=dubbo
dubbo.protocol.port=12345
## Dubbo Registry
dubbo.registry.address=N/A
## DemoService version
demo.service.version=1.0.0
- API
public static void main(String[] args) throws IOException { ServiceConfig<GreetingsService> service = new ServiceConfig<>(); service.setApplication(new ApplicationConfig("first-dubbo-provider")); service.setRegistry(new RegistryConfig("multicast://224.5.6.7:1234")); service.setInterface(GreetingsService.class); service.setRef(new GreetingsServiceImpl()); service.export(); System.out.println("first-dubbo-provider is running."); System.in.read(); }
补充:最新版本的dubbo的使用:
pom.xml
<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"> <modelVersion>4.0.0</modelVersion> <groupId>cn.qlq</groupId> <artifactId>zookeper</artifactId> <version>0.0.1-SNAPSHOT</version> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> <dependency> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> <version>3.4.8</version> </dependency> <dependency> <groupId>org.apache.curator</groupId> <artifactId>curator-framework</artifactId> <version>2.12.0</version> </dependency> <dependency> <groupId>org.apache.curator</groupId> <artifactId>curator-recipes</artifactId> <version>2.12.0</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>dubbo</artifactId> <version>2.6.6</version> </dependency> <dependency> <groupId>org.javassist</groupId> <artifactId>javassist</artifactId> <version>3.20.0-GA</version> </dependency> <dependency> <groupId>io.netty</groupId> <artifactId>netty-all</artifactId> <version>4.1.34.Final</version> </dependency> <dependency> <groupId>com.101tec</groupId> <artifactId>zkclient</artifactId> <version>0.2</version> </dependency> <dependency> <groupId>org.apache.curator</groupId> <artifactId>curator-framework</artifactId> <version>2.12.0</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.16</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.25</version> </dependency> <dependency> <groupId>commons-lang</groupId> <artifactId>commons-lang</artifactId> <version>2.6</version> </dependency> </dependencies> <build> <!-- 配置了很多插件 --> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.5.1</version> <configuration> <source>1.7</source> <target>1.7</target> <encoding>UTF-8</encoding> </configuration> </plugin> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
provider.xml如下:
<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-world-app"> <!-- 关闭QOS:Quality of Service --> <dubbo:parameter key="qos.enable" value="false" /> <dubbo:parameter key="qos.accept.foreign.ip" value="true" /> <dubbo:parameter key="qos.port" value="2222" /> </dubbo:application> <!-- 使用multicast广播注册中心暴露服务地址,IP设置: 224.0.0.0 - 239.255.255.255 --> <dubbo:registry address="zookeeper://127.0.0.1:2181" /> <!-- 用dubbo协议在20880端口暴露服务 --> <dubbo:protocol name="dubbo" port="20880" /> <!-- 声明需要暴露的服务接口 --> <dubbo:service interface="dubbo.DubboService" ref="demoService" /> <!-- 和本地bean一样实现服务 --> <bean id="demoService" class="dubbo.DubboServiceImpl" /> </beans>
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· Obsidian + DeepSeek:免费 AI 助力你的知识管理,让你的笔记飞起来!
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了