0%

网络协议之 TCP

📦 本文已归档到:「blog

简介

什么是 TCP

TCP(Transmission Control Protocol),即传输控制协议,它是一种面向连接的可靠的基于字节流的传输层通信协议。TCP 由 RFC 793 定义。

TCP 的特性

  • 面向连接的 - 面向连接是指 TCP 需要通过三次握手、四次挥手原则建立和断开双向连接。
  • 可靠的 - 可靠是指 TCP 传输的数据包保证以原始顺序到达目的地,且数据包不被损坏。为了实现这点,TCP 通过以下技术来保证:
    • 数据包的序列号和校验码
    • 确认包和自动重传
      • 如果发送者没有收到正确的响应,它将重新发送数据包。如果多次超时,连接就会断开。
      • TCP 实行流量控制和拥塞控制。这些确保措施会导致延迟,而且通常导致传输效率比 UDP 低。
  • 基于字节流的
    • 虽然应用程序和 TCP 的交互是一次一个数据块(大小不等),但 TCP 把应用程序看成是一连串的无结构的字节流。TCP 有一个缓冲,当应用程序传送的数据块太长,TCP 就可以把它划分短一些再传送。如果应用程序一次只发送一个字节,TCP 也可以等待积累有足够多的字节后再构成报文段发送出去。
    • 在 TCP 建立连接前两次握手的 SYN 报文中选项字段的 MSS 值,通信双方商定通信的最大报文长度。如果应用层交付下来的数据过大,就会对数据分段,然后发送;否则通过滑动窗口来控制通信双发的数据。

TCP 的适用场景

基于以上特性,为了确保高吞吐量,Web 服务器可以保持大量的 TCP 连接,从而导致高内存使用。但要注意的是,在 Web 服务器线程间拥有大量开放连接可能开销巨大,消耗资源过多,这时可以考虑在适用情况下切换到 UDP。

TCP 对于需要高可靠性但时间紧迫的应用程序很有用。比如包括 Web 服务器,数据库信息,SMTP,FTP 和 SSH。

以下情况使用 TCP 代替 UDP:

  • 你需要数据完好无损。
  • 你想对网络吞吐量自动进行最佳评估。

TCP 报文

报文字段不一一阐述,重点关注以下几点:

  • TCP 的包是没有 IP 地址的,那是 IP 层上的事。但是有源端口和目标端口。
  • 一个 TCP 连接需要四个元组来表示是同一个连接(src_ip, src_port, dst_ip, dst_port)准确说是五元组,还有一个是协议。但因为这里只是说 TCP 协议,所以,这里我只说四元组。
  • 注意上图中的四个非常重要的东西:
    • Sequence Number是包的序号,用来解决网络包乱序(reordering)问题。
    • Acknowledgement Number就是 ACK——用于确认收到,用来解决不丢包的问题
    • Window 又叫 Advertised-Window,也就是著名的滑动窗口(Sliding Window),用于解决流控的
    • TCP Flag,也就是包的类型,主要是用于操控 TCP 的状态机的

TCP 通信流程

TCP 完整的通信分为三块:

  1. 三次握手建立连接
  2. 数据传输
  3. 四次挥手端口连接

三次握手

(1)三次握手有什么用?

  • 三次握手负责建立 TCP 双向连接。

(2)什么是三次握手?

如上图所示,三次握手流程如下:

  1. 第一次握手 - 客户端向服务端发送带有 SYN 标志的数据包。
  2. 第二次握手 - 服务端向客户端发送带有 SYN/ACK 标志的数据包。
  3. 第三次握手 - 客户端向服务端发送带有带有 ACK 标志的数据包。

至此,TCP 三次握手完成,客户端与服务端已建立双向连接。

💡 说明:SYN 为 synchronize 的缩写,ACK 为 acknowledgment 的缩写。

(3)为什么需要三次握手?

为了便于说明,假设客户端为 A, 服务端为 B。

  1. 第一次握手,A 向 B 发同步消息。B 收到消息后,B 认为:A 发消息没问题;B 收消息没问题。
  2. 第二次握手,B 向 A 发同步消息和确认消息。A 收到消息后,A 认为:A 发消息、收消息都没问题;B 发消息、收消息都没问题。但是,此时 B 不确定自己发消息是否没问题,所以就需要第三次握手。
  3. 第三次握手,A 向 B 发确认消息。B 收到消息后。B 认为:B 发消息没问题。

四次挥手

(1)四次挥手有什么用?

  • 四次挥手负责断开 TCP 连接。

(2)什么是四次挥手?

如上图所示,四次挥手流程如下:

  1. 第一次挥手 - 客户端向服务端发送一个 FIN 包,用来关闭客户端到服务端的数据传送。
  2. 第二次挥手 - 服务端收到这个 FIN 包,向客户端发送一个 ACK 包,确认序号为收到的序号加 1。和 SYN 一样,一个 FIN 将占用一个序号。
  3. 第三次挥手 - 服务端关闭与客户端的连接,向客户端发送一个 FIN 包。
  4. 第四次挥手 - 客户端向服务端发送 ACK 包,并将确认序号设置为收到序号加 1。

(3)为什么建立连接是三次握手,关闭连接确是四次挥手呢?

  • 建立连接的时候, 服务器在 LISTEN 状态下,收到建立连接请求的 SYN 报文后,把 ACK 和 SYN 放在一个报文里发送给客户端。
  • 而关闭连接时,服务器收到对方的 FIN 报文时,仅仅表示对方不再发送数据了但是还能接收数据,而自己也未必全部数据都发送给对方了,所以己方可以立即关闭,也可以发送一些数据给对方后,再发送 FIN 报文给对方来表示同意现在关闭连接,因此,己方 ACK 和 FIN 一般都会分开发送,从而导致多了一次。

滑动窗口

什么是滑动窗口?

滑动窗口是 TCP 的一种控制网络流量的技术。

TCP 必需要解决的可靠传输以及包乱序(reordering)的问题,所以,TCP 必需要知道网络实际的数据处理带宽或是数据处理速度,这样才不会引起网络拥塞,导致丢包。

TCP 头里有一个字段叫 Window,又叫 Advertised-Window,这个字段是接收端告诉发送端自己还有多少缓冲区可以接收数据。于是发送端就可以根据这个接收端的处理能力来发送数据,而不会导致接收端处理不过来

滑动窗口原理是什么?

  1. 已发送已确认 - 数据流中最早的字节已经发送并得到确认。这些数据是站在发送端的角度来看的。上图中的 31 个字节已经发送并确认。
  2. 已发送但尚未确认 - 已发送但尚未得到确认的字节。发送方在确认之前,不认为这些数据已经被处理。上图中的 32 ~ 45 字节为第 2 类。
  3. 未发送而接收方已 Ready - 设备尚未将数据发出 ,但接收方根据最近一次关于发送方一次要发送多少字节确认自己有足够空间。发送方会立即尝试发送。上图中的 46 ~ 51 字节为第 3 类。
  4. 未发送而接收方 Not Ready - 由于接收方 not ready,还不允许将这部分数据发出。上图中的 52 以后的字节为第 4 类。

这张图片相对于上一张图片,滑动窗口偏移了 5 个字节,意味着有 5 个已发送的字节得到了确认。

TCP 重传机制

TCP 要保证所有的数据包都可以到达,所以,必需要有重传机制。

TCP 重传机制主要有两种:

  • 超时重传机制
  • 快速重传机制

超时重传机制

超时重传机制是指:发送数据包在一定的时间周期内没有收到相应的 ACK,等待一定的时间,超时之后就认为这个数据包丢失,就会重新发送。这个等待时间被称为 RTO(Retransmission TimeOut),即重传超时时间。

没有确认的数据包不会从窗口中移走,定时器在重传时间到期内,每个片段的位置不变。

这种机制的重点是 RTO 的设置:

  • RTO 设长了,重发就慢,丢了老半天才重发,没有效率,性能差;
  • RTO 设短了,会导致可能并没有丢就重发。于是重发的就快,会增加网络拥塞,导致更多的超时,更多的超时导致更多的重发

快速重传机制

快速重传机制,实现了另外的一种丢包评定标准,即如果连续收到 3 次重复 ACK,发送方就认为这个 seq 的包丢失了,立刻进行重传。

当接收方收到乱序片段时,需要重复发送 ACK。

参考资料

网络协议之 UDP

📦 本文已归档到:「blog

简介

UDP 是无连接的。数据报(类似于数据包)只在数据报级别有保证。数据报可能会无序的到达目的地,也有可能会遗失。UDP 不支持拥塞控制。虽然不如 TCP 那样有保证,但 UDP 通常效率更高。

UDP 可以通过广播将数据报发送至子网内的所有设备。这对 DHCP 很有用,因为子网内的设备还没有分配 IP 地址,而 IP 对于 TCP 是必须的。

UDP 可靠性更低但适合用在网络电话、视频聊天,流媒体和实时多人游戏上。

以下情况使用 UDP 代替 TCP:

  • 你需要低延迟
  • 相对于数据丢失更糟的是数据延迟
  • 你想实现自己的错误校正方法

UDP 特点

  1. 无连接的,即发送数据之前不需要建立连接,因此减少了开销和发送数据之前的时延。
  2. 不保证可靠交付,因此主机不需要为此复杂的连接状态表
  3. 面向报文的,意思是 UDP 对应用层交下来的报文,既不合并,也不拆分,而是保留这些报文的边界,在添加首部后向下交给 IP 层。
  4. 没有阻塞控制,因此网络出现的拥塞不会使发送方的发送速率降低。
  5. 支持一对一、一对多、多对一和多对多的交互通信,也即是提供广播和多播的功能。
  6. 首部开销小,首部只有 8 个字节,分为四部分。

UDP 应用场景

  1. 名字转换(DNS)
  2. 文件传送(TFTP)
  3. 路由选择协议(RIP)
  4. IP 地址配置(BOOTP,DHTP)
  5. 网络管理(SNMP)
  6. 远程文件服务(NFS)
  7. IP 电话
  8. 流式多媒体通信

UDP 报文

UDP 数据报分为数据字段和首部字段。
首部字段只有 8 个字节,由四个字段组成,每个字段的长度是 2 个字节。

首部各字段意义

  1. 源端口:源端口号,在需要对方回信时选用,不需要时可全 0.
  2. 目的端口:目的端口号,在终点交付报文时必须要使用到。
  3. 长度:UDP 用户数据报的长度,在只有首部的情况,其最小值是 8 。
  4. 检验和:检测 UDP 用户数据报在传输中是否有错,有错就丢弃。

Socket 和 WebSocket

📦 本文已归档到:「blog

Socket

Socket 作为一种抽象层,应用程序通过它来发送和接收数据,使用 Socket 可以将应用程序与处于同一网络中的其他应用程序进行通信交互。简而言之,Socket 提供了应用程序内部与外界通信的端口以及为通信双方提供了数据传输的通道。

Socket 用法

很多编程语言都支持 Socket。这里以 Java 的 Socket 用法为例。

在 Java 的 SDK 中,socket 的共有两个接口:用于监听客户连接的 ServerSocket 和用于通信的 Socket。使用 socket 的步骤如下:

  • 创建 ServerSocket 并监听客户连接
  • 使用 Socket 连接服务端
  • 通过 Socket 获取输入输出流进行通信

Socket 长连接

Socket 长连接,指的是在客户和服务端之间保持一个 socket 连接长时间不断开。

1
socket.setKeepAlive(true);

WebSocket

WebSocket 简介

WebSocket 是什么

WebSocket 是一种网络通信协议。RFC6455 定义了它的通信标准。

WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。

为什么需要 WebSocket

了解计算机网络协议的人,应该都知道:HTTP 协议是一种无状态的、无连接的、单向的应用层协议。它采用了请求/响应模型。通信请求只能由客户端发起,服务端对请求做出应答处理。

这种通信模型有一个弊端:HTTP 协议无法实现服务器主动向客户端发起消息。

这种单向请求的特点,注定了如果服务器有连续的状态变化,客户端要获知就非常麻烦。大多数 Web 应用程序将通过频繁的异步 JavaScript 和 XML(AJAX)请求实现长轮询。轮询的效率低,非常浪费资源(因为必须不停连接,或者 HTTP 连接始终打开)。

因此,工程师们一直在思考,有没有更好的方法。WebSocket 就是这样发明的。WebSocket 连接允许客户端和服务器之间进行全双工通信,以便任一方都可以通过建立的连接将数据推送到另一端。WebSocket 只需要建立一次连接,就可以一直保持连接状态。这相比于轮询方式的不停建立连接显然效率要大大提高。
#### WebSocket 如何工作

Web 浏览器和服务器都必须实现 WebSockets 协议来建立和维护连接。由于 WebSockets 连接长期存在,与典型的 HTTP 连接不同,对服务器有重要的影响。

基于多线程或多进程的服务器无法适用于 WebSockets,因为它旨在打开连接,尽可能快地处理请求,然后关闭连接。任何实际的 WebSockets 服务器端实现都需要一个异步服务器。

WebSocket 使用

WebSocket 客户端

在客户端,没有必要为 WebSockets 使用 JavaScript 库。实现 WebSockets 的 Web 浏览器将通过 WebSockets 对象公开所有必需的客户端功能(主要指支持 Html5 的浏览器)。

以下 API 用于创建 WebSocket 对象。

1
var Socket = new WebSocket(url, [protocol] );

以上代码中的第一个参数 url, 指定连接的 URL。第二个参数 protocol 是可选的,指定了可接受的子协议。

WebSocket 属性

以下是 WebSocket 对象的属性。假定我们使用了以上代码创建了 Socket 对象:

属性 描述
Socket.readyState 只读属性 readyState 表示连接状态,可以是以下值:0 - 表示连接尚未建立。1 - 表示连接已建立,可以进行通信。2 - 表示连接正在进行关闭。3 - 表示连接已经关闭或者连接不能打开。
Socket.bufferedAmount 只读属性 bufferedAmount 已被 send() 放入正在队列中等待传输,但是还没有发出的 UTF-8 文本字节数。
WebSocket 事件

以下是 WebSocket 对象的相关事件。假定我们使用了以上代码创建了 Socket 对象:

事件 事件处理程序 描述
open Socket.onopen 连接建立时触发
message Socket.onmessage 客户端接收服务端数据时触发
error Socket.onerror 通信发生错误时触发
close Socket.onclose 连接关闭时触发
WebSocket 方法

以下是 WebSocket 对象的相关方法。假定我们使用了以上代码创建了 Socket 对象:

方法 描述
Socket.send() 使用连接发送数据
Socket.close() 关闭连接

WebSocket 客户端代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 初始化一个 WebSocket 对象
var ws = new WebSocket('ws://localhost:9998/echo')

// 建立 web socket 连接成功触发事件
ws.onopen = function() {
// 使用 send() 方法发送数据
ws.send('发送数据')
alert('数据发送中...')
}

// 接收服务端数据时触发事件
ws.onmessage = function(evt) {
var received_msg = evt.data
alert('数据已接收...')
}

// 断开 web socket 连接成功触发事件
ws.onclose = function() {
alert('连接已关闭...')
}

WebSocket 服务端

WebSocket 在服务端的实现非常丰富。Node.js、Java、C++、Python 等多种语言都有自己的解决方案。

以下,介绍我在学习 WebSocket 过程中接触过的 WebSocket 服务端解决方案。

Node.js

常用的 Node 实现有以下三种。

Java

Java 的 web 一般都依托于 servlet 容器。

我使用过的 servlet 容器有:Tomcat、Jetty、Resin。其中 Tomcat7、Jetty7 及以上版本均开始支持 WebSocket(推荐较新的版本,因为随着版本的更迭,对 WebSocket 的支持可能有变更)。

此外,Spring 框架对 WebSocket 也提供了支持。

虽然,以上应用对于 WebSocket 都有各自的实现。但是,它们都遵循RFC6455 的通信标准,并且 Java API 统一遵循 JSR 356 - JavaTM API for WebSocket 规范。所以,在实际编码中,API 差异不大。

Spring

Spring 对于 WebSocket 的支持基于下面的 jar 包:

1
2
3
4
5
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-websocket</artifactId>
<version>${spring.version}</version>
</dependency>

在 Spring 实现 WebSocket 服务器大概分为以下几步:

创建 WebSocket 处理器

扩展 TextWebSocketHandlerBinaryWebSocketHandler ,你可以覆写指定的方法。Spring 在收到 WebSocket 事件时,会自动调用事件对应的方法。

1
2
3
4
5
6
7
8
9
10
11
12
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.TextMessage;

public class MyHandler extends TextWebSocketHandler {

@Override
public void handleTextMessage(WebSocketSession session, TextMessage message) {
// ...
}

}

WebSocketHandler 源码如下,这意味着你的处理器大概可以处理哪些 WebSocket 事件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public interface WebSocketHandler {

/**
* 建立连接后触发的回调
*/
void afterConnectionEstablished(WebSocketSession session) throws Exception;

/**
* 收到消息时触发的回调
*/
void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception;

/**
* 传输消息出错时触发的回调
*/
void handleTransportError(WebSocketSession session, Throwable exception) throws Exception;

/**
* 断开连接后触发的回调
*/
void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception;

/**
* 是否处理分片消息
*/
boolean supportsPartialMessages();

}

配置 WebSocket

配置有两种方式:注解和 xml 。其作用就是将 WebSocket 处理器添加到注册中心。

  1. 实现 WebSocketConfigurer
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;

@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {

@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(myHandler(), "/myHandler");
}

@Bean
public WebSocketHandler myHandler() {
return new MyHandler();
}

}
  1. xml 方式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:websocket="http://www.springframework.org/schema/websocket"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/websocket
http://www.springframework.org/schema/websocket/spring-websocket.xsd">

<websocket:handlers>
<websocket:mapping path="/myHandler" handler="myHandler"/>
</websocket:handlers>

<bean id="myHandler" class="org.springframework.samples.MyHandler"/>

</beans>

更多配置细节可以参考:Spring WebSocket 文档

javax.websocket

如果不想使用 Spring 框架的 WebSocket API,你也可以选择基本的 javax.websocket。

首先,需要引入 API jar 包。

1
2
3
4
5
6
<!-- To write basic javax.websocket against -->
<dependency>
<groupId>javax.websocket</groupId>
<artifactId>javax.websocket-api</artifactId>
<version>1.0</version>
</dependency>

如果使用嵌入式 jetty,你还需要引入它的实现包:

1
2
3
4
5
6
7
8
9
10
11
12
<!-- To run javax.websocket in embedded server -->
<dependency>
<groupId>org.eclipse.jetty.websocket</groupId>
<artifactId>javax-websocket-server-impl</artifactId>
<version>${jetty-version}</version>
</dependency>
<!-- To run javax.websocket client -->
<dependency>
<groupId>org.eclipse.jetty.websocket</groupId>
<artifactId>javax-websocket-client-impl</artifactId>
<version>${jetty-version}</version>
</dependency>

@ServerEndpoint

这个注解用来标记一个类是 WebSocket 的处理器。

然后,你可以在这个类中使用下面的注解来表明所修饰的方法是触发事件的回调

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 收到消息触发事件
@OnMessage
public void onMessage(String message, Session session) throws IOException, InterruptedException {
...
}

// 打开连接触发事件
@OnOpen
public void onOpen(Session session, EndpointConfig config, @PathParam("id") String id) {
...
}

// 关闭连接触发事件
@OnClose
public void onClose(Session session, CloseReason closeReason) {
...
}

// 传输消息错误触发事件
@OnError
public void onError(Throwable error) {
...
}

ServerEndpointConfig.Configurator

编写完处理器,你需要扩展 ServerEndpointConfig.Configurator 类完成配置:

1
2
3
4
5
6
7
public class WebSocketServerConfigurator extends ServerEndpointConfig.Configurator {
@Override
public void modifyHandshake(ServerEndpointConfig sec, HandshakeRequest request, HandshakeResponse response) {
HttpSession httpSession = (HttpSession) request.getHttpSession();
sec.getUserProperties().put(HttpSession.class.getName(), httpSession);
}
}

然后就没有然后了,就是这么简单。

WebSocket 代理

如果把 WebSocket 的通信看成是电话连接,Nginx 的角色则像是电话接线员,负责将发起电话连接的电话转接到指定的客服。

Nginx 从 1.3 版开始正式支持 WebSocket 代理。如果你的 web 应用使用了代理服务器 Nginx,那么你还需要为 Nginx 做一些配置,使得它开启 WebSocket 代理功能。

以下为参考配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
server {
# this section is specific to the WebSockets proxying
location /socket.io {
proxy_pass http://app_server_wsgiapp/socket.io;
proxy_redirect off;

proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 600;
}
}

更多配置细节可以参考:Nginx 官方的 websocket 文档

WebSocket 应用示例

如果需要完整示例代码,可以参考我的 Github 代码:

spring-websocket 和 jetty 9.3 版本似乎存在兼容性问题,Tomcat 则木有问题。

我尝试了好几次,没有找到解决方案,只好使用 Jetty 官方的嵌入式示例在 Jetty 中使用 WebSocket 。

FAQ

Http vs. Socket

Http 通信与 Socket 通信方式有何差异?

  • Http
    • 基于请求/响应模式,采取一问一答方式(客户端请求,服务端才会响应)
  • Socket
    • 客户端和服务端建立双向连接。连接成功后,任意一方都可主动发送消息。
    • 数据丢失率低,使用简单,易于移植。

HTTP 和 WebSocket 有什么关系?

Websocket 其实是一个新协议,跟 HTTP 协议基本没有关系,只是为了兼容现有浏览器的握手规范而已,也就是说它是 HTTP 协议上的一种补充。

Html 和 HTTP 有什么关系?

Html 是超文本标记语言,是一种用于创建网页的标准标记语言。它是一种技术标准。Html5 是它的最新版本。

Http 是一种网络通信协议。其本身和 Html 没有直接关系。

参考资料

网络通信之 CDN

📦 本文已归档到:「blog

简介

CDN 是什么

CDN(Content Delivery Network),即内容分发网络

CDN 是一个全球性的代理服务器分布式网络,依靠部署在各地的边缘服务器,通过中心平台的负载均衡、内容分发、调度等功能模块,使用户就近获取所需内容,降低网络拥塞,提高用户访问响应速度和命中率。它从靠近用户的位置提供内容。通常,HTML/CSS/JS,图片和视频等静态内容由 CDN 提供。CDN 的 DNS 解析会告知客户端连接哪台服务器。CDN 的关键技术主要有内容存储和分发技术。

CDN 的优缺点

  • 优点
    • 访问加速 - 由于 CDN 就近服务,大大降低了网络传播时延,所以自然提高了访问速度。
    • 降低负载 - 如果 CDN 已经能获取数据,那么就不必请求源站,这自然降低了源站(服务器)的负载。
  • 缺点
    • CDN 成本可能因流量而异,可能在权衡之后你将不会使用 CDN。
    • 如果在 TTL 过期之前更新内容,CDN 缓存内容可能会过时。
    • CDN 需要更改静态内容的 URL 地址以指向 CDN。

CDN 原理

CDN 的基本原理是:

  • 广泛采用各种缓存服务器,将这些缓存服务器分布到用户访问相对集中的地区或网络中;
  • 在用户访问网站时,实时地根据网络流量和各节点的连接、负载状况以及到用户的距离和响应时间等综合信息来选择最佳缓存服务器;
  • 然后,将用户的请求重新导向最佳的缓存服务器上,由缓存服务器直接响应用户请求。

CDN 网络架构主要由两大部分,分为中心边缘两部分:

  • 中心指 CDN 网管中心和 DNS 重定向解析中心,负责全局负载均衡,设备系统安装在管理中心机房;
  • 边缘主要指异地节点,CDN 分发的载体,主要由 Cache 和负载均衡器等组成。

CDN 是一个策略性部署的整体系统,包括分布式存储负载均衡内容管理网络请求的重定向4个要件。

分布式存储

CDN 网络将存储资源分布到各个地理位置、各个网段。存储系统作为 CDN 系统密不可分的一部分,将 CDN 分发的文件和数据库表记录内容存储起来,提供持续服务。存储系统采用三级存储架构,包括核心存储、CDN 服务节点分布式缓存和终端本地缓存。任意一个点的存储崩溃或失效,并不影响系统服务的可用性。

如 CDN 系统在 5 大运营商(中国电信、中国网通、中国铁通、中国移动、中国联通)以及 2 大专有网络(中国教育和科研计算机网、中国科技网)都布有 CDN 节点。这样就消除了不同运营商之间互联的瓶颈造成的影响,实现了跨运营商的网络加速,保证不同网络中的用户都能得到良好的访问质量。

内容管理

内容管理和全局的网络流量管理(Traffic Management)是 CDN 的核心所在。通过用户就近性和服务器负载的判断,CDN 确保内容以一种极为高效的方式为用户的请求提供服务。总的来说,内容服务基于缓存服务器,也称作**代理缓存(Surrogate)**,它位于网络的边缘,距用户仅有”一跳”(Single Hop)之遥。同时,代理缓存是内容提供商源服务器(通常位于 CDN 服务提供商的数据中心)的一个透明镜像。这样的架构使得 CDN 服务提供商能够代表他们客户,即内容供应商,向最终用户提供尽可能好的体验,而这些用户是不能容忍请求响应时间有任何延迟的。据统计,采用 CDN 技术,能处理整个网站页面的 70%~ 95%的内容访问量,减轻服务器的压力,提升了网站的性能和可扩展性。

负载均衡

CDN 负载均衡系统实现 CDN 的内容路由功能。它的作用是将用户的请求导向整个 CDN 网络中的最佳节点。最佳节点的选定可以根据多种策略,例如距离最近节点负载最轻等。负载均衡系统是整个 CDN 的核心,负载均衡的准确性和效率直接决定了整个 CDN 的效率和性能。通常负载均衡可以分为两个层次:全局负载均衡(GSLB)本地负载均衡(SLB)

网络请求的重定向

当用户访问了使用 CDN 服务的资源时,DNS 域名服务器通过 CNAME 方式将最终域名请求重定向到 CDN 系统中的智能 DNS 负载均衡系统。智能 DNS 负载均衡系统通过一组预先定义好的策略(如内容类型、地理区域、网络负载状况等),将当时能够最快响应用户的节点地址提供给用户,使用户可以得到快速的服务

同时,它还与分布在不同地点的所有 CDN 节点保持通信,搜集各节点的健康状态,确保不将用户的请求分配到任何一个已经不可用的节点上。

参考:

CDN 访问流程

  1. 用户在浏览器中访问域名,域名解析的请求被发往网站的 DNS 域名解析服务器;
  2. 由于网站的 DNS 域名解析服务器对此域名的解析设置了 CNAME,请求被指向 CDN 网络中的智能 DNS 负载均衡系统;
  3. 智能 DNS 负载均衡系统对域名进行智能解析,将响应速度最快的节点 IP 返回给用户;浏览器在得到速度最快节点的 IP 地址以后,向 CDN 节点发出访问请求;
  4. 由于是第一次访问,CDN 节点将回到源站取用户请求的数据并发给用户;
  5. 当有其他用户再次访问同样内容时,CDN 将直接将数据返回给客户,完成请求/服务过程。

同时,它还与分布在不同地点的所有 CDN 节点保持通信,搜集各节点的健康状态,确保不将用户的请求分配到任何一个已经不可用的节点上。

参考:

推送和拉取

CDN 服务有推送和拉取两种方式:

CDN 推送

当你服务器上内容发生变动时,推送 CDN 接受新内容。直接推送给 CDN 并重写 URL 地址以指向你的内容的 CDN 地址。你可以配置内容到期时间及何时更新。内容只有在更改或新增是才推送,流量最小化,但储存最大化。

优点在于节省源站带宽,提前将要分发的内容放到 CDN 节点上了,当某个流量高峰来临时,不会把你的源站带宽占满(源站还要留点带宽提供动态 HTML 啊)。

缺点是需要针对 CDN 做接口开发,在被分发内容生成时主动上传给 CDN。

CDN 拉取

CDN 拉取是当第一个用户请求该资源时,从服务器上拉取资源。你将内容留在自己的服务器上并重写 URL 指向 CDN 地址。直到内容被缓存在 CDN 上为止,这样请求只会更慢,

存活时间(TTL)决定缓存多久时间。CDN 拉取方式最小化 CDN 上的储存空间,但如果过期文件并在实际更改之前被拉取,则会导致冗余的流量。

高流量站点使用 CDN 拉取效果不错,因为只有最近请求的内容保存在 CDN 中,流量才能更平衡地分散。

优点在于实现简单。

参考:推送式与拉取式 CDN 服务的优劣问题

资源

基本操作

软件管理

dmg 格式:双击安装包,然后拖到 applications 文件夹下即可。

浏览器

更改默认搜索引擎

选择「偏好设置–>搜索–>搜索引擎–>Google」。

导入 chrome 浏览器的书签

选择「文件–>导入自–> Google Chrome」,然后选择要导入的项目。

快捷键

Command + R 刷新

上方显示书签栏/收藏栏

选择「显示–> 显示个人收藏栏」。

关闭软件的右上角通知

在 Mac 系统中有对通知的设置,打开系统偏好设置 — 通知 找到 QQ,然后将 QQ 提示样式设置成无即可。

复制文件/文件夹路径

  • OS X 10.11 系统,选中文件夹,「cmd +Option +c」 复制文件夹路径,cmd+v 粘贴。
    之前的系统,利用 Administrator 创建一个到右键菜单,然后到设置里面设置快捷键。具体操作请百度。

打开来自身份不明的开发者的应用程序

在应用程序文件夹,按住 control 键的同时打开应用程序。

复制文件路径

  • 选择文件/文件夹按 Command+C 复制,在终端中 Command+V 粘贴即可。

  • 如果只是想在 Finder 中看到文件的路径, 并方便切换层级, Finder 内置了「显示路径栏」的功能, 并配置了快捷键(Option+Cmd+P). 如下图所示:

20161124-184148.png

参考链接:

隐藏和取消隐藏 Mac App Store 中的已购项目

Mac 同时登陆两个 QQ

在已经打开的 QQ 中,按住「command + N」即可。

系统便好设置

语音播报

打开「系统便好设置–>辅助功能–>语音」,即可设置不同国家的语言。

勾选上图中的红框部分,可以设置全局快捷键。这样的话,在任何一个软件当中,按下「 option+esc」时,就会朗读选中的文本。

调整字体大小

Mac 调整字体大小:「系统偏好设置 -> 显示器 -> 缩放」。如下图:

如何分别设置 Mac 的鼠标和触控板的滚动方向

很多人习惯鼠标使用相反的滚动方向,而触控板类似 iPad 那样的自然滚动,问如何设置,当时我的回答是不知道,因为目前 OS X 的系统设置里,鼠标和触控板的设置是统一
的。今天发现了一个免费的软件 Scroll Reverser,可以实现鼠标和触控板的分别设置。下载地址:https://pilotmoon.com/scrollreverser/
启动后程序显示在顶部菜单栏,设置简单明了,有需要的用户体验一下吧。

Touch Bar 自定义

打开「系统偏好设置-键盘」,下面有个自定义控制条。

色温调节:夜间模式

iOS9.3 的最明显变化,莫过于苹果在发布会上特意提到的 Night Shift 夜间护眼模式。

iCloud 邮箱

如果您用于设置 iCloud 的 Apple ID 不以“@icloud.com”、“@me.com”或“@mac.com”结尾,您必须先设置一个“@icloud.com”电子邮件地址,然后才能使用 iCloud“邮件”。

如果您拥有以“@mac.com”或“@me.com”结尾的电子邮件地址,则您已经拥有了名称相同但以“@icloud.com”结尾的等效地址。如果您使用的电子邮件别名以“@mac.com”或“@me.com”结尾,您也将拥有以“@icloud.com”结尾的等效地址。

操作如下:

  • 在 iOS 设备上,前往“设置”>“iCloud”,开启“邮件”,然后按照屏幕上的说明操作。

  • 在 Mac 上,选取 Apple 菜单 >“系统偏好设置”,点按“iCloud”,再选择“邮件”,然后按照屏幕上的说明操作。

PS:创建 iCloud 电子邮件地址后,您无法对其进行更改。

设置 @icloud.com 电子邮件地址后即可用其登录 iCloud。您也可以用创建 iCloud 帐户时所用的 Apple ID 登录。

您可以从以下任意地址发送 iCloud 电子邮件:

您的 iCloud 电子邮件地址(您的帐号名称@icloud.com)

别名

参考链接:

直接注册以@icloud.com 结尾的 Apple ID:

参考链接:

PodCast

PodCast 中文翻译为播客,是一种特殊的音频 or 视频节目。PodCast 这个单词是由 iPod+Broadcast 这两个单词组成的。

PodCast 可以在 iTunes 中收听。

others

词典

系统有一个自带应用「词典」,可以进行单词的查询。

如何解决 MAC 软件(dmg,akp,app)出现程序已损坏的提示

「xxx.app 已损坏,打不开.你应该将它移到废纸篓」,并非你安装的软件已损坏,而是 Mac 系统的安全设置问题,因为这些应用都是破解或者汉化的,那么解决方法就是临时改变 Mac 系统安全设置。

出现这个问题的解决方法:修改系统配置:系统偏好设置… -> 安全性与隐私。修改为任何来源。

如果没有这个选项的话(macOS Sierra 10.12),打开终端,执行:

1
sudo spctl --master-disable

即可。

参考链接:

备注:这个链接里的各种资源都很不错啊。

终端

在 Finder 的当前目录打开终端

在 Finder 打开 terminal 终端这个功能其实是有的,但是系统默认没有打开。我们可以通过如下方法将其打开:

进入系统偏好设置->键盘->快捷键->服务。

在右边新建位于文件夹位置的终端窗口上打勾。

如此设置后,在 Finder 中右击某文件,在出现的菜单中找到服务,然后点击新建位于文件夹位置的终端窗口即可!

Mac 常用快捷键

Finder

快捷键 作用 备注
Shift + Command + G 前往指定路径的文件夹 包括隐藏文件夹
Shift + Command + . 显示隐藏文件、文件夹 再按一次,恢复隐藏
Command + ↑ 返回上一层
Command + ↓ 进入当前文件夹

编辑

删除文字

快捷键 作用 备注
delete 删除光标的前一个字符 相当于 Windows 键盘上的退格键
fn + delete 删除光标的后一个字符
option + delete 删除光标之前的一个单词 英文有效
command + delete 删除光标之前的整行内容 【荐】
command + delete 在 finder 中删掉该文件
shift + command + delete 清空回收站

剪切文件

首先选中文件,按 Command+C 复制文件;然后按「Command + Option + V」剪切文件。

备注:Command+X 只能剪切文字文本,不要混淆了。

Mac 用户必须知道的 15 组快捷键

参考链接:《轻松玩 Mac》第 6 期:Mac 用户必须知道的 15 组快捷键

「space」键:快速预览

选中文件后, 不需要启动任何应用程序,使用「space」空格键可进行快速预览,再次按下「space」空格键取消预览。

可以预览 mp3、视频、pdf 等文件。

我们还可以选中多张图片, 然后按「space」键,就可以同时对比预览多张图片。这一点,很赞。

改名

选中文件/文件夹后,按 enter 键,就可以改名了。

「command + I」键:查看文件属性

  • 选中文件后,按「command + I」键,可以查看文件的各种属性。

  • 选中文件夹后,按「command + I」键,可以查看文件夹的大小。【荐】

切换输入法

「control + space」

打开 spotlight 搜索框

spotlight 是系统自带的软件,搜索功能不是很强大。我们一般都会用第三方的 Alfred 软件。

编辑相关

Cmd+C、Cmd+V、Cmd+X、Cmd+A、Cmd+Z。

翻页和光标

  • 「control + ↑」:将光标定位到文章的最开头(翻页到文档的最上方)

  • 「control + ↓」:将光标定位到文章的最末尾(翻页到文档的最下方)

  • 「control + ←」:将光标定位到当前行的最左侧

  • 「control + →」:将光标定位到当前行的最右侧

「command + shift + Y」:将文字快速保存到便笺

选中你想要的内容(例如文字、链接等),然后按下 command + shift + Y」,那么你选中的内容就会快速保存到系统自带的「便笺」软件中。

如果你想临时性的保存一段内容,这个操作很实用。

程序相关

  • 「command + Q」:快速退出程序

  • 「command + tab」:切换程序

  • 「command + H」:隐藏当前应用程序。这是一个有趣的快捷键。

  • 「command + ,」:打开当前应用程序的「偏好设置」。

窗口相关

  • 「command + N」:新建一个当前应用程序的窗口

  • 「command + `」:在当前应用程序的不同窗口之间切换【很实用】

我们知道,「command + tab」是在不同的软件之间切换。但你不知道的是,「command + `」是在同一个软件的不同窗口之间切换。

  • 「command + M」:将当前窗口最小化

  • 「command + W」:关闭当前窗口

浏览器相关

  • 「command + T」:浏览器中,新建一个标签

  • 「command + W」:关闭当前标签

  • 「command + R」:强制刷新。
  • 「command + L」:定位到地址栏。【重要】

截图相关

  • 「command + shift + 3」:截全屏(对整个屏幕截图)。

声音相关

选中文字后,按住「ctrl + esc」键,会将文字进行朗读。(我发现,在触控条版的 mac 上,并没有生效)

Dock 栏相关

  • 「option + command + D」:隐藏 dock 栏

强制推出

强制退出的快捷键非常重要

  • 「option + command + esc」:打开强制退出的窗口

option 相关

强烈推荐

  • 「option + command + H」:隐藏除当前应用程序之外的其他应用程序

  • 在文本中,按住「option」键,配合鼠标的选中,可以进行块状文字选取。

  • 「option + command + W」:快速关闭当前应用程序的所有窗口。【很实用】

比如说,你一次性打开了很多文件的详情,然后就可以通过此快捷键,将这些窗口一次性关闭。

  • 「option + command + I」:查看多个文件的总的属性。
  • 打开 launchpad,按住「option」键,可以快速卸载应用程序。

  • 在 dock 栏,右键点击软件图标,同时按住「option」键,就可以强制退出该软件。【重要】

  • 在 Safari 浏览器中,按住「option + command + Q」退出 Safari。等下次进入 Safari 的时候,上次退出时的网址会自动被打开。【实用】

推荐一个软件:CheatSheet

打开 CheatSheet 后,长按 command 键,会弹出当前应用程序的所有快捷键。我们还可以对这些快捷键进行保存。

📚 学习资源

:door: 传送门

| 回首頁 |

Windows 常用技巧总结

软件

扩展阅读:

视频音频

  • Musicbee - 类似 iTunes,但比 iTunes 更好用。
  • ScreenToGif - 它允许你录制屏幕的一部分区域并保存为 gif 或视频。
  • PotPlayer - 多媒体播放器,具有广泛的编解码器集合,它还为用户提供大量配置选项。
  • 射手影音播放器 - 来自射手网,小巧开源,首创自动匹配字幕功能。

压缩

  • 7-Zip - 用于处理压缩包的开源 Windows 实用程序。完美支持 7z,ZIP,GZIP,BZIP2 和 TAR 的全部特性,其他格式也可解压缩。
  • WinRAR - 强大的归档管理器。 它可以备份您的数据并减小电子邮件附件的大小,解压缩 RAR,ZIP 和其他文件。

文件管理

  • Clover - 为资源管理器加上多标签功能。
  • Total Commander - 老牌、功能异常强大的文件管理增强软件。
  • Q-Dir - 轻量级的文件管理器,各种布局视图切换灵活,默认四个小窗口组成一个大窗口,操作快捷。软件虽小,粉丝忠诚。
  • WoX - 新一代文件定位工具,堪称 Windows 上的 Alfred。
  • Everything - 最快的文件/文件夹搜索工具, 通过名称搜索。
  • Listary - 非常优秀的 Windows 文件浏览和搜索增强工具。
  • Beyond Compare - 好用又万能的文件对比工具。
  • CCleaner - 如果你有系统洁癖,那一定要选择一款干净、良心、老牌的清洁软件。
  • chocolatey - 包管理器
  • Ninite - 最简单,最快速的更新或安装软件的方式。
  • Recuva - 来自 piriform 梨子公司产品,免费的数据恢复工具。
  • Launchy:自由的跨平台工具,帮助你忘记开始菜单、桌面图标甚至文件管理器。

开发

  • Fiddler - web 调试代理工具。
  • Postman - 适合 API 开发的完整工具链,最常用的 REST 客户端。
  • SourceTree - 一个免费的 Git & Mercurial 客户端。
  • TortoiseSVN - Subversion(SVN)的图形客户端
  • Wireshark - 一个网络协议分析工具。
  • Switchhosts
  • Cmder
  • Babun - 基于 Cygwin,用于替代 Windows shell。

编辑器

  • JetBrain IDE 系列 - 真香!
  • Visual Studio Code - 用于构建和调试现代 Web 和云应用程序。
  • Eclipse - 一款功能强大的 IDE。
  • Visual Studio - 微软官方的 IDE,通过插件可支持大量编程语言。
  • NetBeans IDE - 免费开源的 IDE。
  • Typora - 个人觉得最好用的 Markdown 编辑器。
  • Cmd Markdown - 跨平台优秀 Markdown 编辑器,本文即用其所写。
  • Notepad++ - 一款支持多种编程语言的源码编辑器。
  • Notepad2 - 用于替代默认文本编辑器的轻量快速的编辑器,拥有众多有用的功能。
  • Sublime Text 3 - 高级文本编辑器。
  • Atom - 面向 21 世纪的极客文本编辑器。

文档

  • Microsoft Office - 微软办公软件。
  • WPS Office - 金山免费办公软件。
  • Calibre - 用于电子书管理和转换的强大软件。
  • 福昕阅读器 - 在全球拥有大量用户,最优秀的国产软件之一。Ribbon 界面,支持手写签名、插入印章等。

效率提升

【笔记】

  • XMind - 优秀的思维导图。
  • OneNote - Windows 下综合评价非常高的笔记应用。
  • 印象笔记 - 老牌跨平台笔记工具,国际版 Evernote。一家立志于做百年公司的企业,安全、可靠。
  • 为知笔记 - 越来越好的笔记应用,记录、查阅一切有价值的信息,同样跨平台支持。
  • 有道云笔记 - 网易旗下笔记工具,同样跨主流平台支持,文字、手写、录音、拍照多种记录方式,支持任意附件格式。
  • ShareX - 你要的所有与截图、录屏相关的功能,这里都有了。

【快捷键】

  • AutoHotkey - Windows 平台的终极自动化脚本语言。

技巧:

办公

  • 有道词典 - 最好用的免费全能翻译软件。
  • Outlook - 大名鼎鼎的 Microsoft Office 组件之一,除了电子邮件,还包含了日历、任务管理、联系人、记事本等功能。
  • Gmail - 功能上可以称为业界标杆,用户数量世界第一,或许你真的找不到比它更好的邮件系统。
  • Chrome - 最好的浏览器。
  • Teamviewer - 专业、功能强大的远程控制软件。使用简单,对个人用户免费。

个性化

  • TranslucentTB - 透明化你的 Windows 任务栏。
  • QTTabBar - 通过多标签和额外的文件夹视图扩展资源管理器的功能。
  • Fences - 管理桌面快捷方式。

参考资料