系统设计——大文件传输方案设计

摘要

大文件传输是指通过网络将体积较大的文件从一个位置发送到另一个位置的过程。这些文件可能包括高清视频、大型数据库、复杂的软件安装包等,它们的大小通常超过几百兆字节(MB)甚至达到几个吉字节(GB)或更大。大文件传输可能面临一些挑战,比如传输速度慢、网络不稳定导致的传输中断、以及存储空间的限制等。为了有效地传输大文件,可能需要使用特定的技术,比如压缩文件以减少传输数据量、使用高速网络连接、或者采用分块传输技术来提高传输的稳定性和效率。

1. 什么是大文件传输

大文件的定义取决于具体的应用场景、传输技术和硬件资源。通常情况下,大文件的定义与以下几个因素相关:

1.1. 大文件常见定义

网络传输中

  • >10MB:对低速网络(如移动网络或不稳定的无线连接)来说,10MB及以上的文件可能需要优化。
  • >100MB:在普通网络环境中,100MB以上的文件一般被认为是大文件,需要特殊优化,如分块或流式传输。
  • >1GB:在高速网络环境中,1GB及以上的文件通常被认为是大文件,传输时需要额外注意内存、带宽和传输错误恢复。

存储或操作中

  • >100MB:对于低配置设备(如嵌入式设备或老旧服务器),内存无法一次加载,文件需要分块处理。
  • >1GB:在文件处理场景中,1GB及以上的文件可能会对 I/O 性能或存储速度造成显著影响。

1.2. 从技术视角分析

大文件的判断标准与以下技术限制相关:

网络传输协议限制

  • HTTP:对于普通 HTTP 上传,传输 >100MB 文件可能会遇到超时问题,需要优化(如分片上传或断点续传)。
  • Socket:理论上无文件大小限制,但需要注意缓冲区大小设置和断点续传。
  • gRPC:默认单个消息限制为 4MB,可以通过配置增加限制,但传输大文件时推荐使用流式传输。

硬件和系统限制

  • 内存:如果文件无法一次性加载到内存中(如文件大小 > 系统内存的 50%),需要分块处理。
  • 文件系统:某些文件系统对单个文件大小有上限。例如,FAT32 的最大文件大小是 4GB。
  • 用户体验:对用户来说:传输文件超过 30秒 就可能被认为是“较大”文件。超过 1分钟 需要提供进度条或断点续传功能。

1.3. 实际场景中的大文件划分参考

文件大小

定义

应对策略

<10MB

小文件

一次性传输即可,无需特别优化。

10MB-100MB

中等大小文件

使用分块传输或流式传输。

100MB-1GB

大文件

必须分块,建议使用断点续传、校验完整性等优化手段。

>1GB

超大文件

分块、多线程传输,尽量使用高效协议(如 gRPC 或专用大文件传输工具)。

>10GB

超级大文件(少见)

考虑带外传输(如 FTP、SFTP)或直接通过硬盘快递等方式完成传输。

1.4. 判断是否为大文件条件参考

  1. 内存不足:如果程序无法一次性加载文件到内存,或者引发内存溢出错误(OutOfMemoryError)。
  2. 传输时间过长:文件传输时间明显超出用户期望(如 10 秒以上)。
  3. I/O 性能瓶颈:文件操作导致磁盘或网络 I/O 压力显著增加。
  4. 网络不稳定:传输过程频繁中断或出现丢包。

1.5. 针对大文件的优化技术参选

  1. 分块传输:将文件分为小块逐步传输。
  2. 断点续传:网络中断时无需重新传输已完成部分。
  3. 压缩传输:减少文件大小,加快传输速度。
  4. 流式传输:在文件读取和写入时流式处理,避免一次性加载到内存。
  5. 多线程并行传输:提高传输效率。
  6. 分片存储(Shard):对于超大文件,考虑存储时按逻辑拆分。

2. 大文件传输有什么挑战

大文件传输的挑战和问题主要来自于文件的体积、传输过程中的网络和硬件限制。以下是详细分析,以及常见问题和对应的解决方案。

2.1. 网络限制

  • 传输速度:文件越大,传输时间越长,尤其在低带宽或高延迟网络中表现明显。
  • 网络中断:大文件传输过程中,网络的不稳定(如超时、丢包)可能导致传输失败,需要重新开始。
  • 带宽占用:大文件传输可能占用大量带宽,影响其他任务的正常运行。
  • 跨网络传输:不同的网络环境(如企业内网与公网)可能有防火墙、代理或限速限制。

2.2. 系统与硬件限制

  • 内存不足:如果需要将大文件加载到内存中处理,可能导致内存溢出(OutOfMemoryError)。
  • 磁盘性能:大文件的读写操作对磁盘 I/O 是一个挑战,尤其是在磁盘性能较差或并发读写多的情况下。
  • 文件系统限制:某些文件系统对单个文件大小有上限(如 FAT32 的单文件大小限制为 4GB)。磁盘空间不足可能导致文件传输失败。

2.3. 数据完整性

  • 文件损坏:网络传输中的数据丢失或错误可能导致接收端文件不完整或损坏。
  • 校验困难:大文件的完整性校验(如 MD5、SHA-256)耗时较长。

2.4. 并发与多用户冲突

  • 多用户竞争资源:多个用户同时上传或下载大文件时,可能导致服务器资源不足(CPU、内存、I/O 等)。
  • 锁机制:大文件传输可能需要锁定部分资源,影响系统性能。

2.5. 应用层面的问题

  • 超时问题:大文件传输时间较长,可能超过默认的连接超时时间。
  • 传输失败后的重试:一旦传输中断,重新传输整个文件可能浪费大量时间和带宽。
  • 兼容性:跨平台传输时,文件格式、编码或路径可能存在不兼容问题。

3. 大文件传输技术方案

3.1. 分块传输

原理:将文件分成小块(如 1MB、10MB),逐块进行传输。

优点:减少内存占用。网络中断时,仅需重新传输未完成的部分,而非整个文件。

常用工具/技术:HTTP 分片上传:如阿里云 OSS 或 AWS S3 的分片上传。gRPC 流式传输:适合逐块传输大文件。

3.2. 断点续传

原理:在传输中断时记录传输进度,重新连接后从中断点继续。

关键技术:客户端和服务端共同维护文件传输的偏移量(offset)。例如:HTTP 的 Range 头支持分段请求

优点:提升传输可靠性。避免重复传输已完成的部分。

3.3. 流式传输

原理:按需读取和发送文件数据,而不是一次性加载整个文件到内存。

使用场景:gRPC:支持流式消息传输。Socket:通过流式 I/O 逐块发送和接收数据。

优点:降低内存消耗。适合超大文件传输(如 >1GB 文件)。

3.4. 校验完整性

传输完成后,通过校验和(如 MD5SHA-256)验证文件完整性。

优化方式:在传输过程中按块计算校验和,避免传输完成后才校验整个文件。

3.5. 限流与优先级控制

限流:对上传或下载速度进行限制,避免占用过多带宽。

优先级:为重要文件传输设置更高优先级,确保快速完成。

3.6. 使用专用工具或协议

FTP/SFTP:传统的文件传输协议,支持断点续传。优点:成熟稳定,支持大文件传输。

第三方工具:阿里云 OSS、AWS S3、Google Drive 等工具均支持大文件分片上传。

3.7. 大文件传输方案总结

问题

描述

解决方法

传输中断

网络中断或超时导致传输失败

实现断点续传,分块传输。

内存不足

文件过大导致内存溢出(OutOfMemoryError)

使用流式传输或分块处理。

传输速度慢

网络带宽不足或文件过大

压缩文件,或采用多线程并发传输。

校验耗时长

文件过大时计算校验和耗时较长

分块校验,每块单独计算和验证。

多用户资源争抢

多用户同时传输大文件时,服务器资源(CPU、带宽等)可能耗尽

实现限流、负载均衡,或引入 CDN。

传输失败后重复传输浪费

中断后需要重新传输整个文件,浪费时间和带宽

实现断点续传,仅重新传输未完成部分。

文件损坏

网络传输中的数据丢失导致文件损坏

传输完成后通过校验和验证完整性(MD5、SHA-256)。

4. 大文件传输功能实现

4.1. 分块传输实现(java)

思路:将文件分成若干小块,逐块传输。客户端和服务器共同管理块的顺序和大小。

4.1.1. 客户端:分块上传

import java.io.File;
import java.io.FileInputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;public class ChunkedFileUploader {public static void main(String[] args) throws Exception {String filePath = "path/to/large/file.zip";String serverUrl = "http://localhost:8080/upload";int chunkSize = 1024 * 1024; // 每块 1MBFile file = new File(filePath);FileInputStream fis = new FileInputStream(file);long fileLength = file.length();long offset = 0;int chunkIndex = 0;byte[] buffer = new byte[chunkSize];while (offset < fileLength) {int bytesRead = fis.read(buffer);if (bytesRead == -1) break;// 上传当前块boolean success = uploadChunk(serverUrl, buffer, bytesRead, file.getName(), chunkIndex, fileLength);if (!success) {System.out.println("Failed to upload chunk " + chunkIndex);break;}offset += bytesRead;chunkIndex++;}fis.close();}private static boolean uploadChunk(String serverUrl, byte[] chunkData, int bytesRead, String fileName, int chunkIndex, long totalSize) throws Exception {HttpURLConnection connection = (HttpURLConnection) new URL(serverUrl).openConnection();connection.setDoOutput(true);connection.setRequestMethod("POST");connection.setRequestProperty("Content-Type", "application/octet-stream");connection.setRequestProperty("File-Name", fileName);connection.setRequestProperty("Chunk-Index", String.valueOf(chunkIndex));connection.setRequestProperty("Total-Size", String.valueOf(totalSize));try (OutputStream os = connection.getOutputStream()) {os.write(chunkData, 0, bytesRead);}return connection.getResponseCode() == 200;}
}

4.1.2. 服务端:接收分块上传

import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;@RestController
@RequestMapping("/upload")
public class FileUploadController {@PostMappingpublic String uploadChunk(@RequestHeader("File-Name") String fileName,@RequestHeader("Chunk-Index") int chunkIndex,@RequestHeader("Total-Size") long totalSize,@RequestBody byte[] chunkData) throws Exception {String outputDir = "path/to/uploaded/files/";File outputFile = new File(outputDir + fileName);// 按块写入try (OutputStream os = new FileOutputStream(outputFile, true)) { // true: 追加模式os.write(chunkData);}System.out.println("Received chunk " + chunkIndex + ", size: " + chunkData.length);return "Chunk " + chunkIndex + " uploaded successfully!";}
}

4.2. 断点续传实现(java)

思路:客户端记录每次上传完成的块索引(offset)。如果传输中断,从上次成功的位置重新开始。

4.2.1. 客户端:带断点续传

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;public class ResumableFileUploader {public static void main(String[] args) throws Exception {String filePath = "path/to/large/file.zip";String serverUrl = "http://localhost:8080/upload";int chunkSize = 1024 * 1024; // 每块 1MBFile file = new File(filePath);long fileLength = file.length();long offset = getUploadedOffset(serverUrl, file.getName()); // 获取已上传的偏移量FileInputStream fis = new FileInputStream(file);fis.skip(offset);byte[] buffer = new byte[chunkSize];int chunkIndex = (int) (offset / chunkSize);while (offset < fileLength) {int bytesRead = fis.read(buffer);if (bytesRead == -1) break;boolean success = uploadChunk(serverUrl, buffer, bytesRead, file.getName(), chunkIndex, fileLength);if (!success) {System.out.println("Failed to upload chunk " + chunkIndex);break;}offset += bytesRead;chunkIndex++;}fis.close();}private static long getUploadedOffset(String serverUrl, String fileName) throws Exception {HttpURLConnection connection = (HttpURLConnection) new URL(serverUrl + "?fileName=" + fileName).openConnection();connection.setRequestMethod("GET");if (connection.getResponseCode() == 200) {BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));return Long.parseLong(reader.readLine());}return 0;}private static boolean uploadChunk(String serverUrl, byte[] chunkData, int bytesRead, String fileName, int chunkIndex, long totalSize) throws Exception {HttpURLConnection connection = (HttpURLConnection) new URL(serverUrl).openConnection();connection.setDoOutput(true);connection.setRequestMethod("POST");connection.setRequestProperty("Content-Type", "application/octet-stream");connection.setRequestProperty("File-Name", fileName);connection.setRequestProperty("Chunk-Index", String.valueOf(chunkIndex));connection.setRequestProperty("Total-Size", String.valueOf(totalSize));try (OutputStream os = connection.getOutputStream()) {os.write(chunkData, 0, bytesRead);}return connection.getResponseCode() == 200;}
}

4.2.2. 服务端:支持断点续传

import org.springframework.web.bind.annotation.*;
import java.io.File;@RestController
@RequestMapping("/upload")
public class ResumableFileUploadController {@GetMappingpublic long getUploadedOffset(@RequestParam("fileName") String fileName) {File file = new File("path/to/uploaded/files/" + fileName);return file.exists() ? file.length() : 0;}@PostMappingpublic String uploadChunk(@RequestHeader("File-Name") String fileName,@RequestHeader("Chunk-Index") int chunkIndex,@RequestHeader("Total-Size") long totalSize,@RequestBody byte[] chunkData) throws Exception {String outputDir = "path/to/uploaded/files/";File outputFile = new File(outputDir + fileName);try (OutputStream os = new FileOutputStream(outputFile, true)) { // true: 追加模式os.write(chunkData);}return "Chunk " + chunkIndex + " uploaded successfully!";}
}

4.3. 流式传输(gRPC 示例)

4.3.1. Proto 文件示例

syntax = "proto3";// 定义服务包名
package fileupload;// 指定 Java 代码生成的包名(可选)
option java_package = "com.example.fileupload";
option java_outer_classname = "FileUploadProto";// 文件上传服务定义
service FileUploadService {// 文件上传接口(客户端流模式)rpc UploadFile(stream UploadRequest) returns UploadResponse;
}// 文件上传请求消息
message UploadRequest {string fileName = 1;         // 文件名bytes chunkData = 2;         // 当前块的二进制数据int64 chunkIndex = 3;        // 当前块的索引(可选)int64 totalChunks = 4;       // 总块数(可选)
}// 文件上传响应消息
message UploadResponse {string status = 1;           // 上传状态,例如 "Success"string message = 2;          // 附加信息,例如错误原因
}

4.3.2. Proto 文件的使用

生成 gRPC 代码 使用 protoc 生成对应的 Java 文件:

protoc --java_out=. --grpc-java_out=. fileupload.proto

Maven 插件生成:

<plugin><groupId>io.grpc</groupId><artifactId>protoc-gen-grpc-java</artifactId><version>1.57.2</version>
</plugin>

服务端实现:继承生成的 FileUploadServiceGrpc.FileUploadServiceImplBase,实现 UploadFile 方法。

客户端实现:使用 FileUploadServiceGrpc.FileUploadServiceStub 创建流式调用,逐块上传文件数据。

4.3.3. gRPC 服务端实现(java)

import io.grpc.stub.StreamObserver;
import java.io.FileOutputStream;public class FileUploadServiceImpl extends FileUploadServiceGrpc.FileUploadServiceImplBase {@Overridepublic StreamObserver<UploadRequest> uploadFile(StreamObserver<UploadResponse> responseObserver) {return new StreamObserver<UploadRequest>() {private FileOutputStream fos;@Overridepublic void onNext(UploadRequest request) {try {// 初始化文件流if (fos == null) {fos = new FileOutputStream("uploaded/" + request.getFileName());}// 写入当前块的数据fos.write(request.getChunkData().toByteArray());} catch (Exception e) {responseObserver.onError(e);}}@Overridepublic void onError(Throwable t) {try {if (fos != null) fos.close();} catch (Exception ignored) {}System.err.println("Error during file upload: " + t.getMessage());}@Overridepublic void onCompleted() {try {if (fos != null) fos.close();} catch (Exception ignored) {}// 返回上传成功响应responseObserver.onNext(UploadResponse.newBuilder().setStatus("Success").setMessage("File uploaded successfully!").build());responseObserver.onCompleted();}};}
}

4.3.4. 客户端实现(java)

import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
import io.grpc.stub.StreamObserver;
import java.io.FileInputStream;public class FileUploadClient {public static void main(String[] args) throws Exception {String filePath = "path/to/large/file.zip";String fileName = "file.zip";// 创建 gRPC 通道ManagedChannel channel = ManagedChannelBuilder.forAddress("localhost", 8080).usePlaintext().build();FileUploadServiceGrpc.FileUploadServiceStub stub = FileUploadServiceGrpc.newStub(channel);// 创建流式请求StreamObserver<UploadRequest> requestObserver = stub.uploadFile(new StreamObserver<UploadResponse>() {@Overridepublic void onNext(UploadResponse response) {System.out.println("Server Response: " + response.getStatus() + " - " + response.getMessage());}@Overridepublic void onError(Throwable t) {System.err.println("Error: " + t.getMessage());}@Overridepublic void onCompleted() {System.out.println("File upload completed.");channel.shutdown();}});// 分块上传文件FileInputStream fis = new FileInputStream(filePath);byte[] buffer = new byte[1024 * 1024]; // 每块 1MBint bytesRead;int chunkIndex = 0;while ((bytesRead = fis.read(buffer)) != -1) {UploadRequest request = UploadRequest.newBuilder().setFileName(fileName).setChunkData(com.google.protobuf.ByteString.copyFrom(buffer, 0, bytesRead)).setChunkIndex(chunkIndex++).build();requestObserver.onNext(request);}fis.close();// 完成请求requestObserver.onCompleted();}
}

博文参考

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/500964.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

国产编辑器EverEdit - 常用资源汇总

1 国产编辑器EverEdit-常用资源汇总 EverEdit是一款国产文本编辑器&#xff0c;历经超过15年的更新和维护&#xff0c;拥有不输业界顶级商业文本编辑器(EmEditor、UltraEdit)的实力&#xff0c;甚至在某些方面的功能更强(当然&#xff0c;各有千秋)&#xff0c;开发者对文本编辑…

Linux C/C++编程-获得套接字地址、主机名称和主机信息

【图书推荐】《Linux C与C一线开发实践&#xff08;第2版&#xff09;》_linux c与c一线开发实践pdf-CSDN博客《Linux C与C一线开发实践&#xff08;第2版&#xff09;&#xff08;Linux技术丛书&#xff09;》(朱文伟&#xff0c;李建英)【摘要 书评 试读】- 京东图书 (jd.com…

爱死机第四季(秘密关卡)4KHDR国语字幕

通过网盘分享的文件&#xff1a;love_death_robot 链接: https://pan.baidu.com/s/1bG3Xtdopenil2O_y93hY_g?pwd8kib 提取码: 8kib

目标检测入门指南:从原理到实践

目录 1. 数据准备与预处理 2. 模型架构设计 2.1 特征提取网络原理 2.2 区域提议网络(RPN)原理 2.3 特征金字塔网络(FPN)原理 2.4 边界框回归原理 2.5 非极大值抑制(NMS)原理 2.6 多尺度训练与测试原理 2.7 损失函数设计原理 3. 损失函数设计 4. 训练策略优化 5. 后…

慧集通iPaaS集成平台低代码培训-基础篇

训练使用素材&#xff1a; 1.数据源&#xff1a; 单号业务日期工厂仓库物料单位数量批次0100012022-5-1210031001030001kg500202304150100012022-5-1210031001030001kg122202304150100012022-5-1210031001030001kg1250202304150100012022-5-1210031001030002kg130202304110100…

框架(Mybatis基础配置)

mybatis的使用步骤 1.引入依赖 <!-- Mybatis依赖--><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.5</version></dependency> <!-- Mysql连接依赖-->…

2、pycharm常用快捷命令和配置【持续更新中】

1、常用快捷命令 Ctrl / 行注释/取消行注释 Ctrl Alt L 代码格式化 Ctrl Alt I 自动缩进 Tab / Shift Tab 缩进、不缩进当前行 Ctrl N 跳转到类 Ctrl 鼠标点击方法 可以跳转到方法所在的类 2、使用pip命令安装request库 命令&#xff1a;pip install requests 安装好了…

常见中间件漏洞复现

1.tomcat 1.1 CVE-2017-12615(put上传) 当在Tomcat的conf&#xff08;配置目录下&#xff09;/web.xml配置文件中添加readonly设置为false时&#xff0c;将导致该漏洞产 ⽣&#xff0c;&#xff08;需要允许put请求&#xff09; , 攻击者可以利⽤PUT方法通过精心构造的数据包…

JavaWeb开发(五)Servlet-ServletContext

1. ServletContext 1.1. ServletContext简介 1.1.1. ServletContext定义 ServletContext即Servlet上下文对象&#xff0c;该对象表示当前的web应用环境信息。 1.1.2. 获取ServletContext对象: &#xff08;1&#xff09;通过ServletConfig的getServletContext()方法可以得到…

【Redis】集群配置(主从复制 哨兵搭建)

文章目录 集群配置主从复制哨兵搭建 集群配置 Redis 集群提供了三种分布式方案&#xff1a; 主从模式&#xff1a;一个主节点和一个或多个从节点&#xff0c;主节点负责写操作&#xff0c;从节点负责读操作&#xff0c;实现读写分离&#xff0c;分担主节点的压力。 哨兵模式…

设计模式の状态策略责任链模式

文章目录 前言一、状态模式二、策略模式三、责任链模式 前言 本篇是关于设计模式中的状态模式、策略模式、以及责任链模式的学习笔记。 一、状态模式 状态模式是一种行为设计模式&#xff0c;核心思想在于&#xff0c;使某个对象在其内部状态改变时&#xff0c;改变该对象的行为…

【设计模式】 基本原则、设计模式分类

设计模式 设计模式是软件工程中的一种通用术语&#xff0c;指的是针对特定问题的经过实践验证的解决方案。设计模式并不是最终的代码实现&#xff0c;而是描述了如何解决某一类问题的思路和方法。 如果熟悉了设计模式&#xff0c;当遇到类似的场景&#xff0c;我们可以快速地…

二、github基础

Github基础 备用github.com网站一、用户界面-Overview&#xff08;概览&#xff09;1用户信息2 导航栏3 热门仓库4 贡献设置5贡献活动6搜索和筛选7自定义收藏8贡献统计9最近活动10其他链接 二、用户界面-Repositories&#xff08;仓库&#xff09;1 libusb_stm322 savedata3 Fi…

nature reviews genetics | 需要更多的针对不同种族的癌症基因组图谱研究,促进精准治疗和维护治疗公平权益

–https://doi.org/10.1038/s41576-024-00796-w Genomic landscape of cancer in racially and ethnically diverse populations 研究团队和单位 Ulrike Peters–Public Health Sciences Division, Fred Hutchinson Cancer Center Claire E. Thomas–Public Health Scienc…

选择器(结构伪类选择器,伪元素选择器),PxCook软件,盒子模型

结构为类选择器 伪元素选择器 PxCook 盒子模型 (内外边距&#xff0c;边框&#xff09; 内外边距合并&#xff0c;塌陷问题 元素溢出 圆角 阴影: 模糊半径&#xff1a;越大越模糊&#xff0c;也就是越柔和 案例一&#xff1a;产品卡片 <!DOCTYPE html> <html lang&q…

vue2+echarts实现水球+外层动效

实现效果 安装echarts-liquidfill 需要安装echarts-liquidfill&#xff01;&#xff01;&#xff01;需要安装echarts-liquidfill&#xff01;&#xff01;&#xff01;需要安装echarts-liquidfill&#xff01;&#xff01;&#xff01; 安装命令 npm install echarts-liqui…

OpenStack的核心组件、主要特点和使用场景

OpenStack 是一个开源的云计算平台&#xff0c;主要用于构建和管理公共及私有云环境。它由多个模块组成&#xff0c;提供虚拟化资源管理、存储管理、网络配置等功能&#xff0c;旨在为数据中心提供自动化的、灵活的云基础设施服务。OpenStack最初由NASA和Rackspace共同开发&…

Java 代码编译和解析方法信息

使用 javassist 可以操作字节码文件&#xff0c;我分享一下一个简单的编译和类方法解析代码。 什么是 Javassist&#xff1f; Javassist 是一个强大的字节码操作工具&#xff0c;它提供了在运行时编辑 Java 字节码的能力。通过Javassist&#xff0c;开发人员可以动态地创建和…

SpringCloud源码分析-Lettue Redis

redis connection异步发送 底层是nio channel

ELK入门教程(超详细)

什么是ELK&#xff1f; ELK是Elasticsearch、Logstash、Kibana三大开源框架首字母大写简称(后来出现的filebeat属于beats家族中的一员&#xff0c;可以用来替代logstash的数据收集功能&#xff0c;比较轻量级)&#xff0c;也被称为Elastic Stack。 Filebeat Filebeat是用于转…