一、集群和分布式
集群:就是很多人一起,干一样的事情
分布式:很多人一起干不一样的事情,但这些不一样的事情合起来就是一件大事,即若干独立系统的集合,但是用户使用起来还是在使用一套系统
特点:高性能,高可用,可伸缩,高可扩展
二、应用架构的发展演变
1.单一架构
把所有的应用放到一台服务器上
优点:开发简单部署简单
缺点:不容易扩展,不容易维护,性能提升难,项目启动慢,可靠性差,可伸缩性差
2.垂直架构
将大应用拆分成小应用(一般按照业务进行分),根据不同的访问频率来确定部署的服务器数量
缺点:界面+业务逻辑的实现分离,应用之间不可能完全独立,大量的应用之间需要交付
3.分布式架构(基于RPC:远程过程调用)
在垂直架构的基础上,将公共业务模块抽取出来,作为独立的服务,供其他调用者消费,以实现服务的共享和重用。
4.SOA架构
将应用程序的不同功能单元(称为服务)进行拆分,并通过这些服务之间定义良好的接口和契约联系起来
5.微服务架构
强调的一个重点是“业务需要彻底的组件化和服务化”,原有的单个业务系统会拆分为多个可以独立开发、设计、运行的小应用。这些小应用之间通过服务完成交互和集成。 微服务架构 = 80%的SOA服务架构思想 + 100%的组件化架构思想 + 80%的领域建模思想
三、RPC
核心模块:通讯,序列化
四、dubbo概述(一个高性能、轻量级的 Java RPC 框架)
Provider:暴露服务的服务提供方
Container:服务运行容器
Consumer:调用远程服务的服务消费方
Registry:服务注册与发现的注册中心
Monitor:统计服务的调用次数和调用时间的监控中心
五、注册中心
zookeeper:更改配置文件要
进去conf目录复制zoo_sample.cfg然后更改复制后的文件 地址为你安装的zookeeper的地址
dataDir=D:\apache-zookeeper-3.6.3-bin\data
dataLogDir=D:\apache-zookeeper-3.6.3-bin\log
如果更在在服务器上的启动端口添加配置:admin.serverPort=没有占用的端口号
六、监控中心
去gitHub下载dubbo-admin
进入到dubbo-admin-develop目录下输入mvn clean package
启动后端
切换到目录dubbo-Admin-develop\dubbo-admin-distribution\target>然后输入
java -jar ./dubbo-admin-0.3.0.jar
启动前端
dubbo-admin-ui 目录下执行命令 npm run dev
访问
浏览器输入http://localhost:8082 用户名密码都是root
七、dubbo的使用
创建三个模块:消费者 提供者 公共接口模块
1.api-interface模块:公共接口层(作用:定义公共接口,也可以导入公共依赖)
实体类模型
package com.gl.pojo;
import java.io.Serializable;
/**
* @description:
* @author: GL
* @create: 2021-10-26 10:36
**/
public class UserAddress implements Serializable {
private Integer id;
private String userAddress;
private String userId;
private String consignee;
private String phoneNum;
private String isDefault;
public UserAddress() {
}
public UserAddress(Integer id, String userAddress, String userId, String consignee, String phoneNum, String isDefault) {
this.id = id;
this.userAddress = userAddress;
this.userId = userId;
this.consignee = consignee;
this.phoneNum = phoneNum;
this.isDefault = isDefault;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUserAddress() {
return userAddress;
}
public void setUserAddress(String userAddress) {
this.userAddress = userAddress;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getConsignee() {
return consignee;
}
public void setConsignee(String consignee) {
this.consignee = consignee;
}
public String getPhoneNum() {
return phoneNum;
}
public void setPhoneNum(String phoneNum) {
this.phoneNum = phoneNum;
}
public String getIsDefault() {
return isDefault;
}
public void setIsDefault(String isDefault) {
this.isDefault = isDefault;
}
@Override
public String toString() {
return "UserAddress{" +
"id=" + id +
", userAddress='" + userAddress + '\'' +
", userId='" + userId + '\'' +
", consignee='" + consignee + '\'' +
", phoneNum='" + phoneNum + '\'' +
", isDefault='" + isDefault + '\'' +
'}';
}
}
接口提取
UserService
package com.gl.service;
import com.gl.pojo.UserAddress;
import java.util.List;
/**
* @description:根据id查询所有的信息
* @author: GL
* @create: 2021-10-26 10:39
**/
public interface UserService {
public List<UserAddress> getUserAddressList(String userId);
}
OrderService
package com.gl.service;
import java.util.List;
import com.gl.pojo.UserAddress;
public interface OrderService {
/**
* 初始化订单
* @param userId
*/
public List<UserAddress> initOrder(String userId);
}
提供者模块(provider-service)
pom依赖
<dependencies>
<!--定义的公共接口的哪个类-->
<dependency>
<groupId>org.example</groupId>
<artifactId>api-interface</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!-- dubbo依赖-->
<!-- https://mvnrepository.com/artifact/org.apache.dubbo/dubbo-spring-boot-starter -->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>2.7.9</version>
</dependency>
<!-- zookeeper依赖-->
<!-- https://mvnrepository.com/artifact/com.github.sgroschupf/zkclient -->
<dependency>
<groupId>com.github.sgroschupf</groupId>
<artifactId>zkclient</artifactId>
<version>0.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- 【新版的坑】zookeeper及其依赖包,解决日志冲突,还需要剔除日志依赖;-->
<!-- 引入zookeeper -->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>2.12.0</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>2.12.0</version>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.14</version>
<!--排除这个slf4j-log4j12-->
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
业务层(UserServiceImpl)
package com.gl.service.impl;
import com.gl.pojo.UserAddress;
import com.gl.service.UserService;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.List;
/**
* @description:
* @author: GL
* @create: 2021-10-26 15:32
**/
@DubboService
@Component
public class UserServiceImpl implements UserService {
@Override
public List<UserAddress> getUserAddressList(String userId) {
UserAddress address1 = new UserAddress(1, "北京市昌平区宏福科技园综合楼3层", "1", "李老师", "010-56253825", "Y");
UserAddress address2 = new UserAddress(2, "深圳市宝安区西部硅谷大厦B座3层(深圳分校)", "1", "王老师", "010-56253825", "N");
return Arrays.asList(address1,address2);
}
}
resources
dubbo:
application:
# 指定当前服务的名字
name: user-provider
# 指定注册中心的地址
registry:
address: zookeeper://127.0.0.1:2181
# 指定通信规则(通信协议 通信端口)
protocol:
name: dubbo
port: 20880
# 连接监控中心
monitor:
protocol: registry
# 注解方式要扫描的包
scan:
base-packages: com.gl
server:
port: 9001
消费者模块(consumer-service)
pom和提供者一样
业务层(OrderServiceImpl)
package com.gl.service.impl;
import com.gl.pojo.UserAddress;
import com.gl.service.OrderService;
import com.gl.service.UserService;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* @description:
* @author: GL
* @create: 2021-10-26 15:32
**/
@Service
@DubboService
public class OrderServiceImpl implements OrderService {
@DubboReference
UserService userService;
@Override
public List<UserAddress> initOrder(String userId) {
System.out.println("用户id:"+userId);
List<UserAddress> userAddressList = userService.getUserAddressList(userId);
return userAddressList;
}
}
controller
package com.gl;
import com.gl.pojo.UserAddress;
import com.gl.service.OrderService;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* @description:
* @author: GL
* @create: 2021-10-26 15:57
**/
@RestController
public class controller {
@Autowired
private OrderService orderService;
@GetMapping("/initOrder/{userId}")
public List<UserAddress> initOrder(@PathVariable String userId) {
return orderService.initOrder(userId);
}
}
resources
server:
port: 9002
dubbo:
application:
name: order-consumer
registry:
address: zookeeper://127.0.0.1:2181
monitor:
protocol: registry
八、dubbo的一些配置
1.启动时检查
意思就是提供者需要注册到服务中心,然后消费者去拿但是没有提供者,只有消费者然后就会报如下的错误
Failed to check the status of the service com.gl.service.UserService. No provider available for the service com.gl.service.UserService from the url consumer://192.168.76.1/com.gl.service.UserService?application=order-consumer&category=providers,configurators,routers&dubbo=2.0.2&id=org.apache.dubbo.config.RegistryConfig#0&init=false&interface=com.gl.service.UserService&metadata-type=remote&methods=getUserAddressList&pid=13140&qos.enable=false&release=2.7.9&side=consumer&sticky=false×tamp=1635239482089 to the consumer 192.168.76.1 use dubbo version 2.7.9
解决方式:(在调用才会去检查)
# 配置统一的规则,所有的服务都不检查
dubbo:
consumer:
check: false
单个不检查
@DubboReference(check = false)
2.超时
由于网络或服务端不可靠,会导致调用出现一种不确定的中间状态(超时)。为了避免超时导致客户端资源(线程)挂起耗尽,必须设置超时时间。
提供者
全局配置
dubbo.provider timeout=""
单个配置
@DubboReference(timeout= “”)
消费者
全局配置
dubbo.consumer timeout=""
单个配置
@DubboReference(timeout= “”)
配置原则
方法级配置别优于接口级别 Consumer端配置 优于 Provider配置 最后才是全局配置
3.重试(不含第一次)
失败自动切换,当出现失败,重试其它服务器,但重试会带来更长延迟。可通过 retries="2" 来设置重试次数。
幂等设置重试次数【查询,删除,修改】:最后的值是否一致
非幂等不设置重试次数【增加】
4.版本号
在提供端的配置
在消费端
最终效果
九、dubbo高可用
1.zookeeper宕机与dubbo直连(zookeeper注册中心宕机,消费者还是能够调到提供方)
- 监控中心宕掉不影响使用,只是丢失部分采样数据
- 数据库宕掉后,注册中心仍能通过缓存提供服务列表查询,但不能注册新服务
- 注册中心对等集群,任意一台宕掉后,将自动切换到另一台
- 注册中心全部宕掉后,服务提供者和服务消费者仍能通过本地缓存通讯
- 服务提供者无状态,任意一台宕掉后,不影响使用
- 服务提供者全部宕掉后,服务消费者应用将无法使用,并无限次重连等待服务提供者恢复
直连的方式:
2.集群下dubbo的负载均衡(默认为random)
通过 loadbalance = ""来设置策略
Random LoadBalance
随机,按权重设置随机概率。
在一个截面上碰撞的概率高,但调用量越大分布越均匀,而且按概率使用权重后也比较均匀,有利于动态调整提供者权重。
RoundRobin LoadBalance
轮循,按公约后的权重设置轮循比率。
存在慢的提供者累积请求的问题,比如:第二台机器很慢,但没挂,当请求调到第二台时就卡在那,久而久之,所有请求都卡在调到第二台上。
LeastActive LoadBalance
最少活跃调用数,相同活跃数的随机,活跃数指调用前后计数差。
使慢的提供者收到更少请求,因为越慢的提供者的调用前后计数差会越大。
ConsistentHash LoadBalance
一致性 Hash,相同参数的请求总是发到同一提供者。
当某一台提供者挂时,原本发往该提供者的请求,基于虚拟节点,平摊到其它提供者,不会引起剧烈变动。
3. 整合hystrix,服务降级,服务容错
服务降级:
当服务器压力剧增,根据实际业务情况及流量,对一些服务和页面有策略的不处理或换种简单的方式处理,从而释放服务器资源以保证核心交易正常运作或高效运作。
1.mock=force:return+null 表示消费方对该服务的方法调用都直接返回 null 值,不发起远程调用。用来屏蔽不重要服务不可用时对调用方的影响。对应控制台的屏蔽
2.还可以改为 mock=fail:return+null 表示消费方对该服务的方法调用在失败后,再返回 null 值,不抛异常。用来容忍不重要服务不稳定时对调用方的影响。对应控制台的容错
集群容错:使用cluster=" "来配置
Failover Cluster
失败自动切换,当出现失败,重试其它服务器。通常用于读操作,但重试会带来更长延迟。可通过 retries="2" 来设置重试次数(不含第一次)
Failfast Cluster
快速失败,只发起一次调用,失败立即报错。通常用于非幂等性的写操作,比如新增记录
Failsafe Cluster
失败安全,出现异常时,直接忽略。通常用于写入审计日志等操作。
Failback Cluster
失败自动恢复,后台记录失败请求,定时重发。通常用于消息通知操作。
Forking Cluster
并行调用多个服务器,只要一个成功即返回。通常用于实时性要求较高的读操作,但需要浪费更多服务资源。可通过 forks="2" 来设置最大并行数。
Broadcast Cluster
广播调用所有提供者,逐个调用,任意一台报错则报错 [2]。通常用于通知所有提供者更新缓存或日志等本地资源信息。
整合hystrix:
Hystrix 旨在通过控制那些访问远程系统、服务和第三方库的节点,从而对延迟和故障提供更强大的容错能力。Hystrix具备拥有回退机制和断路器功能的线程和信号隔离,请求缓存和请求打包,以及监控和配置等功能
在pom加入spring-cloud-starter-netflix-hystrix依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
<version>1.4.4.RELEASE</version>
</dependency>
然后在Application类上增加@EnableHystrix来启用hystrix starter:
@EnableHystrix
配置提供方
在Dubbo的Provider上增加@HystrixCommand配置,这样子调用就会经过Hystrix代理。
配置服务方
测试结果
正常
错误: