Leon Ding Blog - 计算机网络
type: channel
link: https://blog.leonding.me/category/network.html
description: 收录关于计算机网络文章
items: 密码学的应用之 TLS 协议
items: 开发基于网络程序该考虑什么？
items: 浅谈 B/S 架构通信技术
items: 网络配置好帮手 DHCP 协议
items: 万维网的基础设施 DNS 服务
items: Linux 中的网络配置
items: 应用层 Nginx 反向代理
items: 网络层 UDP 传输协议
items: 面向连接的 TCP 协议
items: 互联网基础架构

密码学的应用之 TLS 协议
type: item
date: 2024-07-26T19:14:00+08:00
description: 在现代社会网络通信的隐私和安全性已成为人们日益关注的重要话题，无论是浏览购物网站、在线银行交易，还是日常的社交媒体互动，我们的个人信息都面临着潜在的风险和威胁。在这篇文章中，将探讨在浏览购物网站时，如何保护我们的隐私和确保信息安全，是谁在保护我们的数据隐私和通信的安全性。在谈论网络通信的安全性之前，让我们回顾一下人类在通信保密性的发展史。通信的保密性自古以来就是一个重要的问题，人类不断发展新的方法来保护信息的隐私和安全，最早的加密技术可以追溯到古代文明，古希腊和罗马使用了各种简单的加密方法，如凯撒密码（Caesar Cipher），其中每个字母被替换为其后固定位置的字母。凯撒密码也称为移位密码（Shift Cipher），是以古罗马将军 Julius Caesar 的名字命名的，据说凯撒在军事通信中使用这种密码来加密敏感信息。在战争期间使用这种加密方法来保护军事命令和机密信息，确保即使信息被截获，敌人也无法轻易破译，凯撒通常使用 N <= 25 位移位（即每个字母向后移 N <= 25 个位置）来加密消息。当消息被敌军获取了，敌军在不知道消息加密的方式情况下，只能得到一堆胡乱排列的字母。凯撒密码的数学公式为如下：凯撒密码的核心原理是通信的双方有一个固定字母顺序表，以这个固定顺序的字母表作为消息加密的基础，通过将原本的消息进行移动位置的方式进行加密。凯撒密码易于破译，尤其是使用频率分析法，通过统计文本中各个字母出现的频率，可以很容易地推测出移位量并解密消息。比如，在加密文本中可以通过寻找加密文本中最常出现的字母来推断移位量，当找到这个字母偏移量就很容易破解出来密文信息了。[scode type="blue"]下面是通过 Java 自定义码表实现凯撒密码加密和解密逻辑：[/scode]public class CaesarCipher { private static final char[] ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray(); public static void main(String[] args) { String text = "HELLO"; int shift = 3; String encrypted = encrypt(text, shift); String decrypted = decrypt(encrypted, shift); System.out.println("Original: " + text); System.out.println("Encrypted: " + encrypted); System.out.println("Decrypted: " + decrypted); } // 加密函数 public static String encrypt(String text, int shift) { StringBuilder result = new StringBuilder(); for (int i = 0; i < text.length(); i++) { char ch = text.charAt(i); if (Character.isUpperCase(ch)) { // 拿到对应字母的下标 int originalPosition = findPosition(ch); // 找到偏移量之后字母下标，A 至 Z 之间循环 int newPosition = (originalPosition + shift) % ALPHABET.length; result.append(ALPHABET[newPosition]); } else { result.append(ch); // 非字母字符不变 } } return result.toString(); } // 解密函数 public static String decrypt(String text, int shift) { StringBuilder result = new StringBuilder(); for (int i = 0; i < text.length(); i++) { char ch = text.charAt(i); if (Character.isUpperCase(ch)) { int originalPosition = findPosition(ch); int newPosition = (originalPosition - shift + ALPHABET.length) % ALPHABET.length; result.append(ALPHABET[newPosition]); } e…

开发基于网络程序该考虑什么？
type: item
date: 2023-11-29T02:06:00+08:00
description: 开发基于网络的程序时，有许多因素需要考虑，以确保你的应用程序是高效、安全、可伸缩和用户友好的。但是今天这篇文章更加关注的是 OSI 模型中的应用层协议和运输层的协议，基于这些层的程序开发更加关注什么？如果作为一名应用开发者我们最多接触到的网络层面上的应用协议和运输协议；应用的概念更加面向用户，强调的是提供某种服务或功能，可以是桌面应用、移动应用、Web 应用等，这里围绕的是应用开发如何对网络协议选型，因为应用开发是在操作系统用户态上的开发，对于内核的可编程操作是不允许的，所以本篇文章更加关注的是基于 TCP/UDP 之上的协议选型时要考虑的问题。TCP 和 UDPTCP 和 UDP 都是运输层提供两套协议，提供系统内核的 API 可以使用它进行运输数据包达到另外一台主机上，市面上很多的远程调用框架例如 gRPC 和 Thrift 在底层运输数据包都是采用的内核提供的 API 进行发包的。这些 RPC 框架在应用层之上提供了一种结构化的、高效的远程调用机制，使开发者能够更轻松地构建分布式系统。虽然它们通常在应用层协议的基础上构建，但它们自身更类似于框架或库，提供了更高级别的抽象，用于处理远程服务调用的复杂性。gRPC 使用 Protocol Buffers（ProtoBuf）作为接口定义语言（IDL），这允许开发者定义服务接口、消息格式等，而不用关心底层通信细节。这里围绕的 gRPC 来讨论这个问题，了解 gRPC 协议都知道该协议是基于 HTTP/2 协议，利用了 HTTP/2 的多路复用、头部压缩、二进制帧提供了更高效的网络传输，相比 HTTP/1.1 使用多个 TCP 连接，每个连接只能传输一个请求和响应，这可能导致 TCP 连接的浪费和性能瓶颈，而 HTTP/2 引入了多路复用的特性，允许多个请求和响应在同一 TCP 连接上并行传输，这样也减少了 TCP 连接的数量提高了性能。[scode type="yellow"]通过这么一解释就很容易明白 gRPC 为什么要使用 HTTP/2 协议作为基础的应用数据传输协议了，HTTP/2 协议属于是应用层的协议，它依赖运输层协议是 TCP 协议，确实符合 gRPC 协议的应用场景，针对在分布式系统上对数据的可靠性和高效的数据传输要求。也从侧面角度反映出了为什么 Spring Cloud 没有直接使用 gRPC 这种协议进行数据通信，而是直接使用 HTTP 协议，随着 HTTP 协议版本改进采用更高效的二进制数据传输，性能和 gRPC 也不相上下。Spring Cloud 并没有直接使用 HTTP/2.0 进行通信，而是建立在 HTTP 协议之上。默认情况下 Spring Cloud 使用 HTTP/1.1 作为通信协议，但是可以通过一些配置和定制来启用 HTTP/2.0 ，相比 gRPC 特殊的数据传输格式，HTTP/2.0 反而没有那么多数据格式要求可以自定义是 JSON 还是 XML 这种，最终都是会被编码为二进制数据帧。[/scode]对于需要可靠型网络数据传输的场景，使用 TCP 是一个最佳的选择，但是也并不意味着盲目的去使用它传输数据。 TCP 传输数据之前每次都是需要进行 3 次握手，这 3 个握手数据包是主要的耗时来源，延迟就此产生了，如果在一次性很短暂数据运输需求下，这就显得不是那么适用了，快速打开一个连接使用完成之后快速释放掉，很多应用层的网络程序都是跑在 TCP 协议之上，必须经过这个慢启动的过程。HTTP/1.0 版本主要就是针对此种突发性连接的场景，获取到某个 HTML 内容立马断开 TCP 连接，完全没有利用好 TCP 协议，每次发送一个 HTTP 请求都需要经过一次 TCP 慢启动过程。

浅谈 B/S 架构通信技术
type: item
date: 2023-10-03T00:05:00+08:00
description: 众所周知计算机软件的架构目前最为常见的是 B/S 和 C/S 架构，B/S 和 C/S 架构的软件都采用了分层结构，将系统划分为不同的模块层次，每个模块层负责相应功能，这种架构便于管理和维护，同时提高了系统的可扩展性和灵活性。笔者感觉最主要的特点是在使用软件时都会产生数据，而这些数据如果存储在本地时很不安全的，并且用户产生的数据才是开发对应软件公司想用的东西，数据才是一个软件科技公司的财产。两种架构都将用户界面和数据处理分离，有助于系统的灵活性和维护性，用户界面只需要负责展示信息，而数据处理由服务器端或客户端中的逻辑处理模块完成；无论是 B/S 还是 C/S 架构，都涉及客户端和服务器之间的通信，客户端向服务器发送请求，并接收服务器的响应，这种通信机制实现了应用程序的交互和数据交换，这篇博文将探讨一些在 B/S 架构下的网络通信协议技术。Web 浏览器和客户端[scode type="yellow"]笔者将其 B/S 架构归纳为 C/S 架构中，其 C/S 架构的中的 C （client）一般是指的安装在用户电脑上的软件，那么其浏览器也是归于客户端软件的，浏览器本体也是一款软件，只不过它可能比其他客户端的软件实现了多种的应用层的网络通信协议。B/S 架构中，客户端通常是 Web 浏览器，用户通过浏览器访问应用程序，这种架构具有跨平台、易部署和易维护的优势。B/S 和 C/S 架构都可以支持多个用户同时访问系统，多用户的需求可以通过在服务器端处理实现，架构图：[/scode]当浏览器发生数据请求就会采用 HTTP 协议和应用服务器交换数据，而应用服务器和数据库服务器交互则采用传输层的 TCP 协议。HTTP ProtocolHTTP 协议是 HyperText Transfer Protocol 的缩写 (即超文本传输协议），是由 w3c（万维网联盟）制定的一种应用层协议，用来定义浏览器与 Web 服务器之间如何通信以及通信的数据格式。因为 B/S 架构中的通信模块就是以 HTTP 这个协议作为标准协议的，所以对该协议有所了解可以更好的编写程序。 HTTP 协议的发展历史悠久，已经不断的迭代多个版本，不同时期的 HTTP 版本特性，整理表格：时间段HTTP版本主要特点1989-1995HTTP/0.9- 最初版本，仅支持 GET 请求。- 无请求头或状态码，只有响应主体。- 用于传输 HTML 文件。1996-1999HTTP/1.0- 引入多种 HTTP 方法（GET、POST、HEAD 等）。- 引入状态码、请求头、响应头等概念。- 服务器在每次请求后关闭连接。1999-2015HTTP/1.1- 引入持久连接，减少连接建立的开销。- 引入管道化（Pipelining），实现多请求并发。- 引入 Host 头字段，允许多个域名共享 IP 地址。- 引入分块传输编码和压缩，提高效率。2015-至今HTTP/2.0- 完全重新设计，旨在提高性能和效率。- 改进多路复用，支持并行请求和响应。- 引入头部压缩，减少数据传输大小。- 允许服务器推送资源，提高效率。- 强制使用加密（TLS），提高安全性。2020-至今HTTP/3.0- 基于 QUIC 协议，进一步提高性能和安全性。- 改进连接建立速度和稳定性，减少握手延迟。- 实现数据包级别的错误纠正和拥塞控制。- 采用基于 UDP 的传输协议。[scode type="yellow"]HTTP 协议一次请求对应一次连接，当浏览器再次发请求给服务器时，Web 服务器并不知道这就是上次发请求的客户端，这也是 HTTP 协议的一个特点：无状态协议。这种需要时建立连接，使用结束后立即断开连接的方式使得 Web 服务器可以利用有限的连接为尽可能多的客户提供服务，并且能够处理分散的网络请求，处理来自不同地区浏览器请求，并且服务器也可以多台分散在不同地区的，正因为是一种应用层协议还可以使用多层代理架构，例如使用 Nginx 做代理网关，正是具备了这样的特点，才使得 B/S 架构能够承载企业级应用的大量访问。[/scode]如果要测试 HTTP 协议的一些特性这里推荐使用 telnet 命令行工具，可以在命令行进行 HTTP 数据包封装，Telnet 使用了 TCP/IP 协议进行通讯，Telnet 协议默认是 23 端口。它允许用户通过网络连接到远程主机，并在远程系统上执行命令，就像在本地终端上输入命令一样。完全可以使用 telent 命令行工具，来模拟整个 HTTP 协议连接建立的过程，HTTP 请求和响应的过程如下：[scode type="green"]浏览器根据 IP 地址和端口号与服务器建立连接向 Web 服务器发送请求数据包Web 服务器接收请求数据包后，发送相应的响应数据包浏览器接…

网络配置好帮手 DHCP 协议
type: item
date: 2023-03-28T14:47:00+08:00
description: 前面的技术博文解释过通过 nmcil 来配置网络参数，而这篇文章要介绍的是 DHCP 协议程序，每当我们电脑接入网络时都会自动分配 IP 和 DNS 、子网掩码信息，并没有自己来配置网络连接信息，而是 IP 自动分配，能做到这一点就得益于 DHCP 协议，能帮助我们的设备自动配置网络信息。[scode type="blue"]现在建设你作为学校机房的管理员或者是网吧的管理员，每次都有不同的网络设备要接入到就局域网中，这就会带来大量配置网络信息工作，而且每次上完课部分设备又离开了教室，分配出去的 IP 如果不能回收，会导致 IP 地址被占用，不能被其他人再次使用，导致 IP 不够用浪费 IP 情况，也会带来手动管理 IP 麻烦，DHCP 要解决的问题就是针对这些场景的，自动化配置和自动化管理接入设备的 IP 地址。[/scode]DHCP 协议目前大部分网络设备和操作系统都默认支持 DHCP 协议，如果系统没有支持可以通过软件包的方式安装 DHCP 软件来支持 DHCP 协议，DHCP 分为两个部分一个服务器另外一个是客户端，服务器为提供网络接入服务的设备，而客户端则是要接入网络的设备。[scode type="yellow"]配置 DHCP 服务器：首先，您需要在网络上设置一个 DHCP 服务器，并为 DHCP 服务器分配 IP 地址和其他必要的网络参数，您可以使用现有的服务器，如路由器或专用 DHC P服务器，也可以使用开源 DHCP 服务器软件，如 ISC DHCP 或 dnsmasq ，在 Linux 下安装 dhcp 服务器可以使用下面命令：[/scode]# 安装 dhcp 服务器 dnf install -y dhcp-server 配置文件位如 /etc/dhcp/dhcpd.conf 文件中，DHCP 选项可以用来设置其他网络参数，如 DNS 服务器地址、NTP 服务器地址和 SMTP 服务器地址等，可以在 DHCP 服务器上配置这些选项，并在 DHCP 客户端上使用它们，有客户端接入到网络中 DHCP 会按照这些参数来配置自己的网络参数，官方提供参数参考文件，目录位于 /usr/share/doc/dhcp-server/ ，目前支持的网络参数列表：配置项配置值option domain-nameexample.comoption domain-name-serversns1.example.com, ns2.example.comsubnet192.168.1.0netmask255.255.255.0range192.168.1.100 - 192.168.1.200option routers192.168.1.1option subnet-mask255.255.255.0option broadcast-address192.168.1.255default-lease-time600max-lease-time7200hostclient1hardware ethernet00:11:22:33:44:55fixed-address192.168.1.10class"phone"matchsubstring(hardware, 1, 3) = 00:11:22option domain-name-serversns3.example.comshared-network"office"subnet192.168.2.0netmask255.255.255.0range192.168.2.100 - 192.168.2.200option routers192.168.2[scode type="yellow"]最常用参数也就那么几个，下面整理参数对应的作用说明：[/scode]配置参数说明option domain-name指定 DHCP 服务器分配的主机名所属的域名。option domain-name-servers指定 DHCP 客户端应该使用的 DNS 服务器列表。subnet定义 DHCP 服务器分配 IP 地址的子网。netmask定义 DHCP 子网的子网掩码。range定义 DHCP 服务器可以分配的 IP 地址范围。option routers指定 DHCP 客户端应该使用的网关地址。option subnet-mask指定 DHCP 客户端应该使用的子网掩码。option broadcast-address指定 DHCP 客户端应该使用的广播地址。default-lease-time定义 DHCP 服务器分配的 IP 地址的默认租约时间（以秒为单位）。max-lease-time定义 DHCP 服务器分配的 IP 地址的最大租约时间（以秒为单位）。host指定 DHCP 客户端的…

万维网的基础设施 DNS 服务
type: item
date: 2023-03-25T19:29:00+08:00
description: 有互联网才有很多网络技术应用，让不同设备接入到网络从而达到互联网目的，就和现实世界中物流系统一样，互联网的前身美苏冷战时期的 ARPANET 最初在 1980 年代作为区域学术和军事网路连接的骨干网络，最后苏联解体了结束了冷战，最后这些已经曾在的网络基础设施，逐渐开始转向为民用网络系统了。[scode type="blue"]这篇文章要讲解的是 World Wide Web 这是存在于因特网之上的互联网应用服务，我日常见过很多人和同行认为万维网就是互联网，这是一个错误的认知，他们是有着本质上的区别的，万维网更多是指我们能通过浏览器或者支持通过 HTTP 协议能访问到的网络资源，例如文档、图片、视频、存在其他计算机所提供的资源集合并且通过网络进行开放访问。日常生活中使用的最多是浏览器访问 www 网站服务，而目前程序员做的事情通过不同编程语言和编程技术实现能动态服务的网站。[/scode]DNS 服务器每当我们访问一个已知的网址都是在浏览器的地址栏中输入一串字符串，这个字符串就时域名，而域名是 IP 地址的一串别名，浏览器底层发送一个网络请求时数据包时提供 TCP 协议栈发送出去的，我们也可以通过 IP 地址进行访问万维网服务，但是很少有人这么做，因为 IP 地址时一串由 4 个字节组成的 32 Bit 位数字串，往往一般人很难记住。这和日常生活中的电话号码一样，我们很少记住别人的电话号码的数字，而是通过手机的通讯录保存一个联系人名字，拨打电话时提供联系人姓名来打电话呼叫别人。[scode type="yellow"]同理在计算机中也是这样设计的只不过名称叫 DNS 服务，通过把目标 IP 地址绑定到一串特定便于记忆的字符串域名上，我们通过域名来服务网站，这比通过记住一串数字要容易的多，DNS 服务就是便于使用者查询对应域名所绑定的 IP 信息的，从而把组装数据包通过 TCP 协议栈发送出去。[/scode]DNS 服务是由全球 13 组根服务器所提供的，10 台在美国，另外 3 台分别在欧洲的挪威、伦敦和东亚的日本，就这 13 组根服务器为我们提供了 DNS 服务，不过目前世界上有很多 DNS 从服务器和缓存服务器方便我们快速查找和及时响应查询请求所设置，缓存服务器大部分是缓存已经查询过的域名信息，目录前世界上流行的公共 DNS 服务器 IP 地址有下列表：IP 地址供应商8.8.8.8Google Public DNS1.1.1.1Cloudflare Public DNS[scode type="blue"]DNS 服务器会根据客户的请求的内容，返回对于的信息，这些信息被注册到 DNS 服务器至上，分为不同类型的 DNS 信息，DNS 在设计的时候就考虑到了不是单单为网站域名服务，还有一些其他的类型服务，例如邮箱服务器地址查询，也是由 DNS 服务器负责的，在 DNS 服务器信息有一个 Class 字段，这个字段就是用来区分不同网络服务类型的，目前大部分类型为 IN，一个简单例子如下：[/scode]NameClassTypeDatawww.ibyte.meINA66.888.88.8ibyte.meINMXmxbiz1.qq.com.imgINAAAA2001:4860:4860::8888blogINCNAMEwww.ibyte.meptrINPTR192.168.0.1sevINSEV127.0.0.1整个 DNS 服务可以看作为一个交通指挥中心，存储着互联网上的交通路由表。Linux 的 DNS 服务在 Linux 中默认的 DNS 相关的配置有很多文件来制定，/etc/resolv.conf 为 DNS 解析服务器的配置文件，这样每当我们查询域名信息时，会从配置文件中找到 DNS 服务器的 IP 发送 DNS 查询请求，/etc/hosts.conf 为本机自定义 DNS 域名绑定映射文件，而另外一个至关重要的是 /etc/nsswitch.conf 文件，可以设置每次查询 DNS 服务的步骤。[scode type="yellow"]在 Linux 中如果默认使用 wget 命令和 curl 命令完全根据本地 DNS 配置方案进行查询步骤的，而 Linux 内置的 host 和 dig 命令是不会按照 hosts.conf 文件和 nsswitch.conf 的规则的，而是按照 resolv.conf 文件配置的远程 DNS 根服务器进行的查询。[/scode][root@cs9 ~]# dig www.ibyte.me ; <<>> DiG 9.16.23-RH <<>> www.ibyte.me ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- o…

Linux 中的网络配置
type: item
date: 2023-03-14T23:55:00+08:00
description: 本篇博客将记录一下 Linux 系统下网络配置，会对 Linux 网络配置和基于 Linux 网络的负载均衡的配置介绍，如何在 Linux 系统下配置网络设置是一个极客程序员必须掌握的，如何配置 sshd 服务程序的知识和免密登录、创建虚拟网卡提高系统可靠性。Network ManagerNetworkManager 软件工具的目标是降低在 Linux 与其他类 Unix 操作系统上的计算机网络使用难度，RedHat 在 2004 年发起了 NetworkManager 项目，其目标是让 Linux 用户能够更容易的处理现代的网络需求，特别是无线网络。# 安装 NetWorkManager 软件包 dnf install NetworkManager -y # 查看网卡信息 ifconfig # 查看网卡状态 mii-tools ens160 # 查看网卡详细状态信息 ethtool ens160 # 给某块网卡启一个别名 ip addr 192.168.31.200/24 dev eth0 label eth0:1 # 命令行图像配置 nmtui比较老的版本可以在 /etc/sysconfig/network-scripts/ 目录中，编写对应的网卡脚本文件，Linux 会根据文件内容来设置对应的网卡信息，一个简单模版：# vim ifcfg-ens160 固定前缀 ifcfg- 后面为网卡名称 TYPE=Ethernet # 网络类型 BOOTPROTO=static # 静态分配 NAME=eno16777736 # 网卡名称 ONBOOT=yes # 是否自动启用该网络接口 IPADDR=192.168.10.10 # 分配的 IP NETMASK=255.255.255.0 # 子网掩码 GATEWAY=192.168.10.1 # 网关地址 DNS1=8.8.8.8 # DNS 地址 # 重启网络模块 systemctl restart network以上为老版本系统所使用的方式，不再推荐使用！ RHEL9 和 CentOS 9 Stream 默认使用了 NetworkManager 来管理网络，因此 systemctl restart network 命令已经不再被使用了，目前可以使用 nmcli 命令来管理网络连接，以下是一些常用的 nmcli 命令：nmcli connection show： # 显示所有的网络连接。 nmcli connection up # [连接名称]：启用某个网络连接。 nmcli connection down # [连接名称]：禁用某个网络连接。 nmcli device status # 显示所有网络设备的状态。 nmcli device wifi list # 列出所有可用的 Wi-Fi 热点。 nmcli connection add help # 列出所有适用于 add 的参数信息如果您需要修改网络连接的配置，可以使用以下命令：nmcli connection modify [连接名称] [选项] [值]：修改连接的配置，例如 IP 地址、网关、DNS 等。注意对于任何更改都要谨慎，以免影响系统的网络连接，最可怕是禁止使用网卡导致远程 SSH 连接断开。以下是一些常用的 nmcli connection modify 命令选项：参数名称参数作用ipv4.method设置 IPv4 的获取方式，可选值为 auto、manual、dhcp 或 shared。ipv4.addresses设置 IPv4 地址，格式为 IP 地址/掩码，多个地址之间用逗号分隔。ipv4.gateway设置 IPv4 网关地址。ipv4.dns设置 IPv4 DNS 服务器地址，多个地址之间用逗号分隔。ipv6.method设置 IPv6 的获取方式，可选值为 auto、manual 或 ignore。ipv6.addresses设置 IPv6 地址，格式为 IP 地址/前缀长度，多个地址之间用逗号分隔。ipv6.gateway设置 IPv6 网关地址。ipv6.dns设置 IPv6 DNS 服务器地址，多个地址之间用逗号分隔。例如要修改名为 eth0 的有线网络连接的 IPv4 地址为 192.168.1.2/24、网关为 192.168.1.1，DNS 服务器为 8.8.8.8 和 8.8.4.4，可以执行以下命令：nmcli connection modify eth0 ipv4.addresses 192.168.1.2/24 ipv4.gateway 192.168.1.1 ipv4.dns "8.8.8.8,8.8.4.4"nmctl 不仅可以配置网络参数，还可以基于现有多网卡设备创建新…

应用层 Nginx 反向代理
type: item
date: 2023-01-04T14:55:00+08:00
description: 在传统单体项目中，一个项目的整体都部署在一台服务器之上，组成这个系统的模块可能包括了 Java 应用程序和 Oracle 数据库 ，可能一些项目会加快系统处理请求的性能还会引入缓存模块，在项目不停迭代的过程中可能会出现分布式架构，将数据库和应用程序模块分别部署到不同几台服务器上，这样单台机器的性能就会得到提升。应用程序也可能会分拆成为多个模块，部署到多台服务器之上，这时面临一个问题就是如何将外部的请求分发到不同模块服务器之上，这时就需要一种反向代理服务器将请求分发到不同应用服务器之上。 Nginx 就是这样一种能够具备反向代理负载均衡功能软件，它不仅可以作为 Web 服务器来使用，还能作为网关二次开发功能，也能作为静态资源的服务器并且提供一些静态文件缓存功能。负载均衡至于怎么安装 Nginx 不是本篇文章的重点，安装可以查看官方的文档 官方 Red Hat/CentOS 软件包，能做负载均衡的功能有很多种方式例如云计算厂商的 DNS 负载均衡服务，我经常使用的是 Ngnix 的负载均衡服务可以配置权重，权重越重的服务器处理的请求会相对比较多，默认是轮询的方式处理。首先先使用 server 关键字定义虚拟服务器，然后指定 listen 关键字需要监听的流量端口。接着使用 location 块匹配客户端请求的 URL，再用 proxy_set_header 关键字指定 Host 的 HTTP 请求头，最后用 proxy_pass 关键字将请求转发到 upstream 组，upstream 块定义了 NGINX 用来均衡流量的服务器，一个简单配置模板如下：http { upstream my_upstream { server tomcat1.example.com; server tomcat2.example.com; } server { listen 80; location / { proxy_set_header Host $host; proxy_pass http://my_upstream; } } } NGINX 还可以针对 TCP 应用程序（如 MySQL）和 UDP 应用程序，如 DNS 和 RADIUS 进行负载均衡，对于 TCP 应用程序，配置模板：stream { upstream my_upstream { server server1.example.com:1234; server server2.example.com:2345; } server { listen 1123 [udp]; proxy_pass my_upstream; } }目前 Nginx 支持几种负载均衡策略，为 HTTP、TCP 和 UDP 提供多种负载均衡方式，所有这些方式都能够选择分配到每个上游服务器的流量的权重：Hash： 根据特定的键值分发请求如客户端 IP 地址或请求 URL 上。最少连接： 向活跃连接数最少的服务器转发请求。最少时间： 基于响应时间和活跃连接数进行综合计算，将请求转发到负载最小的服务器。IP Hash： 根据客户端 IP 地址的前三个八位字节进行请求分配。Round Robin 轮询： 默认使用可按顺序在上游服务器之间分发请求。Random with Two Choices： 随机选择两台服务器并将请求转发到活动连接数较少的服务器。默认 Nginx 常用也就是加权重版本的负载均衡，默认有还有一些权重 Tag 的策略，配置如下：upstream tomcat_group { server 192.168.1.16:8080 down; server 192.168.1.18:8080 weight=2; server 192.168.1.13:8080; server 192.168.1.12:8080 backup; }down: 表示当前的 Web Server 暂时不参与负载。weight: 默认为1 Weight 越大，负载的权重就越大。backup: 其它所有的非 Backup Server Down 或者忙的时候，请求 Backup 机器，所以这台机器压力会最轻。静态缓存在计算机中有很多缓存的设计典型就是 CPU 和 硬盘之间的缓存设计，而对应业务开发人员来说大部分使用都是一些缓存中间件来提高系统性能，这里的缓存最大作用将已经计算过的对象数据通过缓存存储起来，下次有类似的需求的时候直接从缓存中返回而不是从数据库中读取，这样设计为通读缓存能降低数据源的计算压力。这里要介绍的是 Nginx 作为静态文件服务器时，可以做的静态文件缓存功能，因为很多静态文件是不变的一次写入很少修改了，所有如果有缓存功能支持，每次处理请求时就从缓存中返回，这种架构如下：每当浏览器访问 CSS 、HTML 、J…

网络层 UDP 传输协议
type: item
date: 2022-08-29T15:58:00+08:00
description: 本文要介绍的是UDP传输协议，相比前面一篇Blog介绍的TCP协议来说要简单的多。UDP不需要建立连接也不需要考虑对方是否收到数据包，也不用考虑丢包重传机制，所以对于UDP的设计要解决的问题来说要简单的多了，UDP更关注的是把用户的数据发送出去就即可完成任务。UDP适用于不需要或在程序中执行错误检查和纠正的应用，它避免了协议栈中此类处理的开销。对时间有较高要求的应用程序通常使用UDP，因为丢弃数据包比等待或重传导致延迟更可取。UDP短数据UDP协议更关注的是用户的数据和发送用户的数据达到互联网上，剩下的步骤就交给物理的网络链路设备了，至于对方能不能收到此数据包UDP协议是不用关心的；但程序员自己可以参考类似于TCP那样的协议在设置超时机制来判断对方是否收到，或者说通过对方回传UDP数据包的方式来保障，那这种UDP通信方式把数据包的传输可靠性交给了用户来控制。udp协议的包头部分相比tcp的包头字段要少得多了，发送端口、接收端口、数据长度、数据包完整性校验和组成的一个数据包，udp只需要关注的是一次性传输的数据。比如DNS的域名查询请求，用户态的程序只需要把数据放入缓冲区然后使用系统调用接口即可发送出去数据包。UDP设计原则第一发送数据之前不需要建立连接，传输数据因为每次适用于小数据包场景也不用考虑丢失重传机制，即使如果真的要重新传输用户态程序可以自定义重传规则，因为没有通信连接状态机所以断开连接也不需要进行复杂的状态机同步断开机制。udp协议可以发送的数据最大长度为IP包的最大长度减去IP包头和自己本身的UDP包头的长度，这里的长度和MTU、MSS不是一个层面的东西，MTU和MSS是基于以太网和通信链路上网络包的最大长度来计算的。从IP协议来看包最大长度为65535，这里减去前面所有包头部分剩下65507字节，当然这么长的长度肯定是超过了MTU允许的范围，所以大数据包传输的时候还是依赖于IP模块拆分包的，所以建议使用UDP协议传输数据的时候使用数据量不多的时候。udp协议常用场景就是直播视频和实时语音通话了，因为追求的是实时性不需要考虑丢包重新传输情况，所以udp非常适合；如果像tcp协议去做的话，数据包丢失了还要考虑重传，可能用户程序会出现卡顿重新加载情况，重新发送数据也会消耗时间，重新发送数据也没有用因为实时性很强的程序是追求的是实时性而不是消息可靠性。此外我们日常使用微信打视频或者语音的时候因为网络情况不好也会出现卡顿情况，这对用户来说是网络问题，而不是实时性问题，用户没有听到也可以要求对方人为重复一遍，哈哈哈哈。小 结由于UDP缺乏可靠性且属于无连接协议，所以应用程序通常必须容许一些丢失、错误或重复的数据包，某些应用程序如TFTP可能会根据需要在应用程序层中添加基本的可靠性机制，具体怎么运用UDP这得看开发者自己的需求了，如果开发者足够了解这些协议应该会做出明智的选择。其他链接TCP vs. UDPUDP in Depth用户数据报协议最大传输单元MTU网络知识十全大补丸

面向连接的 TCP 协议
type: item
date: 2022-08-23T12:01:00+08:00
description: 在计算机网络中的传输层TCP/UDP协议，都是操作系统网络协议栈提供好的接口供开发者使用，但是大家都会听一些有经验的程序员说TCP协议比UDP协议可靠，这是为什么呢？都说TCP协议提供可靠传送，面向连接性的，基于字节流的，数据包不丢包这是怎么做到的？本文将讲解一些关于TCP协议内部实现一些细节。计算机能实现网络通讯全部依靠着是互联网，互联网是有多个广域网组成的，通过世界各地网络运营商组成的通讯网络。但是两个计算机依靠着这些网络上的硬件设备进行通讯，这些硬件设备都不能保证网络数据能正常传到对方计算机，这是做不到的。网络环境是一个很复杂的环境，可能两台通讯的计算机一台东半球，另外一台在西半球，而网络数据包则需要通过遍布在地球表面上的物理网络设备来传输（当然这里也可以通过卫星上网，例如STARLINK，当然在某些所在的地区不提供服务...），路由器、集线器、网络运营商的网络传输节点都不能百分之百保证网络环境是正常的，所以在传输层上设计TCP协议，能解决这些问题。连接的状态对应开发者而言我们只需要使用各种编程语言提供好的Socket接口传入目标IP和端口即可得到相应的网络描述符，这是作为一个开发者而说只需要使用API即可完成数据收发工作，但是具体协议内部是如何工作的呢？这里我要剖析TCP协议工作原理，在TCP协议中通讯时分为3部分，不要看就3个状态而已，内部实现其实挺复杂：建立连接数据传送连接关闭相信很多开发者都听说过TCP的3次握手🤝和4次挥手👋🏻这些概念，但是大家有没有想过为什么要这么设计呢？而且这两个概念在TCP协议那个环节做的呢？为什么要这样做？通常建立连接通讯的时候，相应的计算机会在某进程中监听着某个端口，以便有其他客户端发送连接的请求，当有请求过来的时候会触发TCP建立连接的规则，这里的规则就是三次握手。在说连接建立之前的得先说明一下每个TCP数据包都要包含的TCP数据包头，TCP包头尺寸除非存在选项，否则其正常大小为20字节，如下图：我整理一个表格分别记录其对应的作用或者用途如下：字段名称作用说明源端口用于记录数据包发送者的端口目的端口用于记录数据包接收者的端口序列号TCP为TCP段中包含的每个数据字节分配一个唯一的序列号确认号下需要从对应值位置开始的序列号，它总是最后一个接收到的数据字节的序列号加1包头大小它包含TCP包头的长度，数据从哪里开始读数据窗口它通告发送者无需确认即可接收多少数据校验和发送方在发送数据之前将CRC校验和添加到校验和字段紧急指针添加到序列号的紧急指针指示紧急数据字节的结尾时间戳根据时间戳，接收方可以识别正确的段窗口尺寸扩展如果接收方希望接收更多数据，则可以使用此字段来通告其更大的窗口大小以上为部分TCP包头一些字段，还有一部分不是很重要的我没有列举出来，至于现在你只需要大致了解其作用，这篇文章后面部分我将在网络可靠性上引用这些标记位和要解决的问题，下面为最重要的部分标记位📌这部分主要做一些数据的特殊处理，表格如下：标记位作用说明URG位它指示接收器当前段中的一定数量的数据很紧急ACK位当ACK位设置为1时，表示TCP头中包含的确认号有效PSH位PSH位用于将整个缓冲区立即推送到接收应用程序RST位RST位用于重置TCP连接SYN位SYN位用于同步序列号FIN位FIN位用于终止TCP连接这些标志位在数据包通讯过程中起到很重要的作用，这些消息会数据包头部存储，客户端会服务器通讯的时候会携带着，以上的数据包头部为TCP控制信息，会在连接建立到结束的每次数据通讯都会有。连接的建立TCP在初始化连接建立时其实就为了交换两台计算机的控制信息，这里的控制信息一部分上面我已经讲过了。控制信息一般都是存储在操作系统提供的网络描述符中的，但是在首次建立连接的时候这些信息起到关键的作用，首先我们要了解一下一个标准的TCP数据包是什么样子的？我们主要关注的蓝色部分的控制信息的转换工作，蓝色部分为TCP数据包的包头信息也就是上面介绍的那些字段集合部分。初始化连接的时候就和我们日常生活中习以为常的打电话联系别人一样，在打电话的时候我们要知道被呼叫的那个人手机号，那我们要怎么做呢？日常生活中我们都线下见面留一个电话号然后保存起来，然后下次需要呼叫时候自己拨打即可。换到TCP协议建立连接时就是目标机器的IP和端口号信息，然后操作系统协议栈会帮助我们建立连接，这个过程非常复杂的。计算机网络环境非常复杂的，你不知道当前互联网设备是否存在网络延迟或者说某个光缆被施工队挖断掉了导致数据发送失败等等情况......下面为一个标准的TCP建立连接的过程，如下图：TCP建立连接为什么是3次数据包交换，而不是两次？这个跟互联网网络环境因素有很大关系；注意数据包中对应的标记位是什么意思这里我不过多叙述，不是我要说明的重点，如果读者你不知道这是你…

互联网基础架构
type: item
date: 2022-08-13T16:05:00+08:00
description: 在21世纪互联网几乎已经融入了每个人的生活了，有了互联网使得我们的生活变得更便利的同时，有没有想过互联网倒是是什么？互联网是通过怎么样的方式把每个人连接在一起的？互联网是如何传递我们产生的数据的？当我们在浏览器打开一个网页的时候这个网页是怎么显示出来的？我写这篇文章目的就是要介绍互联网是什么，并且我自己也是一个Z时代，我出身就和互联网融入在一起了。John Gage在1980年代提出了"THE NETWORK IS THE COMPUTER!"宣传口号，之后被Sun使用了数十年，直到 2010 年被Oracle收购。根据Sun前营销总监Ray Rothrock的解释，这个口号的意思是通过个人计算机你在网络中有了一扇窗，如果有合适软件的话你还可以使用其他人的计算机。早期的计算机程序都没有统一的系统，而是各自厂商开发的程序，并且都是运行本机上的。直到后面美国军方把ARPANET开始慢慢民用，才发展起来了互联网。之后每个人的个人计算机就对应上面那句话：通过个人计算机你在网络中有了一扇窗。现在互联网更应该是物联网，接入网络的设备不只是是传统的计算机和手机了，更多家用电器，工业互联网电冰箱、台灯、微波炉、智能汽车等，都接入到互联网中。WORLD WIDE WEB上面说计算机相当于一个连接世界的窗口，我个人认为这里更多的指的是Browser即浏览器，我们可以通过浏览器去访问一些在互联网中其他计算机所提供的服务，我们一般把这种访问其他计算机提供的资源的方式叫做Web网络服务。Web网络服务： 只是一种依赖于互联网计算机提供服务的一种方式，具体的通讯是依靠着HTTP协议进行的。当我们在浏览器输入www.google.com的时候，浏览器就会使用http协议请求到具体服务器上，这里的很多人把www认为是World Wide Web的简称当成了通讯协议，其实并非如此，而是初代网页内容编辑器和网页服务器的简称。World Wide Web只是一种通过互联网的基础之上做的一层网络计算机数据交换的方式；万维网并不等同互联网，万维网只是互联网所能提供的服务其中之一，是靠着互联网运行的一项服务。万维网发源地是欧洲核子研究中心，上面就为万维网的发明者蒂姆·伯纳斯-李，第一代浏览器和HTML编辑器就为他开发的。在万维网还没有普及的时候，大部分个人电脑都是靠着购买软件来使用，当时个人PC市场苹果、惠普，生产软件的公司是像微软这样的公司，靠着卖软件来挣钱的。计算机发展史就是软件行业发展史，最早计算机可能功能单一就是为了计算一些弹道和一些数学相关的，最后各大公司开始研发操作系统软件，在操作系统软件发展中，最后胜利的是微软公司，微软靠着自家的Windows系统占据个人PC市场。微软并没有把目光注重在计算机硬件上，而是更关注计算机软件，怎么充分发挥这些硬件优势。微软开发很多软件，靠着卖软件盈利，例如操作系统，在微软占据了操作系统市场之后几乎就是弄断了整个个人PC市场，除了Apple公司软件和硬件都做以外。在当时大部分软件都是靠着本机运行，直到后面万维网的出现，通过万维网去访问其他计算机上的信息，微软就意识到浏览器的重要性，不能完全依靠着操作系统去占据个人PC市场了，未来的市场应该是在万维网上，提供这一些网络服务的公司都是虚拟的，他们服务大部分运行在自己的万维网服务器上；这也就是后面Yahoo、Google等这些，网络服务公司出现，有浏览器就可以访问这些在线上提供服务的公司。WWW架构现在开发者开发的网络应用服务大部分都是在编写服务端应用或者是服务端的前端应用，都会对依赖于万维网才能正常工作的，所以每个开发者都应该了解万维网是如何工作的。网络应用服务不仅仅是我们日常编写的HTTP协议的应用，现在浏览器还支持更多不同协议例如FTP、mailto、file这些。这里我主要偏重的是HTTP协议进行网络通讯架构介绍：一般我们在浏览器输入一个网址的时候，浏览器会解析输入的网址然后生产请求数据包，但是HTTP是基于TCP协议的在发送数据之前要知道对方的网络服务器IP；这时就需要操作系统请求另外一个服务了DNS，DNS负责解析域名所绑定的IP地址，然后浏览器才能生产请求头和数据包然后交给操作系统发送出去，这就是一次完整浏览器HTTP请求过程。HTTP协议协议这个东西很重要的，做任何事情都需要协议才能达到默契配合，这不紧体现在生活中还体现在计算机的世界里，HTTP协议就是负责浏览器和WEB应用服务器进行数据交换的协议。HTTP是在应用层的协议所以依赖于TCP协议，最后请求数据包是通过tcp发送出去的。所以HTTP需要组织请求数据包，这里的数据包要要按照HTTP协议的规则进行的，例如下面就为一个标准的请求头数据包结构：数据包除了第一行是一些具体请求方式和请求资源路径和协议版本之外，其他一些…