是个远程服务调用的分布式框架(告别Web Service模式中的WSdl,以服务者与消费者的方式在dubbo上注册),核心在于服务的注册和发现.
Dubbo诞生的意义
集群
同一个项目复制多份,每一个用一个tomcat服务,多个请求过来,分发到各个服务进行,但是如果把所有的功能都放在一个项目之中,项目的体积将会非常庞大,不利于项目维护
分布式
一个系统按模块分成n个子模块,每个子模块都是一个单独系统,处理与之有关的业务
Dubbo服务模块化
maven
模块化虽然可以达到业务解耦(业务修改,只需要修改该改动的模块),但是重启需要重启跟这个
模块有关的所有模块,极不方便.
Dubbo
:服务全部注册到注册中心,当有需要调用该服务的时候,(RPC远程过程调用)给予其服务,服务不存在,则提示无此服务,这种方式改动需要改动的模块时,不需要启动其他的项目,单独启动该服务即可.
面向服务架构
流动计算架构(SOA)
:随着服务化的进一步发展,服务越来越多,服务之间的调用和依赖关系也越来越复杂,诞生了面向服务的架构体系(SOA),也因此衍生出了一系列相应的技术,如对服务提供、服务调用、连接处理、通信协议、序列化方式、服务发现、服务路由、日志输出等行为进行封装的服务框架
注册使用ZAB协议
Zookeeper协议
:ZAB协议:(原子消息协议)在zookeeper的所有事务都由一个主服务器也就是leader来处理,其服务器为follower,leader将所有客户端的事务请求转换为事务proposal(提议,请求),并且将它分发给集群中的其他follower,然后leader等待follower反馈,当过半数>n/2+1,leader广播给所以follower发布commit信息,将之前的proposal提交
dubbo调用采用RPC方式
RPC(Remote Procedure Call Protocol):远程过程调用:
两台服务器A、B,分别部署不同的应用a,b。当A服务器想要调用B服务器上应用b提供的函数或方法的时候,由于不在一个内存空间,不能直接调用,需要通过网络来表达调用的语义传达调用的数据。
Dubbo创建服务
1.打开zookeeper
2.解压dubbo包,修改文件夹名为:dubbo
,修改WEB_INF
下的dubbo.properties
,确保其连接能到zookeeper
dubbo.registry.address=zookeeper://127.0.0.1:2181
3.启动tomcat服务,然后浏览器进入对应地址,登录root/root,成功如下图
4.idea公共父模块引入包(dubbo,zkcli)
<dependency>
<groupId>io.dubbo.springboot</groupId>
<artifactId>spring-boot-starter-dubbo</artifactId>
<version>1.0.0</version>
</dependency>
SpringBoot中Dubbo的多模块思路说明
由于要让模块中的实体类和服务暴露在各个模块中,就务必把这两个包用一个服务模块包含起来,其他的模块引用该模块即可,提供者和消费者应该分模块放置
创建提供者provider
创建提供者的pom依赖父工程和service工程
<parent>
<groupId>com.wei</groupId>
<artifactId>dubbo</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<dependency>
<groupId>com.wei.dubbo</groupId>
<artifactId>service</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
修改application.properties为application.yml,修改内容为
spring:
dubbo:
application: #应用配置,用于配置当前应用信息,不管该应用是提供者还是消费者。
name: Provide
registry: #注册中心配置,用于配置连接注册中心相关信息。
address: zookeeper://127.0.0.1:2181
protocol: #协议配置,用于配置提供服务的协议信息,协议由提供方指定,消费方被动接受。
name: dubbo
port: 20880
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://数据库连接地址
username: 数据库连接账号
password: 数据库连接地址密码
提供者的业务数据
package com.wei.dubbo.provider.service;
import com.alibaba.dubbo.config.annotation.Service;
import com.wei.dubbo.service.bo.Employee;
import com.wei.dubbo.service.bo.EmployeeExample;
import com.wei.dubbo.provider.dao.EmployeeDao;
import com.wei.dubbo.service.service.EmployeeService;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.List;
@Service
public class EmploueeServiceImpl implements EmployeeService {
@Autowired
private EmployeeDao employeeDao;
@Override
public long countByExample(EmployeeExample example) {
return employeeDao.countByExample(example);
}
@Override
public int deleteByExample(EmployeeExample example) {
return employeeDao.deleteByExample(example);
}
@Override
public int deleteByPrimaryKey(Integer employeeId) {
return employeeDao.deleteByPrimaryKey(employeeId);
}
@Override
public int insert(Employee record) {
return employeeDao.insert(record);
}
@Override
public int insertSelective(Employee record) {
return employeeDao.insertSelective(record);
}
@Override
public List<Employee> selectByExample(EmployeeExample example) {
return employeeDao.selectByExample(example);
}
@Override
public Employee selectByPrimaryKey(Integer employeeId) {
return employeeDao.selectByPrimaryKey(employeeId);
}
@Override
public int updateByExampleSelective(Employee record, EmployeeExample example) {
return employeeDao.updateByExampleSelective(record, example);
}
@Override
public int updateByExample(Employee record, EmployeeExample example) {
return employeeDao.updateByExample(record, example);
}
@Override
public int updateByPrimaryKeySelective(Employee record) {
return employeeDao.updateByPrimaryKeySelective(record);
}
@Override
public int updateByPrimaryKey(Employee record) {
return employeeDao.updateByPrimaryKey(record);
}
}
这里使用的是@Service,注意这里的service注解是dubbo提供的,不是spring提供的注解
创建服务模块
pom.xml引入父依赖
<parent>
<groupId>com.wei</groupId>
<artifactId>dubbo</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
创建具有公共实体类,服务接口的服务模块service和bo的package
定义bo类和接口类(实现类定义在提供者之中)
package com.wei.dubbo.service.service;
import com.wei.dubbo.service.bo.Employee;
import com.wei.dubbo.service.bo.EmployeeExample;
import org.apache.ibatis.annotations.Param;
import java.util.List;
public interface EmployeeService {
long countByExample(EmployeeExample example);
int deleteByExample(EmployeeExample example);
int deleteByPrimaryKey(Integer employeeId);
int insert(Employee record);
int insertSelective(Employee record);
List<Employee> selectByExample(EmployeeExample example);
Employee selectByPrimaryKey(Integer employeeId);
int updateByExampleSelective(@Param("record") Employee record, @Param("example") EmployeeExample example);
int updateByExample(@Param("record") Employee record, @Param("example") EmployeeExample example);
int updateByPrimaryKeySelective(Employee record);
int updateByPrimaryKey(Employee record);
}
创建消费者consumer
pom
的构建
<parent>
<groupId>com.wei</groupId>
<artifactId>dubbo</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<dependency>
<groupId>com.wei.dubbo</groupId>
<artifactId>service</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
配置消费者的yml(注意8084和21880端口不要重复)
server:
port: 8084
spring:
dubbo:
application: #应用配置,用于配置当前应用信息,不管该应用是提供者还是消费者。
name: Provide
registry: zookeeper://127.0.0.1:2181 #注册中心配置,用于配置连接注册中心相关信息。
consumer:
check: false
protocol: #协议配置,用于配置提供服务的协议信息,协议由提供方指定,消费方被动接受。
name: dubbo
port: 20880
服务消费者调用服务的提供者
@Reference
private EmployeeService employeeService;
@RequestMapping("hello")
public Object hello() {
return employeeService.selectByPrimaryKey(65);
}
注意这里的@reference注解是dubbo提供的rpc调用的引入注解,用法和@autowired类似
可以的话再创建一个同一服务的提供者
顺序启动提供者,消费者
在网页浏览器打开dubbo管理器
我这里因为有2个提供者,一个消费者
访问一下,搭建成功
Dubbo负载均衡
用于创建多个同一服务的提供者,当请求来到时,通过分发请求的方式,分别分配服务,
以达到降低单个服务器的压力
策略:
方式 | 意义 |
---|---|
轮询(roundrobin) | 遵循规律,轮流访问 |
随机 | 随机 |
最少并发 | 根据服务响应的时间,哪个响应快,就访问权值大一点 |
搭建方式
提供者搭建
按之前的搭建服务的方式再建一个提供者,注意启动端口(8080)和dubbo提供者端口(21880)不要重复,在此不赘述
负载均衡配置
或者进行权重调节