10 倍提升应用性能的 10 个建议

1. 10 倍提升应用性能的 10 个建议

Original: https://www.nginx.com/blog/10-tips-for-10x-application-performance/

提升 Web 应用的性能从未像今天这样刻不容缓。在线经济活动的比例日益提高, 就连发展中国家和地区的经济活动都已经有 5% 以上在线进行了(相关数据请参考本文后面的资源)。在这个超级链接、随时在线的现代世界, 用户的期望也远非昔日可比。如果你的网站不能马上响应, 你的应用不能立即运行, 用户转身就会投奔你的竞争对手。

亚马逊大约 10 年前的一项研究表明, 页面加载时间减少 1/10 秒, 能够使其营收增长 1%。另一项近期的调查也显示, 一多半受访站点所有者提到因为自己应用的性能不佳导致了收入减少或者用户流失。

一个网站到底多快才行? 页面加载每花 1 秒钟, 就有大约 4% 的用户走掉。排名最靠前的电商站点的首次交互时间为 1 至 3 秒, 这个区间的转换率最高。显而易见, Web 应用性能的重要性与日俱增。

提升性能其实不难, 难的是怎么看到结果。本文给出能够提升大约 10 倍网站性能的 10 个建议供大家参考。如此全面地涵盖各种性能优化技术, 这还是头一回, 但这些建议可能需要 NGINX 的一点支持。除了性能, 这些建议也会涉及提升安全性。

1. 建议一: 使用反向代理服务器让应用更快更安全

如果你的 Web 应用只跑在一台机器上, 那要提升其性能非常简单: 换一台更快的, 多配几个处理器, 多加几条内存, 磁盘阵列也要高速的。换了以后, 这台机器上跑的 WordPress 服务器、Node.js 或 Java 应用速度都会加快。(要是应用还会访问另一台数据库服务器, 那也简单: 找两台更快的机器, 用更快的网络连起来就行了。)

麻烦在于, 机器速度并不是问题。很多时候 Web 应用慢, 是因为要在各种任务之间切换, 一会儿要处理数千个连接上的用户请求, 一会儿要向磁盘读写文件, 一会儿又要运行应用的代码, 一会儿又要去干别的。应用服务器因此可能出现各种状况, 耗尽内存、交换文件, 或者让很多请求等待一个硬盘 I/O 之类的任务。

除了升级硬件, 其实你还可以选择另外一种完全不同的方法: 加一台反向代理服务器, 分担上述一些任务。反向代理服务器位于运行应用的机器之前, 负责处理来自外网的请求。反向代理服务器直接连到互联网, 它与应用服务器通信使用的是快速的内部网络。

反向代理服务器可以让应用服务器专注于构建页面, 然后交给反向代理向外网发送, 而不必理会用户与应用的交互。由于不必等待客户端的响应, 应用服务器的运行速度能达到接近最优的水平。

增加反向代理服务器同时也可以为 Web 服务器增添灵活性。比如, 假设执行某种任务的服务器过载了, 那随时可以再增加一台同类服务器; 而如果这台服务器挂了, 替换它也很容易。

鉴于这种灵活性, 反向代理服务器往往也是其他性能优化手段的先决条件, 比如:

  • 负载均衡(参见"建议二"), 反向代理服务器上运行负载均衡服务, 把流量平均分配给几台应用服务器。有了负载均衡, 添加应用服务器根本不需要修改应用。
  • 缓存静态文件(参见"建议三"), 图片或代码之类的可以直接请求的文件, 都可以保存在反向代理服务器中, 以便直接发给客户端。这样不仅可以更快地响应请求, 还能减轻应用服务器的负担, 加快其运行速度。
  • 保证站点安全, 可以配置反向代理服务器提升其安全级别, 通过它监控来快速识别和响应攻击, 从而保存应用服务器安全。
    NGINX 专门为使用反向代理服务器做了设计, 使其天然支持上述优化。由于使用事件驱动的处理机制, NGINX 比传统服务器效率更高。NGINX Plus 则增加了更高端的反向代理功能, 如应用体检、特有的请求路由、高级缓存和售后支持。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3STESh4g-1655368264456)(https://www.nginx.com/wp-content/uploads/2015/10/Graph-11.png)]

传统服务器与 NGINX Worker 的比较

2. 建议二: 增加负载均衡服务器

增加负载均衡服务器相对简单, 但却能显着提升站点性能和安全性。通过它把流量分配给多个服务器, 就可以不必升级 Web 服务器了。就算应用本身写得不太好, 或者难以扩展, 负载均衡都可以在不做其他改变的情况下提升用户体验。

负载均衡服务器首先是一个反向代理服务器(参见"建议一"), 负责把来自互联网的请求转发给其他服务器。这里关键在于负载均衡服务器可以支持两台以上的应用服务器, 使用一种选择算法在不同的服务器间分配请求。最简单的负载均衡算法是循环调度, 即把新请求依次转发给可用服务器中的下一台服务器。其他算法还有把请求发给活动连接最少的服务器。NGINX Plus 支持一种功能, 就是把用户会话保持在同一台服务器上, 叫做会话保持。

负载均衡服务器可以避免一台服务器过载而其他服务器过闲, 从而极大提升性能。同时, 有了它还可以让 Web 服务器扩容更简单, 因为可以选用比较便宜的服务器, 同时保证物尽其用。

可以通过负载均衡调度的协议包括 HTTP、HTTPS、SPDY、HTTP/2、WebSocket、FastCGI、SCGI、uwsgi、memcached, 以及其他一些应用形式, 包括基于 TCP 的应用和其他第四层的协议。为此, 首先要分析 Web 应用, 看性能短板在哪里, 然后再确定使用哪一个。

同一台服务器或用于负载均衡的服务器也可以承担其他任务, 比如 SSL 终止、视客户端不同支持 HTTP/1/x 或 HTTP/2、缓存静态文件。

NGINX 经常被用来做负载均衡, 更多信息请参考我们以前发的介绍性文章有关配置的文章电子书和相关的在线视频, 当然还有文档。我们的商业版本 NGINX Plus 支持更多的负载均衡功能, 如基于服务器响应时间路由负载和支持微软 NTLM 协议的负载均衡。

3. 建议三: 缓存静态及动态内容

缓存能提升 Web 应用性能, 因为可以更快地把内容交付给客户端。缓存的策略包括预处理内容、在较快的设备上存储内容、把内容保存在靠近客户端的地方, 以及同时运用这些策略。

缓存有两种。

  • 静态内容缓存, 不常变化的文件, 如图片(JPEG、PNG)和代码(CSS、JavaScript), 可以保存在边缘服务器中, 以便快速从内容或磁盘中获取。
  • 动态内容缓存, 很多 Web 应用会为每个页面请求生成全新的 HTML, 把生成的每个 HTML 都缓存一小段时间, 可能显着减少需要生成的页面总数, 同时又可以保证交付的内容足够新鲜。
    假设一个页面每秒被查看 10 次, 而你缓存它 1 秒, 那么 90% 针对这个页面的请求都将来自在缓存。如果你单独缓存静态内容, 那么即使全新生成的页面, 很可能大部分都来自缓存的内容。

缓存 Web 应用生成内容的技术主要分三种。

  • 把内容放到离用户近的地方。离用户近, 传输时间少。
  • 把内容放到较快的机器上。机器快, 检索速度快。
  • 把内容从过度使用的机器中拿走。有时候机器会比在专注执行特定任务时慢很多, 那是因为太多任务让它们分心。这时候把内容拿到其他机器上, 不仅对缓存的内容有好处, 对非缓存的内容同样有利, 因为托管它们的主机的负担减轻了。
    Web 应用的缓存可以在 Web 应用服务器内部或外部实现。首先, 考虑缓存动态内容, 以减轻应用服务器的负载。其次, 缓存用于静态内容(包括那些动态生成内容的临时副本), 进一步减轻应用服务器的负担。然后, 考虑把缓存转移到其他更快或更靠近用户的机器, 给应用服务器减负, 缩短传输时间。

用好缓存能显着加快应用的响应速度。对很多网页来说, 大图片之类的静态数据, 往往占据一半以上的内容。不用缓存, 查询和传输这类数据可能会花好几秒钟, 而用缓存, 则可能只要花几分之一秒。

可以举一个例子来说明怎么使用缓存, NGINX 和 NGINX Plus 通过两个指令来设置缓存: proxy_cache_pathproxy_cache 指定缓存的位置和大小、最长缓存时间以及其他参数。使用第三个(也是很受欢迎的)指令 proxy_cache_use_stale, 甚至可以告诉缓存在本来应该提供新鲜内容的服务器太忙或宕机时, 提供原来的旧文件, 对客户端来说, 拿到内容总比拿不到强。从用户角度看, 这样也可以树立你的站点或应用非常稳定的形象。

NGINX Plus 支持高级缓存功能, 包括缓存净化(caching purging)和通过控制板以可视化的形式展示缓存状态, 实现实时监控。

要了解 NGINX 中关于缓存的更多信息, 可以看看参考文档和 NGINX Plus Admin Guide 中的 NGINX Content Caching

注意: 缓存涉及开发、决策和运维, 完善的缓存策略, 比如本文提到的这些, 能够体现从 DevOps 角度考虑的价值。也说是说, 开发人员、架构师、运维人员此时携手, 共同保障一个网站的功能、响应时间、安全和业务目标。

4. 建议四: 压缩数据

压缩同样能极大提升性能。图片、视频、音乐等文件都有非常成熟和高效的压缩标准(JPEG 和 PNG、MPEG-4、MP3), 任何一个标准都可以把文件大小缩小一个数量级甚至更多。

文本文件, 包括 HTML(纯文本和 HTML 标签)、CSS 和 JavaScript 代码, 经常在不压缩的情况下传输。压缩这些数据对提升 Web 应用的感知性能有时候特别明显, 尤其是移动用户的网络很慢又不稳定的情况下。

因为文本数据通过对于页面交互能够起到必要的支援作用, 而多媒体数据则更多是锦上添花的作用。聪明的内容压缩可以把 HTML、JavaScript、CSS 等文本内容的缩小 30% 以上, 因此能够相应地减少加载时间。

如果你使用 SSL, 压缩又可以减少必须经过 SSL 编码的数据量, 从而补偿了压缩这些数据的 CPU 时间。

压缩数据的方法非常多。比如, 建议六中关于 HTTP/2 的部分就描述了一个新颖的压缩思路, 特别适合首部数据压缩。还有一个关于文本压缩的例子, 就是可以在 NGINX 中开启 GZIP 压缩。预压缩文本数据之后, 可以使用 gzip_static 指令直接发送. gz 文件。

5. 建议五: 优化 SSL/TLS

越来越多的网站在使用 Secure Sockets Layer(SSL)及后来的 Transport Layer Security(TLS)协议。SSL/TLS 通过加密从源服务器发送给用户的数据来提升网站安全性。Google 会提升使用 SSL/TLS 的网站的搜索引擎排名, 将有力地推动这一进程。

尽管采用率越来越高, 但 SSL/TLS 造成的性能损失也困扰着很多网站。SSL/TLS 拖慢网站的原因有两个。

  1. 每次打开新连接的初次握手都必须创建加密密钥, 而浏览器使用 HTTP/1.x 对每个服务器建立多个连接的方式进一步加剧了这个问题。
  2. 服务器端加密数据和客户端解密数据的操作同样也是开销。

为了鼓励人们使用 SSL/TLS, HTTP/2 和 SPDY(参见建议六)的作者将这两个协议设计为只让浏览器针对一次会话建立一个连接。这样就把 SSL 导致性能降低的两个主要原因之一消灭掉了。然而, 说到优化 SSL/TLS 性能, 还是有很多事情可做。

优化 SSL/TLS 的方法因 Web 服务器而异。以 NGINX 为例, NGINX 使用 OpenSSL, 运行于普通机器上, 能够提供接近定制机器的性能。NGINX SSL performance 详细介绍了如何将 SSL/TLS 加密和解密的开销降至最低。

此外, 这里还有一篇文章, 介绍了很多种提升 SSL/TLS 性能的方法。简单总结一下, 涉及的技术主要有如下几种。

  • 会话缓存。使用 ssl_session_cache 指令开启缓存, 缓存每次 SSL/STL 连接时用到的参数。
  • 会话票或 ID。把特定 SSL/TLS 会话的信息保存为一个会话票或 ID, 以便连接重用, 而不必重新握手。
  • OCSP 封套。通过缓存 SSL/TLS 证书信息减少握手时间。

NGINX 和 NGINX Plus 都可以来终止 SSL/TLS, 即处理客户端信息的加密和解密, 同时与其他服务器保持明文通信。在 NGINX 或 NGINX Plus 中设置处理 SSL/TLS 终止可以采取这几个步骤。而对于在接受 TCP 连接的服务器上使用 NGINX Plus 而言, 可以参考这里的设置步骤

6. 建议六: 实现 HTTP/2 或 SPDY

已经使用 SSL/TLS 的站点, 如果再使用 HTTP/2 或 SPDY 则很可能提升性能, 因为一个连接只要一次握手。尚未使用 SSL/TLS、HTTP/2 和 SPDY 的站点切换到 SSL/TLS(通常会降低性能), 从响应速度方面看, 可能是一次倒退。

谷歌 2012 年开始 SPDY 项目, 致力于在 HTTP/1.x 之上实现更快的速度。HTTP/2 则是 IETF 最近批准的基于 SPDY 的标准。SPDY 得到了广泛支持, 但很快就将被 HTTP/2 取代。

SPDY 和 HTTP/2 的关键在于只用一个连接, 而非多个连接。这一个连接是多路复用的, 因此可以同时承载多个请求和响应。

只维持一个连接, 可以省掉多个连接所需的设置和管理消耗。而且一个连接对 SSL 特别重要, 因为可以将 SSL/TLS 建立安全连接所需的握手时间降至最少。

SPDY 协议要求使用 SSL/TLS, HTTP/2 并没有正式要求, 但目前所有支持 HTTP/2 的浏览器都只会在启用 SSL/TLS 的情况下才会使用它。换句话说, 支持 HTTP/2 的浏览器只有在网站使用 SSL 且服务器接受 HTTP/2 流量的情况下才会使用 HTTP/2。否则, 浏览器会基于 HTTP/1.x 通信。

实现了 SPDY 或 HTTP/2 之后, 域名分片、资源合并、图片精灵等之前针对 HTTP 的性能优化措施就用不着了。因此也可以简化代码和部署。关于 HTTP/2 会带来哪些变化, 可以参考我们的这个白皮书

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NlSaoj5F-1655368264458)(https://www.nginx.com/wp-content/uploads/2015/10/http2-27.png)]

NGINX 很早就开始支持 SPDY, 而且今天使用 SPDY 的大多数站点都在运行 NGINX。NGINX 同样率先支持了 HTTP/2, 2015 年 9 月, NGINX 开源和 NGINX Plus 开始支持 HTTP/2。

随着时间推移, NGINX 希望大多数站点启用 SSL 并迁移到 HTTP/2。这样不仅可以让网站更安全, 而且随着新的优化技术不断涌现, 也可以通过简单的代码实现更高的性能。

7. 建议七: 升级软件

提升应用性能的一个简单的方法, 就是根据可靠性及性能选择软件。此外, 高质量组件的开发者更可能不断提升性能和修复问题, 因此使用最新的稳定版本是划算。新发布的版本会得到开发者和用户更多的关注, 同时也会利用新的编译器优化技术, 包括针对新硬件的调优。

相对旧版本, 新发布的稳定版本明显性能更高。坚持升级, 也可以保证在调优、问题修复和安全警报方面与时俱进。

不升级软件也会妨碍利用新能力。比如, HTTP/2 目前要求 OpenSSL 1.0.1。从 2016 年下半年开始, HTTP/2 会要求 OpenSSL 1.0.2, 该版本发布于 2015 年 1 月。

NGINX 用户可以从 NGINX 开源软件的最新版本NGINX Plus 开始, 它们支持套接字共享、线程池(参见下文), 而且都会持续优化性能。因此, 检查一下自己的软件, 尽量把它们升级到最新的版本。

8. 建议八: 调优 Linux

Linux 是今天大多数 Web 服务器的底层操作系统, 作为一切基础设施的基础, Linux 对提升性能至关重要。默认情况下, 很多 Linux 系统都比较保守, 仅以桌面办公为需求, 以占用少量资源为调优目标。对于 Web 应用而言, 为达到性能最佳, 肯定需要重新调优。

Linux 优化因 Web 服务器而异。以 NGINX 为例, 可以从以下几方面考虑。

  • 存量队列。如果发现有一些连接得不到处理, 可以增大 net.core.somaxconn, 即等待 NGINX 处理的最大连接数。如果这个连接数限制过小, 应该可以看到错误消息, 可以逐步提高这个值, 直到错误消息不再出现。
  • 文件描述符。NGINX 对每个连接最多使用两个文件描述符。如果系统服务于很多连接, 可能需要增大 sys.fs.file_max 这个对描述符的系统级限制, 以及 nofile 这个用户文件描述符限制, 以支持增大后的负载。
  • 临时端口。在作为代理使用时, NGINX 会为每个上游服务器创建临时端口。可以设置 net.ipv4.ip_local_port_range, 增大端口值的范围, 以增加可用的端口量。此外, 还可以减小 net.ipv4.tcp_fin_timeout 的值, 它控制非活动端口释放重用的等待时间, 加快周转。

对 NGINX 而言, 请参考 NGINX 性能调优指南, 了解如何不费吹灰之力将你的 Linux 系统优化为能够支持更大的吞吐量。

9. 建议九: 调优 Web 服务器

无论使用什么 Web 服务器, 都需要针对应用对其调优。以下建议适用于任何 Web 服务器, 但会给出只有 NGINX 的设置说明。

  • 访问日志。不要每个请求的日志都马上写到磁盘, 可以在内存里做个缓存, 然后批量定入。对 NGINX 而言, 将 buffer=_size_ 参数添加到 access_log 指令, 等内存缓冲区写满后再把日志写到磁盘。如果你添加了 **flush=_time_** 参数, 那么缓冲区的内容也会按照指定时间写入磁盘。
  • 缓冲。缓冲用于在内存里保存部分响应, 直到缓冲区被填满, 可以实现对客户端更有效的响应。无法写入内存的响应会被写到磁盘, 从而降低性能。在 NGINX 的缓冲启用时, 可以使用 proxy_buffer_sizeproxy_buffers 指令来管理它。
  • 客户端活动连接。活动连接可以减少时间消耗, 特别是在使用 SSL/TLS 的情况下。对 NGINX 而言, 可以针对客户端提高 keepalive_requests 的数值, 默认值为 100; 也可以增大 keepalive_timeout 的值, 让活动连接持续时间更长, 从而让后续请求得到更快响应。
  • 上游活动连接。上游连接, 即连接到应用服务器、数据库服务器的连接, 同样可以从活动连接的设置中获得好处。对上游连接来说, 可以增加活动连接, 也就是每个工作进程可用的空闲活动连接的数量。这样可以增进连接重用, 减少重开连接。关于活动连接的更多信息, 请参考这篇博客
  • 限制。限制客户端使用的资源可以提升性能和安全性。对 NGINX 而言, limit_connlimit_conn_zone 指令限制指定源的连接数, 而 limit_rate 限制带宽。这些设置可以防止合法用户 “侵吞” 资源, 同时也有助于防止攻击。limit_reqlimit_req_zone 指令限制客户端请求。对于到上游服务器的连接, 可以在上游配置区的服务器指令中使用 max_conns 参数, 它限制对上游服务器的连接, 防止过载。相关的队列指令会创建一个队列, 在 max_conns 限制到达后将指定的请求数保存指定的时间。
  • 工作进程。工作进程负责处理请求。NGINX 采用基于事件的模型和 OS 相关的机制有效地在工作进程间分配请求。建议将 worker_processes 的值设置为每个 CPU 一个工作进程。如果需要, 大多数系统都支持提高 worker_connections 的值(默认为 512)。可以通过试验找到最适合你系统的这个值。
  • 套接字分片。通常, 一个套接字监听器向所有工作进程分发新连接。套按字分片则为每个工作进程都创建一个套接字监听器, 由内核在套接字监听器可用时为其指定连接。这样可以减少锁争用, 提升多核系统上的性能。要启用套接字分片, 在 listen 指令中包含 reuseport 参数。
  • 线程池。一个费时的操作会阻塞任何计算机进程。对 Web 服务器软件来说, 磁盘访问可能阻碍很多较快的操作, 比如内存中的计算和复制。在使用线程池的情况下, 慢操作会被指定给一组独立的任务, 而主处理循环会继续运行较快的操作。磁盘操作完成后, 结果会返回到主处理循环。在 NGINX 中, read() 系统调用和 sendfile() 被转载到了线程池

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Lf9atIC0-1655368264458)(https://www.nginx.com/wp-content/uploads/2015/10/Graph-17.png)]

提示 修改任何操作系统及周边设备的设置时, 每次只修改一项, 然后测试性能。如果该项修改导致了问题, 或者并未提升性能, 再改回去。

关于调优 NGINX 的更多内容, 请参考这篇博客

10. 建议十: 监控实时动态以发现问题和瓶颈

保存应用高性能的关键是实时监控应用性能。必须实时监控特定设备及相应 Web 基础设施中应用的动态。

监控站点活动多数情况下是被动的, 它只告诉你发生了什么, 至于如何发现和解决问题, 则是你自己的事情。

监控可以捕获以下几种问题:

  1. 服务器停机
  2. 服务器不稳, 漏处理连接
  3. 服务器出现大面积缓存失效
  4. 服务器发送的内容不对

New Relic 或 Dynatrace 等全局性的性能监控工具, 可以帮我们监控远程加载页面的时间, 而 NGINX 则可以帮你监控应用交付这一端。应用的性能数据可以告诉你优化手段什么时候真正给用户带去了不同的体验, 以及什么时候需要扩容以满足越来越多的流量。

为了帮助用户尽快发现问题, NGINX Plus 增加了应用程序体检功能, 会报告经常重复出现的问题。NGINX Plus 还具备 session draining 特性, 会在已有任务完成前阻止新连接, 以及慢启动容量, 从而让恢复的服务器在负载均衡集群中达到应有的速度。使用得当的情况下, 健康体检会在问题显着影响用户体验之前帮你定位问题, 而 session draining 和慢启动则让你替换服务器时不影响感知的性能和在线时间。这张图展示了 NGINX Plus 内置的实时活动监控的控制板, 涵盖了服务器、TCP 连接和缓存。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-do0DlRY2-1655368264458)(https://assets.wp.nginx.com/wp-content/uploads/2016/05/dashboard-nginx-plus-r9.png)]

11. 结论: 10 倍性能提升

性能提升因 Web 应用不同会有巨大差异。实际的提升取决于预算、时间, 以及现有实现的与理想性能的差距。那么怎么让你的应用获得 10 倍的性能提升呢?

为了帮大家理解每项优化建议的潜能, 下面再针对之前的建议给出一些实施方针, 希望大家各取所需。

  • 反向代理服务器及负载均衡。没有负载均衡或池负载均衡, 可能导致极低的性能。添加一个反向代理服务器, 比如 NGINX, 可以减少 Web 应用在内存和磁盘之间的往返。负载均衡可以把任务从过载的服务器转移到空闲的服务器, 也便于扩展。这些改变能极大地提升性能, 与原有的部署方式最差的时候相比, 10 倍性能提升是很轻松的事, 即使不到 10 倍那也在总体上有了质的飞跃。
  • 缓存动态和静态内容。如果你的 Web 服务器同时又充当了应用服务器, 那么通过缓存动态内容就可以达到高峰期 10 倍的性能提升。缓存静态内容也可以有几倍的性能提升。
  • 压缩数据。使用 JPEG、PNG、MPEG-4 以及 MP3 等压缩格式能显着提升性能。如果这些手段都用上了, 那么压缩的文本数据(代码及 HTML)可以将初始页面加载时间提升两倍。
  • 优化 SSL/TLS。安全握手对性能有很大影响, 因此对其进行优化可以让初次响应加快两倍, 对于文本内容较多的网站尤其如此。优化 SSL/TLS 下的媒体文件带来的性能提升很小。
  • 实施 HTTP/2 和 SPDY。在使用 SSL/TLS 的情况下, 这两个协议有可能提升网站的整体性能。
  • 调优 Linux 和 Web 服务器。使用优化的缓冲策略、使用活动连接, 将耗时的任务转载至独立的线程池, 可以显着提升性能。比如线程池可以将磁盘操作密集性任务的性能提升至少一个数量级

希望大家自己多尝试以上技术, 也希望大家分享自己在性能改进方面的心得。如果有好的想法和实现方案, 欢迎留言。

12. 参考资源与网络数据

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

云满笔记

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值