Hi I’m Shendi
Dubbo入门详解,API方式与SpringBoot方式
在之前一直使用的自己编写的RPC框架,因为是自己编写的,功能上比不过市面上的开源框架,包括后面Spring Cloud系列,如果还用自己编写的话就需要去做整合之类的,是一个庞大的工作量。
本着能不造轮子就不造轮子的想法,于是开始学习一下Dubbo
Dubbo
Apache Dubbo 是一款易用、高性能的 WEB 和 RPC 框架,同时为构建企业级微服务提供服务发现、流量治理、可观测、认证鉴权等能力、工具与最佳实践。
使用 Dubbo 开发的微服务原生具备相互之间的远程地址发现与通信能力, 利用 Dubbo 提供的丰富服务治理特性,可以实现诸如服务发现、负载均衡、流量调度等服务治理诉求。Dubbo 被设计为高度可扩展,用户可以方便的实现流量拦截、选址的各种定制逻辑。
官方文档:https://cn.dubbo.apache.org/zh-cn/index.html
RPC、分布式、微服务
这里简述一下,RPC即远程过程调用(Remote Procedure Call),通过RPC,可以使得一个程序调用其他设备程序的函数(通过网络)
分布式即将多个程序通过网络方式进行通信,组成一个系统,通常使用RPC来实现分布式
而微服务是将一个程序拆分成多个程序,程序之间通过分布式的方式进行通信
快速入门
启动 Zookeeper
官方文档目前使用的 zookeeper,所以首先需要安装zookeeper,关于zookeeper的安装使用可以参考这篇文章
Zookeeper安装入门详解,简单使用
基于 Dubbo API 开发微服务应用
任意Maven项目,编辑 pom.xml
增加以下内容
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo</artifactId>
<version>3.2.0-beta.4</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-x-discovery</artifactId>
<version>4.3.0</version>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.8.0</version>
<exclusions>
<exclusion>
<groupId>io.netty</groupId>
<artifactId>netty-handler</artifactId>
</exclusion>
<exclusion>
<groupId>io.netty</groupId>
<artifactId>netty-transport-native-epoll</artifactId>
</exclusion>
</exclusions>
</dependency>
注:依赖包大多都是用 org.apache.dubbo 的
服务提供者
新建两个包,一个api,包含服务接口定义,一个provider,包含服务接口的具体实现
在 api 包下新建一个接口,内容如下
public interface ITest {
String sayHi(String name);
}
在 provider 包中新建一个类实现此接口,并发布服务端,内容如下
import org.apache.dubbo.config.ProtocolConfig;
import org.apache.dubbo.config.RegistryConfig;
import org.apache.dubbo.config.ServiceConfig;
import org.apache.dubbo.config.bootstrap.DubboBootstrap;
import demo.api.ITest;
public class Test implements ITest {
public static void main(String[] args) {
// 定义具体的服务
ServiceConfig<ITest> service = new ServiceConfig<>();
service.setInterface(ITest.class);
service.setRef(new Test());
// 启动 Dubbo
DubboBootstrap.getInstance()
.application("first-dubbo-provider")
.registry(new RegistryConfig("zookeeper://127.0.0.1:2181"))
.protocol(new ProtocolConfig("dubbo", -1))
.service(service)
.start()
.await();
}
public String sayHi(String name) {
return "hi, " + name;
}
}
上面的 zookeeper 是 zookeeper地址,更改了端口上面的字符串也要对应更改
现在可以启动服务提供者了,启动后控制台会输出大量的信息…
等待一会,看到有以下信息就代表启动成功了
Got ping response for session id:…
这个东西会一直输出,是ZK的心跳机制日志
简单叙述一下上面实现的功能,相当于提供了一个sayHi接口,接口接收一个name参数,返回一个字符串,字符串内容为 hi, + 传递的name参数
服务消费者
新建一个包 client
用于专门存放客户端(消费者)
在包下新建一个类 Test2,用来订阅提供的服务并调用
内容如下
import java.io.IOException;
import org.apache.dubbo.config.RegistryConfig;
import org.apache.dubbo.config.bootstrap.DubboBootstrap;
import com.alibaba.dubbo.config.ReferenceConfig;
import demo.api.ITest;
public class Test2 {
public static void main(String[] args) throws IOException {
ReferenceConfig<ITest> reference = new ReferenceConfig<>();
reference.setInterface(ITest.class);
DubboBootstrap.getInstance()
.application("first-dubbo-consumer")
.registry(new RegistryConfig("zookeeper://127.0.0.1:2181"))
.reference(reference);
ITest service = reference.get();
String message = service.sayHi("dubbo");
System.out.println("Receive result ======> " + message);
System.in.read();
}
}
运行后,输出了大量信息,最终可以看到以下信息
根据上面的代码就实现了一个简单的通过服务发现进行 RPC 调用了,代码简单,看一眼基本上就知道啥意思了
基于SpringBoot开发微服务应用
和API开发类似,但SpringBoot的特点是采用基于注解的配置方式,这样可以快速开发
官网的示例是使用的Maven多模块,有三个模块,分别为
- 接口
- 提供者
- 消费者
在上面,我们知道提供者和消费者都需要定义接口部分,提供者实现接口,消费者使用接口,为了使接口部分共用,所以官方示例使用的多模块
官方示例使用的IDEA,我这里列出Eclipse的流程
(当然不使用多模块也是可以的,也可以分成一个项目或者两个项目)
新建一个Maven项目,Packaging选择pom,pom.xml增加以下依赖
<properties>
<dubbo.version>3.2.0-beta.4</dubbo.version>
<spring-boot.version>2.7.8</spring-boot.version>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencyManagement>
<dependencies>
<!-- Spring Boot -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- Dubbo -->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-bom</artifactId>
<version>${dubbo.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-dependencies-zookeeper-curator5</artifactId>
<version>${dubbo.version}</version>
<type>pom</type>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring-boot.version}</version>
</plugin>
</plugins>
</pluginManagement>
</build>
然后新建三个模块,分别为
- demo-consumer(消费者)
- demo-provider(提供者)
- demo-interface(共用接口)
在项目处右键 -> New -> Other -> Maven -> Maven Module
Packaging选择jar,创建模块
更改demo-provider和demo-consumer的pom.xml内容,将SpringBoot需要的内容copy进来,并增加以下依赖
<dependencies>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-samples-spring-boot-interface</artifactId>
<version>${project.parent.version}</version>
</dependency>
<!-- dubbo -->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-dependencies-zookeeper-curator5</artifactId>
<type>pom</type>
<exclusions>
<exclusion>
<artifactId>slf4j-reload4j</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
</exclusions>
</dependency>
<!-- spring boot starter -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
</dependencies>
除上面的依赖外,还需要引入共用部分,demo-interface
<dependency>
<groupId>demo-interface</groupId>
<artifactId>demo-interface</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
贴一下项目图
共用部分(demo-interface)
demo-interface模块为共用部分,在src/main/java下新建一个包命名为demo,包下新建一个接口命名为Service
Service内定义提供者消费者所用的行为,内容如下
因为这个模块只需要创建接口就可以了,因此pom基本上不需要引入任何依赖
服务提供者(demo-provider)
提供者和消费者都需要引入共用部分,在上面有说过
demo-provider模块为提供者,新建一个包,命名为 demo.provider,在包下新建一个类,命名为 ServerImpl
ServerImpl 实现共用部分(interface)提供的接口 Service,内如如下
package demo.provider;
import org.apache.dubbo.config.annotation.DubboService;
import demo.Service;
@DubboService
public class ServiceImpl implements Service {
@Override
public String sayHi(String name) {
return "hi, " + name;
}
}
和基于API开发不同的是在类上多了个 @DubboService
注解
@DubboService注解是一个用于标记服务提供者接口的注解。 该注解的作用是将一个接口标记为一个Dubbo的服务提供者,使得该接口的实现类可以被Dubbo注册和暴露为一个可供其他服务调用的服务。被@DubboService注解标记的接口实现类将会被Dubbo框架扫描到,并且会自动生成相应的服务接口代理对象,并注册到Dubbo的注册中心,供其他服务消费方进行调用。使用该注解可以简化Dubbo服务的发布与暴露的步骤,提高开发效率。
然后创建SpringBoot启动类 ProviderApplication
,内容如下
@SpringBootApplication
@EnableDubbo
public class ProviderApplication {
public static void main(String[] args) {
SpringApplication.run(ProviderApplication.class, args);
}
}
增加了 @EnableDubbo
注解,经尝试,没有这个注解也没问题(但避免其他问题还是加上比较好)
修改SpringBoot的配置文件,因为我创建的Maven项目,那么就需要在 src/main/resources 下新建 application.properties 或者 application.yml
properties
dubbo.application.name=demo-provider
dubbo.protocol.name=dubbo
dubbo.protocol.port=-1
dubbo.registry.address=zookeeper://${zookeeper.address:127.0.0.1}:2181
yml
dubbo:
application:
name: dubbo-springboot-demo-provider
protocol:
name: dubbo
port: -1
registry:
address: zookeeper://${zookeeper.address:127.0.0.1}:2181
这样,服务提供者就做好了
服务消费者(demo-consumer)
demo-consumer为消费者模块,新建一个包demo.consumer,在包下先新建启动类 ConsumerApplication,内容如下
package demo.consumer;
import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@EnableDubbo
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class, args);
}
}
这里需要编写Web接口,所以pom.xml内需要增加web依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
新建一个类,命名为 TestControl 内容如下
package demo.consumer;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import demo.Service;
@RestController
public class TestControl {
@DubboReference
private Service service;
@GetMapping("/")
public String test(String name) {
return service.sayHi(name);
}
}
上面定义了一个Web接口,路由为 /
,接口接收一个参数name,接口将调用Service金额可的sayHi函数,并将name参数传入。
这里的service使用了 @DubboReference
注解注入,调用sayHi实际等于调用了 demo-provider 的实现类的 sayHi
这里原理我就不去了解了,略微猜一猜,照我的思路,大致应该就是提供者与消费者连接zookeeper,消费者通过zookeeper与提供者进行rpc通信,消费者使用 @DubboReference 注入的对象我猜大概是RPC发送数据到提供者,例如类为Service,函数为sayHi,那么就发个 Service|sayHi,提供者接收到数据后就去找对应实现类,和实现类的函数然后执行返回数据这样,剩下的就是细节问题了,比如参数之类的。当然,我这里只是以我的思路来实现这样的框架,提供一个简单的思路,要知道具体还是要去看源码、文档和debug
SpringBoot配置文件同提供者一样,但是需要有 server.port 设置 web 端口
这样,消费者也做好了
不通过注解方式获取 Service,通过Context 获取
这里延伸以一下,有的时候不能使用注解注入对象,这个时候就需要用别的方式获取提供者对象了
获取代码如下
ReferenceConfig<Service> referenceConfig = new ReferenceConfig<>();
referenceConfig.setInterface(Service.class);
Service service = referenceConfig.get();
启动应用
运行 ProviderApplication
和 ConsumerApplication
需要注意的是,需要先启动提供者再启动消费者,否则消费者模块会报错导致整个程序Over。这个问题是由 @DubboReference
注解导致的,默认在启动时会去检查对应的提供者是否可用,当然,可以通过配置之类的取消掉检查。
有以下几种解决办法
-
注解上增加参数check = false,例
@DubboReference(check = false)
-
SpringBoot配置文件增加内容
-
properties增加
dubbo.consumer.check=false
-
yml增加
-
dubbo: consumer: check: false
-
-
在启动类或配置类增加以下代码
-
@Bean public ConsumerConfig consumerConfig() { ConsumerConfig consumerConfig = new ConsumerConfig(); consumerConfig.setCheck(false); return consumerConfig; }
-
启动后,消费者服务会爆一些错误,但不影响,通过浏览器访问地址,效果如下
问题解决
[DUBBO] qos-server can not bind localhost:22222, dubbo version: 3.2.0-beta.4, current host: 192.168.0.108, error code: 7-4. This may be caused by , go to https://dubbo.apache.org/faq/7/4 to find instructions.
java.net.BindException: Address already in use: bind
...
Fail to start qos server: , dubbo version: 3.2.0-beta.4, current host: 192.168.0.108, error code: 7-4. This may be caused by , go to https://dubbo.apache.org/faq/7/4 to find instructions.
java.net.BindException: Address already in use: bind
这个错误是说 qos 服务的端口被占用了,因为带Dubbo启动就会自动启动 qos server,默认端口为22222,上面我在同一台电脑上启动了提供者,消费者,所以就报这个错误了
Dubbo的QoS(Quality of Service)服务器是一个独立的服务器,用于提供Dubbo服务的质量保证和对服务的相关指标进行监控和管理。
可以通过修改SpringBoot配置文件的方式解决
properties
# 是否启用,默认启用
dubbo.application.qosEnable=true
# 端口,默认22222
dubbo.application.qosPort=12345
dubbo.application.qosAcceptForeignIp=false
至此,基础使用已经ok了文章来源:https://www.toymoban.com/news/detail-542079.html
END文章来源地址https://www.toymoban.com/news/detail-542079.html
到了这里,关于Dubbo入门详解,API方式与SpringBoot方式的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!