文章目录
前言
先行概念
什么是rpc
很多人都会以为rpc是一种网络协议,实际上这种想法是非常错误的,笔者认为rpc协议应该说是一种通信协议的风格,与之相对应进行比较的不是http这种传输层协议,而是restful。
如下图所示,rpc协议所要求请求风格是查询一律使用get,而resultful则对增和改是put,删是delete,查则是get。
rpc与dubbo框架
阿里巴巴公司开源的一个高性能优秀的服务框架,使得应用可通过高性能的 RPC 实现服务的输出和输入功能,可以和 Spring框架无缝集成
为什么项目中会使用到dubbo协议呢?
随着项目业务越来越复杂,各个功能被抽取成模块是必不可免的,所以服务之间的交互也会随着规模扩大而不断扩大,一次请求可能需要无数个服务之间来会交互,这时候dubbo协议的优势就来了。
http是标准的应用层协议为了保证各个语言间通用性等,势必会携带很多报文参数,而dubbo协议则是阿里自定义的一个rpc协议,他的报文内容并没有http那么多,所以解析数据速度更快。而且是基于socket长连接,且dubbo协议是Nio多路复用,支持高并发请求,正是因为这种特性,决定了dubbo协议适用于数据量小消费方大于服务方且内部服务协作十分复杂的应用场景,具体可参照下文:
从Dubbo浅谈RPC和HTTP
代码示例基于zk+dubbo实现soa项目
工作原理
通过spring boot整合dubbo完成各个服务注册,保证消费者可以zk发现服务并基于dubbo协议完成调用。
而以下示例是一个服务方提供城市信息查询,而消费者通过服务查询城市信息的案例。
启动zk
基于springboot实现dubbo服务注册
代码示例
城市类
package org.spring.springboot.domain;
import java.io.Serializable;
/**
* 城市实体类
*
*
*/
public class City implements Serializable {
private static final long serialVersionUID = -1L;
/**
* 城市编号
*/
private Long id;
/**
* 省份编号
*/
private Long provinceId;
/**
* 城市名称
*/
private String cityName;
/**
* 描述
*/
private String description;
public City() {
}
public City(Long id, Long provinceId, String cityName, String description) {
this.id = id;
this.provinceId = provinceId;
this.cityName = cityName;
this.description = description;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Long getProvinceId() {
return provinceId;
}
public void setProvinceId(Long provinceId) {
this.provinceId = provinceId;
}
public String getCityName() {
return cityName;
}
public void setCityName(String cityName) {
this.cityName = cityName;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
城市查询接口
package org.spring.springboot.dubbo;
import org.spring.springboot.domain.City;
/**
* 城市业务 Dubbo 服务层
*
*
*/
public interface CityDubboService {
/**
* 根据城市名称,查询城市信息
* @param cityName
*/
City findCityByName(String cityName);
}
城市查询实现
package org.spring.springboot.dubbo.impl;
import com.alibaba.dubbo.config.annotation.Service;
import org.spring.springboot.domain.City;
import org.spring.springboot.dubbo.CityDubboService;
import org.springframework.beans.factory.annotation.Autowired;
/**
* 城市业务 Dubbo 服务层实现层
*
*
*/
// 注册为 Dubbo 服务
@Service(version = "1.0.0")
public class CityDubboServiceImpl implements CityDubboService {
@Override
public City findCityByName(String cityName) {
return new City(1L,2L,"福建福州","有福之州");
}
}
启动代码
package org.spring.springboot;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* Spring Boot 应用启动类
*
*
*/
// Spring Boot 应用的标识
@SpringBootApplication
public class ServerApplication {
public static void main(String[] args) {
// 程序启动入口
// 启动嵌入式的 Tomcat 并初始化 Spring 环境及其各 Spring 组件
SpringApplication.run(ServerApplication.class,args);
}
}
配置
## Dubbo 服务提供者配置
#应用名称
spring.dubbo.application.name=provider
#注册中心地址
spring.dubbo.registry.address=zookeeper://127.0.0.1:2181
#协议名称
spring.dubbo.protocol.name=dubbo
#协议端口
spring.dubbo.protocol.port=20880
#服务类包目录
spring.dubbo.scan=org.spring.springboot.dubbo
启动并查看zk节点
[zk: localhost:2181(CONNECTED) 2] ls /dubbo/org.spring.springboot.dubbo.CityDubboService/providers
[dubbo%3A%2F%2F192.168.2.1%3A20880%2Forg.spring.springboot.dubbo.CityDubboService%3Fanyhost%3Dtrue%26application%3Dprovider%26dubbo%3D2.5.3%26interface%3Dorg.spring.springboot.dubbo.CityDubboService%26methods%3DfindCityByName%26pid%3D17044%26revision%3D1.0.0%26side%3Dprovider%26timestamp%3D1635264068561%26version%3D1.0.0]
基于spring boot实现dubbo服务调用
复制provder的城市类和城市查询接口
注入城市查询dubbo服务
package org.spring.springboot.dubbo;
import com.alibaba.dubbo.config.annotation.Reference;
import org.spring.springboot.domain.City;
import org.springframework.stereotype.Component;
/**
* 城市 Dubbo 服务消费者
*
*
*/
@Component
public class CityDubboConsumerService {
@Reference(version = "1.0.0")
CityDubboService cityDubboService;
public void printCity() {
String cityName="温岭";
City city = cityDubboService.findCityByName(cityName);
System.out.println(city.toString());
}
}
测试结果
如下图所示,消费者就会通过zk发现服务再调用该服务完成请求。
总结
从上面的实现我们可以看出zk+dubbo的强大之处,通过zk来监控服务后续还可以通过集群保证zk的健壮性,以及保证provider和consumer之间的解耦,更是方便后续服务扩展,只需将服务注册到zk即可。加上dubbo强大的rpc协议更是保证了一个用户请求的畅通无阻。
参考项目源代码地址
https://github.com/JeffLi1993/springboot-learning-example
注:只需关注以下两个spring boot项目即可
springboot-dubbo-client
springboot-dubbo-server
具体教程部署教程可参考
Spring Boot 集成 Dubbo/ZooKeeper 详解