前言
随着云原生的兴起,越来越多的微服务化改造在演进过程中也开始提上日程,微服务治理框架能否很好的兼容和支持云原生的体系,也成为很多架构设计者考虑的重要因素;
在微服务治理框架中,dubbo作为一款优秀的服务治理框架,随着dubbo3.0的发布,通过增加的新特性,为云原生的支持带来了福音,也为dubbo2.X过渡到3.0提供了更多好用,且性能高效的亮点;
dubbo3.0新特性介绍
官网新特性介绍 ,下面结合官网的介绍做一些关于 dubbo3.x的新特性总结。
一、注册模型的改变
我们知道,dubbo2.X版本,服务都是以接口的形式注册到注册中心(如zk)。一个接口在注册中心中就是一个数据节点,多个接口就注册多个节点。
当dubbo提供的服务非常多的时候,会给注册中心带来非常大的读写压力,比如在并发量较高的时候,消费端因服务寻址耗费的时间会拉长。而在dubbo3.0版本中对这个问题进行了优化。
dubbo3.0引入服务级别的注册
在dubbo3.0中,只需将应用名和对应的ip、端口注册到注册中心即可。无需再对每个接口进行注册(可通过配置参数进行选择)。以此来减少注册中心的压力。
但是只注册应用,如何查找消费端具体调用的是哪个服务呢?
于是dubbo3.0引入了元数据服务的概念。
具体做法就是,接口提供的服务映射关系,都存在了元数据服务里。元数据服务的数据可以默认存在dubbo内部实现的一个服务里,也可以手动指定存入ZK等服务中。
这样,消费端通过注册中心获取服务列表,然后通过元数据服务映射具体某个接口,进行远程调用。
由此可见,尽管在3.0中以应用纬度进行了注册,看似减轻了注册中心的压力,但引入了元数据服务,也提高了使用的复杂度。
二、引入Triple协议
Dubbo3.0新引入了Triple协议。Triple协议可以视为gRPC协议的copy版本。
什么是gRPC?
如果你在了解dubbo3.0之前,或者说没听过gRPC,说明你所涉及的业务或者数据量不需要用到gRPC来达到很高的性能的。所以Triple协议所带来的性能的提升对你而言也是可有可无的。
dubbo认为,http1.X版本性能比较低,主要是因为协议的数据格式复杂,解析带来的一定的性能瓶颈,所以http2.0对性能进行了提升。
而Triple协议是基于http2.0的高性能的基础上,又支持gRPC的远程调用,更具兼容性。这就是Triple协议的特性。
其实在dubbo2.X版本时,dubbo协议是默认的协议,而在3.0版本,Triple协议成为了默认协议。
相比dubbo协议,Triple协议的特点有:
- triple协议兼容了gPRC(Triple服务可以直接调用gRPC服务,反过来也可以);
- dubbo协议不是基于的HTTP,不够通用,triple协议底层基于HTTP所以更通用(比如跨语言、跨异构系统实现起来比较方便);
- dubbo协议不支持流式调用;
三、跨语言调用
跨语言调用对于dubbo来说可以说是一个很大的突破,3.0 支持go语言,python语言等应用进行接口的调用。
涉及到跨语言调用的服务接口,可考虑使用dubbo作为服务。可以使用protobuf格式的数据作为数据传输格式,来进行跨语言调用。
四、SpringCloud的互通
至目前而已,经管两者之间可以实现互通,但是Dubbo3.0与SpringCloud的互通方式也是很繁琐,但看趋势以后的发展肯定会很方便的和SpringCloud进行互通。让我们拭目以待。
dubbo3.0与springboot的整合
接下来演示下与springboot的整合,方便后续在业务中快速运用,完整结构如下:
- 统一定义服务接口和实体类,被其他工程模块引用;
- consumer,服务消费方模块;
- provider,服务提供方模块;
common-service 模块
pomy依赖
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.8</version>
</dependency>
服务接口
import com.congge.entity.User;
public interface UserService {
User getByUserId(String userId);
}
实体类
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User implements Serializable {
private static final long serialVersionUID = 8728327146677888239L;
private String userId;
private String userName;
private String address;
}
provider模块
1、pom依赖
<dependencies>
<dependency>
<groupId>com.congge</groupId>
<artifactId>common-service</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.6.6</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.22</version>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>3.0.7</version>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-rpc-dubbo</artifactId>
<version>3.0.7</version>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-rpc-rest</artifactId>
<version>3.0.6</version>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-registry-zookeeper</artifactId>
<version>3.0.7</version>
</dependency>
</dependencies>
2、核心配置文件
## 这里的配置属性只是基础配置,如需更多功能配置,请自行扩展
dubbo:
application:
name: dubbo-provider
registry:
address: zookeeper://127.0.0.1:2181
protocol:
name: dubbo
port: 20880
3、服务实现类
@DubboService
public class UserServiceImpl implements UserService {
// 模拟数据
private static final List<User> USERS = Arrays.asList(
new User("001", "张三", "北京市东城区"),
new User("002", "李四", "杭州市西湖区"),
new User("003", "王五", "武汉市汉口区")
);
@Override
public User getByUserId(String userId) {
User user = USERS.stream().filter(item -> item.getUserId().equals(userId)).findFirst().get();
return user;
}
}
4、启动类
import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@EnableDubbo
public class ProviderApp {
public static void main(String[] args) {
SpringApplication.run(ProviderApp.class, args);
}
}
consumer模块
1、pom依赖
<dependencies>
<dependency>
<groupId>com.congge</groupId>
<artifactId>common-service</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.6.6</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.22</version>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>3.0.7</version>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-rpc-dubbo</artifactId>
<version>3.0.7</version>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-rpc-rest</artifactId>
<version>3.0.9</version>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-registry-zookeeper</artifactId>
<version>3.0.7</version>
</dependency>
</dependencies>
2、核心配置文件
dubbo:
application:
name: dubbo-consumer
registry:
address: zookeeper://127.0.0.1:2181
protocol:
name: dubbo
port: 20880
# 由于zookeeper启动时要占用8080端口,我们要显示指定端口,要不然会端口冲突
server:
port: 8081
3、接口层
为了模拟外部调用效果,这里提供一个接口类
import com.congge.entity.User;
import com.congge.service.MyUserService;
import com.congge.service.UserService;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class UserController {
/*@DubboReference
private UserService userService;*/
@Autowired
private MyUserService myUserService;
//http://localhost:8081/user/dubbo?userId=001
@GetMapping("/user/dubbo")
public Object getByUserIdV1(@RequestParam("userId") String userId) {
return myUserService.getUserFromDubbo();
}
//http://localhost:8081/user/rest?userId=001
@GetMapping("/user/rest")
public Object getByUserIdV2(@RequestParam("userId") String userId) {
return myUserService.getUserFromRest();
}
}
4、业务实现层
import com.congge.entity.User;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
@Service
public class MyUserService {
@Autowired
private RestTemplate restTemplate;
@DubboReference
UserService userService;
public User getUserFromDubbo(){
User user = userService.getByUserId("001");
return user;
}
public Object getUserFromRest() {
User user = restTemplate.getForObject("http://localhost:8082/user/001",User.class);
return user;
}
}
5、启动类
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class ConsumerApp {
public static void main(String[] args) {
SpringApplication.run(ConsumerApp.class, args);
}
}
功能测试
1、启动zookeeper服务
2、分别启动生产端和消费端的服务
3、浏览器调用接口模拟
通过上面的案例,我们完成了dubbo3.0与springboot的整合使用,希望对看到的你有用哦。
版权归原作者 逆风飞翔的小叔 所有, 如有侵权,请联系我们删除。