mirror of
https://github.com/Snailclimb/JavaGuide
synced 2025-06-16 18:10:13 +08:00
Compare commits
15 Commits
b93f1384d0
...
a2308d233c
Author | SHA1 | Date | |
---|---|---|---|
|
a2308d233c | ||
|
a313680284 | ||
|
563505e8ec | ||
|
8d0221f701 | ||
|
89d9ca7504 | ||
|
9258fd29c3 | ||
|
342526b2bc | ||
|
0d8b829ce0 | ||
|
d2ce6448f5 | ||
|
d7454e3a19 | ||
|
41369dc412 | ||
|
a06aec192c | ||
|
470c9cbfd3 | ||
|
610c103d30 | ||
|
3104392b9a |
@ -15,7 +15,7 @@ HTTP 使用客户端-服务器模型,客户端向服务器发送 HTTP Request
|
||||
|
||||
HTTP 协议基于 TCP 协议,发送 HTTP 请求之前首先要建立 TCP 连接也就是要经历 3 次握手。目前使用的 HTTP 协议大部分都是 1.1。在 1.1 的协议里面,默认是开启了 Keep-Alive 的,这样的话建立的连接就可以在多次请求中被复用了。
|
||||
|
||||
另外, HTTP 协议是”无状态”的协议,它无法记录客户端用户的状态,一般我们都是通过 Session 来记录客户端用户的状态。
|
||||
另外, HTTP 协议是“无状态”的协议,它无法记录客户端用户的状态,一般我们都是通过 Session 来记录客户端用户的状态。
|
||||
|
||||
## Websocket:全双工通信协议
|
||||
|
||||
|
@ -45,7 +45,7 @@ SOHO 子网的“代理人”,也就是和外界的窗口,通常由路由器
|
||||
针对以上过程,有以下几个重点需要强调:
|
||||
|
||||
1. 当请求报文到达路由器,并被指定了新端口号时,由于端口号有 16 位,因此,通常来说,一个路由器管理的 LAN 中的最大主机数 $≈65500$($2^{16}$ 的地址空间),但通常 SOHO 子网内不会有如此多的主机数量。
|
||||
2. 对于目的服务器来说,从来不知道“到底是哪个主机给我发送的请求”,它只知道是来自`138.76.29.7:5001`的路由器转发的请求。因此,可以说,**路由器在 WAN 和 LAN 之间起到了屏蔽作用,**所有内部主机发送到外部的报文,都具有同一个 IP 地址(不同的端口号),所有外部发送到内部的报文,也都只有一个目的地(不同端口号),是经过了 NAT 转换后,外部报文才得以正确地送达内部主机。
|
||||
2. 对于目的服务器来说,从来不知道“到底是哪个主机给我发送的请求”,它只知道是来自`138.76.29.7:5001`的路由器转发的请求。因此,可以说,**路由器在 WAN 和 LAN 之间起到了屏蔽作用**,所有内部主机发送到外部的报文,都具有同一个 IP 地址(不同的端口号),所有外部发送到内部的报文,也都只有一个目的地(不同端口号),是经过了 NAT 转换后,外部报文才得以正确地送达内部主机。
|
||||
3. 在报文穿过路由器,发生 NAT 转换时,如果 LAN 主机 IP 已经在 NAT 转换表中注册过了,则不需要路由器新指派端口,而是直接按照转换记录穿过路由器。同理,外部报文发送至内部时也如此。
|
||||
|
||||
总结 NAT 协议的特点,有以下几点:
|
||||
@ -55,6 +55,6 @@ SOHO 子网的“代理人”,也就是和外界的窗口,通常由路由器
|
||||
3. WAN 的 ISP 变更接口地址时,无需通告 LAN 内主机。
|
||||
4. LAN 主机对 WAN 不可见,不可直接寻址,可以保证一定程度的安全性。
|
||||
|
||||
然而,NAT 协议由于其独特性,存在着一些争议。比如,可能你已经注意到了,**NAT 协议在 LAN 以外,标识一个内部主机时,使用的是端口号,因为 IP 地址都是相同的。**这种将端口号作为主机寻址的行为,可能会引发一些误会。此外,路由器作为网络层的设备,修改了传输层的分组内容(修改了源 IP 地址和端口号),同样是不规范的行为。但是,尽管如此,NAT 协议作为 IPv4 时代的产物,极大地方便了一些本来棘手的问题,一直被沿用至今。
|
||||
然而,NAT 协议由于其独特性,存在着一些争议。比如,可能你已经注意到了,**NAT 协议在 LAN 以外,标识一个内部主机时,使用的是端口号,因为 IP 地址都是相同的**。这种将端口号作为主机寻址的行为,可能会引发一些误会。此外,路由器作为网络层的设备,修改了传输层的分组内容(修改了源 IP 地址和端口号),同样是不规范的行为。但是,尽管如此,NAT 协议作为 IPv4 时代的产物,极大地方便了一些本来棘手的问题,一直被沿用至今。
|
||||
|
||||
<!-- @include: @article-footer.snippet.md -->
|
||||
|
@ -194,7 +194,7 @@ HTTP 状态码用于描述 HTTP 请求的结果,比如 2xx 就代表请求被
|
||||
|
||||

|
||||
|
||||
- **多路复用(Multiplexing)**:HTTP/2.0 在同一连接上可以同时传输多个请求和响应(可以看作是 HTTP/1.1 中长链接的升级版本),互不干扰。HTTP/1.1 则使用串行方式,每个请求和响应都需要独立的连接,而浏览器为了控制资源会有 6-8 个 TCP 连接的限制。。这使得 HTTP/2.0 在处理多个请求时更加高效,减少了网络延迟和提高了性能。
|
||||
- **多路复用(Multiplexing)**:HTTP/2.0 在同一连接上可以同时传输多个请求和响应(可以看作是 HTTP/1.1 中长链接的升级版本),互不干扰。HTTP/1.1 则使用串行方式,每个请求和响应都需要独立的连接,而浏览器为了控制资源会有 6-8 个 TCP 连接的限制。这使得 HTTP/2.0 在处理多个请求时更加高效,减少了网络延迟和提高了性能。
|
||||
- **二进制帧(Binary Frames)**:HTTP/2.0 使用二进制帧进行数据传输,而 HTTP/1.1 则使用文本格式的报文。二进制帧更加紧凑和高效,减少了传输的数据量和带宽消耗。
|
||||
- **头部压缩(Header Compression)**:HTTP/1.1 支持`Body`压缩,`Header`不支持压缩。HTTP/2.0 支持对`Header`压缩,使用了专门为`Header`压缩而设计的 HPACK 算法,减少了网络开销。
|
||||
- **服务器推送(Server Push)**:HTTP/2.0 支持服务器推送,可以在客户端请求一个资源时,将其他相关资源一并推送给客户端,从而减少了客户端的请求次数和延迟。而 HTTP/1.1 需要客户端自己发送请求来获取相关资源。
|
||||
|
@ -53,7 +53,7 @@ var 并不会改变 Java 是一门静态类型语言的事实,编译器负责
|
||||
|
||||
## G1 并行 Full GC
|
||||
|
||||
从 Java9 开始 G1 就了默认的垃圾回收器,G1 是以一种低延时的垃圾回收器来设计的,旨在避免进行 Full GC,但是 Java9 的 G1 的 FullGC 依然是使用单线程去完成标记清除算法,这可能会导致垃圾回收期在无法回收内存的时候触发 Full GC。
|
||||
从 Java9 开始 G1 就成了默认的垃圾回收器,G1 是以一种低延时的垃圾回收器来设计的,旨在避免进行 Full GC,但是 Java9 的 G1 的 FullGC 依然是使用单线程去完成标记清除算法,这可能会导致垃圾回收期在无法回收内存的时候触发 Full GC。
|
||||
|
||||
为了最大限度地减少 Full GC 造成的应用停顿的影响,从 Java10 开始,G1 的 FullGC 改为并行的标记清除算法,同时会使用与年轻代回收和混合回收相同的并行工作线程数量,从而减少了 Full GC 的发生,以带来更好的性能提升、更大的吞吐量。
|
||||
|
||||
|
@ -77,7 +77,7 @@ System.out.println(op.isEmpty());//判断指定的 Optional 对象是否为空
|
||||
ZGC 主要为了满足如下目标进行设计:
|
||||
|
||||
- GC 停顿时间不超过 10ms
|
||||
- 即能处理几百 MB 的小堆,也能处理几个 TB 的大堆
|
||||
- 既能处理几百 MB 的小堆,也能处理几个 TB 的大堆
|
||||
- 应用吞吐能力不会下降超过 15%(与 G1 回收算法相比)
|
||||
- 方便在此基础上引入新的 GC 特性和利用 colored 针以及 Load barriers 优化奠定基础
|
||||
- 当前只支持 Linux/x64 位平台
|
||||
|
@ -419,33 +419,66 @@ Class B {
|
||||
|
||||
**3.`TransactionDefinition.PROPAGATION_NESTED`**:
|
||||
|
||||
如果当前存在事务,就在嵌套事务内执行;如果当前没有事务,就执行与`TransactionDefinition.PROPAGATION_REQUIRED`类似的操作。也就是说:
|
||||
如果当前存在事务,则创建一个事务作为当前事务的嵌套事务执行; 如果当前没有事务,就执行与`TransactionDefinition.PROPAGATION_REQUIRED`类似的操作。也就是说:
|
||||
|
||||
- 在外部方法开启事务的情况下,在内部开启一个新的事务,作为嵌套事务存在。
|
||||
- 如果外部方法无事务,则单独开启一个事务,与 `PROPAGATION_REQUIRED` 类似。
|
||||
|
||||
这里还是简单举个例子:如果 `bMethod()` 回滚的话,`aMethod()`不会回滚。如果 `aMethod()` 回滚的话,`bMethod()`会回滚。
|
||||
`TransactionDefinition.PROPAGATION_NESTED`代表的嵌套事务以父子关系呈现,其核心理念是子事务不会独立提交,依赖于父事务,在父事务中运行;当父事务提交时,子事务也会随着提交,理所当然的,当父事务回滚时,子事务也会回滚;
|
||||
> 与`TransactionDefinition.PROPAGATION_REQUIRES_NEW`区别于:`PROPAGATION_REQUIRES_NEW`是独立事务,不依赖于外部事务,以平级关系呈现,执行完就会立即提交,与外部事务无关;
|
||||
|
||||
```java
|
||||
@Service
|
||||
Class A {
|
||||
@Autowired
|
||||
B b;
|
||||
@Transactional(propagation = Propagation.REQUIRED)
|
||||
public void aMethod {
|
||||
//do something
|
||||
b.bMethod();
|
||||
}
|
||||
}
|
||||
子事务也有自己的特性,可以独立进行回滚,不会引发父事务的回滚,但是前提是需要处理子事务的异常,避免异常被父事务感知导致外部事务回滚;
|
||||
|
||||
@Service
|
||||
Class B {
|
||||
@Transactional(propagation = Propagation.NESTED)
|
||||
public void bMethod {
|
||||
//do something
|
||||
举个例子:
|
||||
- 如果 `aMethod()` 回滚的话,作为嵌套事务的`bMethod()`会回滚。
|
||||
- 如果 `bMethod()` 回滚的话,`aMethod()`是否回滚,要看`bMethod()`的异常是否被处理:
|
||||
- `bMethod()`的异常没有被处理,即`bMethod()`内部没有处理异常,且`aMethod()`也没有处理异常,那么`aMethod()`将感知异常致使整体回滚。
|
||||
```java
|
||||
@Service
|
||||
Class A {
|
||||
@Autowired
|
||||
B b;
|
||||
@Transactional(propagation = Propagation.REQUIRED)
|
||||
public void aMethod (){
|
||||
//do something
|
||||
b.bMethod();
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@Service
|
||||
Class B {
|
||||
@Transactional(propagation = Propagation.NESTED)
|
||||
public void bMethod (){
|
||||
//do something and throw an exception
|
||||
}
|
||||
}
|
||||
```
|
||||
- `bMethod()`处理异常或`aMethod()`处理异常,`aMethod()`不会回滚。
|
||||
|
||||
```java
|
||||
@Service
|
||||
Class A {
|
||||
@Autowired
|
||||
B b;
|
||||
@Transactional(propagation = Propagation.REQUIRED)
|
||||
public void aMethod (){
|
||||
//do something
|
||||
try {
|
||||
b.bMethod();
|
||||
} catch (Exception e) {
|
||||
System.out.println("方法回滚");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Service
|
||||
Class B {
|
||||
@Transactional(propagation = Propagation.NESTED)
|
||||
public void bMethod {
|
||||
//do something and throw an exception
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**4.`TransactionDefinition.PROPAGATION_MANDATORY`**
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user