一、Dubbo概述
① Apache Dubbo (incubating) |ˈdʌbəʊ| 是一款高性能、轻量级的开源Java RPC框架,它提供了三大核心能力:面向接口的远程方法调用,智能容错和负载均衡,以及服务自动注册和发现。
② Dubbo(读音[ˈdʌbəʊ])是阿里巴巴公司开源的一个高性能优秀的服务框架,使得应用可通过高性能的 RPC 实现服务的输出和输入功能,可以和 Spring框架(由Rod Johnson创建的一个开源框架)无缝集成
③ Dubbo是一个分布式服务框架,致力于提供高性能和透明化的RPC远程服务调用方案、服务治理方案。
官网:http://dubbo.apache.org/zh-cnhttp://dubbo.apache.org/zh-cn特性:
面向接口代理:调用接口的方法,在A服务器调用B服务器的方法,由dubbo实现对B的调用,无需关心实现的细节,就像MyBatis访问Dao的接口,可以操作数据库一样。不用关心Dao接口方法的实现。这样开发是方便,舒服的。
二、基本架构
① 服务提供者(Provider):暴露服务的服务提供方,服务提供者在启动时,向注册中心注册自己提供的服务。
② 服务消费者(Consumer): 调用远程服务的服务消费方,服务消费者在启动时,向注册中心订阅自己所需的服务,服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
③ 注册中心(Registry):注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者 –如果信息有变,注册中心提供新的信息给消费者
监控中心(Monitor):服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心 –监控服务提供者、消费者状态,与开发没有直接关系。
调用关系说明:
① 服务容器spring负责启动,加载,运行服务提供者。
② 服务提供者在启动时,向注册中心注册自己提供的服务。
③ 服务消费者在启动时,向注册中心订阅自己所需的服务。
④ 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。
⑤ 服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
⑥ 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。
三、Dubbo支持的协议
支持多种协议:dubbo , hessian , rmi , http, webservice , thrift , memcached , redis。
dubbo官方推荐使用dubbo协议。dubbo协议默认端口20880
使用dubbo协议,spring配置文件加入:
<dubbo:protocol name="dubbo" port="20880" />
四、电商平台需求
某电商平台系统需求,用户浏览商品;选择商品下订单,订单系统需要获取用户信息中的送货地址;向支付系统请求完成付款。
服务 | 功能 |
---|---|
网站系统 | 展示商品,修改用户信息 |
订单系统 | 生成订单 |
用户系统 | 用户信息(地址,收件人,联系方式等) |
五、直连方式dubbo
点对点的直连项目:消费者直接访问服务提供者,没有注册中心。消费者必须指定服务提供者的访问(URL)地址。
消费者直接通过URL地址访问固定的服务提供者。这个URL地址是不变的。
1. 实现目标
用户访问 ------>【商品网站服务】访问-----> 【订单服务】
2. 实现方式
以JavaSE为例,服务提供者,服务消费者都是JavaSE项目
(1) 创建父工程:parent
A. maven pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.suke</groupId>
<artifactId>parent</artifactId>
<version>1.0-SNAPSHOT</version>
<modules>
<module>../order-provider</module>
<module>../web-consumer</module>
</modules>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion>
<spring.version>5.0.3.RELEASE</spring.version>
<dubbo.version>2.6.2</dubbo.version>
</properties>
<packaging>pom</packaging>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<!--Dubbo依赖-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>${dubbo.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<!-- <pluginManagement>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</pluginManagement>-->
</build>
</project>
B. 删除src目录
(2)创建服务提供者:订单服务
A. 新建java project
项目名称:orderservice-provider
设置version 为 1.0.0
B. maven pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>parent</artifactId>
<groupId>com.suke</groupId>
<version>1.0-SNAPSHOT</version>
<relativePath>../parent/pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>order-provider</artifactId>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<!--Dubbo依赖-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
</dependency>
</dependencies>
</project>
C. 创建订单实体类:Order
package com.suke.provider.bean;
import java.io.Serializable;
public class Order implements Serializable {
private String id;
private String goodsName;
private Double price;
private Integer amount;
@Override
public String toString() {
return "Order{" +
"id='" + id + '\'' +
", goodsName='" + goodsName + '\'' +
", price=" + price +
", amount=" + amount +
'}';
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getGoodsName() {
return goodsName;
}
public void setGoodsName(String goodsName) {
this.goodsName = goodsName;
}
public Double getPrice() {
return price;
}
public void setPrice(Double price) {
this.price = price;
}
public Integer getAmount() {
return amount;
}
public void setAmount(Integer amount) {
this.amount = amount;
}
}
D. 新建订单服务接口:OrderService
package com.suke.provider.service;
import com.suke.provider.bean.Order;
public interface OrderService {
Order addOrder(String id, String goodsName, Double price, Integer amount);
}
E. 新建接口的实现类:OrderServiceImpl
package com.suke.provider.service.impl;
import com.suke.provider.bean.Order;
import com.suke.provider.service.OrderService;
import java.util.UUID;
public class OrderServiceImpl implements OrderService {
@Override
public Order addOrder(String id, String goodsName, Double price, Integer amount) {
Order order = new Order();
order.setId(UUID.randomUUID().toString().replace("-", ""));
order.setGoodsName(goodsName);
order.setPrice(price);
order.setAmount(amount);
return order;
}
}
F. 创建dubbo配置文件:provider.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://dubbo.apache.org/schema/dubbo
http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
<!--给服务提供从起一个唯一标识-->
<dubbo:application name="provider"/>
<!--使用Dubbo协议通信-->
<dubbo:protocol name="dubbo" port="20880"/>
<!--对外开放的接口,N/A:不使用注册中心-->
<dubbo:service interface="com.suke.provider.service.OrderService"
ref="orderService" registry="N/A"/>
<bean id="orderService" class="com.suke.provider.service.impl.OrderServiceImpl"/>
</beans>
G. 测试配置文件
package com.suke.provider.test;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.Scanner;
public class TestProvider {
public static void main(String[] args) {
BeanFactory beanFactory =
new ClassPathXmlApplicationContext("classpath:provider.xml");
((ClassPathXmlApplicationContext) beanFactory).start();
//服务的提供方必须一直运行 阻塞方式
System.out.println("服务器已运行");
Scanner scanner = new Scanner(System.in);
scanner.nextInt();
}
}
H. 安装本地jar 到maven仓库
① 服务接口中的方法要给消费者使用,消费者项目需要知道接口名称和接口中的方法名称、参数等。这些信息服务提供者才知道。需要把接口的class文件打包为jar。
② 服务接口项目的类文件打包为jar, 安装到maven仓库,仓库中的提供者jar可以被消费者使用。
③ 使用IDEA的maven窗口执行 install。
(2)创建服务消费者:商品网站
A. 新建java project
项目名称:web-consumer
设置version 为 1.0.0
B. maven pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>parent</artifactId>
<groupId>com.suke</groupId>
<version>1.0-SNAPSHOT</version>
<relativePath>../parent/pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>web-consumer</artifactId>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<!--Dubbo依赖-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
</dependency>
<!--引入提供者坐标-->
<dependency>
<groupId>com.suke</groupId>
<artifactId>order-provider</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
</project>
C. 创建购买商品接口:GoodService
package com.suke.consumer.service;
import com.suke.provider.bean.Order;
public interface GoodService {
Order buyGood(String id, String goodsName, Double price, Integer amount);
}
D. 创建购买接口的实现类:GoodServiceImpl
package com.suke.consumer.service.impl;
import com.suke.consumer.service.GoodService;
import com.suke.provider.bean.Order;
import com.suke.provider.service.OrderService;
public class GoodServiceImpl implements GoodService {
private OrderService orderService;
public OrderService getOrderService() {
return orderService;
}
public void setOrderService(OrderService orderService) {
this.orderService = orderService;
}
@Override
public Order buyGood(String id, String goodsName, Double price, Integer amount) {
return orderService.addOrder(id, goodsName, price, amount);
}
}
E. 创建dubbo配置文件:consume.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://dubbo.apache.org/schema/dubbo
http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
<!--给服务消费者起一个唯一标识-->
<dubbo:application name="consumer"/>
<!--查找开放指定接口-->
<dubbo:reference interface="com.suke.provider.service.OrderService"
url="dubbo://localhost:20880" registry="N/A" id="remoteService"/>
<!--配置消费方的服务对象-->
<bean id="goodService" class="com.suke.consumer.service.impl.GoodServiceImpl">
<property name="orderService" ref="remoteService"/>
</bean>
</beans>
F. 执行消费者
六、Dubbo服务化最佳实践
1. 分包
建议将服务接口、服务模型、服务异常等均放在公共包中。
2. 粒度
① 服务接口尽可能大粒度,每个服务方法应代表一个功能,而不是某功能的一个步骤,
② 服务接口建议以业务场景为单位划分,并对相近业务做抽象,防止接口数量爆炸。
③ 不建议使用过于抽象的通用接口,如:Map query(Map),这样的接口没有明确语义,会给后期维护带来不便。
3. 版本
每个接口都应定义版本号,区分同一接口的不同实现,如: <dubbo:service interface="com.xxx.XxxService" version="1.0" />。
七、改造Dubbo项目
抽象分散在多个项目中的公共接口,实体类,异常,工具类到一个项目中,在其他项目如服务提供者,消费者共用公共的资源。
1. 实现目标
用户访问电商网站浏览商品—选择商品购买
用户访问电商网站—查看用户信息(收件人地址)
项目是web应用,需要加入spring web开发jar:
maven依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.3.16.RELEASE</version>
</dependency>
2. 创建公共资源项目
服务提供者,消费者,网站等多个服务中共用,重复使用的类单独定义在一个项目。
A. 创建公共的maven java project
项目名称:bean
项目名称:common-interface
项目名称:common-util
接口工程的Maven坐标
B. 复制之前的Order实体类、OrderService业务接口到新建项目
八、dubbo常用标签
Dubbo中常用标签。分为三个类别:公用标签,服务提供者标签,服务消费者标签
1. 公用标签
<dubbo:application/> 和 <dubbo:registry/>
A. 配置应用信息
<dubbo:application name=”服务的名称”/>
B. 配置注册中心
<dubbo:registry address=”ip:port” protocol=”协议”/>
2. 服务提供者标签
配置暴露的服务
<dubbo:service interface=”服务接口名” ref=”服务实现对象bean”>
3. 服务消费者
配置服务消费者引用远程服务
<dubbo:reference id=”服务引用bean的id” interface=”服务接口名”/>