docs: format document with prettier

全面整理项目内容,可读性更佳
This commit is contained in:
yanglbme
2020-09-24 09:54:38 +08:00
parent ffb727bbf2
commit dd2740751e
85 changed files with 1057 additions and 907 deletions

View File

@@ -4,40 +4,40 @@
## 系统拆分
* [为什么要进行系统拆分?如何进行系统拆分?拆分后不用 Dubbo 可以吗?](/docs/distributed-system/why-dubbo.md)
- [为什么要进行系统拆分?如何进行系统拆分?拆分后不用 Dubbo 可以吗?](/docs/distributed-system/why-dubbo.md)
## 分布式服务框架
* [说一下 Dubbo 的工作原理?注册中心挂了可以继续通信吗?](/docs/distributed-system/dubbo-operating-principle.md)
* [Dubbo 支持哪些序列化协议?说一下 Hessian 的数据结构PB 知道吗?为什么 PB 的效率是最高的?](/docs/distributed-system/dubbo-serialization-protocol.md)
* [Dubbo 负载均衡策略和集群容错策略都有哪些?动态代理策略呢?](/docs/distributed-system/dubbo-load-balancing.md)
* [Dubbo 的 SPI 思想是什么?](/docs/distributed-system/dubbo-spi.md)
* [如何基于 Dubbo 进行服务治理、服务降级、失败重试以及超时重试?](/docs/distributed-system/dubbo-service-management.md)
* [分布式服务接口的幂等性如何设计(比如不能重复扣款)?](/docs/distributed-system/distributed-system-idempotency.md)
* [分布式服务接口请求的顺序性如何保证?](/docs/distributed-system/distributed-system-request-sequence.md)
* [如何自己设计一个类似 Dubbo 的 RPC 框架?](/docs/distributed-system/dubbo-rpc-design.md)
* [CAP定理的P是什么](/docs/distributed-system/distributed-system-cap.md)
- [说一下 Dubbo 的工作原理?注册中心挂了可以继续通信吗?](/docs/distributed-system/dubbo-operating-principle.md)
- [Dubbo 支持哪些序列化协议?说一下 Hessian 的数据结构PB 知道吗?为什么 PB 的效率是最高的?](/docs/distributed-system/dubbo-serialization-protocol.md)
- [Dubbo 负载均衡策略和集群容错策略都有哪些?动态代理策略呢?](/docs/distributed-system/dubbo-load-balancing.md)
- [Dubbo 的 SPI 思想是什么?](/docs/distributed-system/dubbo-spi.md)
- [如何基于 Dubbo 进行服务治理、服务降级、失败重试以及超时重试?](/docs/distributed-system/dubbo-service-management.md)
- [分布式服务接口的幂等性如何设计(比如不能重复扣款)?](/docs/distributed-system/distributed-system-idempotency.md)
- [分布式服务接口请求的顺序性如何保证?](/docs/distributed-system/distributed-system-request-sequence.md)
- [如何自己设计一个类似 Dubbo 的 RPC 框架?](/docs/distributed-system/dubbo-rpc-design.md)
- [CAP 定理的 P 是什么](/docs/distributed-system/distributed-system-cap.md)
## 分布式锁
* [Zookeeper 都有哪些应用场景?](/docs/distributed-system/zookeeper-application-scenarios.md)
* [使用 Redis 如何设计分布式锁?使用 Zookeeper 来设计分布式锁可以吗?以上两种分布式锁的实现方式哪种效率比较高?](/docs/distributed-system/distributed-lock-redis-vs-zookeeper.md)
- [Zookeeper 都有哪些应用场景?](/docs/distributed-system/zookeeper-application-scenarios.md)
- [使用 Redis 如何设计分布式锁?使用 Zookeeper 来设计分布式锁可以吗?以上两种分布式锁的实现方式哪种效率比较高?](/docs/distributed-system/distributed-lock-redis-vs-zookeeper.md)
## 分布式事务
* [分布式事务了解吗你们如何解决分布式事务问题的TCC 如果出现网络连不通怎么办XA 的一致性如何保证?](/docs/distributed-system/distributed-transaction.md)
- [分布式事务了解吗你们如何解决分布式事务问题的TCC 如果出现网络连不通怎么办XA 的一致性如何保证?](/docs/distributed-system/distributed-transaction.md)
## 分布式会话
* [集群部署时的分布式 Session 如何实现?](/docs/distributed-system/distributed-session.md)
- [集群部署时的分布式 Session 如何实现?](/docs/distributed-system/distributed-session.md)
---
## 公众号
GitHub 技术社区 [Doocs](https://github.com/doocs) 旗下唯一公众号「**Doocs开源社区**」​,欢迎扫码关注,**专注分享技术领域相关知识及行业最新资讯**。当然也可以加我个人微信备注GitHub拉你进技术交流群。
GitHub 技术社区 [Doocs](https://github.com/doocs) 旗下唯一公众号「**Doocs 开源社区**」​,欢迎扫码关注,**专注分享技术领域相关知识及行业最新资讯**。当然也可以加我个人微信备注GitHub拉你进技术交流群。
关注「**Doocs开源社区**」公众号,回复 **PDF**,即可获取本项目离线 PDF 文档283 页精华),学习更加方便!
关注「**Doocs 开源社区**」公众号,回复 **PDF**,即可获取本项目离线 PDF 文档283 页精华),学习更加方便!
![](./images/pdf.png)

View File

@@ -1,4 +1,5 @@
## 面试题
一般实现分布式锁都有哪些方式?使用 Redis 如何设计分布式锁?使用 zk 来设计分布式锁可以吗?这两种分布式锁的实现方式哪种效率比较高?
## 面试官心理分析
@@ -13,9 +14,9 @@
这个分布式锁有 3 个重要的考量点:
* 互斥(只能有一个客户端获取锁)
* 不能死锁
* 容错(只要大部分 Redis 节点创建了这把锁就可以)
- 互斥(只能有一个客户端获取锁)
- 不能死锁
- 容错(只要大部分 Redis 节点创建了这把锁就可以)
#### Redis 最普通的分布式锁
@@ -33,7 +34,7 @@ SET resource_name my_random_value PX 30000 NX
释放锁就是删除 key ,但是一般可以用 `lua` 脚本删除,判断 value 一样才删除:
``` lua
```lua
-- 删除锁的时候,找到 key 对应的 value跟自己传过去的 value 做比较,如果是一样的才删除。
if redis.call("get",KEYS[1]) == ARGV[1] then
return redis.call("del",KEYS[1])
@@ -65,7 +66,7 @@ end
zk 分布式锁,其实可以做的比较简单,就是某个节点尝试创建临时 znode此时创建成功了就获取了这个锁这个时候别的客户端来创建锁会失败只能**注册个监听器**监听这个锁。释放锁就是删除这个 znode一旦释放掉就会通知客户端然后有一个等待着的客户端就可以再次重新加锁。
``` java
```java
/**
* ZooKeeperSession
*/
@@ -93,7 +94,7 @@ public class ZooKeeperSession {
/**
* 获取分布式锁
*
*
* @param productId
*/
public Boolean acquireDistributedLock(Long productId) {
@@ -126,7 +127,7 @@ public class ZooKeeperSession {
/**
* 释放掉一个分布式锁
*
*
* @param productId
*/
public void releaseDistributedLock(Long productId) {
@@ -177,7 +178,7 @@ public class ZooKeeperSession {
/**
* 获取单例
*
*
* @return
*/
public static ZooKeeperSession getInstance() {
@@ -198,7 +199,7 @@ public class ZooKeeperSession {
如果有一把锁,被多个人给竞争,此时多个人会排队,第一个拿到锁的人会执行,然后释放锁;后面的每个人都会去监听**排在自己前面**的那个人创建的 node 上,一旦某个人释放了锁,排在自己后面的人就会被 ZooKeeper 给通知,一旦被通知了之后,就 ok 了,自己就获取到了锁,就可以执行代码了。
``` java
```java
public class ZooKeeperDistributedLock implements Watcher {
private ZooKeeper zk;
@@ -257,17 +258,17 @@ public class ZooKeeperDistributedLock implements Watcher {
// locksRoot = locks
// /locks/10000000000/locks/10000000001/locks/10000000002
lockNode = zk.create(locksRoot + "/" + productId, new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
// 看看刚创建的节点是不是最小的节点
// locks100000000001000000000110000000002
List<String> locks = zk.getChildren(locksRoot, false);
Collections.sort(locks);
if(lockNode.equals(locksRoot+"/"+ locks.get(0))){
//如果是最小的节点,则表示取得锁
return true;
}
//如果不是最小的节点找到比自己小1的节点
int previousLockIndex = -1;
for(int i = 0; i < locks.size(); i++) {
@@ -276,7 +277,7 @@ public class ZooKeeperDistributedLock implements Watcher {
break;
}
}
this.waitNode = locks.get(previousLockIndex);
} catch (KeeperException e) {
throw new LockException(e);
@@ -327,8 +328,8 @@ public class ZooKeeperDistributedLock implements Watcher {
### redis 分布式锁和 zk 分布式锁的对比
* redis 分布式锁,其实**需要自己不断去尝试获取锁**,比较消耗性能。
* zk 分布式锁,获取不到锁,注册个监听器即可,不需要不断主动尝试获取锁,性能开销较小。
- redis 分布式锁,其实**需要自己不断去尝试获取锁**,比较消耗性能。
- zk 分布式锁,获取不到锁,注册个监听器即可,不需要不断主动尝试获取锁,性能开销较小。
另外一点就是,如果是 Redis 获取锁的那个客户端 出现 bug 挂了,那么只能等待超时时间之后才能释放锁;而 zk 的话,因为创建的是临时 znode只要客户端挂了znode 就没了,此时就自动释放锁。

View File

@@ -1,4 +1,5 @@
## 面试题
集群部署时的分布式 Session 如何实现?
## 面试官心理分析
@@ -25,11 +26,11 @@ Session 是啥?浏览器有个 Cookie在一段时间内这个 Cookie 都存
### Tomcat + Redis
这个其实还挺方便的,就是使用 Session 的代码,跟以前一样,还是基于 Tomcat 原生的 Session 支持即可,然后就是用一个叫做 `Tomcat RedisSessionManager` 的东西,让所有我们部署的 Tomcat 都将 Session 数据存储到 Redis 即可。
这个其实还挺方便的,就是使用 Session 的代码,跟以前一样,还是基于 Tomcat 原生的 Session 支持即可,然后就是用一个叫做 `Tomcat RedisSessionManager` 的东西,让所有我们部署的 Tomcat 都将 Session 数据存储到 Redis 即可。
在 Tomcat 的配置文件中配置:
``` xml
```xml
<Valve className="com.orangefunction.tomcat.redissessions.RedisSessionHandlerValve" />
<Manager className="com.orangefunction.tomcat.redissessions.RedisSessionManager"
@@ -37,7 +38,7 @@ Session 是啥?浏览器有个 Cookie在一段时间内这个 Cookie 都存
port="{redis.port}"
database="{redis.dbnum}"
maxInactiveInterval="60"/>
```
```
然后指定 Redis 的 host 和 port 就 ok 了。
@@ -61,7 +62,7 @@ Session 是啥?浏览器有个 Cookie在一段时间内这个 Cookie 都存
在 pom.xml 中配置:
``` xml
```xml
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
@@ -76,7 +77,7 @@ Session 是啥?浏览器有个 Cookie在一段时间内这个 Cookie 都存
在 Spring 配置文件中配置:
``` xml
```xml
<bean id="redisHttpSessionConfiguration"
class="org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration">
<property name="maxInactiveIntervalInSeconds" value="600"/>
@@ -100,7 +101,7 @@ Session 是啥?浏览器有个 Cookie在一段时间内这个 Cookie 都存
在 web.xml 中配置:
``` xml
```xml
<filter>
<filter-name>springSessionRepositoryFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
@@ -113,7 +114,7 @@ Session 是啥?浏览器有个 Cookie在一段时间内这个 Cookie 都存
示例代码:
``` java
```java
@RestController
@RequestMapping("/test")
public class TestController {

View File

@@ -1,4 +1,5 @@
## 面试题
分布式服务接口的幂等性如何设计(比如不能重复扣款)?
## 面试官心理分析
@@ -21,9 +22,9 @@
其实保证幂等性主要是三点:
* 对于每个请求必须有一个唯一的标识,举个栗子:订单支付请求,肯定得包含订单 id一个订单 id 最多支付一次,对吧。
* 每次处理完请求之后,必须有一个记录标识这个请求处理过了。常见的方案是在 mysql 中记录个状态啥的,比如支付之前记录一条这个订单的支付流水。
* 每次接收请求需要进行判断判断之前是否处理过。比如说如果有一个订单已经支付了就已经有了一条支付流水那么如果重复发送这个请求则此时先插入支付流水orderId 已经存在了,唯一键约束生效,报错插入不进去的。然后你就不用再扣款了。
- 对于每个请求必须有一个唯一的标识,举个栗子:订单支付请求,肯定得包含订单 id一个订单 id 最多支付一次,对吧。
- 每次处理完请求之后,必须有一个记录标识这个请求处理过了。常见的方案是在 mysql 中记录个状态啥的,比如支付之前记录一条这个订单的支付流水。
- 每次接收请求需要进行判断判断之前是否处理过。比如说如果有一个订单已经支付了就已经有了一条支付流水那么如果重复发送这个请求则此时先插入支付流水orderId 已经存在了,唯一键约束生效,报错插入不进去的。然后你就不用再扣款了。
实际运作过程中,你要结合自己的业务来,比如说利用 Redis用 orderId 作为唯一键。只有成功插入这个支付流水,才可以执行实际的支付扣款。

View File

@@ -1,4 +1,5 @@
## 分布式系统面试连环炮
有一些同学,之前呢主要是做传统行业,或者外包项目,一直是在那种小的公司,技术一直都搞的比较简单。他们有共同的一个问题,就是都没怎么搞过分布式系统,现在互联网公司,一般都是做分布式的系统,大家都不是做底层的分布式系统、分布式存储系统 Hadoop HDFS、分布式计算系统 Hadoop MapReduce / Spark、分布式流式计算系统 Storm。
分布式业务系统,就是把原来用 Java 开发的一个大块系统,给拆分成**多个子系统**,多个子系统之间互相调用,形成一个大系统的整体。假设原来你做了一个 OA 系统里面包含了权限模块、员工模块、请假模块、财务模块一个工程里面包含了一堆模块模块与模块之间会互相去调用1 台机器部署。现在如果你把这个系统给拆开,权限系统、员工系统、请假系统、财务系统 4 个系统4 个工程,分别在 4 台机器上部署。一个请求过来完成这个请求这个员工系统调用权限系统调用请假系统调用财务系统4 个系统分别完成了一部分的事情,最后 4 个系统都干完了以后,才认为是这个请求已经完成了。
@@ -11,27 +12,27 @@
### 为什么要进行系统拆分?
* 为什么要进行系统拆分?如何进行系统拆分?拆分后不用 Dubbo 可以吗Dubbo 和 thrift 有什么区别呢?
- 为什么要进行系统拆分?如何进行系统拆分?拆分后不用 Dubbo 可以吗Dubbo 和 thrift 有什么区别呢?
### 分布式服务框架
* 说一下的 Dubbo 的工作原理?注册中心挂了可以继续通信吗?
* Dubbo 支持哪些序列化协议?说一下 Hessian 的数据结构PB 知道吗?为什么 PB 的效率是最高的?
* Dubbo 负载均衡策略和高可用策略都有哪些?动态代理策略呢?
* Dubbo 的 SPI 思想是什么?
* 如何基于 Dubbo 进行服务治理、服务降级、失败重试以及超时重试?
* 分布式服务接口的幂等性如何设计(比如不能重复扣款)?
* 分布式服务接口请求的顺序性如何保证?
* 如何自己设计一个类似 Dubbo 的 RPC 框架?
- 说一下的 Dubbo 的工作原理?注册中心挂了可以继续通信吗?
- Dubbo 支持哪些序列化协议?说一下 Hessian 的数据结构PB 知道吗?为什么 PB 的效率是最高的?
- Dubbo 负载均衡策略和高可用策略都有哪些?动态代理策略呢?
- Dubbo 的 SPI 思想是什么?
- 如何基于 Dubbo 进行服务治理、服务降级、失败重试以及超时重试?
- 分布式服务接口的幂等性如何设计(比如不能重复扣款)?
- 分布式服务接口请求的顺序性如何保证?
- 如何自己设计一个类似 Dubbo 的 RPC 框架?
### 分布式锁
* 使用 Redis 如何设计分布式锁?使用 zk 来设计分布式锁可以吗?这两种分布式锁的实现方式哪种效率比较高?
- 使用 Redis 如何设计分布式锁?使用 zk 来设计分布式锁可以吗?这两种分布式锁的实现方式哪种效率比较高?
### 分布式事务
* 分布式事务了解吗你们如何解决分布式事务问题的TCC 如果出现网络连不通怎么办XA 的一致性如何保证?
- 分布式事务了解吗你们如何解决分布式事务问题的TCC 如果出现网络连不通怎么办XA 的一致性如何保证?
### 分布式会话
* 集群部署时的分布式 Session 如何实现?
- 集群部署时的分布式 Session 如何实现?

View File

@@ -1,4 +1,5 @@
## 面试题
分布式服务接口请求的顺序性如何保证?
## 面试官心理分析

View File

@@ -37,9 +37,9 @@
TCC 的全称是: `Try``Confirm``Cancel`
* Try 阶段:这个阶段说的是对各个服务的资源做检测以及对资源进行**锁定或者预留**。
* Confirm 阶段:这个阶段说的是在各个服务中**执行实际的操作**。
* Cancel 阶段:如果任何一个服务的业务方法执行出错,那么这里就需要**进行补偿**,就是执行已经执行成功的业务逻辑的回滚操作。(把那些执行成功的回滚)
- Try 阶段:这个阶段说的是对各个服务的资源做检测以及对资源进行**锁定或者预留**。
- Confirm 阶段:这个阶段说的是在各个服务中**执行实际的操作**。
- Cancel 阶段:如果任何一个服务的业务方法执行出错,那么这里就需要**进行补偿**,就是执行已经执行成功的业务逻辑的回滚操作。(把那些执行成功的回滚)
这种方案说实话几乎很少人使用,我们用的也比较少,但是也有使用的场景。因为这个**事务回滚**实际上是**严重依赖于你自己写代码来回滚和补偿**了,会造成补偿代码巨大,非常之恶心。

View File

@@ -1,4 +1,5 @@
## 面试题
说一下的 dubbo 的工作原理?注册中心挂了可以继续通信吗?说说一次 rpc 请求的流程?
## 面试官心理分析
@@ -9,29 +10,29 @@ MQ、ES、Redis、Dubbo上来先问你一些**思考性的问题**、**原理
当然去年开始 spring cloud 非常火,现在大量的公司开始转向 spring cloud 了spring cloud 人家毕竟是微服务架构的全家桶式的这么一个东西。但是因为很多公司还在用 dubbo所以 dubbo 肯定会是目前面试的重点,何况人家 dubbo 现在重启开源社区维护了,捐献给了 apache未来应该也还是有一定市场和地位的。
既然聊 dubbo那肯定是先从 dubbo 原理开始聊了,你先说说 dubbo 支撑 rpc 分布式调用的架构啥的,然后说说一次 rpc 请求 dubbo 是怎么给你完成的,对吧。
既然聊 dubbo那肯定是先从 dubbo 原理开始聊了,你先说说 dubbo 支撑 rpc 分布式调用的架构啥的,然后说说一次 rpc 请求 dubbo 是怎么给你完成的,对吧。
## 面试题剖析
### dubbo 工作原理
* 第一层service 层,接口层,给服务提供者和消费者来实现的
* 第二层config 层,配置层,主要是对 dubbo 进行各种配置的
* 第三层proxy 层,服务代理层,无论是 consumer 还是 providerdubbo 都会给你生成代理,代理之间进行网络通信
* 第四层registry 层,服务注册层,负责服务的注册与发现
* 第五层cluster 层,集群层,封装多个服务提供者的路由以及负载均衡,将多个实例组合成一个服务
* 第六层monitor 层,监控层,对 rpc 接口的调用次数和调用时间进行监控
* 第七层protocal 层,远程调用层,封装 rpc 调用
* 第八层exchange 层,信息交换层,封装请求响应模式,同步转异步
* 第九层transport 层,网络传输层,抽象 mina 和 netty 为统一接口
* 第十层serialize 层,数据序列化层
- 第一层service 层,接口层,给服务提供者和消费者来实现的
- 第二层config 层,配置层,主要是对 dubbo 进行各种配置的
- 第三层proxy 层,服务代理层,无论是 consumer 还是 providerdubbo 都会给你生成代理,代理之间进行网络通信
- 第四层registry 层,服务注册层,负责服务的注册与发现
- 第五层cluster 层,集群层,封装多个服务提供者的路由以及负载均衡,将多个实例组合成一个服务
- 第六层monitor 层,监控层,对 rpc 接口的调用次数和调用时间进行监控
- 第七层protocal 层,远程调用层,封装 rpc 调用
- 第八层exchange 层,信息交换层,封装请求响应模式,同步转异步
- 第九层transport 层,网络传输层,抽象 mina 和 netty 为统一接口
- 第十层serialize 层,数据序列化层
### 工作流程
* 第一步provider 向注册中心去注册
* 第二步consumer 从注册中心订阅服务,注册中心会通知 consumer 注册好的服务
* 第三步consumer 调用 provider
* 第四步consumer 和 provider 都异步通知监控中心
- 第一步provider 向注册中心去注册
- 第二步consumer 从注册中心订阅服务,注册中心会通知 consumer 注册好的服务
- 第三步consumer 调用 provider
- 第四步consumer 和 provider 都异步通知监控中心
![dubbo-operating-principle](./images/dubbo-operating-principle.png)

View File

@@ -1,12 +1,13 @@
## 面试题
如何自己设计一个类似 Dubbo 的 RPC 框架?
## 面试官心理分析
说实话,就这问题,其实就跟问你如何自己设计一个 MQ 一样的道理,就考两个:
* 你有没有对某个 rpc 框架原理有非常深入的理解。
* 你能不能从整体上来思考一下,如何设计一个 rpc 框架,考考你的系统设计能力。
- 你有没有对某个 rpc 框架原理有非常深入的理解。
- 你能不能从整体上来思考一下,如何设计一个 rpc 框架,考考你的系统设计能力。
## 面试题剖析
@@ -16,11 +17,11 @@
举个栗子,我给大家说个最简单的回答思路:
* 上来你的服务就得去注册中心注册吧,你是不是得有个注册中心,保留各个服务的信息,可以用 zookeeper 来做,对吧。
* 然后你的消费者需要去注册中心拿对应的服务信息吧,对吧,而且每个服务可能会存在于多台机器上。
* 接着你就该发起一次请求了,咋发起?当然是基于动态代理了,你面向接口获取到一个动态代理,这个动态代理就是接口在本地的一个代理,然后这个代理会找到服务对应的机器地址。
* 然后找哪个机器发送请求?那肯定得有个负载均衡算法了,比如最简单的可以随机轮询是不是。
* 接着找到一台机器,就可以跟它发送请求了,第一个问题咋发送?你可以说用 netty 了nio 方式;第二个问题发送啥格式数据?你可以说用 hessian 序列化协议了,或者是别的,对吧。然后请求过去了。
* 服务器那边一样的,需要针对你自己的服务生成一个动态代理,监听某个网络端口了,然后代理你本地的服务代码。接收到请求的时候,就调用对应的服务代码,对吧。
- 上来你的服务就得去注册中心注册吧,你是不是得有个注册中心,保留各个服务的信息,可以用 zookeeper 来做,对吧。
- 然后你的消费者需要去注册中心拿对应的服务信息吧,对吧,而且每个服务可能会存在于多台机器上。
- 接着你就该发起一次请求了,咋发起?当然是基于动态代理了,你面向接口获取到一个动态代理,这个动态代理就是接口在本地的一个代理,然后这个代理会找到服务对应的机器地址。
- 然后找哪个机器发送请求?那肯定得有个负载均衡算法了,比如最简单的可以随机轮询是不是。
- 接着找到一台机器,就可以跟它发送请求了,第一个问题咋发送?你可以说用 netty 了nio 方式;第二个问题发送啥格式数据?你可以说用 hessian 序列化协议了,或者是别的,对吧。然后请求过去了。
- 服务器那边一样的,需要针对你自己的服务生成一个动态代理,监听某个网络端口了,然后代理你本地的服务代码。接收到请求的时候,就调用对应的服务代码,对吧。
这就是一个最最基本的 rpc 框架的思路,先不说你有多牛逼的技术功底,哪怕这个最简单的思路你先给出来行不行?

View File

@@ -1,4 +1,5 @@
## 面试题
dubbo 支持哪些通信协议?支持哪些序列化协议?说一下 Hessian 的数据结构PB 知道吗?为什么 PB 的效率是最高的?
## 面试官心理分析
@@ -15,7 +16,7 @@ dubbo 支持哪些通信协议?支持哪些序列化协议?说一下 Hessian
### dubbo 支持不同的通信协议
* dubbo 协议
- dubbo 协议
**默认**就是走 dubbo 协议,单一长连接,进行的是 NIO 异步通信,基于 hessian 作为序列化协议。使用的场景是:传输数据量小(每次请求在 100kb 以内),但是并发量很高。
@@ -29,19 +30,19 @@ dubbo 支持哪些通信协议?支持哪些序列化协议?说一下 Hessian
![dubbo-not-keep-connection](./images/dubbo-not-keep-connection.png)
* rmi 协议
- rmi 协议
走 Java 二进制序列化,多个短连接,适合消费者和提供者数量差不多的情况,适用于文件的传输,一般较少用。
* hessian 协议
- hessian 协议
走 hessian 序列化协议,多个短连接,适用于提供者数量比消费者数量还多的情况,适用于文件的传输,一般较少用。
* http 协议
- http 协议
走表单序列化。
* webservice
- webservice
走 SOAP 文本序列化。
@@ -53,24 +54,24 @@ dubbo 支持 hession、Java 二进制序列化、json、SOAP 文本序列化多
Hessian 的对象序列化机制有 8 种原始类型:
* 原始二进制数据
* boolean
* 64-bit date64 位毫秒值的日期)
* 64-bit double
* 32-bit int
* 64-bit long
* null
* UTF-8 编码的 string
- 原始二进制数据
- boolean
- 64-bit date64 位毫秒值的日期)
- 64-bit double
- 32-bit int
- 64-bit long
- null
- UTF-8 编码的 string
另外还包括 3 种递归类型:
* list for lists and arrays
* map for maps and dictionaries
* object for objects
- list for lists and arrays
- map for maps and dictionaries
- object for objects
还有一种特殊的类型:
* ref用来表示对共享对象的引用。
- ref用来表示对共享对象的引用。
### 为什么 PB 的效率是最高的?

View File

@@ -1,4 +1,5 @@
## 面试题
如何基于 dubbo 进行服务治理、服务降级、失败重试以及超时重试?
## 面试官心理分析
@@ -27,17 +28,17 @@
需要自动统计**各个接口和服务之间的调用次数以及访问延时**,而且要分成两个级别。
* 一个级别是接口粒度就是每个服务的每个接口每天被调用多少次TP50/TP90/TP99三个档次的请求延时分别是多少
* 第二个级别是从源头入口开始,一个完整的请求链路经过几十个服务之后,完成一次请求,每天全链路走多少次,全链路请求延时的 TP50/TP90/TP99分别是多少。
- 一个级别是接口粒度就是每个服务的每个接口每天被调用多少次TP50/TP90/TP99三个档次的请求延时分别是多少
- 第二个级别是从源头入口开始,一个完整的请求链路经过几十个服务之后,完成一次请求,每天全链路走多少次,全链路请求延时的 TP50/TP90/TP99分别是多少。
这些东西都搞定了之后,后面才可以来看当前系统的压力主要在哪里,如何来扩容和优化啊。
#### 3. 其它
* 服务分层(避免循环依赖)
* 调用链路失败监控和报警
* 服务鉴权
* 每个服务的可用性的监控(接口调用成功率?几个 999.99%99.9%99%
- 服务分层(避免循环依赖)
- 调用链路失败监控和报警
- 服务鉴权
- 每个服务的可用性的监控(接口调用成功率?几个 999.99%99.9%99%
### 服务降级
@@ -45,7 +46,7 @@
举个栗子,我们有接口 `HelloService``HelloServiceImpl` 有该接口的具体实现。
``` java
```java
public interface HelloService {
void sayHello();
}
@@ -57,7 +58,7 @@ public class HelloServiceImpl implements HelloService {
}
```
``` xml
```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"
@@ -92,7 +93,7 @@ public class HelloServiceImpl implements HelloService {
mock 的值也可以修改为 true然后再跟接口同一个路径下实现一个 Mock 类,命名规则是 “接口名称+ `Mock` ” 后缀。然后在 Mock 类里实现自己的降级逻辑。
``` java
```java
public class HelloServiceMock implements HelloService {
public void sayHello() {
// 降级逻辑
@@ -104,7 +105,7 @@ public class HelloServiceMock implements HelloService {
所谓失败重试,就是 consumer 调用 provider 要是失败了,比如抛异常了,此时应该是可以重试的,或者调用超时了也可以重试。配置如下:
``` xml
```xml
<dubbo:reference id="xxxx" interface="xx" check="true" async="false" retries="3" timeout="2000"/>
```
@@ -114,5 +115,5 @@ public class HelloServiceMock implements HelloService {
可以结合你们公司具体的场景来说说你是怎么设置这些参数的:
* `timeout` :一般设置为 `200ms` ,我们认为不能超过 `200ms` 还没返回。
* `retries` :设置 retries一般是在读请求的时候比如你要查询个数据你可以设置个 retries如果第一次没读到报错重试指定的次数尝试再次读取。
- `timeout` :一般设置为 `200ms` ,我们认为不能超过 `200ms` 还没返回。
- `retries` :设置 retries一般是在读请求的时候比如你要查询个数据你可以设置个 retries如果第一次没读到报错重试指定的次数尝试再次读取。

View File

@@ -1,4 +1,5 @@
## 面试题
dubbo 的 spi 思想是什么?
## 面试官心理分析
@@ -10,11 +11,12 @@ dubbo 的 spi 思想是什么?
## 面试题剖析
### spi 是啥?
spi简单来说就是 `service provider interface` ,说白了是什么意思呢,比如你有个接口,现在这个接口有 3 个实现类,那么在系统运行的时候对这个接口到底选择哪个实现类呢?这就需要 spi 了,需要**根据指定的配置**或者是**默认的配置**,去**找到对应的实现类**加载进来,然后用这个实现类的实例对象。
举个栗子。
你有一个接口 A。A1/A2/A3 分别是接口A的不同实现。你通过配置 `接口 A = 实现 A2` ,那么在系统实际运行的时候,会加载你的配置,用实现 A2 实例化一个对象来提供服务。
你有一个接口 A。A1/A2/A3 分别是接口 A 的不同实现。你通过配置 `接口 A = 实现 A2` ,那么在系统实际运行的时候,会加载你的配置,用实现 A2 实例化一个对象来提供服务。
spi 机制一般用在哪儿?**插件扩展的场景**,比如说你开发了一个给别人使用的开源框架,如果你想让别人自己写个插件,插到你的开源框架里面,从而扩展某个功能,这个时候 spi 思想就用上了。
@@ -32,7 +34,7 @@ Java 定义了一套 jdbc 的接口,但是 Java 并没有提供 jdbc 的实现
dubbo 也用了 spi 思想,不过没有用 jdk 的 spi 机制,是自己实现的一套 spi 机制。
``` java
```java
Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension();
```
@@ -42,26 +44,26 @@ Protocol 接口在系统运行的时候dubbo 会判断一下应该选
上面那行代码就是 dubbo 里大量使用的,就是对很多组件,都是保留一个接口和多个实现,然后在系统运行的时候动态根据配置去找到对应的实现类。如果你没配置,那就走默认的实现好了,没问题。
``` java
@SPI("dubbo")
public interface Protocol {
int getDefaultPort();
@Adaptive
<T> Exporter<T> export(Invoker<T> invoker) throws RpcException;
@Adaptive
<T> Invoker<T> refer(Class<T> type, URL url) throws RpcException;
```java
@SPI("dubbo")
public interface Protocol {
void destroy();
}
int getDefaultPort();
@Adaptive
<T> Exporter<T> export(Invoker<T> invoker) throws RpcException;
@Adaptive
<T> Invoker<T> refer(Class<T> type, URL url) throws RpcException;
void destroy();
}
```
在 dubbo 自己的 jar 里,在 `/META_INF/dubbo/internal/com.alibaba.dubbo.rpc.Protocol` 文件中:
``` xml
```xml
dubbo=com.alibaba.dubbo.rpc.protocol.dubbo.DubboProtocol
http=com.alibaba.dubbo.rpc.protocol.http.HttpProtocol
hessian=com.alibaba.dubbo.rpc.protocol.hessian.HessianProtocol
@@ -83,7 +85,7 @@ hessian=com.alibaba.dubbo.rpc.protocol.hessian.HessianProtocol
然后自己搞一个 `dubbo provider` 工程,在这个工程里面依赖你自己搞的那个 jar然后在 spring 配置文件里给个配置:
``` xml
```xml
<dubbo:protocol name=”my” port=”20000” />
```
@@ -93,4 +95,4 @@ provider 启动的时候,就会加载到我们 jar 包里的 `my=com.bingo.MyP
dubbo 里面提供了大量的类似上面的扩展点,就是说,你如果要扩展一个东西,只要自己写个 jar让你的 consumer 或者是 provider 工程,依赖你的那个 jar在你的 jar 里指定目录下配置好接口名称对应的文件,里面通过 `key=实现类`
然后对于对应的组件,类似 `<dubbo:protocol>` 用你的那个 key 对应的实现类来实现某个接口,你可以自己去扩展 dubbo 的各种功能,提供你自己的实现。
然后对于对应的组件,类似 `<dubbo:protocol>` 用你的那个 key 对应的实现类来实现某个接口,你可以自己去扩展 dubbo 的各种功能,提供你自己的实现。

View File

@@ -1,4 +1,5 @@
## 面试题
为什么要进行系统拆分?如何进行系统拆分?拆分后不用 dubbo 可以吗?
## 面试官心理分析
@@ -20,6 +21,7 @@
## 面试题剖析
### 为什么要将系统进行拆分?
网上查查,答案极度零散和复杂,很琐碎,原因一大坨。但是我这里给大家直观的感受:
要是**不拆分**一个大系统几十万行代码20 个人维护一份代码,简直是悲剧啊。代码经常改着改着就冲突了,各种代码冲突和合并要处理,非常耗费时间;经常我改动了我的代码,你调用了我的,导致你的代码也得重新测试,麻烦的要死;然后每次发布都是几十万行代码的系统一起发布,大家得一起提心吊胆准备上线,几十万行代码的上线,可能每次上线都要做很多的检查,很多异常问题的处理,简直是又麻烦又痛苦;而且如果我现在打算把技术升级到最新的 spring 版本,还不行,因为这可能导致你的代码报错,我不敢随意乱改技术。
@@ -42,7 +44,7 @@ A 就检查了自己负责的 1 万行代码对应的功能,确保 ok 就闪
系统拆分为分布式系统,拆成多个服务,拆成微服务的架构,是需要拆很多轮的。并不是说上来一个架构师一次就给拆好了,而以后都不用拆。
第一轮;团队继续扩大,拆好的某个服务,刚开始是 1 个人维护 1 万行代码,后来业务系统越来越复杂,这个服务是 10 万行代码5 个人第二轮1个服务 -> 5个服务每个服务 2 万行代码,每人负责一个服务。
第一轮;团队继续扩大,拆好的某个服务,刚开始是 1 个人维护 1 万行代码,后来业务系统越来越复杂,这个服务是 10 万行代码5 个人第二轮1 个服务 -> 5 个服务,每个服务 2 万行代码,每人负责一个服务。
如果是多人维护一个服务最理想的情况下几十个人1 个人负责 1 个或 2~3 个服务;某个服务工作量变大了,代码量越来越多,某个同学,负责一个服务,代码量变成了 10 万行了他自己不堪重负他现在一个人拆开5 个服务1 个人顶着,负责 5 个人接着招人2 个人给那个同学带着3 个人负责 5 个服务,其中 2 个人每个人负责 2 个服务1 个人负责 1 个服务。

View File

@@ -1,9 +1,10 @@
## 面试题
zookeeper 都有哪些使用场景?
## 面试官心理分析
现在聊的 topic 是分布式系统,面试官跟你聊完了 dubbo 相关的一些问题之后,已经确认你对分布式服务框架/RPC框架基本都有一些认知了。那么他可能开始要跟你聊分布式相关的其它问题了。
现在聊的 topic 是分布式系统,面试官跟你聊完了 dubbo 相关的一些问题之后,已经确认你对分布式服务框架/RPC 框架基本都有一些认知了。那么他可能开始要跟你聊分布式相关的其它问题了。
分布式锁这个东西,很常用的,你做 Java 系统开发,分布式系统,可能会有一些场景会用到。最常用的分布式锁就是基于 zookeeper 来实现的。
@@ -13,10 +14,10 @@ zookeeper 都有哪些使用场景?
大致来说zookeeper 的使用场景如下,我就举几个简单的,大家能说几个就好了:
* 分布式协调
* 分布式锁
* 元数据/配置信息管理
* HA高可用性
- 分布式协调
- 分布式锁
- 元数据/配置信息管理
- HA 高可用性
### 分布式协调
@@ -36,7 +37,7 @@ zookeeper 可以用作很多系统的配置信息的管理,比如 kafka、stor
![zookeeper-meta-data-manage](./images/zookeeper-meta-data-manage.png)
### HA高可用性
### HA 高可用性
这个应该是很常见的,比如 hadoop、hdfs、yarn 等很多大数据系统,都选择基于 zookeeper 来开发 HA 高可用机制,就是一个**重要进程一般会做主备**两个,主进程挂了立马通过 zookeeper 感知到切换到备用进程。