首页 / 资讯中心 / 文章详情

IncludeOS TCP 集成测试完全指南:从 VirtualBox 双机联调到源码级状态机验证

IncludeOS TCP 集成测试完全指南:从 VirtualBox 双机联调到源码级状态机验证 ★ FEATURED ARTICLE
操作系统云原生虚拟化网络【免费下载链接】IncludeOSA minimal, resource efficient unikernel for cloud services项目地址https://gitcode.com/gh_mirrors/in/IncludeOS点击查看免费下载本指南以test/integration/net/tcp/目录下的 TCP 集成测试为线索系统讲解如何在 IncludeOS unikernel 中构建、启动一个 TCP 测试服务并用宿主机 Python 脚本对 TCP 栈进行端到端验证。读完本文你将掌握该测试的完整运行方式含 VirtualBox NAT 端口转发配置、六组测试用例各自验证的 TCP 能力以及 IncludeOS 的 TCP API、连接状态机与相关源码实现细节。一、测试概览与目录结构IncludeOS 的 TCP 集成测试位于仓库的 test/integration/net/tcp 目录采用unikernel 服务端 宿主机 Python 客户端的双端结构文件角色service.cppIncludeOS unikernel 内的 TCP 测试服务编译为net_tcp.elf.bintest.py宿主机 Python 测试脚本通过 vmrunner 驱动虚拟机并充当 TCP 对端debug.py面向 IPv4 的简化调试脚本Python 2 风格用于快速手工验证vm.json虚拟机配置virtio 网卡、固定 MAC、256 MiB 内存CMakeLists.txt测试服务的 CMake 构建脚本linux/在 Linux 用户态非 unikernel运行同一测试的配置与脚本该测试覆盖了 TCP 栈的多项核心能力监听与连接分配、小/中/大三种规模的收发、TCP 状态机迁移含主动关闭的完整流程、资源释放以及出站 Internet 连接。二、快速开始两行命令跑通测试根据 README 的说明测试分两步执行# 1. 启动 TCP 测试服务构建并启动 IncludeOS 虚拟机镜像 ./test.sh # 2. 在宿主机运行 Python 测试端 python test.py $GUEST_IP $HOST_IP其中$GUEST_IP与$HOST_IP均为可选参数默认值分别为GUEST10.0.0.42、HOST10.0.0.1。脚本的作用是在服务运行期间从宿主机发起真实的 TCP 连接来验证 IncludeOS TCP 栈的收发行为。需要特别说明的是README 中标注的默认地址10.0.0.42与实际源码 service.cpp 中配置的10.0.0.44略有出入——服务端通过network_config()将 unikernel 的 IPv4 地址设置为10.0.0.44并配置网关10.0.0.1、DNS8.8.8.8。因此实际联调时客户端应使用10.0.0.44作为 GUEST 地址可参考 debug.py 中的默认值。若要让 unikernel 发起出站 Internet 连接必须在宿主/网关上设置正确的转发规则详见下文「出站连接与网络配置」。三、双端联动机制vmrunner 事件驱动的测试编排这套测试的精髓在于 test.py 与虚拟机之间的输出触发on_output协作unikernel 内的服务在完成某个阶段的准备后打印标记文本Python 脚本捕获到该输出即执行对应的连接测试。# Get an auto-created VM from the vmrunner vm vmrunner.vms[0] # Add custom event-handler vm.on_output(TEST1, test1) vm.on_output(TEST2, test2) vm.on_output(TEST3, test3) vm.on_output(TEST4, test4) vm.on_output(TEST5, test5) if len(sys.argv) 1: vm.boot(image_namestr(sys.argv[1])) else: # Boot the VM, taking a timeout as parameter vm.boot(120, image_namenet_tcp.elf.bin)脚本默认启动镜像net_tcp.elf.bin超时 120 秒。端口与测试阶段的对应关系定义在脚本头部TEST1 8081 TEST2 8082 TEST3 8083 TEST4 8084 TEST5 8085同时service.cpp 中定义了包含 8080 在内的六组端口tcp::port_t TEST0{8080},TEST1{8081}, TEST2{8082}, TEST3{8083}, TEST4{8084}, TEST5{8085};端口 8080 用于 Test 0 的回显压力验证80818085 则分别对应 Python 脚本的test1test5回调。虚拟机的两种角色client 与 serverPython 脚本中的connect()与listen()分别模拟 TCP 客户端与服务端connect()向 GUEST 的指定端口发起连接进入循环recv(1024)后sendall(data)原样回传从而验证服务端发送、客户端接收、客户端回传的完整数据路径listen()绑定 HOST 的端口等待连接收到数据后回传并关闭连接——这是为了验证 unikernel 的出站连接能力即 unikernel 主动connect到宿主机。有趣的是脚本中 GUEST 与 HOST 的默认值使用了 IPv6 链路本地地址fe80:...%bridge43说明这套测试在 vmbuild/vmrunner 的标准桥接网络bridge43下同时覆盖 IPv4 与 IPv6 场景。四、构建配置与虚拟机规格CMakeLists.txt 揭示了镜像的构建方式project (service) include(os) set(SOURCES service.cpp ) os_add_executable(net_tcp TCP test ${SOURCES}) os_add_drivers(net_tcp virtionet e1000 vmxnet3) os_add_stdout(net_tcp default_stdout) configure_file(test.py ${CMAKE_CURRENT_BINARY_DIR})os_add_executable(net_tcp ...)生成名为net_tcp的 unikernel 可执行镜像os_add_drivers同时注册了 virtio-net、e1000、vmxnet3 三类网卡驱动使其能适配不同虚拟化平台configure_file(test.py ...)会把测试脚本复制到构建输出目录方便与镜像一同交付。虚拟机本身在 vm.json 中定义{ net : [{device : virtio, mac : c0:01:0a:00:00:2a}], mem : 256 }即一块 virtio 网卡固定 MACc0:01:0a:00:00:2a、256 MiB 内存。该 MAC 以c0:01:0a开头对应 IPv4 链路10.0.x.x段的常规分配规律。五、六组测试用例深度解析5.1 测试数据构造service.cpp 在Service::start()中构造了三种规模的测试负载std::string small, big, huge; int S{150}, B{1500}, H{150000}; std::string TEST_STR {Kappa!}; // Default MSL is 30s. Timeout 2*MSL. // To reduce test duration, lower MSL to 3s. milliseconds MSL_TEST 3s;small150 个Kappa!拼接约 1 KB 级big以start-开头、-end结尾中间拼接 1500 个递增数字约 10 KB 级huge150000 个Kappa!拼接约 1.2 MB 级用于验证 TCP 在大数据量下的分片、重组与滑动窗口行为。同时将 MSL最大报文段生存期从默认的 30 秒下调为 3 秒以缩短 TIME-WAIT 阶段的测试等待时间——因为连接关闭后需要等待2 × MSL才能确认资源被完全释放。5.2 Test 08080 端口回显压力验证Circle of Evil// Trigger with e.g.: // dd if/dev/zero bs9000 count1000000 | nc 10.0.0.44 8080 | grep Received -a tcp.listen(TEST0).on_connect([](tcp::Connection_ptr conn) { INFO(Test 0, Circle of Evil); conn-on_read(424242, conn { recv buffer-size(); chunks; if (chunks % 100 0) { std::string res std::string(Received ) util::Byte_r(recv).to_string() \n; printf(%s, res.c_str()); auto new_buf std::make_sharedstd::pmr::vectoruint8_t(res.begin(), res.end()); conn-write(new_buf); } conn-write(buffer); }); });该用例在连接建立后注册一个容量高达 424242 字节的读请求收到多少数据就原样写回多少回显每累计 100 个数据块打印一次累计接收量。注释中的命令展示了如何手工触发压力测试dd if/dev/zero bs9000 count1000000 | nc 10.0.0.44 8080 | grep Received -a5.3 Test 1小字符串精确收发tcp.listen(TEST1).on_connect([](tcp::Connection_ptr conn) { INFO(Test 1, SMALL string (%u), small.size()); conn-on_read(small.size(), conn { CHECKSERT(std::string((char*)buffer-data(), buffer-size()) small, Received SMALL); INFO(Test 1, Succeeded, TEST2); conn-close(); }); conn-write(small); });连接建立后服务端立即写入small字符串并注册一个容量恰好等于small.size()的读请求。只有当接收到的内容与small完全一致时CHECKSERT断言才会通过随后关闭连接。5.4 Test 2大字符串累积校验tcp.listen(TEST2).on_connect([](tcp::Connection_ptr conn) { INFO(Test 2, BIG string (%u), big.size()); auto response std::make_sharedstd::string(); conn-on_read(big.size(), [response, conn] (tcp::buffer_t buffer) { response-append(std::string{(char*)buffer-data(), buffer-size()}); if(response-size() big.size()) { CHECKSERT((*response big), Received BIG); INFO(Test 2, Succeeded, TEST3); conn-close(); } }); conn-write(big.data(), big.size()); });由于big超过单个 TCP 段的承载能力数据会被拆分为多个段到达。服务端利用on_read(big.size(), ...)让回调累积拼接直到总长度等于big.size()才进行内容比对——这直接验证了 TCP 流的按序重组能力。5.5 Test 3超大字符串分块收发tcp.listen(TEST3).on_connect([](tcp::Connection_ptr conn) { INFO(Test 3, HUGE string (%u), huge.size()); auto temp std::make_sharedBuffer(huge.size()); conn-on_read(16384, [temp, conn] (tcp::buffer_t buffer) { memcpy(temp-data temp-written, buffer-data(), buffer-size()); temp-written buffer-size(); // when all expected data is read if(temp-written huge.size()) { bool OK (temp-str() huge); CHECKSERT(OK, Received HUGE); INFO(Test 3, Succeeded, TEST4); } }); auto half huge.size() / 2; conn-on_write(half { CHECKSERT(n half, Wrote half HUGE (%lu bytes), n); }); conn-write(huge.data(), half); conn-write(huge.data()half, half); conn-close(); });该用例同时验证发送与接收两个方向发送侧把huge拆成两半写入并通过on_write校验每半恰好发送half字节接收侧用on_read(16384, ...)以 16 KiB 的粒度分块收集全部到位后整体比对。Buffer结构written、read、data、size跟踪写入进度是对大流量场景下 TCP 收发一致性的强校验。5.6 Test 4连接状态机与主动关闭这是全测试中对TCP 状态机验证最深入的一组tcp.listen(TEST4).on_connect([](tcp::Connection_ptr conn) { INFO(Test 4,Connection/TCP state); // There should be at least one connection. CHECKSERT(stack().tcp().active_connections() 0, There is (0) open connection(s)); // Test if connected. CHECKSERT(conn-is_connected(), Is connected); // Test if writable. CHECKSERT(conn-is_writable(), Is writable); // Test if state is ESTABLISHED. CHECKSERT(conn-is_state({ESTABLISHED}), State: ESTABLISHED); INFO(Test 4, Active close); CHECKSERT(!conn-is_closing(), Is NOT closing); // Setup on_disconnect event conn-on_disconnect([](auto conn, tcp::Connection::Disconnect) { CHECKSERT(conn-is_closing(), Is closing); CHECKSERT(conn-is_state({FIN-WAIT-2}), State: FIN-WAIT-2); Timers::oneshot(1s, [conn] (auto) { CHECKSERT(conn-is_state({TIME-WAIT}), State: TIME-WAIT); INFO(Test 4, Succeeded. Trigger TEST5); OUTGOING_TEST({gateway, TEST5}); }); Timers::oneshot(5s, [] (Timers::id_t) { FINISH_TEST(); }); }); // Test for active close. conn-close(); CHECKSERT(!conn-is_writable(), Is NOT writable); CHECKSERT(conn-is_state({FIN-WAIT-1}), State: FIN-WAIT-1); });验证路径非常清晰连接建立后必须处于ESTABLISHED状态且is_connected()、is_writable()为真调用conn-close()发起主动关闭立即断言进入FIN-WAIT-1且不可写收到对端 ACK 后迁移到FIN-WAIT-21 秒后断言进入TIME-WAIT此时通过OUTGOING_TEST({gateway, TEST5})触发下一阶段——unikernel 主动向网关IPv6 链路本地地址的 8085 端口发起出站连接5 秒后调用FINISH_TEST()进入收尾校验。5.7 出站连接与资源释放收尾FINISH_TEST()是整套测试的终点void FINISH_TEST() { INFO(TEST, Started 2 x MSL 100ms timeout.); Timers::oneshot(2 * MSL_TEST 100ms, [] (Timers::id_t) { INFO(TEST, Verify release of resources); CHECKSERT(stack().tcp().active_connections() 0, No (0) active connections); printf(# TEST SUCCESS #\n); }); }它等待2 × MSL 100msMSL 已从默认 30s 降为 3s因此约 6.1 秒然后断言active_connections() 0证明所有连接及其占用的资源读缓冲、写队列、端口绑定都已随 TIME-WAIT 结束而彻底释放。# TEST SUCCESS #是整套测试成功的最终标志。出站连接的代码路径在OUTGOING_TEST()与OUTGOING_TEST_INTERNET()中体现void OUTGOING_TEST(Socket outgoing) { INFO(TEST, Outgoing Connection (%s), outgoing.to_string().c_str()); stack().tcp().connect(outgoing, [](tcp::Connection_ptr conn) { CHECKSERT(conn ! nullptr, Connection successfully established.); conn-on_read(small.size(), ...); conn-write(small); conn-on_disconnect([](tcp::Connection_ptr conn, tcp::Connection::Disconnect) { CHECK(true, Connection closed by server); CHECKSERT(conn-is_state({CLOSE-WAIT}), State: CLOSE-WAIT); conn-close(); }) .on_close([]{ OUTGOING_TEST_INTERNET(TEST_ADDR_TIME); }); }); }当 unikernel 主动发起连接后对方Python 脚本的listen(TEST5)会接收、回传并关闭连接此时 unikernel 侧应进入CLOSE-WAIT随后on_close回调触发最后一步——OUTGOING_TEST_INTERNET(TEST_ADDR_TIME)尝试解析并连接真实外网主机india.colorado.edu:13daytime 服务完成对 DNS 解析与外部连接能力的验证。六、TCP 状态机与 API 的源码级验证测试中反复出现的is_state({ESTABLISHED})、FIN-WAIT-1、CLOSE-WAIT、TIME-WAIT等状态全部定义在 connection_states.hpp 中。IncludeOS 的 TCP 连接状态机完整实现了 RFC 793 定义的全部状态状态定义位置测试覆盖点CLOSEDconnection_states.hpp资源释放后的最终态Test 收尾LISTENINGconnection_states.hpp服务端监听tcp.listenSYN-SENTconnection_states.hpp出站连接建立Test 5SYN-RCVconnection_states.hpp被动打开的三次握手中间态ESTABLISHEDconnection_states.hppTest 4 的核心断言FIN-WAIT-1 / FIN-WAIT-2connection_states.hppTest 4 主动关闭路径CLOSE-WAITconnection_states.hppTest 5 对端先关闭场景CLOSING / LAST-ACK / TIME-WAITconnection_states.hppTest 4 的 TIME-WAIT 断言状态的判定通过is_state()实现——它既支持按状态对象比较is_state(const State)也支持按字符串比较connection.hpp后者正是测试中conn-is_state({ESTABLISHED})的调用方式。TCP 可调参数与测试中的运用TCP 类的公开 API 提供了丰富的协议参数测试用到了其中两个其余可在实际服务中按需配置API测试中的用法说明set_MSL(ms)tcp.set_MSL(3s)设置最大报文段生存期决定 TIME-WAIT 时长连接在 2×MSL 后关闭set_total_bufsize(bytes)tcp.set_total_bufsize(64_MiB)限制 TCP 层可用的总内存池上限防止大数据测试耗尽内存listen(port)80808084绑定端口开始监听返回Listenerconnect(socket)Test 5发起出站连接可附带ConnectCallbackset_window_size(wsize, factor)—设置通告窗口可配窗口缩放因子因子最大 14对应 RFC 7323set_DACK(timeout)—延迟 ACK 超时RFC 1122set_SACK(bool)—选择性确认开关RFC 2018set_max_syn_backlog(n)—SYN 队列最大积压set_min/max_bufsize—缓冲区大小范围须为 2 的幂其中set_MSL与set_total_bufsize在 service.cpp 中的调用如下auto tcp inet.tcp(); // reduce test duration tcp.set_MSL(MSL_TEST); // Modify total buffers assigned to TCP here tcp.set_total_bufsize(64_MiB);从源码看set_total_bufsize最终会同步到 TCP 内部的内存池mempool_tcp.hpp所有连接的读写缓冲都由该池分配。此外连接对象的 TCBTransmission Control Block 完整保存了 RFC 793 定义的发送序列变量SND.UNA/SND.NXT/SND.WND、接收序列变量RCV.NXT/RCV.WND以及拥塞控制变量cwnd、ssthresh并实现了 New Reno 快速恢复RFC 6582、Limited TransmitRFC 3042等拥塞控制机制。测试中 424242 字节的读缓冲与huge字符串的分块收发正是对这些机制的实战压测。连接事件回调模型测试大量使用事件回调这些回调定义于 connection.hppon_connect(cb)连接建立时触发出站连接失败时回调参数为nullptrL68-L80on_read(recv_bufsz, cb)当收到PSHPUSH标志或接收缓冲已满时触发recv_bufsz决定读缓冲大小L82-L94on_disconnect(cb)对端发送 FIN表示想关闭或收到 RST连接被重置时触发回调携带Disconnect原因CLOSING/REFUSED/RESET默认行为是本地也关闭连接L125-L139on_close(cb)连接彻底关闭后触发此后连接对象不可再用适合清理连接副本L141-L153on_write(cb)一次写请求发送完成后触发仅代表数据已发出而非对端已收到L155-L168。Test 4 的on_disconnect链式用法.on_close([]{ OUTGOING_TEST_INTERNET(TEST_ADDR_TIME); })展示了如何利用事件编排多阶段测试流程。七、VirtualBox 环境实操README 原始配方README 特别提供了在 OS X VirtualBox 上运行该测试的完整配方适用于没有 vmrunner 桥接环境的读者。完整步骤如下构建镜像执行make注意先导出LD_INC与AR_INC环境变量启动虚拟机/includeos_repo/etc/vboxrun.sh IncludeOS_TCP_Test.img TCP_test实际镜像名以构建产物为准例如net_tcp.elf.bin关闭虚拟机测试结束后 Kill VM打开 VirtualBox 网络设置Virtualbox TCP_test Settings Network将 Adapter 1 改为 NAT进入Advanced Port Forwarding添加端口转发规则添加以下端口转发规则$ vboxmanage showvminfo TCP_test ... NIC 1 Rule(0): name Rule 1, protocol tcp, host ip 127.0.0.1, host port 8081, guest ip , guest port 8081 NIC 1 Rule(1): name Rule 2, protocol tcp, host ip 127.0.0.1, host port 8082, guest ip , guest port 8082 NIC 1 Rule(2): name Rule 3, protocol tcp, host ip 127.0.0.1, host port 8083, guest ip , guest port 8083 NIC 1 Rule(3): name Rule 4, protocol tcp, host ip 127.0.0.1, host port 8084, guest ip , guest port 8084即把宿主机的 80818084 端口分别转发到虚拟机的同名端口对应 Test 1Test 4。随后重新启动虚拟机重复步骤 2由于 NAT 转发已经生效即可在宿主机用回环地址直接验证$ python test.py 127.0.0.1 127.0.0.1注意NAT 端口转发规则只覆盖 80818084Test 08080 回显压力测试与 Test 5出站连接需要 HOST 侧监听 8085如需验证可参照同样方式补充转发规则。八、出站连接与网络配置README 明确指出To make outgoing internet connection work, correct forwarding rules needs to be setup.要使出站 Internet 连接可用必须设置正确的转发规则。服务端在启动时通过 Inet::network_config 完成 IPv4 网络配置inet.network_config( { 10, 0, 0, 44 }, // IP { 255,255,255, 0 }, // Netmask { 10, 0, 0, 1 }, // Gateway { 8, 8, 8, 8 } // DNS ); inet.add_addr({fe80::e823:fcff:fef4:85bd}, 64); static ip6::Addr gateway{fe80::e823:fcff:fef4:83e7};同时配置了 IPv6 链路本地地址与网关。测试流程中OUTGOING_TEST_INTERNET依赖stack().resolve(host, callback)进行 DNS 解析此处解析india.colorado.edu再对解析出的地址发起connect。要让这一步在 NAT/桥接网络下真正成功宿主机需开启相应的地址转换与转发如 iptables MASQUERADE 或 VirtualBox NAT 的端口转发这也正是 README 强调转发规则的用意所在。此外在 Linux 用户态USERSPACE_LINUX构建时service.cpp 会先创建虚拟网络设备#ifdef USERSPACE_LINUX extern void create_network_device(int N, const char* route, const char* ip); create_network_device(0, 10.0.0.0/24, 10.0.0.1); #endif九、Linux 用户态运行模式除了在虚拟机中运行同一份 service.cpp 还可以编译为 Linux 用户态程序省去虚拟化开销便于调试。linux/run.sh 的流程是编译并安装 IncludeOS 的 Linux 用户态库$INCLUDEOS_SRC/linux/build可用num_jobs控制并行度默认-j32在本目录build/下用linux.service.cmake见 cmake/linux.service.cmake构建测试服务以sudo运行产物二进制需要创建/dev/net/tap之类的 tun/tap 设备。对应的 linux/CMakeLists.txt 将服务命名为tcp_test并复用上一级的../service.cpp作为唯一源码。十、集成到自动化测试框架该测试已接入仓库的 CI 冒烟测试。在 test/test.sh 中smoke_tests()将test/integration/net/tcp列为关键冒烟用例之一smoke_tests(){ nix-shell ./unikernel.nix $CCACHE_FLAG --argstr unikernel ${INTEGRATION_TESTS}/net/udp --arg doCheck true nix-shell ./unikernel.nix $CCACHE_FLAG --argstr unikernel ${INTEGRATION_TESTS}/net/tcp --arg doCheck true nix-build ./unikernel.nix $CCACHE_FLAG --argstr unikernel ${INTEGRATION_TESTS}/memory/paging --arg doCheck true nix-build ./unikernel.nix $CCACHE_FLAG --argstr unikernel ${INTEGRATION_TESTS}/kernel/smp --arg doCheck true }同时test.sh 将net/tcp列入unsandbox_list——因为该测试需要创建 tun 设备与网桥bridge43在沙箱环境中会报错failed to create tun device: Operation not permitted因此必须以非沙箱方式运行。测试断言使用 IncludeOS 提供的CHECK/CHECKSERT宏定义于 api/info#define CHECK(TEST, TEXT, ...) kprintf(%16s[%s] TEXT \n,, TEST ? x : , ##__VA_ARGS__) #define CHECKSERT(TEST, TEXT, ...) CHECK(TEST, TEXT, ##__VA_ARGS__), assert(TEST)CHECK打印[x]通过或[ ]失败的检查项仅用于观测CHECKSERT在CHECK基础上叠加assert失败即触发断言中止运行。因此# TEST SUCCESS #出现即代表从 TCP 连接建立、数据收发、状态迁移到资源释放的全部断言依次通过。总结IncludeOS 的 TCP 集成测试是一套麻雀虽小、五脏俱全的协议验证体系它以 service.cpp 承载六组覆盖小、中、大、超大流量与状态机迁移的用例以 test.py 通过 vmrunner 事件驱动完成宿主机侧的双向验证并以 VirtualBox NAT 端口转发或 Linux 用户态模式作为补充运行环境。对开发者而言它既是验证 TCP 栈正确性的回归测试也是学习 IncludeOS TCP APIlisten、connect、on_read、on_disconnect、set_MSL等与 RFC 793 状态机实现的最佳示例。赞分享操作系统云原生虚拟化网络【免费下载链接】IncludeOSA minimal, resource efficient unikernel for cloud services项目地址https://gitcode.com/gh_mirrors/in/IncludeOS点击查看免费下载相关推荐IncludeOS DHCP 客户端功能测试指南从 negotiate_dhcp 调用到网桥联调验证IncludeOS DHCP 客户端功能测试指南从 negotiate_dhcp 调用到网桥联调验证 导读 本指南围绕 IncludeOS 仓库中的 DHCP操作系统云原生虚拟化网络AxonHub 负载均衡集成测试完全指南从 TESTING_GUIDE 到源码级验证AxonHub 负载均衡集成测试完全指南从 TESTING_GUIDE 到源码级验证 本指南以 TESTING_GUIDE.md https://link.gAI 应用API网关LLM 网关后端前端IncludeOS 内建 DHCP 服务器测试指南从桥接网络配置到 DHCPD 状态机源码解析IncludeOS 内建 DHCP 服务器测试指南从桥接网络配置到 DHCPD 状态机源码解析 本文以仓库内 test/integration/net/dhc操作系统云原生虚拟化网络上一篇CL4R1T4S教育资源包教师使用指南与学生活动设计下一篇Higress网关CPU/内存优化实战将资源占用降低50%的架构级调优方案创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
阅读完成 · 觉得有帮助?
咨询建站