互联网的发展过程中,在以前只需要一个服务器,程序的前后端一起打包就可以了,但是随着流量的增加,常规的垂直应用架构也无法应对了,分布式服务架构势在必行,需要一个治理系统架构的方案。
随着服务化的进一步发展,服务越来越多,服务之间的调用和依赖关系也越来越复杂,诞生了面向服务的架构体系(SOA),也因此衍生出了一系列相应的技术,如对服务提供、服务调用、连接处理、通信协议、序列化方式、服务发现、服务路由、日志输出等行为进行封装的服务框架。就这样为分布式系统的服务治理框架就出现了,Dubbo 也就这样产生了。
什么是Dubbo
Dubbo官网:dubbo.incubator.apache.org/zh/
Apache Dubbo 是一款 RPC 服务开发框架,用于解决微服务架构下的服务治理与通信问题,官方提供了 Java、Golang 等多语言 SDK 实现。使用 Dubbo 开发的微服务原生具备相互之间的远程地址发现与通信能力, 利用 Dubbo 提供的丰富服务治理特性,可以实现诸如服务发现、负载均衡、流量调度等服务治理诉求。Dubbo 被设计为高度可扩展,用户可以方便的实现流量拦截、选址的各种定制逻辑。
Dubbo架构
主要组件
- Provider: 暴露服务的服务提供方。
- Consumer: 调用远程服务的服务消费方。
- Registry: 服务注册与发现的注册中心。
- Monitor: 统计服务的调用次数和调用时间的监控中心。
- Container:服务运行容器。
调用流程
-
服务容器负责启动,加载,运行服务提供者。
-
服务提供者在启动时,向注册中心注册自己提供的服务。
-
服务消费者在启动时,向注册中心订阅自己所需的服务。
-
注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。
-
服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用。
-
服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。
注册中心
注册中心是Dubbo核心组件之一。 Dubbo通过注册中心实现了分布式环境中各服务之间的注册与发现, 是各个分布式节点之间的纽带。
Dubbo可以使用多种注册中心,比如redis、zookeeper、eureka、nacos等,但注册中心又该如何选择呢?
官方推荐使用zookeeper注册中心。 个人意见,zookeeper在大数据计算时做注册中心是一个好的选择,但是在服务调用时,也许数据不需要超强的一致性。nacos是目前来说很友好的一个注册中心,他提供了CP+AP。还有可视化界面,还有配置中心等功能,功能相当完善。
到此,一些同学心里也可能和一样,心里还存在一些问题?
Spring Cloud 和 Dubbo 是什么关系,又有什么区别呢?
初始定位不同:SpringCloud定位为微服务架构下的一站式解决方案;Dubbo 是 SOA 时代的产物,它的关注点主要在于服务的调用和治理。
生态环境不同:SpringCloud依托于Spring平台,具备更加完善的生态体系;而Dubbo一开始只是做RPC远程调用,生态相对匮乏,现在逐渐丰富起来。
调用方式:SpringCloud是采用Http协议做远程调用,接口一般是Rest风格,比较灵活;Dubbo是采用Dubbo协议,接口一般是Java的Service接口,格式固定。但调用时采用Netty的NIO方式,性能较好。
组件差异:例如SpringCloud注册中心一般用Eureka,而Dubbo用的是Zookeeper。
作为远程调用,Dubbo 和 Feign 有什么差异呢?
Feign是SpringCloud中的远程调用方式,基于成熟Http协议,所有接口都采用Rest风格。因此接口规范更统一,而且只要符合规范,实现接口的微服务可以采用任意语言或技术开发。但受限于http协议本身的特点,请求和响应格式臃肿,其通信效率相对会差一些。
Dubbo框架默认采用Dubbo自定义通信协议,与Http协议一样底层都是TCP通信。但是Dubbo协议自定义了Java数据序列化和反序列化方式、数据传输格式,因此Dubbo在数据传输性能上会比Http协议要好一些。
Dubbo实战
下面基于Naocs注册中心集成Dubbo实现RPC调用。
环境
- spring-boot:2.3.7.RELEASE
- spring-cloud:Hoxton.SR10
- spring-cloud-alibaba:2.2.5.RELEASE
- dubbo:2.7.8
工程搭建
- 公共接口工程 nacos-dubbo-api
- 服务发布工程 nacos-dubbo-provider
- 服务消费工程 nacos-dubbo-provider
父级工程搭建
pom引入spring-cloud、spring-cloud-alibaba。
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<spring-cloud.version>Hoxton.SR10</spring-cloud.version>
<spring-cloud-alibaba.version>2.2.5.RELEASE</spring-cloud-alibaba.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring-cloud-alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- 此依赖是为了解决java.lang.NoClassDefFoundError: org/apache/commons/lang3/StringUtils 错误-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
</dependencies>
公共接口工程
创建接口
public interface ApiService {
String test();
}
服务发布工程
pom引入nacos、dubbo
<dependency>
<groupId>com.syun</groupId>
<artifactId>nacos-dubbo-api</artifactId>
<version>0.0.1-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-dubbo</artifactId>
</dependency>
nacos配置文件bootstrap.yml
spring:
cloud:
nacos:
discovery:
server-addr: localhost:8848
namespace: 7e98b650-0c03-4663-b747-b3d4848630aa
group: DEFAULT_GROUP
application.yml配置文件
server:
port: 9001
servlet:
context-path: /provider
spring:
application:
name: nacos-dubbo-provider
#dubbo配置
dubbo:
application:
id: nacos-dubbo-provider
name: nacos-dubbo-provider
protocol:
port: -1
name: dubbo # 协议
registry:
address: nacos://localhost:8848
# 配置namespace
parameters[namespace]: 7e98b650-0c03-4663-b747-b3d4848630aa
scan:
base-packages: com.syun.nacos.dubbo
- dubbo.scan.base-packages: 指定,提供服务的接口的包
- dubbo.protocol.name: Dubbo 为协议名称
- dubbo.protocol.port: -1 表示自增端口,从 20880 开始
- dubbo.registry.address: 注册中心地址
服务实现类
import org.apache.dubbo.config.annotation.DubboService;
import syun.nacos.dubbo.service.ApiService;
@DubboService(version = "1.0.0",group = "test1")
public class ApiServiceImpl implements ApiService {
@Override
public String test() {
return "hello";
}
}
启动类
@SpringBootApplication
@EnableDiscoveryClient
@DubboComponentScan
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
服务消费工程
pom.xml 与 bootstrap.yml 同服务生产工程
application.yml配置文件,和服务生产工程有一个地方不同,去掉dubbo.scan.base-packages。增加dubbo.cloud.subscribed-services(注册到nacos的服务名称)。
server:
port: 9002
servlet:
context-path: /consumer
spring:
application:
name: nacos-dubbo-consumer
#dubbo配置
dubbo:
application:
id: nacos-dubbo-consumer
name: nacos-dubbo-consumer
protocol:
port: -1
name: dubbo
registry:
address: nacos://localhost:8848
#设置订阅的服务
cloud:
subscribed-services: nacos-dubbo-provider
消费者实现类
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import syun.nacos.dubbo.service.ApiService;
@RestController
public class TestController {
@DubboReference(version = "1.0.0",group = "test1")
ApiService apiService;
@GetMapping("/test")
public String hello() {
return apiService.test();
}
}
先后启动服务生产工程、服务消费工程,最后应在nacos-server看到provider和consumer的名称。
测试接口:http://localhost:9002/consumer/test
工程Gitee地址:gitee.com/renxiaoshi/…