web 开发中服务端性能优化有哪些策略
web 编程中,不仅仅包含前端 html 的页面,还有很重要的部分就是服务端。那什么是服务端编程?
服务端编程:
服务端编程是指在服务器端执行的编程工作,与客户端编程相对,它涉及到开发和维护运行在服务器上的应用程序和系统。
服务端程序通常处理客户端请求、数据库交互、业务逻辑处理、数据存储和安全性等任务。
服务端编程的特点
- 运行环境:服务端代码运行在服务器上,而不是在用户的浏览器中执行。一般就是 linux 系统。
- 处理请求:接受并处理来自客户端(例如浏览器、API)的HTTP请求。
- 动态生成内容:根据客户端请求和服务器端逻辑,动态生成 HTML、JSON、XML 等内容。
- 数据处理:进行数据的增、删、改、查操作,通常与数据库交互。
- 安全性:在服务器端处理敏感数据和逻辑,可以保护代码和数据不被客户端直接访问。
服务端编程的架构模式
服务端编程一般都使用 MVC 架构模式,不过现在大部分的网站使用了前后端分离的模式。
前后端分离模式与 MVC 的架构模式的区别就是 V。MVC 的架构模式中的 V(view 视图)也是由服务器解析,渲染的。
而前后端分离的模式中 V 的部分是单独渲染,需要的数据通过 OpenAI API 请求服务端获取,然后使用 MVVM 架构模式渲染数据部分。
在上一篇文章 juejin.cn/post/737127… 中我们已经讨论了前端性能优化的策略。本篇文章我们讨论服务端编程的性能优化策略。
服务端组件
服务端编程我们几乎都要使用到的组件有: 数据库存储(mysql、postgres、MongoDB、ES),缓存(redis、memory cache)
可能用到组件:消息队列(RabbitMQ、RocketMQ,Kafka等),ETCD、consul、RPC
以及每个程序员都需要会的编程语言(PHP、Golang、NodeJS、Python、Java 等)
服务端构架
服务端架构如下图所示:
性能提升策略
选择合适的编程语言
选择合适的编程语言对于服务端程序的性能有很大的提升。但是需要考虑具体的业务场景以及团队中对于某种语言的掌握情况,编程语言的社区活跃度等等。具体选择什么编程语言个人认为是个哲学问题。
编程语言在服务端编程中简单理解可以认为是上图中的充当 controller。所以最好选择性能强的编程语言。
数据库性能优化
服务端中几乎所有的数据都会落到数数据库的查询,所以我们需要对数据库做必要的性能优化。
1 索引优化
- 创建索引:为经常查询的字段创建索引,可以显著提高查询速度以及性能。
- 删除不需要的索引:删除不在使用或重复的索引,以减少索引维护的开销。更多的索引会导致数据库维护数据的时候还需要维护索引的部分,所以会导致更多性能损耗。
- 选择合适的索引类型:使用 B-tree、Hash 等适当的索引类型,根据查询的具体需求来选择。可以查看我的上一篇文章 MySQL 使用哪种索引类型会使数据库性能更高?
2 查询优化
- 推荐使用
EXPLAIN分析查询:通过EXPLAIN命令查看查询的执行计划,识别并优化低效的sql语句。 - 优化查询sql:对于效率低的
sql语句,尽量避免全表扫描。使用LIMIT限制返回结果数据的大小。 - 避免使用
SELECT *:只查询业务中需要的字段,减少没必要字段的数据查询。 - 使用联合索引:使用联合索引需要注意联合索引的最左前缀原则。
3 数据表结构优化
- 设计合适的数据表字段:在合理的范围内进行表的字段设计,避免字段冗余。同时有必要时可进行冗余部分字段来提高查询性能。
- 字段类型:选择合适的字段类型,避免使用过大的字段类型(例如
TEXT),以减少存储和处理的性能消耗。 - 表拆分:将大表进行横向扩展或者垂直拆分,以提高查询性能。
4 数据库配置优化
- 调整缓存参数:如调整
InnoDB Buffer Pool、Query Cache等参数,使其适应具体的应用需求。 - 调整内存参数:根据服务器的内存情况,合理分配给数据库的使用内存。
- 使用连接池:在项目中使用数据库连接池,减少数据库连接句柄的建立和释放的开销。
5 硬件升级
- 使用SSD磁盘:
SSD的随机读写性能远高于传统HDD,能够显著提高数据库的I/O性能。 - 增加
memory:尽量使数据库的热数据能够保存在内存中,以减少磁盘I/O。 - 使用更高性能的
CPU:对于计算密集型的查询,升级CPU可以带来性能提升。
6 架构设计
- 读写分离:将读操作和写操作分离到不同的服务器上,减轻主库的负担,从而提升数据库的整体查询性能。
- 分库分表:根据业务需求进行分库分表,将数据分布到多个数据库中,降低单一数据库的查询压力。
- 微服务拆分: 如果你的业务以及团队足够大,可以考虑微服务架构,将业务拆分,使每一个业务数据查询的性能提升。
小结
对于 硬件性能提升 可以在一定程度上提升单机的性能,但它并不能无限扩展。
架构设计 理论上说性能可以无限扩展,但是它对于整个团队的架构、运维能力有更高的要求。
作为程序员的我们更多的性能提升还需要合理的使用数据库、索引、建立合适的字段以及类型、写高效的 sql 查询语句。这样性能提升的效果也是很明显的。
使用Redis提升性能
如上图所示,我们的系统使用了 Redis 缓存,那么 Redis 高性能的原因有哪些?
采用内存存储:Redis 是一个内存数据库,数据存储在内存中,而不是磁盘上。内存的访问速度比磁盘快很多,因此 Redis 的读写性能非常高。
数据结构简单:Redis 支持多种数据结构,如字符串、哈希表、列表、集合和有序集合等。这些数据结构都非常简单,可以高效地进行操作。
单线程模型:Redis 采用单线程模型,这意味着所有命令都是由一个线程串行执行的。这种模型可以避免多线程并发带来的性能开销。
非阻塞 I/O:Redis 采用非阻塞 I/O 模型,这意味着即使在执行 I/O 操作时,Redis 也能够处理其他请求。这种模型可以提高 Redis 的吞吐量。
高效的命令执行:Redis 的命令执行经过了高度优化,可以高效地完成各种操作。例如,Redis 的 SET 命令可以将一个字符串值存储到键中,平均耗时只有 0.01 毫秒。
这样在使用了 redis 后,系统中很多的数据查询请求就不需要打到数据库中进行查询了,而是直接由 redis 返回数据。这样就保证了数据库的稳定性从而我们的业务系统更加健壮。
Redis 性能优化
有一个必然的情况就是使用了
Redis后那么业务系统就一定性能高么?答案是:不一定。
那么我们同样需要对
Redis做一些配置,以使Redis尽可能的高性能。
选用合适的硬件资源:
为 Redis 提供足够的 CPU、内存和网络带宽。CPU 会影响Redis 的运行性能,而网络带宽会影响 Redis 数据的吞吐量,从而影响我们业务的吞吐。
选择合适的数据类型:
根据我们自己实际业务场景选择合适的数据类型(比如什么时候使用 string,什么时候选用**Hash**、List 等)。
使用多路复用:
使用 pipelining 一次性发送多个命令,可以减少网络开销,从而增加网络吞吐量,提升性能。
配置优化:
- 最大内存配置:配置
maxmemory参数限制 Redis 使用的最大内存,避免内存不足导致的系统崩溃。配置maxmemory-policy参数选择适合的内存淘汰策略(如LRU、LFU)。 - 持久化配置: 使用
AOF(Append-Only File)时,设置合理的appendfsync策略平衡性能和数据安全。 - 网络配置:调整
tcp-keepalive参数保持长连接,减少连接建立的开销。增大tcp-backlog参数值,处理更多的并发连接。
使用优化
- 慢查询日志:使用
Redis的慢查询日志slowlog定位和优化慢查询。 - 使用多路复用命令: 使用多路复用命令(如
MSET、MGET)减少网络往返。 - 优化数据结构:使用
hash存储多个字段,减少键的数量,降低内存开销。 - 缓存热点数据:将频繁访问的数据缓存在 Redis 中,提高访问速度。
- 设置过期时间:使用
EXPIRE设置缓存的过期时间,自动清理过期数据。
小结:
使用 redis 能在很大程度上提升我们应用程序的整体性能。不过我们需要正确的使用 Redis。
性能优化并不是一层不变的,而是会随着业务的发展、架构的调整不断的做出调整,才能满足性能的要求。
总结
以上我们仅从简单的服务端架构中挑选了两种优化策略。在实际项目中,面对各种复杂的项目和架构,需要针对不同的技术架构、组件和业务场景,制定相应的性能优化策略。
Web编程的性能优化涉及多个方面,需要从前端到后端进行全面考虑。优化策略应根据具体项目需求进行调整和实施,并通过持续监测和测试来确保优化效果。性能优化不仅能提升用户体验,还能提高系统的稳定性和可扩展性。
推荐阅读
下面两篇文章来源于外网,感兴趣的可以阅读