mirror of
https://github.com/doocs/advanced-java.git
synced 2026-08-18 10:43:29 +08:00
chore: update some articles
This commit is contained in:
@@ -13,11 +13,9 @@
|
|||||||
|
|
||||||
本项目大部分内容来自中华石杉,版权归作者所有,内容涵盖[高并发](#高并发架构)、[分布式](#分布式系统)、[高可用](#高可用架构)、[微服务](#微服务架构)、[海量数据处理](#海量数据处理)等领域知识。我对这部分知识做了一个系统的整理,方便学习查阅。
|
本项目大部分内容来自中华石杉,版权归作者所有,内容涵盖[高并发](#高并发架构)、[分布式](#分布式系统)、[高可用](#高可用架构)、[微服务](#微服务架构)、[海量数据处理](#海量数据处理)等领域知识。我对这部分知识做了一个系统的整理,方便学习查阅。
|
||||||
|
|
||||||
本项目已开通 [Discussions](https://github.com/doocs/advanced-java/discussions) 功能。学习之前,先来看看 [Discussions 讨论区](https://github.com/doocs/advanced-java/discussions/9)的技术面试官是怎么说的吧。本项目欢迎各位开发者朋友到 [Discussions 讨论区](https://github.com/doocs/advanced-java/discussions)分享自己的一些想法和实践经验。也不妨 Star 关注 [doocs/advanced-java](https://github.com/doocs/advanced-java),随时追踪项目最新动态。
|
本项目已开通 Discussions 功能。学习之前,先来看看 [Discussions 讨论区](https://github.com/doocs/advanced-java/discussions/9)的技术面试官是怎么说的吧。本项目欢迎各位开发者朋友到 Discussions 讨论区分享自己的一些想法和实践经验。也不妨 Star 关注 [doocs/advanced-java](https://github.com/doocs/advanced-java),随时追踪项目最新动态。
|
||||||
|
|
||||||
本项目基于 [Docsify](https://docsify.js.org) 进行构建,并使用开源小工具 [Gitee Pages Action](https://github.com/yanglbme/gitee-pages-action) 实现站点的自动部署更新。
|
本项目基于 Docsify 进行构建,并使用开源小工具 [Gitee Pages Action](https://github.com/yanglbme/gitee-pages-action) 实现站点的自动部署更新。目前支持以下三个站点访问:
|
||||||
|
|
||||||
目前支持以下三个站点访问:
|
|
||||||
|
|
||||||
- Netlify: https://adjava.netlify.app
|
- Netlify: https://adjava.netlify.app
|
||||||
- Gitee Pages: https://doocs.gitee.io/advanced-java
|
- Gitee Pages: https://doocs.gitee.io/advanced-java
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ snowflake 算法是 twitter 开源的分布式 id 生成算法,采用 Scala
|
|||||||
- 10 bits:记录工作机器 id,代表的是这个服务最多可以部署在 2^10 台机器上,也就是 1024 台机器。但是 10 bits 里 5 个 bits 代表机房 id,5 个 bits 代表机器 id。意思就是最多代表 `2^5` 个机房(32 个机房),每个机房里可以代表 `2^5` 个机器(32 台机器)。
|
- 10 bits:记录工作机器 id,代表的是这个服务最多可以部署在 2^10 台机器上,也就是 1024 台机器。但是 10 bits 里 5 个 bits 代表机房 id,5 个 bits 代表机器 id。意思就是最多代表 `2^5` 个机房(32 个机房),每个机房里可以代表 `2^5` 个机器(32 台机器)。
|
||||||
- 12 bits:这个是用来记录同一个毫秒内产生的不同 id,12 bits 可以代表的最大正整数是 `2^12 - 1 = 4096` ,也就是说可以用这个 12 bits 代表的数字来区分**同一个毫秒内**的 4096 个不同的 id。
|
- 12 bits:这个是用来记录同一个毫秒内产生的不同 id,12 bits 可以代表的最大正整数是 `2^12 - 1 = 4096` ,也就是说可以用这个 12 bits 代表的数字来区分**同一个毫秒内**的 4096 个不同的 id。
|
||||||
|
|
||||||
```
|
```sh
|
||||||
0 | 0001100 10100010 10111110 10001001 01011100 00 | 10001 | 1 1001 | 0000 00000000
|
0 | 0001100 10100010 10111110 10001001 01011100 00 | 10001 | 1 1001 | 0000 00000000
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ RabbitMQ 有三种模式:单机模式、普通集群模式、镜像集群模
|
|||||||
|
|
||||||
#### 单机模式
|
#### 单机模式
|
||||||
|
|
||||||
单机模式,就是 Demo 级别的,一般就是你本地启动了玩玩儿的 😄,没人生产用单机模式。
|
单机模式,就是 Demo 级别的,一般就是你本地启动了玩玩儿的,没人生产用单机模式。
|
||||||
|
|
||||||
#### 普通集群模式(无高可用性)
|
#### 普通集群模式(无高可用性)
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
|
|
||||||
#### 实现方式
|
#### 实现方式
|
||||||
|
|
||||||
- 控制单位时间内的请求数量
|
控制单位时间内的请求数量。
|
||||||
|
|
||||||
```java
|
```java
|
||||||
|
|
||||||
@@ -54,16 +54,17 @@ public class Counter {
|
|||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
- 劣势
|
劣势:
|
||||||
- 假设在 00:01 时发生一个请求,在 00:01-00:58 之间不在发送请求,在 00:59 时发送剩下的所有请求 `n-1` (n 为限流请求数量),在下一分钟的 00:01 发送 n 个请求,这样在 2 秒钟内请求到达了 `2n - 1` 个.
|
|
||||||
- 设每分钟请求数量为 60 个,每秒可以处理 1 个请求,用户在 00:59 发送 60 个请求,在 01:00 发送 60 个请求 此时 2 秒钟有 120 个请求(每秒 60 个请求),远远大于了每秒钟处理数量的阈值
|
假设在 00:01 时发生一个请求,在 00:01-00:58 之间不在发送请求,在 00:59 时发送剩下的所有请求 `n-1` (n 为限流请求数量),在下一分钟的 00:01 发送 n 个请求,这样在 2 秒钟内请求到达了 `2n - 1` 个。
|
||||||
|
|
||||||
|
设每分钟请求数量为 60 个,每秒可以处理 1 个请求,用户在 00:59 发送 60 个请求,在 01:00 发送 60 个请求 此时 2 秒钟有 120 个请求(每秒 60 个请求),远远大于了每秒钟处理数量的阈值。
|
||||||
|
|
||||||
### 滑动窗口
|
### 滑动窗口
|
||||||
|
|
||||||
#### 实现方式
|
#### 实现方式
|
||||||
|
|
||||||
- 滑动窗口是对计数器方式的改进, 增加一个时间粒度的度量单位
|
滑动窗口是对计数器方式的改进,增加一个时间粒度的度量单位,把一分钟分成若干等分(6 份,每份 10 秒),在每一份上设置独立计数器,在 00:00-00:09 之间发生请求计数器累加 1。当等分数量越大限流统计就越详细。
|
||||||
- 把一分钟分成若干等分(6 份,每份 10 秒), 在每一份上设置独立计数器,在 00:00-00:09 之间发生请求计数器累加 1.当等分数量越大限流统计就越详细
|
|
||||||
|
|
||||||
```java
|
```java
|
||||||
package com.example.demo1.service;
|
package com.example.demo1.service;
|
||||||
@@ -86,7 +87,7 @@ public class TimeWindow {
|
|||||||
*/
|
*/
|
||||||
private int max;
|
private int max;
|
||||||
|
|
||||||
public TimeWindow(int max, int seconds) {
|
public TimeWindow(int max, int seconds) {
|
||||||
this.seconds = seconds;
|
this.seconds = seconds;
|
||||||
this.max = max;
|
this.max = max;
|
||||||
|
|
||||||
@@ -109,10 +110,10 @@ public class TimeWindow {
|
|||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
|
|
||||||
final TimeWindow timeWindow = new TimeWindow(10, 1);
|
final TimeWindow timeWindow = new TimeWindow(10, 1);
|
||||||
|
|
||||||
// 测试3个线程
|
// 测试3个线程
|
||||||
IntStream.range(0, 3).forEach((i) -> {
|
IntStream.range(0, 3).forEach((i) -> {
|
||||||
new Thread(() -> {
|
new Thread(() -> {
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
@@ -193,7 +194,7 @@ public class TimeWindow {
|
|||||||
|
|
||||||
#### 实现方式
|
#### 实现方式
|
||||||
|
|
||||||
- 规定固定容量的桶, 有水进入, 有水流出. 对于流进的水我们无法估计进来的数量、速度, 对于流出的水我们可以控制速度.
|
规定固定容量的桶,有水进入,有水流出。对于流进的水我们无法估计进来的数量、速度,对于流出的水我们可以控制速度。
|
||||||
|
|
||||||
```java
|
```java
|
||||||
public class LeakBucket {
|
public class LeakBucket {
|
||||||
@@ -216,7 +217,7 @@ public class LeakBucket {
|
|||||||
|
|
||||||
public boolean limit() {
|
public boolean limit() {
|
||||||
long now = System.currentTimeMillis();
|
long now = System.currentTimeMillis();
|
||||||
nowSize = Math.max(0, (nowSize - (now - time) * rate));
|
nowSize = Math.max(0, (nowSize - (now - time) * rate));
|
||||||
time = now;
|
time = now;
|
||||||
if ((nowSize + 1) < total) {
|
if ((nowSize + 1) < total) {
|
||||||
nowSize++;
|
nowSize++;
|
||||||
@@ -233,7 +234,7 @@ public class LeakBucket {
|
|||||||
|
|
||||||
#### 实现方式
|
#### 实现方式
|
||||||
|
|
||||||
- 规定固定容量的桶, token 以固定速度往桶内填充, 当桶满时 token 不会被继续放入, 每过来一个请求把 token 从桶中移除, 如果桶中没有 token 不能请求
|
规定固定容量的桶, token 以固定速度往桶内填充, 当桶满时 token 不会被继续放入, 每过来一个请求把 token 从桶中移除, 如果桶中没有 token 不能请求。
|
||||||
|
|
||||||
```java
|
```java
|
||||||
public class TokenBucket {
|
public class TokenBucket {
|
||||||
@@ -256,7 +257,7 @@ public class TokenBucket {
|
|||||||
|
|
||||||
public boolean limit() {
|
public boolean limit() {
|
||||||
long now = System.currentTimeMillis();
|
long now = System.currentTimeMillis();
|
||||||
nowSize = Math.min(total, nowSize + (now - time) * rate);
|
nowSize = Math.min(total, nowSize + (now - time) * rate);
|
||||||
time = now;
|
time = now;
|
||||||
if (nowSize < 1) {
|
if (nowSize < 1) {
|
||||||
// 桶里没有token
|
// 桶里没有token
|
||||||
@@ -275,7 +276,7 @@ public class TokenBucket {
|
|||||||
|
|
||||||
### spring cloud gateway
|
### spring cloud gateway
|
||||||
|
|
||||||
- spring cloud gateway 默认使用 redis 进行限流, 笔者一般只是修改修改参数属于拿来即用. 并没有去从头实现上述那些算法.
|
- spring cloud gateway 默认使用 redis 进行限流,笔者一般只是修改修改参数属于拿来即用,并没有去从头实现上述那些算法。
|
||||||
|
|
||||||
```xml
|
```xml
|
||||||
<dependency>
|
<dependency>
|
||||||
@@ -354,12 +355,12 @@ spring:
|
|||||||
```json
|
```json
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"resource": "/hello",
|
"resource": "/hello",
|
||||||
"limitApp": "default",
|
"limitApp": "default",
|
||||||
"grade": 1,
|
"grade": 1,
|
||||||
"count": 1,
|
"count": 1,
|
||||||
"strategy": 0,
|
"strategy": 0,
|
||||||
"controlBehavior": 0,
|
"controlBehavior": 0,
|
||||||
"clusterMode": false
|
"clusterMode": false
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -375,4 +376,4 @@ spring:
|
|||||||
|
|
||||||
### 总结
|
### 总结
|
||||||
|
|
||||||
> sentinel 和 spring cloud gateway 两个框架都是很好的限流框架, 但是在我使用中还没有将[spring-cloud-alibaba](https://github.com/alibaba/spring-cloud-alibaba)接入到项目中进行使用, 所以我会选择**spring cloud gateway**, 当接入完整的或者接入 Nacos 项目使用 setinel 会有更加好的体验.
|
> sentinel 和 spring cloud gateway 两个框架都是很好的限流框架, 但是在我使用中还没有将[spring-cloud-alibaba](https://github.com/alibaba/spring-cloud-alibaba)接入到项目中进行使用, 所以我会选择**spring cloud gateway**, 当接入完整的或者接入 Nacos 项目使用 setinel 会有更加好的体验.
|
||||||
|
|||||||
Reference in New Issue
Block a user