Dubbo
为什么用Dubbo
它是一个RPC框架,提供了对远程通信的支持。其本身是一个服务治理框架,能够提供服务的监控(如果我们的服务大规模集群后,我们需要一些服务来监控服务的调用链路,监控每个服务的吞吐量,这样就能够及时做到服务性能提升和响应)、服务注册发现(在服务与服务通信之间,去管理服务的一个组件)、服务的通信、服务容错(通信过程中怎么实现容错)、服务的负载均衡。
类似于京东的 jsf框架。
那为什么每个公司要开发自己的框架呢?是因为即便是开源的技术也好,它能够满足大部分的业务场景,但是对于每个公司来说可能存在一些定制化的需求,或者说做一些开源的支持,所以会有一些架构组去专门开发这样的组件,提供给我们这样使用。
Dubbo 最早是阿里内部分布式服务治理的框架,后面对外开源,然后后面的很多公司都沿着阿里的生态线去发展,在2014年dubbo就停止维护了,在2017年阿里重启了维护,在18年集成到了springcloud团队,集成是为了大家使用springcloud这套标准去提供服务治理这套完整的解决方案,让大家在使用这项技术的时候,成本更低,使用起来更加容易。
所以SpringCloud Alibaba 说的是基于阿里开源的技术,按照springcloud这套标准去进行集成,然后提供的一系列解决方法,包括 nacos、sentinel、rocketmq、dubbo等。
Dubbo架构
其提供了客户端和服务端在分布式情况下的通信,服务启动的时候,把服务地址注册到注册中心上,消费者监听注册中心上的地址的变化,发起调用,每次调用,会有监视的模块,去监控每次调用请求的耗时等等关系。
Dubbo的使用
服务端
dubbo-server-sample
----dubbo-server
public class LoginServiceImpl implements ILoginService{ @Override public String login(String username, String password) { //写业务逻辑 if(username.equals("admin")&&password.equals("admin")){ return "SUCCESS"; } return "FAILED"; } }
----dubbo-server-api
public interface ILoginService { String login(String username,String password); }
如果想让另一个进行也能访问到 login 方法,那么首先需要将 dubbo-server 上的服务发布出去。
<dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo</artifactId> <version>2.7.8</version> </dependency>
配置 application.xml
<dubbo:application name="dubbo-server"/> <!-- 声明服务对外的名字--> <dubbo:protocol name="dubbo" port="20880"/> <!-- 表示当前要以什么协议发布出去 --> <dubbo:registry address="N/A"/> <!-- 配置注册中心 当前配置为不需要注册到 注册中心--> <dubbo:service interface="com.gupaoedu.dubbo.server.ILoginService" ref="loginService"/> <bean id="loginService" class="com.gupaoedu.dubbo.server.LoginServiceImpl"/> <!-- dubbo的发布,表示要将那个服务发布出去-->
启动
import org.apache.dubbo.container.Main; public class App { public static void main( String[] args ){ Main.main(args); } }
发布服务之后,会提供一个url地址
dubbo://192.168.1.104:20880/com.gupaoedu.dubbo.server.ILoginService
消费端
dubbo-client-sample
<dubbo:application name="dubbo-server"/> <!--不需要注册到服务注册中心--> <dubbo:registry address="N/A"/> <dubbo:reference id="loginService" interface="com.gupaoedu.dubbo.server.ILoginService" url="dubbo://192.168.1.104:20880/com.gupaoedu.dubbo.server.ILoginService"/> // 引入dubbo-server-api
public static void main( String[] args ) { ILoginService loginService=null; ApplicationContext context=new ClassPathXmlApplicationContext ("classpath:META-INF/spring/application.xml"); loginService=context.getBean(ILoginService.class); System.out.println(loginService.login("admin","admin")); }
此时就能够完成一次通信了。
虽然上述案例跑通了,但是可以看到,必须在 dubbo:reference 里配置 了 url才能完成通信,实际上根据前面说的Dubbo的架构图来看,其生产者 和 消费者都是通过注册中心通信的。
<dubbo:registry address="zookeeper://192.168.216.128:1281" timeout="10000"/> <dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo-dependencies-zookeeper</artifactId> <version>2.7.8</version> </dependency>
当生产者消费者都配置了注册中心的时候,此时消费者的dubbo:reference 就不需要配置url了,就能够完成通信了。
Dubbo Spring Cloud
创建一个项目
创建一个spring-cloud-dubbo-example的maven工程
分别添加三个模块
- spring-cloud-dubbo-sample-api
- spring-cloud-dubbo-sample-provider
- spring-cloud-dubbo-sample-consumer
其中后面两个模块都是spring boot的应用。
修改 spring-cloud-dubbo-sample-provider 这个模块中。
- 将dependencyManagement部分的依赖移动到parent pom.xml
- 修改spring-cloud-dubbo-sample-provider中的pom.xml,增加parent模块的依赖
<parent> <groupId>com.gupaoedu.dubbo</groupId> <artifactId>spring-cloud-dubbo-example</artifactId> <version>1.0-SNAPSHOT</version> </parent>
- 添加maven依赖
<dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-dubbo</artifactId> </dependency> <dependency> <groupId>com.gupaoedu.dubbo</groupId> <version>1.0-SNAPSHOT</version> <artifactId>spring-cloud-dubbo-sample-api</artifactId> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency>
定义服务接口
在spring-boot-dubbo-sample-api模块中,定义接口
public interface IHelloService { String sayHello(); }
实现服务
在spring-boot-dubbo-sample-provider中,实现IHelloService接口
public class HelloServiceImpl implements IHelloService{ @Override public String sayHello() { return "Hello GuPao"; } }
添加 @EnableDiscoveryClient 注解
@EnableDiscoveryClient @SpringBootApplication public class SpringCloudDubboSampleProviderApplication { public static void main(String[] args) { SpringApplication.run(SpringCloudDubboSampleProviderApplication.class,args); } }
配置dubbo服务发布
- 在服务实现类中添加 @Service 注解
@Service public class HelloServiceImpl implements IHelloService{ @Override public String sayHello() { return "Hello GuPao"; } }
- 配置dubbo提供方信息
# dubbo 服务扫描基础包路径 dubbo.scan.base-packages=com.gupaoedu.dubbo.springclouddubbosampleprovider dubbo.protocol.id=dubbo # Dubbo 服务暴露的协议配置,其中子属性 name 为协议名称,port 为协议端口( -1 表示自增端 口,从 20880 开始) dubbo.protocol.name=dubbo # 使用的是dubbo协议 dubbo.protocol.port=-1 spring.cloud.nacos.discovery.server-addr=192.168.216.128:8848
dubbo.scan.base-packages : 指定 Dubbo 服务实现类的扫描基准包
dubbo.protocol : Dubbo 服务暴露的协议配置,其中子属性 name 为协议名称, port 为协议端口( -1 表示自增端口,从 20880 开始)
spring.cloud.nacos.discovery : Nacos 服务发现与注册配置,其中子属性 server-addr指定 Nacos 服务器主机和端口
构建服务消费者
- 添加jar包依赖
<dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-dubbo</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-actuator</artifactId> </dependency> <dependency> <groupId>com.gupaoedu.dubbo</groupId> <version>1.0-SNAPSHOT</version> <artifactId>spring-cloud-dubbo-sample-api</artifactId> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
- 添加配置文件
spring.application.name=spring-cloud-dubbo-sample-consumer dubbo.application.name=spring-cloud-dubbo-sample-consumer dubbo.cloud.subscribed-services=spring-cloud-dubbo-sample-provider spring.cloud.nacos.discovery.server-addr=192.168.216.128:8848
除应用名称 spring.application.name 存在差异外, spring-cloud-dubbo-client-sample 新增了属性 dubbo.cloud.subscribed-services 的设置。并且该值为服务提供方应用 “springcloud-dubbo-sample-provider”。它的主要作用是服务消费方订阅服务提供方的应用名称的列表,若需订阅多应用,使用 “,” 分割。
不推荐使用默认值为 “*”,它将订阅所有应用。
- 编写测试代码
@RestController @EnableDiscoveryClient @SpringBootApplication public class SpringCloudDubboSampleConsumerApplication { public static void main(String[] args) { SpringApplication.run(SpringCloudDubboSampleConsumerApplication.class,args); } @Reference IHelloService helloService; @GetMapping("/say") public String say(){ return helloService.sayHello(); } }
Dubbo Spring Boot
基于spring boot集成Dubbo方式
dubbo集成到spring boot中有一个好处,就是它可以继承spring boot本身的特性
- 自动装配(注解驱动、自动装配)
- production-ready(安全机制、健康检测、外部化配置)
创建项目结构
创建基础的项目结构
spring-boot-dubbo-example [maven]
- spring-boot-dubbo-sample-api [maven]
- spring-boot-dubbo-sample-provider [spring boot]
- spring-boot-dubbo-sample-consumerp [spring-boot]
添加jar包依赖
从2.7开始,dubbo的版本和dubbo-spring-boot的版本是保持一致的,所以大家不用再去担心版本的问题。
<dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo-spring-boot-starter</artifactId> <version>2.7.7</version> </dependency> <dependency> <groupId>com.alibaba.nacos</groupId> <artifactId>nacos-client</artifactId> <version>1.2.1</version> </dependency>
添加服务以及发布
@DubboService public class SayHelloServiceImpl implements ISayHelloService{ @Override public String sayHello() { return "Hello GuPaoEdu.com"; } }
spring.application.name=spring-boot-dubbo-sample-provider dubbo.registry.address=nacos://192.168.216.128:8848 dubbo.scan.basepackages=com.gupaoedu.springboot.dubbo.springbootdubbosampleprovider.service dubbo.protocol.name=dubbo dubbo.protocol.port=-1
编写服务引用代码
添加jar包依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>com.gupaoedu.com</groupId> <version>1.0-SNAPSHOT</version> <artifactId>spring-boot-dubbo-sample-api</artifactId> </dependency> <dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo-spring-boot-starter</artifactId> <version>2.7.7</version> </dependency> <dependency> <groupId>com.alibaba.nacos</groupId> <artifactId>nacos-client</artifactId> <version>1.2.1</version> </dependency>
添加web测试类
@DubboReference ISayHelloService sayHelloService; @GetMapping("/get") public String get(){ return sayHelloService.sayHello(); }
dubbo.registry.address=nacos://192.168.216.128:8848