dubbo笔记
1 分布式与集群
分布式:一个业务拆分为多个子业务,部署在多个服务器上 。
集群:同一个业务,部署在多个服务器上 。
1.1分布式中的相关概念
响应数:执行一个请求从开始到最后收到响应数据所花费的总体时间。
并发数:指系统同时能处理的请求数量。
并发连接数:客户端详服务器发起请求,并建立了TCP连接,每秒钟
服务器连接的总的TCP数量。
并发用户数:单位时间内有多少用户。
吞吐量:单位时间内系统能处理的请求数量。
QPS:每秒查询数。
TPS:Transactions Per Second 每秒事务数。
QPS>=并发连接数>=TPS
2 架构演进
单体架构 、垂直架构、分布式架构、SOA架构、微服务架构
2.1 单体架构
优点:开发部署方便,小型项目首选
缺点:项目启动慢、可靠性差,可伸缩性差、扩展性和可维护性差。
2.2 垂直架构
可以理解为将单体架构里的多个模块拆分为多个独立的项目,形成多个独立的单体架构。
2.3分布式架构
分布式架构是指在垂直架构的基础上,将公共业务模块抽取出来,作为独立的服务,供其他调用者消费,以实现服务的共享和重用。
RPC:Remote Procedure Call 远程过程调用,有很多的技术来实现RPC技术。比如,HTTP REST风格,Java RMI规范,WebService SOAP协议、Hession等。
分布式架构存在的问题:服务提供方一旦产生变更,所有的消费方都需要变更。
2.4 SOA架构
SOA:(Service-Oriented Architecture ,面向服务的架构)是一个组件模型,它将应用程序的不同功能单元(成为服务)进行拆分,并通过这些服务之间的定义良好的接口和契约联系起来。
ESB:(Enterparise Service Bus)企业服务总线,服务中介。主要提供了一个服务于服务之间的交互。ESB包含的功能:负载均衡、流量控制、加密处理、服务的监控、异常处理、监控告急。
2.5 微服务架构
微服务架构实在SOA上做的升华,微服务架构强调的一个重点是“业务需要彻底的组件化和服务化”,原有的单个业务系统会拆分为多个可以独立开发、设计、运行的小应用。这些小应用之间通过服务完成交互和集成。
特点:
服务实现组件化,开发者可以自由选择开发技术,也不需要协调其他团队;
服务之间交互一般使用REST API;
去中心化,每个微服务有自己私有的数据库持久化业务数据;
自动化部署,把应用拆分成一个一个独立的单个服务,方便自动化部署、测试、运维。
3 Dubbo
3.1 Duboo概述
Dubbo是阿里巴巴公司开源的一个高性能、轻量级的Java RPC框架。
致力于提供高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案。
3.2 Duboo架构
Provider:暴露服务的服务提供方,
Container:服务运行容器,
Consumer:调用远程服务的服务消费方,
Registry:服务注册与发现的注册中心,
Monitor:统计服务的调用册数和调用时间的监控中心。
3.3 dubbo快入门
1、创建服务提供者Provider模块
2、创建服务消费者Consumer模块
3、在服务提供者编写UerServiceImpl提供服务
4、在服务消费者中的UserConcroller远程调用UsersericeImpl提供的服务
5、分别启动2个服务,进行测试
<!-- dubbo的配置-->
<!--< dubbo:protocol port="20880"/>-->
<!--1.配置项目的名称-->
<dubbo:application name="dubbo-service"/>
<!--2.配置注册中心的地址-->
<dubbo:registry address="zookeeper://127.0.0.1:2181"/>
<!--3.配置dubbo包扫描-->
<dubbo:annotation package="com.it.service.impl"/>
<!--元数据配置-->
<dubbo:metadata-report address="zookeeper://127.0.0.1:2181"/>
3.4 dubbo高级特性
3.4.1 dubbo-admin
dubbo-admin管理平台,是图形化的服务管理页面。
从注册中心获取到所有的提供者/消费者进行配置管理。
路由规则、动态配置、服务降级、访问控制、权重调整、负载均衡等管理功能。
dubbo-admin是一个前后端分离的项目,前端vue,后端springboot。
安装dubbo-admin就是部署该项目。
部署:启动zookeeper;cmd到dubbo-admin-develop下执行mvn clean package;cmd到dubbo-admin-ui下执行npm run dev。
3.4.2 序列化
问题:2个机器传输数据,如何传输java对象呢?
dubbo内部已经将对象的序列化和反序列化的过程内部封装了,我们只需在定义pojo类时实现Serializable接口即可,一般定义一个公共的pojo模块,让生产者消费者都依赖该模块。
3.4.3 地址缓存
问题:注册中心挂了,服务是否可以正常访问?
可以,因为dubbo服务消费者在第一次调用时,会将服务提供方地址缓存到本地,以后在调用则不会访问注册中心。
当服务提供者地址发生变化时,注册中心会通知服务消费者。
3.4.4 超时与重试
服务消费者在调用服务提供者的时候发生阻塞、等待的情形,这个时候,服务消费者会一直等待下去;在某个峰值时刻,大量的请求都在同时请求服务消费者,会造成线程的大量堆积,势必造成雪崩。
解决办法:dubbo利用超时机制来解决这个问题,设置一个超时时间,在这个时间段内,无法完成服务访问,则自动断开连接。使用timeout属性配置超时时间,默认值1000,单位毫秒。重试默认值为2。
package com.it.service.impl;
import com.it.pojo.User;
import com.it.service.UserService;
import org.apache.dubbo.config.annotation.Service;
//import org.springframework.stereotype.Service;
/**
* Created by 12594 on 2021/10/18.
*/
//@Service//将该类的对象创建出来,放到Spring的IOC容器中,bean定义
//将这个类提供的方法(服务)对外发布,将访问的地址ip、端口、路径注册到注册中心中
@Service(timeout = 3000,retries = 0)
public class UserServiceImpl implements UserService {
public String sayHello() {
return "hello dubbo";
}
public User findUserByTd(int id) {
User user = new User(1,"张三","12345");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return user;
}
}
也可以在消费者设置超时时间
package com.it.controller;
import com.it.pojo.User;
import com.it.service.UserService;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
/**
* Created by 12594 on 2021/10/18.
*/
@Controller
@RequestMapping("/user")
public class UserController {
//@Autowired//本地注入
/*
1.从zookeeper注册中心获取userService的访问url
2.进行远程调用RPC
3.将结果封装成一个代理对象。给变量赋值
*/
@Reference(timeout = 1000)
private UserService userService;
@RequestMapping("/sayHello")
@ResponseBody
public String sayHello(){
return userService.sayHello();
}
@RequestMapping("/find")
@ResponseBody
public User find(int id){
return userService.findUserByTd( id);
}
}
3.4.5 多版本
灰度发布:当出现新功能时,会让一部分用户先使用新功能,用户反馈没问题时,再将所有用户迁移到新功能。
dubbo中使用version属性来设置和调用同一个接口的不同版本。
在服务提供者里写上版本
@Service(version = "v1.0")
在服务消费者里标明要调用的版本
@Reference(version = "v2.0")
3.4.6 负载均衡
4种负载均衡策略
1、Random:按权重随机,默认值。按权重设置随机概率。
2、RoundRobin:按权重轮询
3、LeastActive:最少活跃调用数,相同活跃数的随机。
(消费者先看服务提供者最后一次请求调用花费了多少时间,消费者会选择一个耗时最小的服务器去请求)
4、ConsistentHash:一致性Hash,相同参数的请求总是发到同一提供者。
可以打开AbstractLoadBalance类,看它的接口实现,如下:
public class RandomLoadBalance extends AbstractLoadBalance {
public static final String NAME = "random";
public RandomLoadBalance() {
}
3.4.7 集群容错
1、Failover Cluster
失败自动切换,当出现失败,重试其它服务器。通常用于读操作,但重试会带来更长延迟。可通过 retries=“2” 来设置重试次数(不含第一次)。
2、Failfast Cluster
快速失败,只发起一次调用,失败立即报错。通常用于非幂等性的写操作,比如新增记录。
3、Failsafe Cluster
失败安全,出现异常时,直接忽略。通常用于写入审计日志等操作。
4、Failback Cluster
失败自动恢复,后台记录失败请求,定时重发。通常用于消息通知操作。
5、Forking Cluster
并行调用多个服务器,只要一个成功即返回。通常用于实时性要求较高的读操作,但需要浪费更多服务资源。可通过 forks=“2” 来设置最大并行数。
6、Broadcast Cluster
广播调用所有提供者,逐个调用,任意一台报错则报错。通常用于通知所有提供者更新缓存或日志等本地资源信息。
参考dubbo文档
打开Cluster接口,看其实现,如下:
public class FailoverCluster implements Cluster {
public static final String NAME = "failover";
public FailoverCluster() {
}
3.4.8 服务降级
1、mock=force:return null
表示消费方对该服务的方法调用都直接返回 null 值,不发起远程调用。用来屏蔽不重要服务不可用时对调用方的影响。
2、 mock=fail:return null
表示消费方对该服务的方法调用在失败后,再返回 null 值,不抛异常。用来容忍不重要服务不稳定时对调用方的影响。
例如:
@Reference(mock = "force:return null")
private UserService userService;