1. JWT的过程解析
JWT(JSON Web Token)是一种基于 JSON 的开放标准(RFC 7519)实现的用于在各方之间传递信息的紧凑且自包含的方式。JWT 是一种 token,可以对信息进行数字签名(例如使用 HMAC 算法或 RSA 加密),因此可以保证信息的真实性和完整性。
JWT 的结构由三部分组成:Header(头部)、Payload(负载)、Signature(签名),这三部分通过点(.)进行分隔。JWT 的过程可以分为生成和验证两个主要步骤。
1.1 JWT生成过程
1.Header(头部):
类型:声明这是一个JWT.
签名算法: 指定用于签名的算法,如 HMAC SHA256 或 RSA。
{
"alg": "HS256",
"typ": "JWT"
}
2. Payload(负载)
包含要传输的数据(声明),这些声明可以是标准化的字段,也可以是自定义字段,常见的标准字段包括:
iss (issuer):签发者
exp (expiration time):过期时间
sub (subject):主题
aud (audience):受众
例如:
{
"sub": "1234567890",
"name": "John Doe",
"admin": true
}
3.Signature(签名):
将编码后的 Header、编码后的 Payload 和一个密钥进行签名。签名过程如下:
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret
)
生成的签名用于验证消息的发送者,以及保证消息在传输过程中未被篡改。
4. 完整的 JWT:
最终,JWT 生成的格式为:header.payload.signature。
例如,生成的 JWT 可能是:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
1.2 JWT验证过程
1.分离 JWT:
接收方获取 JWT 后,将其按 . 分割为三部分:Header、Payload 和 Signature。
2.验证签名:
使用接收方保存的密钥与 Header 中指定的算法,重新计算签名部分。如果计算结果与 JWT 中的 Signature 一致,则表明数据未被篡改,且来源可信。
3.验证 Payload:
验证 Payload 中的声明,特别是时间相关的字段(如 exp 和 iat),以确定 JWT 是否仍然有效。
其他验证如 iss 和 aud 也可以根据需求进行。
4.使用 Payload 中的数据:
如果验证通过,接收方可以使用 Payload 中的数据来执行进一步的业务逻辑。
JWT 通过将认证信息和其他声明封装在一个自包含的令牌中,使得服务器端无需保存会话状态。这种机制使得 JWT 特别适合分布式系统中的身份认证和信息传递。不过,在使用 JWT 时要特别注意令牌的存储安全性以及令牌的过期时间设置,防止重放攻击等安全问题。
2.Http建立连接的过程
HTTP(Hypertext Transfer Protocol)是应用层协议,通常运行在 TCP/IP 协议之上。HTTP 的工作原理基于请求-响应模型,即客户端向服务器发送请求,服务器返回响应。为了理解 HTTP 建立连接的过程,我们需要了解其底层的 TCP 三次握手过程。以下是 HTTP 建立连接的过程概述:
1.DNS 解析
在建立 HTTP 连接之前,首先需要将域名解析为 IP 地址。这是通过 DNS(Domain Name System)完成的。
步骤:
客户端向 DNS 服务器发送请求,询问某个域名对应的 IP 地址。
DNS 服务器返回相应的 IP 地址。
客户端获得 IP 地址后,才能与对应的服务器建立连接。
2. TCP三次握手
HTTP 运行在 TCP 协议之上,连接的建立依赖于 TCP 的三次握手过程。三次握手的目的是在客户端和服务器之间建立可靠的传输通道。
步骤:
SYN(Synchronize): 客户端向服务器发送一个 SYN 报文,表示请求建立连接,并且客户端进入 SYN_SENT 状态。
SYN-ACK(Synchronize-Acknowledgment): 服务器收到 SYN 报文后,回应一个 SYN-ACK 报文,表示同意建立连接,并且服务器进入 SYN_RECEIVED 状态。
ACK(Acknowledgment): 客户端收到服务器的 SYN-ACK 报文后,发送一个 ACK 报文以确认连接建立。此时,客户端和服务器都进入 ESTABLISHED 状态,TCP 连接建立完成。
3. HTTP 请求与响应
TCP 连接建立后,客户端可以发送 HTTP 请求,服务器接收到请求后会进行处理并返回响应。
步骤:
1.客户端发送请求:
客户端向服务器发送一个 HTTP 请求报文,包含请求行(方法、URL、协议版本)、请求头部(Host、User-Agent 等)、以及可选的请求体(如 POST 数据)。
例如:
GET /index.html HTTP/1.1
Host: www.example.com
2. 服务器处理请求:
服务器收到请求后,根据请求的资源路径(URL)和方法(GET、POST 等)进行处理。
服务器处理完请求后,生成一个 HTTP 响应报文。
3. 服务器返回响应:
服务器将响应报文返回给客户端,包含响应行(协议版本、状态码、状态描述)、响应头部(Content-Type、Content-Length 等)、以及可选的响应体(如 HTML 内容)。
例如:
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 137
<html>
<head><title>Example</title></head>
<body>Hello, World!</body>
</html>
4. 客户端处理响应
客户端收到响应后,根据状态码和响应头部进行处理,并将响应体中的数据呈现给用户(如浏览器显示 HTML 页面)。
4.连接关闭
在 HTTP/1.0 中,每个请求响应对之间都需要建立和关闭一次 TCP 连接。而在 HTTP/1.1 中,默认启用 Keep-Alive 机制,允许在同一 TCP 连接上传递多个请求和响应,从而减少连接建立和关闭的开销。
TCP 四次挥手:
连接关闭时,TCP 使用四次挥手来确保连接的关闭是可靠的:
1.FIN(Finish): 客户端发送 FIN 报文,表示不再发送数据,进入 FIN_WAIT_1 状态。
2.ACK: 服务器收到 FIN 后,回应 ACK 报文,进入 CLOSE_WAIT 状态。
3.FIN: 服务器发送 FIN 报文,表示不再发送数据,进入 LAST_ACK 状态。
4.ACK: 客户端收到 FIN 后,回应 ACK 报文,进入 TIME_WAIT 状态。等待一段时间后,关闭连接。
HTTP 建立连接的过程依赖于底层的 TCP 三次握手,而整个过程包括 DNS 解析、TCP 建立连接、HTTP 请求与响应,以及最终的连接关闭。在 HTTP/1.1 中,为了提高性能,可以使用连接复用(Keep-Alive)机制在同一个 TCP 连接上进行多次请求和响应。
3. 什么是网络编程?
网络编程是指编写能够在计算机网络上进行通信的应用程序的过程。它涉及创建软件,使计算机、设备或应用程序能够通过网络(如互联网、局域网)互相交换数据或资源。网络编程的核心是处理各种网络协议,使用不同的编程语言和技术栈来实现网络通信的功能。
3.1 基本概念
1.通信协议:
通信协议是网络编程的基础,定义了数据传输的规则、格式和顺序。常见的协议包括:
HTTP/HTTPS: 用于浏览器和服务器之间的数据传输。
TCP/IP: 提供可靠的、面向连接的数据传输。
UDP: 提供无连接的、不保证可靠性的快速数据传输。
FTP: 文件传输协议。
SMTP/POP3/IMAP: 电子邮件传输协议。
2.客户端-服务器模型:
网络编程通常采用客户端-服务器模型,其中客户端发起请求,服务器处理请求并返回响应。客户端可以是浏览器、移动应用、命令行工具等,服务器则是运行在远程计算机上的应用程序。
3.Socket(套接字):
Socket 是网络编程中用于建立连接和通信的编程接口。它提供了与网络协议的接口,使开发者可以通过 Socket API 创建、管理和关闭网络连接。
TCP Socket: 通过 TCP 协议进行通信,保证数据传输的可靠性和顺序。
UDP Socket: 通过 UDP 协议进行通信,适用于需要快速传输而不要求可靠性的场景。
4.网络编程中的编程语言:
网络编程可以使用多种编程语言实现,常见的包括:
C/C++: 提供底层的 Socket 编程接口,用于高性能的网络服务开发。
Java: 提供丰富的网络编程库,如 java.net 包,便于开发跨平台的网络应用。
Python: 提供了简单易用的 socket 模块和高级的网络框架(如 Flask、Django),适合快速开发网络应用。
JavaScript: 用于开发前端的网络交互功能(如 AJAX)、Node.js 服务器端开发等。
5.并发和多线程:
网络编程通常涉及并发处理,因为网络应用可能需要同时处理多个客户端的请求。这可以通过多线程、异步编程、事件驱动等方式实现。
6.安全性:
网络编程需要考虑数据传输的安全性,包括数据加密、认证、授权、防御攻击(如 SQL 注入、XSS、CSRF)等。
3.2 网络编程的应用场景
1.Web开发: 通过 HTTP/HTTPS 协议与服务器通信,实现动态网页、API 服务等功能。
2.实时通信: 使用 TCP、UDP、WebSocket 等技术开发即时通讯应用、在线游戏、视频会议等。
3.文件传输: 实现基于 FTP 或定制协议的文件上传、下载、共享服务。
4.物联网(IoT): 开发能够通过网络控制或监测硬件设备的应用程序。
5.分布式系统: 开发分布式计算系统,多个节点通过网络协同完成计算任务。
3.3 网络编程的挑战
网络延迟和带宽: 网络条件不稳定可能导致数据传输的延迟或丢失,需要合理处理重传和超时机制。
跨平台兼容性: 不同平台的网络编程接口可能有所不同,开发者需要考虑代码的可移植性。
安全问题: 开发者必须确保数据的传输和存储安全,防止被恶意攻击。
4. 生产环境下项目爆异常,怎么排查项目错误?
在生产环境中,当项目发生异常时,快速有效地排查问题非常重要。以下是排查生产环境项目错误的常见步骤和策略:
4.1 日志分析
查看日志: 首先,查看应用程序的日志文件。生产环境通常会有详细的日志记录,包括错误日志、警告日志和信息日志。这些日志可以提供关于异常发生的详细信息,如错误堆栈、发生时间、请求参数等。
日志级别: 确保生产环境的日志级别设置得当,一般应为 ERROR 或 WARN,但在排查问题时可以临时调整为 DEBUG 以获取更多细节。
集中式日志管理: 如果使用了集中式日志管理工具(如 ELK Stack、Splunk),可以通过关键字搜索、过滤和可视化的方式快速定位问题。
4.2 监控工具
应用性能监控(APM): 使用 APM 工具(如 New Relic、Prometheus、Datadog、SkyWalking)来监控应用的性能指标(如响应时间、CPU、内存、数据库查询时间)和错误率。这些工具通常可以帮助你快速定位性能瓶颈和异常代码段。
报警系统: 检查是否收到了监控系统的报警通知,报警可能会包含具体的异常信息和可能的根因分析。
4.3 查看系统资源
检查服务器资源: 通过监控或命令行工具(如 top、htop、free)检查服务器的 CPU、内存、磁盘 I/O、网络流量等资源使用情况,查看是否存在资源瓶颈或泄漏。
数据库性能: 检查数据库的运行状态和性能指标,如慢查询日志、连接池状态、死锁等问题。
4.4 重现问题
测试环境重现:如果可能,将生产环境的问题在测试环境或开发环境中重现,以便详细调试和分析。
特定请求分析:根据日志或监控,找到导致异常的特定请求或操作,然后在测试环境中模拟该请求或操作。
4.5 代码审查
错误栈追踪:通过日志中的错误堆栈信息,回溯问题发生的代码路径,找到异常发生的代码行。
最近的代码更改:检查最近是否有代码更新,尤其是异常发生之前的代码提交。新功能或变更往往是引发问题的原因。
4.6 第三方依赖
检查依赖版本: 如果使用了第三方库或服务,确认它们是否有兼容性问题或已知的 bug。
外部服务问题: 检查外部 API 或服务是否正常工作,是否有超时、网络问题或返回了错误的数据。
4.7 安全问题
安全漏洞检查: 排查是否由于安全问题导致的异常,如 SQL 注入、XSS、CSRF 等。检查系统的安全配置和日志中的可疑活动。
权限问题: 确认应用程序的各类操作权限设置是否正确,某些权限问题可能导致部分请求失败或异常。
4.8 回滚和恢复
快速回滚:如果异常导致了严重的问题且无法快速修复,考虑将代码或配置回滚到上一个稳定版本。
自动化恢复:确保有自动化的恢复机制,比如 Kubernetes 的健康检查与自动重启功能,可以帮助系统快速恢复。
4.9 与团队沟通
协作解决问题:与开发团队、运维团队和其他相关人员沟通,共同分析和解决问题。集体讨论可以提供更多的思路和解决方案。
4.10 总结与预防
问题总结: 问题解决后,进行总结,分析根本原因并记录下来,确保在未来的项目中避免类似问题。
增加监控与测试: 根据此次问题改进监控策略和自动化测试用例,尽量在开发和测试阶段发现问题。
5. Mysql三范式
MySQL中的数据库设计通常遵循三种范式(Normal Forms),即第一范式(1NF)、第二范式(2NF)和第三范式(3NF)。这些范式旨在规范化数据库表的结构,减少数据冗余,提高数据的一致性和完整性。
5.1 第一范式(1NF)
定义: 第一范式要求数据库表中的每一列都必须是原子的,不可再分的数据项。也就是说,表中的每个字段都只能包含单一值,不能包含多个值或重复的组。
要点:
列中的值是不可分割的基本数据项。
表中没有重复的列。
例子:
5.2 第二范式(2NF)
定义: 第二范式在满足第一范式的基础上,要求表中的每个非主属性(非主键字段)都完全依赖于候选键的全部,而不是仅依赖于其中的一部分。第二范式消除了部分依赖。
要点:
表必须符合1NF。
非主键字段必须完全依赖于主键,而不是部分依赖。
例子:
在这个表中,学生姓名 依赖于 学生ID,而 课程名称 依赖于 课程ID,这是部分依赖,不符合2NF。
5.3 第三范式(3NF)
定义: 第三范式在满足第二范式的基础上,要求表中非主键字段不依赖于其他非主键字段,即消除传递依赖。3NF 消除了非主属性之间的依赖关系,确保每个非主键字段直接依赖于主键。
要点:
表必须符合2NF。
非主键字段之间不能有传递依赖。
例子:
在这个表中,系名称 依赖于 系ID,而 系ID 又依赖于 学生ID,这是传递依赖,不符合3NF。
符合3NF的表应该拆分为两个表:
总结
1.1NF 保证了列的原子性,即每个字段只能包含一个值。
2.2NF 消除了表中的部分依赖,使得每个非主键字段都完全依赖于主键。
3.3NF 消除了表中的传递依赖,确保每个非主键字段直接依赖于主键。