| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> Java知识库 -> 浅谈 高并发 处理方案 -> 正文阅读 |
|
[Java知识库]浅谈 高并发 处理方案 |
文章目录本文部分是我曾经的手稿,今天在草稿箱里面发现,居然没发出去。。。。。 高性能开发十大必须掌握的核心技术我们循序渐进,从内存、磁盘I/O、网络I/O、CPU、缓存、架构、算法等多层次递进,串联起高性能开发十大必须掌握的核心技术。
I/O优化:零拷贝技术从磁盘读文件、再通过网络发送数据,数据从磁盘到网络,兜兜转转需要拷贝四次,其中CPU亲自搬运都需要两次。 最近在学习nginx的底层设计,正好有看到这个。后面可以在nginx系列里面补上这个。 零拷贝技术,解放CPU,文件数据直接从内核发送出去,无需再拷贝到应用程序缓冲区,白白浪费资源。 Linux API:
函数名字已经把函数的功能解释的很明显了:发送文件。指定要发送的文件描述符和网络套接字描述符,一个函数搞定! I/O优化:多路复用技术每个线程都要阻塞在recv等待对方的请求,这来访问的人多了,线程开的就多了,大量线程都在阻塞,系统运转速度也随之下降。 这个时候,你需要多路复用技术,使用select模型,将所有等待(accept、recv)都放在主线程里,工作线程不需要再等待。 过了一段时间之后,网站访问的人越来越多了,就连select也开始有点应接不暇,老板继续让你优化性能。 这个时候,你需要升级多路复用模型为epoll。 select有三弊,epoll有三优。
用上了epoll多路复用技术,开发了3.0版本,你的网站能同时处理很多用户请求了。 之前的方案中,工作线程总是用到才创建,用完就关闭,大量请求来的时候,线程不断创建、关闭、创建、关闭,开销挺大的。这个时候,你需要: 线程池技术我们可以在程序一开始启动后就批量启动一波工作线程,而不是在有请求来的时候才去创建,使用一个公共的任务队列,请求来临时,向队列中投递任务,各个工作线程统一从队列中不断取出任务来处理,这就是线程池技术。 多线程技术的使用一定程度提升了服务器的并发能力,但同时,多个线程之间为了数据同步,常常需要使用互斥体、信号、条件变量等手段来同步多个线程。这些重量级的同步手段往往会导致线程在用户态/内核态多次切换,系统调用,线程切换都是不小的开销。 在线程池技术中,提到了一个公共的任务队列,各个工作线程需要从中提取任务进行处理,这里就涉及到多个工作线程对这个公共队列的同步操作。 有没有一些轻量级的方案来实现多线程安全的访问数据呢?这个时候,你需要: 无锁编程技术多线程并发编程中,遇到公共数据时就需要进行线程同步。而这里的同步又可以分为阻塞型同步和非阻塞型同步。 阻塞型同步好理解,我们常用的互斥体、信号、条件变量等这些操作系统提供的机制都属于阻塞型同步,其本质都是要加“锁”。 与之对应的非阻塞型同步就是在无锁的情况下实现同步,目前有三类技术方案:
三类技术方案都是通过一定的算法和技术手段来实现不用阻塞等待而实现同步,这其中又以Lock-free最为应用广泛。 Lock-free能够广泛应用得益于目前主流的CPU都提供了原子级别的read-modify-write原语,这就是著名的CAS(Compare-And-Swap)操作。在Intel x86系列处理器上,就是cmpxchg系列指令。 我们常常见到的无锁队列、无锁链表、无锁HashMap等数据结构,其无锁的核心大都来源于此。在日常开发中,恰当的运用无锁化编程技术,可以有效地降低多线程阻塞和切换带来的额外开销,提升性能。 服务器上线了一段时间,发现服务经常崩溃异常,排查发现是工作线程代码bug,一崩溃整个服务都不可用了。于是你决定把工作线程和主线程拆开到不同的进程中,工作线程崩溃不能影响整体的服务。这个时候出现了多进程,你需要: 进程间通信技术提起进程间通信,你能想到的是什么?
以上各种进程间通信的方式详细介绍和比较,推荐一篇文章再探进程间通信,这里不再赘述。 Scale-out(横向拓展)采用分布式部署的方式把流量分开,让每个服务器都承担一部分并发和流量。这也是我最喜欢的一种方法。 缓存使用缓存来提高系统的性能。 为什么缓存可以大幅度提升系统的性能呢? 那肯定是要更普通磁盘进行对比的啊。我们来看看普通磁盘的速度: 至于缓存为什么快,因为它是内置的啊,在内存中。不过也有个缺点,就是烧内存。 异步这是业务层面的异步。 内核层面的异步,需要调用内核指定的异步函数(aio族),不然,不论阻塞还是非阻塞都是同步。 高性能、高可用、高拓展 解决方案以下实践方案,有些我已经试过了,有些还没体验但是知道那么一回事儿,有些则不知道啥时候能实践了。 ? 高性能的实践方案
上述方案无外乎从计算和 IO 两个维度考虑所有可能的优化点,需要有配套的监控系统实时了解当前的性能表现,并支撑你进行性能瓶颈分析,然后再遵循二八原则,抓主要矛盾进行优化。 ? 高可用的实践方案
高可用的方案主要从冗余、取舍、系统运维3个方向考虑,同时需要有配套的值班机制和故障处理流程,当出现线上问题时,可及时跟进处理。 ? 高扩展的实践方案
插播一条: 对吞吐量(TPS)、QPS、并发数、响应时间(RT)几个概念做下了解吞吐量吞吐量是指系统在单位时间内处理请求的数量。对于无并发的应用系统而言,吞吐量与响应时间成严格的反比关系,实际上此时吞吐量就是响应时间的倒数。前面已经说过,对于单用户的系统,响应时间(或者系统响应时间和应用延迟时间)可以很好地度量系统的性能,但对于并发系统,通常需要用吞吐量作为性能指标。 对于一个多用户的系统,如果只有一个用户使用时系统的平均响应时间是t,当有你n个用户使用时,每个用户看到的响应时间通常并不是n×t,而往往比n×t小很多(当然,在某些特殊情况下也可能比n×t大,甚至大很多)。这是因为处理每个请求需要用到很多资源,由于每个请求的处理过程中有许多步骤难以并发执行,这导致在具体的一个时间点,所占资源往往并不多。也就是说在处理单个请求时,在每个时间点都可能有许多资源被闲置,当处理多个请求时,如果资源配置合理,每个用户看到的平均响应时间并不随用户数的增加而线性增加。实际上,不同系统的平均响应时间随用户数增加而增长的速度也不大相同,这也是采用吞吐量来度量并发系统的性能的主要原因。一般而言,吞吐量是一个比较通用的指标,两个具有不同用户数和用户使用模式的系统,如果其最大吞吐量基本一致,则可以判断两个系统的处理能力基本一致。 QPS(每秒查询率)每秒查询率QPS是对一个特定的查询服务器在规定时间内所处理流量多少的衡量标准,在因特网上,作为域名系统服务器的机器的性能经常用每秒查询率来衡量。对应fetches/sec,即每秒的响应请求数,也即是最大吞吐能力。 并发数并发用户数是指系统可以同时承载的正常使用系统功能的用户的数量。与吞吐量相比,并发用户数是一个更直观但也更笼统的性能指标。实际上,并发用户数是一个非常不准确的指标,因为用户不同的使用模式会导致不同用户在单位时间发出不同数量的请求。 响应时间响应时间是指系统对请求作出响应的时间。直观上看,这个指标与人对软件性能的主观感受是非常一致的,因为它完整地记录了整个计算机系统处理请求的时间。由于一个系统通常会提供许多功能,而不同功能的处理逻辑也千差万别,因而不同功能的响应时间也不尽相同,甚至同一功能在不同输入数据的情况下响应时间也不相同。所以,在讨论一个系统的响应时间时,人们通常是指该系统所有功能的平均时间或者所有功能的最大响应时间。当然,往往也需要对每个或每组功能讨论其平均响应时间和最大响应时间。 写在最后,本篇核心贪多嚼不烂,合适的才是最好的。 1、最简单的系统设计满足业务需求和流量现状,选择最熟悉的技术体系。 2、随着流量的增加和业务的变化,修正架构中存在问题的点,如单点问题,横向扩展问题,性能无法满足需求的组件。 3、当对架构的小修小补无法满足需求时,考虑重构、重写等大的调整方式以解决现有的问题。 |
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/23 18:37:25- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |