Dubbo服务治理
2018-10-23 本文已影响3人
老鼠AI大米_Java全栈
dubbo源于电商系统,是由传统应用一步步演变而来,下面我们先了解下演变过程
系统演变过程
- 单一应用
- 当网站流量很小时,只需一个应用,将所有功能都部署在一起,以减少部署节点和成本。
- 此时,用于简化增删改查工作量的 数据访问框架(ORM) 是关键。
- 垂直应用架构
- 当访问量逐渐增大,单一应用增加机器带来的加速度越来越小,将应用拆成互不相干的几个应用,以提升效率。
- 此时,用于加速前端页面开发的 Web框架(MVC) 是关键。
- 分布式服务架构
- 当垂直应用越来越多,应用之间交互不可避免,将核心业务抽取出来,作为独立的服务,逐渐形成稳定的服务中心,使前端应用能更快速的响应多变的市场需求。
- 此时,用于提高业务复用及整合的分布式服务框架(RPC) 是关键。
- 流动计算架构
- 当服务越来越多,容量的评估,小服务资源的浪费等问题逐渐显现,此时需增加一个调度中心基于访问压力实时管理集群容量,提高集群利用率。
- 此时,用于提高机器利用率的 资源调度和治理中心(SOA) 是关键。
RPC(Remote Procedure Call Protocol):远程过程调用
RPC需要解决的问题
- 通讯问题 : 主要是通过在客户端和服务器之间建立TCP连接,远程过程调用的所有交换的数据都在这个连接里传输。连接可以是按需连接,调用结束后就断掉,也可以是长连接,多个远程过程调用共享同一个连接。
- 寻址问题 : A服务器上的应用怎么告诉底层的RPC框架,如何连接到B服务器(如主机或IP地址)以及特定的端口,方法的名称名称是什么,这样才能完成调用。比如基于Web服务协议栈的RPC,就要提供一个endpoint URI,或者是从UDDI服务上查找。如果是RMI调用的话,还需要一个RMI Registry来注册服务的地址。
- 序列化 与 反序列化 : 当A服务器上的应用发起远程过程调用时,方法的参数需要通过底层的网络协议如TCP传递到B服务器,由于网络协议是基于二进制的,内存中的参数的值要序列化成二进制的形式,也就是序列化(Serialize)或编组(marshal),通过寻址和传输将序列化的二进制发送给B服务器。
同理,B服务器接收参数要将参数反序列化。B服务器应用调用自己的方法处理后返回的结果也要序列化给A服务器,A服务器接收也要经过反序列化的过程。
Dubbo特点
- 一款分布式服务框架
- 高性能和透明化的RPC远程服务调用方案
- SOA服务治理方案
Dubbo架构
- Provider: 暴露服务的服务提供方。
- Consumer: 调用远程服务的服务消费方。
- Registry: 服务注册与发现的注册中心。
- Monitor: 统计服务的调用次数和调用时间的监控中心。
服务启动及调用过程
- 先启动服务提供者,再启动服务消费者
- 服务提供者在启动时,向注册中心注册自己提供的服务。
- 服务消费者在启动时,向注册中心订阅自己所需的服务。
- 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。
- 服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
- 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。
下面我们开始搭建一个服务提供者与服务消费者。
主要是以下几个步骤:
- 安装Zookeeper,启动
- 创建maven项目,构建Dubbo+Zookeeper+Boot工程
安装zookeeper
因dubbo是基于zk的,所以要先启动zk。
下载zookeeper,将原配置文件zoo_sample.cfg重命名配置文件为zoo.cfg,再启动zkServer.cmd(windows下直接运行即可)
创建工程
在maven工程中创建如下几个module:
- dubbo-api 公共接口
- dubbo-consumer 服务消费者
- dubbo-provider 服务提供者
dubbo-api
public interface DubboService {
//声明服务方法
String sayHello(String name);
}
dubbo-consumer
配置文件consumer.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://code.alibabatech.com/schema/dubbo"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://code.alibabatech.com/schema/dubbo
http://code.alibabatech.com/schema/dubbo/dubbo.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<!--配置服务名称-->
<dubbo:application name="dubbo-consumer" />
<!--配置服务注册中心,dubbo不仅仅支持zookeeper-->
<dubbo:registry address="zookeeper://127.0.0.1:2181" />
<!--声明服务引用,与服务声明接口类型一致-->
<dubbo:reference interface="com.iti.DubboService" id="dubboService" />
</beans>
引导文件,需要加载dubbo的配置文件
package com.iti;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ImportResource;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
@SpringBootApplication
@ImportResource("classpath:/consumer.xml")
@RestController
public class Consumer {
//注入声明的服务
@Autowired
private DubboService dubboService;
public static void main(String[] args){
SpringApplication.run(Consumer.class,args);
}
//测试服务调用
@ResponseBody
@RequestMapping("/sayhello/{name}")
public String hello(@PathVariable String name){
for(int i=0; i<10; i++){
System.out.println(dubboService.sayHello(name+i));
}
return dubboService.sayHello(name);
}
}
dubbo-provider
添加上面接口的具体实现,注意这里的value要与上面的id相同
@Component("dubboService")
public class DubboServiceImpl implements DubboService {
@Override
public String sayHello(String name) {
return "hello " + name;
}
}
同样也要对服务提供者配置dubbo,如下
<?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://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://code.alibabatech.com/schema/dubbo
http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
<!--定义了提供方应用信息,用于计算依赖关系;在 dubbo-admin 或 dubbo-monitor 会显示这个名字,方便辨识-->
<dubbo:application name="dubbo-provider" owner="programmer" organization="dubbox"/>
<!--使用 zookeeper 注册中心暴露服务,注意要先开启 zookeeper-->
<dubbo:registry address="zookeeper://localhost:2181"/>
<!-- 用dubbo协议在20880端口暴露服务 -->
<dubbo:protocol name="dubbo" port="20880" />
<!--使用 dubbo 协议实现定义好的 api.PermissionService 接口-->
<dubbo:service interface="com.iti.DubboService" ref="dubboService" protocol="dubbo" />
</beans>
很多情况下,服务提供者也是服务消费者,怎么办?
可以在dubbo配置文件中直接配置对应的服务引用,如添加对DubboService2的引用
<dubbo:reference interface="com.iti.DubboService2" id="dubboService2" />
当然需要再创建一个服务提供者dubbo-provider2,步骤同上。
服务自动负载均衡
只需把dubbo-provider多启动几份(注意端口),这样针对DubboService接口的服务提供者就有多个,当调用服务消费者消费服务时,可以写一个循环打印服务接口的方法,就可以看到输出的日志已经负载均衡了。
学习交流群:64691032