Добро пожаловать, чтобы следовать за Xiao Gedan Architecture Friends Souhu под деревом Новая тема Вы действительно понимаете оптимизацию производительности веб-сайтов с миллиардным трафиком?Наггетс.Талант/пост/689314…
Общие сведения о параллелизме, стресс-тестирование и оптимизация серверов
1. Параллелизм и высокий параллелизм
1. Что такое параллелизм?
• В операционной системе это означает наличие нескольких программ в промежутке времени между моментом их запуска и завершением, и все эти программы выполняются на одном и том же процессоре.
Точно так же, как разделение времени с разделением времени в операционной системе, упомянутое ранее. Игра в игры и прослушивание музыки выполняются от начала до конца на одном компьютере в один и тот же период времени. Тогда можно сказать, что прослушивание музыки и игра в игры происходят одновременно.
2. Параллелизм и параллелизм
Мы обедаем вдвоем. Во время еды вы едите рис, овощи и говядину. Три вещи, такие как рис, овощи и говядина, на самом деле выполняются одновременно.
Вам кажется, что весь процесс происходит одновременно. Но на самом деле вы переключаетесь между едой разных вещей.
Или только вдвоем за обедом. Во время еды вы едите рис, овощи, говядину. У меня также был рис, овощи и говядина.
Питание между нами происходит параллельно. Два человека могут вместе есть говядину одновременно или один может есть говядину, а другой есть овощи. независимы друг от друга.
Следовательно, параллелизм относится к макроскопической работе нескольких программ одновременно в течение определенного периода времени. Параллелизм относится к тому факту, что несколько задач действительно выполняются одновременно.
Разница между параллелизмом и параллелизмом:
Параллелизм — это когда несколько вещей происходят одновременно в один и тот же период времени.
Параллелизм относится к тому, что несколько вещей происходят одновременно в одно и то же время.
Несколько одновременных задач вытесняют друг друга за ресурсы.
Параллельное выполнение нескольких задач не вытесняет ресурсы друг друга,
Параллелизм имеет место только в случае нескольких процессоров. В противном случае вещи, которые кажутся происходящими одновременно, на самом деле выполняются одновременно.
3. Что такое высокий параллелизм?
«Высокий параллелизм и многопоточность» всегда упоминаются вместе, создавая впечатление, что они равны, но на самом деле высокий параллелизм ≠ многопоточность (они не обязательно напрямую связаны)
多线程是完成任务的一种方法,高并发是系统运行的一种状态,通过多线程有助于系统承受高并发状态的实现。
高并发是一种系统运行过程中遇到的一种“短时间内遇到大量操作请求”的情况,主要发生在web系统集中大量访问或者socket端口集中性收到大量请求(例如:12306的抢票情况;天猫双十一活动)。
该情况的发生会导致系统在这段时间内执行大量操作,例如对资源的请求,数据库的操作等。如果高并发处理不好,不仅仅降低了用户的体验度(请求响应时间过长),同时可能导致系统宕机,严重的甚至导致OOM异常,系统停止工作等。
如果要想系统能够适应高并发状态,则需要从各个方面进行系统优化,包括,硬件、网络、系统架构、开发语言的选取、数据结构的运用、算法优化、数据库优化……而多线程只是其中解决方法之一。
实现高并发需要考虑:
(1)系统的架构设计,如何在架构层面减少不必要的处理(网络请求,数据库操作等)例如:使用Cache来减少IO次数,使用异步来增加单服务吞吐量,使用无锁数据结构来减少响应时间;
(2)网络拓扑优化减少网络请求时间、如何设计拓扑结构,分布式如何实现?
(3)系统代码级别的代码优化,使用什么设计模式来进行工作?哪些类需要使用单例,哪些需要尽量减少new操作?
(4)提高代码层面的运行效率、如何选取合适的数据结构进行数据存取?如何设计合适的算法?
(5)任务执行方式级别的同异步操作,在哪里使用同步,哪里使用异步?
(6)JVM调优,如何设置Heap、Stack、Eden的大小,如何选择GC策略,控制Full GC的频率?
(7)服务端调优(线程池,等待队列)
(8)数据库优化减少查询修改时间。数据库的选取?数据库引擎的选取?数据库表结构的设计?数据库索引、触发器等设计?是否使用读写分离?还是需要考虑使用数据仓库?
(9)缓存数据库的使用,如何选择缓存数据库?是Redis还是Memcache? 如何设计缓存机制?
(10)数据通信问题,如何选择通信方式?是使用TCP还是UDP,是使用长连接还是短连接?NIO还是BIO?netty、mina还是原生socket?
(11)操作系统选取,是使用winserver还是Linux?或者Unix?
(12)硬件配置?是8G内存还是32G,网卡10G还是1G? 例如:增加CPU核数如32核,升级更好的网卡如万兆,升级更好的硬盘如SSD,扩充硬盘容量如2T,扩充系统内存如128G;
以上的这些问题在高并发中都是必须要深入考虑的,就像木桶原理一样,只要其中的某一方面没有考虑到,都会造成系统瓶颈,影响整个系统的运行。而高并发问题不仅仅涉及面之广,同时又要求有足够的深度!!!
而多线程在这里只是在同/异步角度上解决高并发问题的其中的一个方法手段,是在同一时刻利用计算机闲置资源的一种方式。
多线程在解决高并发问题中所起到的作用就是使计算机的资源在每一时刻都能达到最大的利用率,不至于浪费计算机资源使其闲置。
unix是第一个成熟的计算机操bai作系统,一开始都du是作为服务器操作系统,zhi企业或是高校才dao能买得起,之后出现过几类其他基于unix的操作系统,有一个miniunix是开发用来教学使用的,功能很有限,所以Linus决定自己在mini的基础上开发一个系统,他在互联网上发布了这个想法并开发了第一个linux版本,之后开发人员越来越多,之后就有公司或团队开发,就有了现在的ubuntu、Suse、deban、red hat等发行版。
好坏不是绝对的,unix作为服务器绝对是最牛的,不然IBM早不干了,但是他的价格也是很高的。所以就选linux服务器版,好处很明显,开源价廉,现在虽然linux免费,但作为服务器很多其他功能还是收费的,并不是完全免费。
而对于个人用户,linux绝对是没的选,现在各种发行版有桌面版,使用很方便。而且由于linux对于unix的继承性,学会linux指令就基本上学会了unix指令,所以linux相对好一点。
4. Вы действительно понимаете высокий параллелизм?
Высокий уровень параллелизма — это то, чем все считают хвастовством. На самом деле, в большинстве бизнес-сценариев нет параллельной конкуренции за данные, поэтому добавление служб и машин может в основном решить проблему. решать проблему.
# 所谓的亿级流量,100w级qps ,你真的懵逼了吗??
例:某服务1天36万笔(粗粒度统计),平均RT在100ms,指标计算如下
**指标=(日量36万/10小时高峰期/3600秒)x5倍保险系数**=50qps、rt100ms
例:某服务近期监控请求峰值为1小时36万笔(粗粒度统计),平均RT在100ms,,指标计算如下
**指标=(时量36万/3600秒)x5倍保险系数**=500qps、rt100ms
# 衡量高并发的指标
Qps , TPS , RT , 吞吐量
# 商品详情页可能有以下查询
--- 亿级流量:每天大概会有 100w 单,这么多商品详情的流量会有多少呢?
1、商品数据信息查询 2~3次
2、规格选择查询(每一个规格都点一遍) 20次
3、商品评论查询 3次
4、几个商品反复比较 10次
5、再去其他平台查询商品,回来再看2-3次
46次 ,姑且按照 50次算
经过50次查询,可能才能成交一单。
峰值:假设节假日期间流量增大3倍,50*3 = 150
那么 100w单就可能有: 100w * 150 = 1.5亿
做系统设计的时候,统计流量都必须往多了算, 为了应付突发情况,流量会突然一下变大,一般将算出来的值再乘以三倍。
只算高峰期请求,1.8 亿可能有 1.5 亿都在 12 个小时的高峰期内
每小时的流量是:1.8亿 / 12 = 1250w
每分的流量是:1250w / 60 = 20.8w
每秒的流量是:20.8w / 60 = 3472
# 内存预估
它内部的属性跟它是引用关系,意思就是:这 8 mb 在堆内存中大大小小可能会有很多个对象, 它的每个引用变量背后都是一个对象。(这个一个套娃的关系 懂的伐)
深圳 - 上海属于热门航线所以报文会比较大, 冷门航线比如 海拉尔 - 银川 这种 可能只有几条航线 报文可能只有几百 kb 但热门航线被请求的概率又要大一些,综合来看:我们把每次报文大小算作 5mb
qps110 * 5 mb = 550 mb
这意味着:新生代每秒钟将会有,550mb 的空间会被占用。
五、其他系统如何分析
注意:这个系统跟其他系统不太一样
因为这个核心服务的核心接口就两个:列表查询、指定查询
但是其他系统 , 比如订单系统可能会有很多个接口 , 除了比较核心的订单查询接口 , 还有创单、下单、查库存等接口
一般核心接口逻辑会要复杂一点 , 对象占用的大小要更大一点 , 我们用最占内存的那个接口来分析
因为最差的情况就是所有的流量都打到核心接口
指定查询其实相对于列表查询来说频率会低一些 , 这里仅拿列表查询的情况当做一个系统所有接口来作为参考
因为这个接口的一次平均 5mb 其实也挺大了, 当然这里只是作为一个参考
分析思路
根据 集群的 qps 除以机器数量 , 估算出每分钟每个接口的 qps
计算出各个接口中所有对象实际占用的内存
qps 不是很高可以用每分钟的内存大小做参考即可
并发量很高 就用每秒占用内存的大小来做参考
六、总结
今天先分享这个亿级流量系统的大概情况 , 部分数据只是作为参考
其实这个系统高峰期流量不止亿级 , 机器也不只是 8C 16G
不过来用做案例分析是 ok 的
2. Анализ сопутствующих показателей
1. Пропускная способность
Прежде чем понять qps, tps, rt и параллелизм, мы должны сначала уточнить, что означает пропускная способность системы. Вообще говоря, пропускная способность системы относится к сопротивлению давлению и нагрузочной способности системы, представляющей систему в секунду. посещений пользователей, которые часы могут выдержать.
Пропускная способность системы обычно определяется qps (tps) и числом параллелизма. Каждая система имеет относительный предел для этих двух значений. Пока определенный элемент достигает максимального значения, пропускная способность системы не будет увеличиваться. .
Так называемая пропускная способность системы на самом деле: количество запросов в секунду системы
2. Число запросов в секунду
Запросов в секунду (количество запросов в секунду) – это количество запросов, на которые можно ответить в секунду. Обратите внимание, что здесь под запросом понимается количество раз, когда пользователь отправляет запрос на сервер для успешного ответа. В простом понимании , можно считать, что запрос = запрос запрос.
qps=Количество запросов в секунду
3. ТПС
Аббревиатура Transactions Per Second, число транзакций, обрабатываемых в секунду. Транзакция — это процесс, в котором клиент отправляет запрос на сервер, а сервер отвечает. Клиент начинает отсчет времени при отправке запроса и заканчивает отсчет времени после получения ответа от сервера, чтобы рассчитать использованное время и количество завершенных транзакций.
针对单接口而言,TPS可以认为是等价于QPS的,比如访问一个页面/index.html,是一个TPS,而访问/index.html页面可能请求了3次服务器比如css、js、index接口,产生了3个QPS。
tps = транзакций в секунду
QPS和TPS区别个人理解如下:
1、Tps即每秒处理事务数,包括了用户请求服务器 服务器自己的内部处理 服务器返回给用户这三个过程,每秒能够完成N个这三个过程,Tps也就是N;
2、Qps基本类似于Tps,但是不同的是,对于一个页面的一次访问,形成一个Tps;但一次页面请求,可能产生多次对服务器的请求,服务器对这些请求,就可计入“Qps”之中。例子: 例如:访问一个页面会请求服务器3次,一次放,产生一个“T”,产生3个“Q”
例如:一个大胃王一秒能吃10个包子,一个女孩子0.1秒能吃1个包子,那么他们是不是一样的呢?答案是否定的,因为这个女孩子不可能在一秒钟吃下10个包子,她可能要吃很久。这个时候这个大胃王就相当于TPS,而这个女孩子则是QPS。虽然很相似,但其实是不同的。
# 大部分情况不用纠结QPS TPS
TPS=QPS(每秒请求数),所以大部分条件下,这两个概念不用纠结的!
举个例子,我需要进行一次查询,但这个查询需要调用A服务和B服务,而调用B服务需要2次调用,那么这种情况,以我查询这个场景成功作为一次事务的话,我一秒请求一笔就是1tps,当然对于A系统是1tps=1qps的.
但对于B系统而言,就是2qps,因为调用了两次(如果只看B服务的话,把每次请求当做一次事务的话2qps=2tps,还是可以等同的)所以仅仅是关注维度的不同,绝大多数时候我们不用去刻意区分的,毕竟我可以说我流程是1tps,B系统受到的双倍额压力是2tps的量(压测过程中也务必关注这样的流量放大服务,因为很有可能前面的服务抗的住,后面扛不住),这样也是完全没有问题的。
?Если запрос одного интерфейса, QPS = TPS, но размеры наблюдения этой переменной разные, если нет удаленного вызова какого-либо сервиса от инициации запроса до конца запроса, то можно не сомневаться, что QPS = TPS, но если если есть несколько удаленных вызовов, то для сервера с QPS = TPS проблемы нет, а для всей цепочки запросов QPS > TPS
4. РТ
Аббревиатура времени отклика, просто понимаемая как интервал времени от ввода до вывода системы.В широком смысле, это представляет собой разницу во времени с момента, когда клиент инициирует запрос, до момента, когда сервер получает запрос и отвечает на все данные. Обычно берется среднее время ответа.
?Для RT клиент и сервер сильно различаются, потому что запрос должен пройти через глобальную сеть от клиента к серверу, поэтому RT клиента часто намного больше, чем RT сервера, а RT клиента часто определяет реальный опыт. , RT на стороне сервера часто является ключевым фактором в оценке качества нашей системы.
在开发过程中,我们一定面临过很多的线程数量的配置问题,这种问题往往让人摸不到头脑,往往都是拍脑袋给出一个线程池的数量,但这可能恰恰是不靠谱的,过小的话会导致请求RT极具增加,过大也一样RT也会升高。所以对于最佳线程数的评估往往比较麻烦。
Одновременно:
Короче говоря, количество запросов/транзакций, которые система может обрабатывать одновременно.
Расчет:
QPS=параллельность/RT или Concurrency=QPS*RT
Возьмите каштан:
Предположим, в компании есть сотрудники, которым нужно сходить в туалет в течение часа с 9:00 до 10:00 утра.В компании работает 3600 сотрудников, и среднее время посещения туалета каждым сотрудником составляет 10 минут. Давайте посчитаем.
QPS = 3600/60*60 1
ВР = 10*60 600 секунд
Параллелизм = 1 * 600 600
Это означает, что если вы хотите получить наилучшие впечатления от приседаний, компании необходимо 600 ям для удовлетворения потребностей сотрудников, в противном случае вам придется стоять в очереди, чтобы сходить в туалет.
随着请求数量的增加,带来大量的上下文的切换、gc和锁变化。qps更高,产生对象越多,gc越频繁,cpu time和利用率都受到影响,尤其在串行的时候,锁自旋、自适应、偏向等等也成为影响par的因素。
总结,为了提升达到最好的性能,我们需要不断的进行性能测试,调整小城池大小,找到最合适的参数来达到提高性能的目的。
3. Анализ узких мест в отчете о стресс-тестах
?После запуска сервиса, под давлением бизнеса, вы обнаружите, что программа работает очень медленно, или дает сбои, и возникают разные проблемы по необъяснимым причинам.Будут проводиться только какие-то бездумные расширения.Может ли расширение действительно решить проблему? ?
Это может решить проблему, но это также принесет некоторые другие проблемы, поэтому, прежде чем проект будет запущен, должен быть этап стресс-теста производительности, чтобы найти некоторые проблемы службы, исправить и оптимизировать проблемы службы заранее.
1. Развертывание приложения
1.1. Упаковка обслуживания
Упаковка элементов: вы можете упаковать загрузку напрямую с помощью IDEA, или вы можете упаковать ее напрямую через Maven на сервере Gitlab, или использовать Jenkins для создания упаковки, теперь мы сначала используем Maven IDEA.
# 注意打包必须的依赖
<build>
<plugins>
<--此依赖必须有,否则项目的依赖包无法被打进项目:mysql.jar,spring*.jar都无法打包进入-->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<!-- 编译项目,然后打包,只会打包自己的代码 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
</build>
пакет maven идеи:
Примечание: при упаковке службы вы должны обратить внимание на соответствующий IP-адрес службы.Поскольку служба, mysql и redis в настоящее время находятся на одном сервере, адрес доступа к соединению может быть установлен на localhost.
server:
port: 9000
spring:
application:
name: sugo-seckill-web
datasource:
url: jdbc:mysql://127.0.0.1:3306/shop?useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true
# url: jdbc:mysql://47.113.81.149:3306/shop?useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true
username: root
password: root
driver-class-name: com.mysql.jdbc.Driver
druid:
#配置初始化大小、最小、最大
initial-size: 1
min-idle: 5
max-active: 5
max-wait: 20000
time-between-eviction-runs-millis: 600000
# 配置一个连接在池中最大空闲时间,单位是毫秒
min-evictable-idle-time-millis: 300000
# 设置从连接池获取连接时是否检查连接有效性,true时,每次都检查;false时,不检查
test-on-borrow: true
#设置往连接池归还连接时是否检查连接有效性,true时,每次都检查;false时,不检查
test-on-return: true
# 设置从连接池获取连接时是否检查连接有效性,true时,如果连接空闲时间超过minEvictableIdleTimeMillis进行检查,否则不检查;false时,不检查
test-while-idle: true
# 检验连接是否有效的查询语句。如果数据库Driver支持ping()方法,则优先使用ping()方法进行检查,否则使用validationQuery查询进行检查。(Oracle jdbc Driver目前不支持ping方法)
validation-query: select 1 from dual
keep-alive: true
remove-abandoned: true
remove-abandoned-timeout: 80
log-abandoned: true
#打开PSCache,并且指定每个连接上PSCache的大小,Oracle等支持游标的数据库,打开此开关,会以数量级提升性能,具体查阅PSCache相关资料
pool-prepared-statements: true
max-pool-prepared-statement-per-connection-size: 20
# 配置间隔多久启动一次DestroyThread,对连接池内的连接才进行一次检测,单位是毫秒。
#检测时:
#1.如果连接空闲并且超过minIdle以外的连接,如果空闲时间超过minEvictableIdleTimeMillis设置的值则直接物理关闭。
#2.在minIdle以内的不处理。
redis:
host: 127.0.0.1
port: 6379
mybatis:
type-aliases-package: com.supergo.pojo
mapper:
not-empty: false
identity: mysql
1.2, загрузка пакета
Команда запуска: java -jar jshop-web-1.0-SNAPSHOT.jar
Примечание: когда сервер развернут, из-за другой серверной среды часто необходимо изменить файл конфигурации службы, перекомпилировать и упаковать, и должен использоваться IP-адрес сервера.IP-адрес локальной среды разработки отличается с онлайн-ip.Иногда эти конфигурации необходимо изменять каждый раз, что очень хлопотно. Поэтому при развертывании службы у нее должна быть возможность подключить файл конфигурации.
#启动命令,注意:配置文件的名称必须是application.yaml,或者application.properties
java -jar xxx.jar --spring.config.addition-location=/usr/local/src/application.yaml
Файл конфигурации плагина использует локальный адрес подключения:
spring:
application:
name: sugo-seckill-web
datasource:
url: jdbc:mysql://127.0.0.1:3306/shop?useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true
username: root
password: root
driver-class-name: com.mysql.jdbc.Driver
druid:
#配置初始化大小、最小、最大
initial-size: 1
min-idle: 5
max-active: 5
max-wait: 20000
time-between-eviction-runs-millis: 600000
# 配置一个连接在池中最大空闲时间,单位是毫秒
min-evictable-idle-time-millis: 300000
# 设置从连接池获取连接时是否检查连接有效性,true时,每次都检查;false时,不检查
test-on-borrow: true
#设置往连接池归还连接时是否检查连接有效性,true时,每次都检查;false时,不检查
test-on-return: true
# 设置从连接池获取连接时是否检查连接有效性,true时,如果连接空闲时间超过minEvictableIdleTimeMillis进行检查,否则不检查;false时,不检查
test-while-idle: true
# 检验连接是否有效的查询语句。如果数据库Driver支持ping()方法,则优先使用ping()方法进行检查,否则使用validationQuery查询进行检查。(Oracle jdbc Driver目前不支持ping方法)
validation-query: select 1 from dual
keep-alive: true
remove-abandoned: true
remove-abandoned-timeout: 80
log-abandoned: true
#打开PSCache,并且指定每个连接上PSCache的大小,Oracle等支持游标的数据库,打开此开关,会以数量级提升性能,具体查阅PSCache相关资料
pool-prepared-statements: true
max-pool-prepared-statement-per-connection-size: 20
# 配置间隔多久启动一次DestroyThread,对连接池内的连接才进行一次检测,单位是毫秒。
#检测时:
#1.如果连接空闲并且超过minIdle以外的连接,如果空闲时间超过minEvictableIdleTimeMillis设置的值则直接物理关闭。
#2.在minIdle以内的不处理。
redis:
host: 127.0.0.1
port: 6379
1.3, сценарий запуска
Создайте файл сценария оболочки, такой как deploy.sh, чтобы выполнить внутреннюю работу по запуску программы Java.
#使用nohup启动,使得Java进程在后台以进程模试运行
nohup java -Xms500m -Xmx500m -XX:NewSize=300m -XX:MaxNewSize=300m -jar jshop-web-1.0-SNAPSHOT.jar --spring.config.addition-location=application.yaml > log.log 2>&1 &
#授权
chmod 777 deploy.sh
#查询进程
jps
jps -l
Тестовый доступ к интерфейсу браузера обнаружил, что служба успешно запущена:
2. Запустите измерение давления
2.1 Подготовка к измерению давления
Цель испытания под давлением:
Градиент потоков: 500, 1000, 1500, 2000, 2500, 3000 потоков, то есть имитация этих чисел пользовательского параллелизма;
Настройка времени: значение периода нарастания (в секундах) устанавливается равным 1 (т. е. 1 с, 5 с, 10 с при запуске 500, 1000, 1500, 2000, 2500, 3000 одновременных доступов).
Время цикла: 50 раз
1) Установите запрос стресс-теста
2.2, добавить слушателя
Сводные отчеты: Добавить сводные отчеты
Просмотр дерева результатов: Добавить представление дерева результатов
Статистический анализ TPS: транзакций в секунду
Мониторинг производительности сервера: процессор, память, ввод-вывод
Примечание. Для мониторинга процессора jmeter можно отслеживать только одноядерный процессор, и эталонное значение невелико.В реальном тесте вы можете использовать команду top для наблюдения за использованием процессора.
3. Принцип параметра
Задаем количество потоков n = 5, количество циклов a = 1000, запрашиваем www.google.com и получаем агрегированный отчет, как показано на рисунке:
)
Среднее время запроса на получение главной страницы Google на рисунке составляет около t = 0,2 секунды.
Здесь для удобства анализа мы установили Ramp-Up Period равным T = 10 секунд (фактическое разумное время будет объяснено позже)
Еще n = 5, получаем S = (T-T/n) = 8, то есть когда первый поток запускается до 8-й секунды, последний поток начинает запускаться, если нужно запустить последний поток Когда первый поток все еще не закрыто, оно должно удовлетворять при > S , и известно, что S = 8, t = 0,2 и получается a > 40.
线程数:n=5
循环次数:a = 1000
平均响应时间: t = 0.2s
Ramp-Up Period T=10s
S = (T-T/n) = 8
# 循环次数 * 平均响应时间
a * t > S ==> a > S/t = 40
Ramp-Up Period:
【1】决定多长时间启动所有线程。如果使用10个线程,ramp-up period是100秒,那么JMeter用100秒使所有10个线程启动并运行。每个线程会在上一个线程启动后10秒(100/10)启动。Ramp-up需要要充足长以避免在启动测试时有一个太大的工作负载,并且要充足小以至于最后一个线程在第一个完成前启动。 一般设置ramp-up=线程数启动,并上下调整到所需的。
【2】用于告知JMeter 要在多长时间内建立全部的线程。默认值是0。如果未指定ramp-up period ,也就是说ramp-up period 为零, JMeter 将立即建立所有线程。假设ramp-up period 设置成T 秒, 全部线程数设置成N个, JMeter 将每隔T/N秒建立一个线程。
【3】Ramp-Up Period(in-seconds)代表隔多长时间执行,0代表同时并发
Хорошо, так как количество циклов больше 40, мы могли бы также установить цикл равным 100, тогда время работы одного потока R = at = 20 секунд, что означает, что первый поток остановится на 20-й секунде. , и весь тест. Теоретическое время выполнения S + R = (1-1/n) T + a t = 28 секунд.
Мы используем картинку, чтобы наглядно увидеть работу каждого потока
Из рисунка видно, что с 8-й по 20-ю секунду одновременно работают 5 потоков, в это время это реальная симуляция 5 пользователей одновременно.
Сказав все это, какова наша цель? Не более чем установка количества потоков, периода нарастания и количества циклов. Я не буду много говорить о количестве потоков.Я буду смотреть на требования к тестированию каждого проекта.Я только что сказал так много.По сути, я просто ввел некоторые понятия и как разумно установить количество циклов.Что касается того,как разумный период разгона, пожалуйста, ознакомьтесь с приведенным ниже анализом.
4. Анализ параметров производительности
4.1. Пропускная способность TPS
Сводный отчет: TPS 3039, но что такое пик TPS здесь не видно, требует доработки
样本(sample): 发送请求的总样本数量
平均值(average):平均的响应时间
中位数(median): 中位数的响应时间,50%请求的响应时间
90%百分位(90% Line): 90%的请求的响应时间,意思就是说90%的请求是<=1765ms返回,另外10%的请求是大于等于1765ms返回的。
95%百分位(95% Line): 95%的请求的响应时间,95%的请求都落在1920ms之内返回的
99%百分位(99% Line): 99%的请求的响应时间
最小值(min):请求返回的最小时间,其中一个用时最少的请求
最大值(max):请求返回的最大时间,其中一个用时最大的请求
异常(error): 出现错误的百分比,错误率=错误的请求的数量/请求的总数
吞吐量TPS(throughout): 吞吐能力,这个才是我们需要的并发数
Received KB/sec----每秒从服务器端接收到的数据量
Sent KB/sec----每秒从客户端发送的请求的数量
Используйте Tps для мониторинга графика:
Видно, что в положении 1s+ TPS обладает наибольшей способностью, а в остальное время TPS плавно переходит.
В качестве одновременного давления увеличивается и расширение времени, изменения в производительности системы. При нормальных обстоятельствах средняя отклик проб должен быть гладким и существенно параллельным нижней границе графики.
4.2, кривая производительности
По мере увеличения одновременного давления и времени производительность системы меняется. Обычно кривая средней длительности выборочного ответа должна быть гладкой и примерно параллельной нижней границе графика.
Могут быть проблемы с производительностью:
①Среднее значение на начальном этапе подскакивает, а затем постепенно стабилизируется
Во-первых, система имеет дефекты производительности на начальном этапе и нуждается в дальнейшей оптимизации, например, медленные запросы к базе данных.
Во-вторых, в системе есть механизм кэширования, и данные теста производительности не меняются в процессе теста, поэтому время отклика одних и тех же данных на начальном этапе должно быть медленнее, это проблема подготовки данных теста производительности, а не производительности. дефект, который необходимо исправить в тесте
Третье — неотъемлемое явление, вызванное архитектурой системы: например, после того, как система получит первый запрос, она установит связь между сервером приложений и базой данных, и соединение не будет разорвано в течение периода время.
②Среднее значение продолжает увеличиваться, и картина становится все круче и круче.
Во-первых, могут быть утечки памяти, в этом случае вы можете локализовать проблему, наблюдая за системным журналом, отслеживая состояние сервера приложений и другими распространенными методами.
③Среднее значение внезапно подскакивает во время теста производительности, а затем возвращается к норме
Во-первых, могут быть дефекты производительности системы.
Во-вторых, это может быть вызвано нестабильностью тестовой среды (проверьте состояние сервера приложений [использование ЦП, использование памяти] или проверьте, не перегружена ли сеть тестовой среды)
4. Оптимизация сервиса
1. Увеличьте количество потоков
# server端线程数到245就已经上不去了,导致服务端的性能提升不上去
# pstree 查询线程数量
jps -l
# 查询所有线程
pstree -p pid
# 统计线程数量
pstree -p pid | wc -l
#开启压测,再次统计线程数量,查看线程数量是否增大,是否还有增大的空间
2. Встроенная конфигурация
Служба, разработанная Springboot, использует встроенный сервер tomcat для запуска службы, затем конфигурация tomcat использует конфигурацию по умолчанию Нам нужно внести некоторые соответствующие оптимизации в конфигурацию tomcat, чтобы повысить производительность tomcat.
Конечно, конфигурация встроенного пула потоков tomcat также относительно невелика, мы можем переписать соответствующую конфигурацию tomcat через внешний файл конфигурации, а затем перезапустить сервер для тестирования. Измените конфигурацию следующим образом:
Три конфигурации Tomcat: maxConnections, maxThreads и acceptCount представляют максимальное количество подключений, максимальное количество потоков и максимальное количество ожиданий. Эти три значения можно изменить в файле конфигурации application.yml. Стандартный пример: следующее:
server:
tomcat:
uri-encoding: UTF-8
#最大工作线程数,默认200, 4核8g内存,线程数经验值800
#操作系统做线程之间的切换调度是有系统开销的,所以不是越多越好。
max-threads: 1000
# 等待队列长度,默认100
accept-count: 1000
max-connections: 20000
# 最小工作空闲线程数,默认10, 适当增大一些,以便应对突然增长的访问量
min-spare-threads: 100
1), accept-count: максимальное количество ожиданий
В официальной документации указано: Когда все потоки обработки запросов используются, максимальная длина очереди запросов на подключение, которая может быть получена. Когда очередь заполнена, любые запросы на подключение будут отклонены. Значение по умолчанию для accept-count равно 100. Подробно: когда количество вызовов HTTP-запросов достигает максимального количества потоков tomcat и поступает новый HTTP-запрос, тогда tomcat помещает запрос в очередь ожидания. acceptCount относится к максимальному количеству ожиданий, которые могут быть приняты , По умолчанию 100. Если очередь ожидания также заполнена, новые запросы в это время будут отклонены tomcat (отказано в соединении).
2), maxThreads: максимальное количество потоков
Каждый раз, когда HTTP-запрос прибывает на веб-сервисе, Tomcat создаст поток для обработки запроса, поэтому максимальное количество потоков определяет, сколько запросов контейнер для веб-сервисов может обрабатывать одновременно. MaxThreads по умолчанию до 200, и он определенно рекомендуется увеличить. Тем не менее, существует затрата для добавления потоков. Больше потоков не только принесут больше затрат на переключение контекста потоков, но также приносят больше потребления памяти. По умолчанию JVM выделяет стек резьбы 1M при создании новой поток, поэтому требуется больше потоков, необходима больше памяти. Эмпирическое значение количества потоков: 1 ядра с 2G памяти составляет 200, а количество потоков 200; с 4 ядрами и 8 г памяти количество потоков составляет 800.
3) MaxConnections: максимальное соединение
Официальная документация гласит:
Этот параметр относится к максимальному количеству подключений, которые tomcat может принимать одновременно. Для блокировки BIO в Java значением по умолчанию является значение maxthreads; если пользовательский Executor используется в режиме BIO, значением по умолчанию будет значение maxthreads в исполнителе. Для нового режима NIO в Java значение maxConnections по умолчанию равно 10000. Для режима APR/собственного ввода-вывода в Windows значение maxConnections по умолчанию равно 8192. Это сделано из соображений производительности.Если настроенное значение не кратно 1024, фактическое значение maxConnections будет уменьшено до максимального значения, кратного 1024. Если установлено значение -1, функция maxconnections отключена, что означает, что количество подключений контейнера tomcat не ограничено. Связь между maxConnections и accept-count такова: когда количество подключений достигает максимального значения maxConnections, система продолжит получать подключения, но не превысит значение acceptCount.
3. Решение проблем
Недавно при использовании jmeter для стресс-тестирования обнаружил проблему, когда поток продолжает расти до определенного значения, сообщается об ошибке: java.net.BindException: Address уже используется: connect, как показано на следующем рисунке:
Причина: порты, предоставляемые Windows для ссылок TCP/IP, — 1024-5000, и их переработка занимает четыре минуты, что заставляет нас выполнять большое количество запросов за короткий период времени и заполнять порты, что приводит к вышеуказанная ошибка.
Обходной путь (в работе сервера JMeter):
Введите команду regedit в CMD, чтобы открыть реестр;
2. Щелкните правой кнопкой мыши Параметры в HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters;
3. Добавьте новый DWORD с именем MaxUserPort;
4. Затем дважды щелкните MaxUserPort, введите числовые данные как 65534 и выберите десятичное для основания;
5. После выполнения вышеуказанных операций обязательно перезагрузите машину, проблема будет решена, и личный тест будет эффективным;
4. Сравнение производительности
Таблица сравнения производительности неоптимизированного теста:
Параллелизм / 5 с | Количество образцов | Среднее время отклика (мс) | Пропускная способность (т/с) | Частота ошибок | KB/sec |
---|---|---|---|---|---|
200 | 10000 | 7 | 1849 | 0 | 791 |
300 | 15000 | 14 | 2654 | 0 | 1135 |
500 | 25000 | 71 | 2925 | 0 | 1251 |
700 | 35000 | 141 | 2865 | 0 | 1225 |
1000 | 50000 | 244 | 2891 | 0 | 1236 |
1500 | 75000 | 418 | 2910 | 0 | 1224 |
2000 | 100000 | 553 | 2920 | 0 | 1249 |
3000 | 150000 | 889 | 2533 | 0.05 | 1086 |
3200 | |||||
3500 | |||||
4000 | |||||
4500 | |||||
5000 |
Сравнительная таблица производительности после оптимизации:
# 优化的参数配置
server:
tomcat:
accept-count: 800
max-connections: 20000
max-threads: 800
min-spare-threads: 100
# 优化后,性能不升反降
# 1、 由于根据主键从数据库查询数据,基本不耗时,也就是说这个是一个不耗时操作,增加线程反而会增加cpu切换的时间
# 2、由于从数据库查询数据封装到对象,然后对象被垃圾回收(每次请求封装一个对象,然后垃圾回收),这个过程在并发下不停的重复,也会造成大量的性能的消耗。
# 总结:想要看见优化服务器参数后的性能提升,那么必须要增加方法的业务耗时,如果消耗的时间变长,才能看出优化参数的效果,否则不可能看出效果。
# 服务的单纯优化,已经能看出效果: 让线程睡了1s,然后在测试为优化,和已经优化后的结果,发现优化后效果tps明显提升。
Сравнение тестов производительности:
Параллелизм / 5 с | Количество образцов | Среднее время отклика (мс) | Пропускная способность (т/с) | Частота ошибок | KB/sec |
---|---|---|---|---|---|
200 | 10000 | 11 | 1836 | 0 | 785 |
300 | 15000 | 17 | 2486 | 0 | 1063 |
500 | 25000 | 85 | 2693 | 0 | 1152 |
700 | 35000 | 151 | 2769 | 0 | 1184 |
1000 | 50000 | 260 | 2736 | 0 | 1171 |
1500 | 75000 | 445 | 2766 | 0 | 1183 |
2000 | 100000 | 582 | 2813 | 0 | 1203 |
3000 | 150000 | 937 | 2794 | 0 | 1195 |
3200 | 160000 | 1147 | 2429 | 0 | 1039 |
3500 | 175000 | 1150 | 2796 | 0.05 | 1198 |
4000 | 200000 | 1292 | 2852 | 0 | 1220 |
4500 | 225000 | 1428 | 2825 | 0 | 1208 |
5000 | 250000 | 1581 | 2867 | 0.03 | 1228 |
5. Поддержание активности
Длительное соединение будет потреблять много ресурсов.Если соединение не может быть разорвано вовремя, TPS системы не улучшится.Поэтому нам необходимо преобразовать веб-службу, чтобы повысить производительность длительного соединения веб-службы. .
package com.sugo.seckill.web.config;
//当Spring容器内没有TomcatEmbeddedServletContainerFactory这个bean时,会吧此bean加载进spring容器中
@Component
public class WebServerConfig implements WebServerFactoryCustomizer<ConfigurableWebServerFactory> {
@Override
public void customize(ConfigurableWebServerFactory configurableWebServerFactory) {
//使用对应工厂类提供给我们的接口定制化我们的tomcat connector
((TomcatServletWebServerFactory)configurableWebServerFactory).addConnectorCustomizers(new TomcatConnectorCustomizer() {
@Override
public void customize(Connector connector) {
Http11NioProtocol protocol = (Http11NioProtocol) connector.getProtocolHandler();
//定制化keepalivetimeout,设置30秒内没有请求则服务端自动断开keepalive链接
protocol.setKeepAliveTimeout(30000);
//当客户端发送超过10000个请求则自动断开keepalive链接
protocol.setMaxKeepAliveRequests(10000);
}
});
}
}
// 监控ESTABLISHED,TIME_WAIT 线程的数量
netstat -n | awk '/^tcp/ {++y[$NF]} END {for(w in y) print w, y[w]}'
//查看网络连接数:
netstat -an |wc -l
netstat -an |grep xx |wc -l // 查看某个/特定PID的连接数
netstat -an |grep TIME_WAIT |wc -l // 查看连接数等待time_wait状态连接数
netstat -an |grep ESTABLISHED |wc -l // 查看建立稳定连接数量
//常用的三个状态是:ESTABLISHED 表示正在通信,TIME_WAIT 表示主动关闭,CLOSE_WAIT 表示被动关
Точки передачи состояния TCPПротокол TCP предусматривает, что для установленного соединения обе стороны сети должны выполнить четыре рукопожатия для успешного разрыва соединения.Если один из этих шагов пропущен, соединение будет находиться в приостановленном состоянии, а ресурсы заняты самим соединением. не будет выпущен. Программе сетевого сервера необходимо одновременно управлять большим количеством подключений, поэтому необходимо следить за тем, чтобы бесполезные подключения были полностью отключены, иначе большое количество мертвых подключений приведет к трате большого количества ресурсов сервера. Среди многих состояний TCP есть два наиболее заметных состояния: CLOSE_WAIT и TIME_WAIT.
1. ПРОСЛУШИВАНИЕПосле запуска службы FTP она сначала находится в состоянии ПРОСЛУШИВАНИЯ.
2. УСТАНОВЛЕННЫЙ статусESTABLISHED означает установить соединение. Указывает, что две машины обмениваются данными.
* 3. Close_wait *
* Другая сторона принимает инициативу, чтобы закрыть соединение или сетевое соединение теряется в результате ненормального *, тогда наше состояние станет CLOSE_WAIT. В это время нам нужно вызвать close(), чтобы правильно закрыть соединение
*4. TIME_WAIT*
***Мы активно вызываем close() для отключения, и статус меняется на TIME_WAIT после получения подтверждения от другой стороны*. **Протокол TCP предусматривает, что состояние TIME_WAIT будет длиться 2MSL (то есть вдвое больше максимального времени жизни сегмента), чтобы гарантировать, что старое состояние соединения не повлияет на новое соединение.Ресурсы, занятые соединением в состоянии TIME_WAIT, не будут освобождены ядром., так как сервер, по возможности, старайтесь не отключаться активно, чтобы уменьшить трату ресурсов, вызванную состоянием TIME_WAIT.
В настоящее время существует способ избежать отходов ресурсов time_wait, который должен отключить вариант задержания розетки. Но эта практика не рекомендуется протоколом TCP, а в некоторых случаях эта операция может принести ошибки.
состояние сокета
1.1 Описание состояния
CLOSED Этот сокет не используется [netstat не может отображать закрытый статус] LISTEN Сокет прослушивает соединения [после вызова прослушивания] SYN_SENT Сокет пытается активно установить соединение [после отправки SYN не было получено ACK] SYN_RECEIVED Он находится в начальном состоянии синхронизации соединения [получил SYN другой стороны, но не получил ACK SYN, отправленного самим собой] ESTABLISHED Соединение установлено CLOSE_WAIT Удаленный сокет был закрыт: ожидание закрытия этого сокета [пассивная закрытая сторона получила FIN] FIN_WAIT_1 Сокет закрыт, соединение закрыто [FIN отправлен, ни ACK, ни FIN не получены] CLOSING Сокет закрыт, удаленный сокет закрывается, ожидается подтверждение закрытия [состояние FIN_WAIT_1, получен FIN от пассивной стороны] LAST_ACK Удаленный сокет был закрыт и ожидает подтверждения закрытия от локального сокета [пассивная сторона отправляет FIN в состоянии CLOSE_WAIT] FIN_WAIT_2 Сокет закрыт и ожидает закрытия удаленного сокета [получен ACK, соответствующий FIN, отправленному в состоянии FIN_WAIT_1] TIME_WAIT Этот сокет был закрыт и ожидает закрытия передачи удаленного сокета [FIN, ACK, FIN, ACK завершены, это последнее состояние активной стороны, и оно становится состоянием CLOSED после 2MSL]
Диаграмма перехода состояния: (диаграмма перехода состояния соединения TCP)
Серверной стороне Java NIO нужно только запустить специальный поток для обработки всех событий ввода-вывода Как реализована эта модель связи? О, давайте исследовать его тайны вместе. Java NIO использует двусторонний канал (channel) для передачи данных, а не односторонний поток (stream), на котором могут быть зарегистрированы интересующие события. Существует четыре типа событий:
название события | соответствующее значение |
---|---|
Сервер получает событие подключения клиента | SelectionKey.OP_ACCEPT(16) |
Событие сервера подключения клиента | SelectionKey.OP_CONNECT(8) |
прочитать событие | SelectionKey.OP_READ(1) |
Написать событие | SelectionKey.OP_WRITE(4) |
Сервер и клиент поддерживают объект, который управляет каналом, который мы называем селектором, который может обнаруживать события на одном или нескольких каналах. Возьмем сервер в качестве примера.Если в селекторе сервера зарегистрировано событие чтения, клиент отправляет какие-то данные на сервер в определенное время, и ввод-вывод блокируется.В это время read() метод будет вызываться для блокировки чтения данных, и сервер NIO добавит событие чтения в селектор. Поток обработки сервера будет обращаться к селектору в режиме опроса. Если при доступе к селектору будут обнаружены интересные события, эти события будут обработаны. Если интересные события не поступят, поток обработки будет заблокирован до поступления интересных событий. . Ниже приведена схема коммуникационной модели java NIO, как я ее понимаю:
Селектор. Можно сказать, что это самая важная часть NIO.Функция селектора заключается в опросе каждого зарегистрированного канала.Как только в канале будет найдено зарегистрированное событие, он получит это событие и обработает его.
Процесс отправки данных от клиента на сервер и последующего получения данных с сервера. Когда клиент отправляет данные, он должен сначала сохранить данные в буфере, а затем записать содержимое буфера в канал. Чтобы получить данные на стороне сервера, он должен прочитать данные в буфер через канал, а затем извлечь данные из буфера для обработки.
Запросите тип io, используемый встроенным tomcat в Springboot, и исходный код будет просто проанализирован:
6. нио2
Используйте http-протокол nio2, чтобы переписать запрос, чтобы увидеть, улучшилась ли производительность сервера.
# 使用nio2
#嵌入tomcat配置
spring.server.port=8095
#和CPU数
spring.server.acceptorThreadCount=4
spring.server.minSpareThreads=50
spring.server.maxSpareThreads=50
spring.server.maxThreads=1000
spring.server.maxConnections=10000
#10秒超时
spring.server.connectionTimeout=10000
spring.server.protocol=org.apache.coyote.http11.Http11Nio2Protocol
spring.server.redirectPort=443
spring.server.compression=on
#文件请求大小
spring.server.MaxFileSize=300MB
spring.server.MaxRequestSize=500MB
@Slf4j
@Component
class AppTomcatConnectorCustomizer implements WebServerFactoryCustomizer<ConfigurableServletWebServerFactory> {
@Override
public void customize(ConfigurableServletWebServerFactory factory) {
((TomcatServletWebServerFactory) factory).setProtocol("org.apache.coyote.http11.Http11Nio2Protocol");
((TomcatServletWebServerFactory) factory).addConnectorCustomizers(new TomcatConnectorCustomizer() {
@Override
public void customize(Connector connector) {
ProtocolHandler protocol = connector.getProtocolHandler();
log.info("Tomcat({}) -- MaxConnection:{};MaxThreads:{};MinSpareThreads:{}", //
protocol.getClass().getName(), //
((AbstractHttp11Protocol<?>) protocol).getMaxConnections(), //
((AbstractHttp11Protocol<?>) protocol).getMaxThreads(), //
((AbstractHttp11Protocol<?>) protocol).getMinSpareThreads());
}
});
}
}
7, откат
# Undertow是Red Hat公司的开源产品, 它完全采用Java语言开发,是一款灵活的高性能Web服务器,支持阻塞IO和非阻塞IO。由于Undertow采用Java语言开发,可以直接嵌入到Java项目中使用。同时, Undertow完全支持Servlet和Web Socket,在高并发情况下表现非常出色
# 设置IO线程数, 它主要执行非阻塞的任务,它们会负责多个连接, 默认设置每个CPU核心一个线程
# 不要设置过大,如果过大,启动项目会报错:打开文件数过多
server.undertow.io-threads=16
# 阻塞任务线程池, 当执行类似servlet请求阻塞IO操作, undertow会从这个线程池中取得线程
# 它的值设置取决于系统线程执行任务的阻塞系数,默认值是IO线程数*8
server.undertow.worker-threads=256
# 以下的配置会影响buffer,这些buffer会用于服务器连接的IO操作,有点类似netty的池化内存管理
# 每块buffer的空间大小,越小的空间被利用越充分,不要设置太大,以免影响其他应用,合适即可
server.undertow.buffer-size=1024
# 每个区分配的buffer数量 , 所以pool的大小是buffer-size * buffers-per-region
server.undertow.buffers-per-region=1024
# 是否分配的直接内存(NIO直接分配的堆外内存)
server.undertow.direct-buffers=true
# 配置说明
undertow默认配置情况下,官方默认配置的是 CPU核数*8,比如8核CPU,实际工作线程数也就8*8=64,这个配置对于高并发场景来看,一台8核CPU的机器一般内存都会32G或以上,即使跑满64线程,占用的资源远远无法充分利用该机器的性能。
当然啦,官方也是建议工作线程数的配置,取决于你机器的负载情况,其实也就是跟你的具体业务有关,我们现在的业务场景,64线程跑满的情况,CPU利用率仅仅百分之十几、CPU内存远远没利用完,再有请求过来,undertow则直接阻塞队列中,无法正常处理,资源浪费严重,还导致了服务中断的情况。
因此,从实际情况来看,一定不要采用undertow的官方默认配置。像我们线上业务来看,每个API接口业务耗时大多数在10ms以内,少部分耗时30-50ms时间,单接口耗用资源不大。 修改undertow配置 worker-threads=256,单节点可以承载256的并发任务,剩下的就是根据实际业务情况动态扩展节点数量即可。
Пять наиболее часто используемых методов анализа производительности
? Язык Java является наиболее широко используемым языком в современном Интернете. Как программист Java, когда бизнес относительно стабилен, в дополнение к кодированию большую часть времени (70% ~ 80%) используется для устранения неполадок в чрезвычайных ситуациях или периодических проблема онлайн.
Из-за ошибок бизнес-приложений (либо самих, либо из-за внедрения сторонних библиотек), экологических причин, проблем с оборудованием и т. Д., Сбои / проблемы онлайн-сервиса Java почти неизбежны. Например, общие явления включают тайм-аут некоторых запросов, явное ощущение пользователями, что система зависла, и так далее.
Онлайн-проблема в кратчайшие сроки очень очевидна по внешнему виду системы, но все еще трудно исследовать причину ее возникновения, поэтому она доставила много хлопот студентам, которые разрабатывают, тестируют или эксплуатируют и поддерживают.
Устранение неполадок и обнаружение онлайн-проблем требует определенных навыков или опыта.
В любом случае, овладение идеями онлайн-устранения неполадок службы Java и умение устранять неполадки с распространенными инструментами/командами/платформами — это практические навыки, которыми должен овладеть каждый продвинутый Java-программист.
1. Часто задаваемые онлайн-вопросы о службах Java
С точки зрения внешнего вида системы все онлайн-проблемы Java-сервисов можно свести к четырем аспектам: ЦП, память, диск и сеть. Например, внезапный пик загрузки ЦП, переполнение памяти (утечка), переполнение диска, аномальный сетевой трафик, FullGC и т. д.
Основываясь на этих явлениях, мы можем разделить онлайн-проблемы на две категории: системные аномалии и аномалии бизнес-служб.
1.1. Неисправность системы
Общие системные аномальные явления включают в себя: высокую загрузку ЦП, высокую частоту переключения контекста ЦП, переполнение диска, слишком частый дисковый ввод-вывод, ненормальный сетевой трафик (слишком много подключений) и системную доступную память с низким значением в течение длительного времени (вызывая перегрузку). убийца) и так далее.
Эти проблемы могут быть получены с помощью таких инструментов, как top (процессор), free (память), df (диск), dstat (сетевой трафик), pstack, vmstat, strace (низкоуровневый системный вызов) и другие инструменты.
Кроме того, если система и приложение проверены и более глупая причина аномалии не обнаружена, это также может быть проблемой, вызванной внешней инфраструктурой, такой как сама платформа IAAS.
1.2. Нестандартное деловое обслуживание
Общие аномалии бизнес-сервисов включают в себя: чрезмерный объем PV, аномальные длительные вызовы служб, тупиковые ситуации потоков, многопоточные проблемы параллелизма, частый полный сборщик мусора, аномальное сканирование атак безопасности и т. д.
2. Место проблемы
Как правило, мы используем метод исключения, чтобы локализовать проблемы онлайн-сервисов, начиная с внешнего расследования и заканчивая внутренним расследованием.
- Во-первых, нам нужно исключить проблемы с ошибками, которые могут вызывать другие процессы (кроме основного процесса);
- Затем исключить проблемы с отказом бизнес-приложений, которые могут возникнуть;
- Можно рассмотреть, вызвана ли неисправность оператором или поставщиком облачных услуг.
2.1 Процесс устранения неполадок системы
Процесс локализации проблемы, метод и процесс устранения неполадок в системе Linux.
2.2 Процесс устранения неполадок бизнес-приложений
3. Обычно используемые инструменты анализа производительности Linux
Обычно используемые инструменты анализа производительности в Linux включают: top (процессор), free (память), df (диск), dstat (сетевой трафик), pstack, vmstat, strace (низкоуровневые системные вызовы) и т. д.
3.1 ЦП
ЦП является важным индикатором мониторинга системы, который может анализировать общее рабочее состояние системы. Показатели мониторинга обычно включают очереди выполнения, использование ЦП и переключение контекста.
Команда top — это широко используемый инструмент анализа производительности ЦП в Linux, который может отображать статус занятости ресурсов каждого процесса в системе в режиме реального времени и часто используется для анализа производительности сервера.
top 命令显示了各个进程 CPU 使用情况 , 一般 CPU 使用率从高到低排序展示输出。其中 Load Average 显示最近 1 分钟、5 分钟和 15 分钟的系统平均负载,上图各值为 2.46,1.96,1.99。
我们一般会关注 CPU 使用率最高的进程,正常情况下就是我们的应用主进程。第七行以下:各进程的状态监控
# 各个组件的作用说明
PID : 进程 id
USER : 进程所有者
PR : 进程优先级
NI : nice 值。负值表示高优先级,正值表示低优先级
VIRT : 进程使用的虚拟内存总量,单位 kb。VIRT=SWAP+RES
RES : 进程使用的、未被换出的物理内存大小,单位 kb。RES=CODE+DATA
SHR : 共享内存大小,单位 kb
S : 进程状态。D= 不可中断的睡眠状态 R= 运行 S= 睡眠 T= 跟踪 / 停止 Z= 僵尸进程
%CPU : 上次更新到现在的 CPU 时间占用百分比
%MEM : 进程使用的物理内存百分比
TIME+ : 进程使用的 CPU 时间总计,单位 1/100 秒
COMMAND : 进程名称
3.2, память
Память является важным ориентиром для устранения неполадок в сети, а проблемы с памятью часто являются причиной высокой загрузки ЦП.
Системная память: свободно отображается текущее использование памяти, -m означает M байт для отображения содержимого.
# free 查询当前内存使用情况
free -m
# 部分参数说明
total 内存总数: 7821M
used 已经使用的内存数: 713M
free 空闲的内存数: 3107M
shared 当前已经废弃不用 , 总是 0
buffers Buffer 缓存内存数: 3999M
2.3 Диск
# 使用df查看磁盘是否被占满,占用情况
df -h
# 查看具体目录下的磁盘使用情况
du -m /path
2.4 Сеть
Команда dstat объединяет задачи, которые могут выполнять vmstat, iostat, netstat lsof и другие инструменты.
1) Подробное объяснение команды vmstat:
# 【在5秒时间内进行5次采样】
vmstat 5 5
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
1 0 0 519512 199436 4079816 0 0 1 7 12 1 0 0 99 0 0
0 0 0 519232 199436 4079816 0 0 0 10 1920 3413 0 0 99 0 0
0 0 0 519380 199436 4079816 0 0 0 10 1854 3348 0 0 100 0 0
字段说明:
Procs(进程):
r: 运行队列中进程数量
b: 等待IO的进程数量
Memory(内存):
swpd: 使用虚拟内存大小
free: 可用内存大小
buff: 用作缓冲的内存大小
cache: 用作缓存的内存大小
Swap:
si: 每秒从交换区写到内存的大小
so: 每秒写入交换区的内存大小
IO:(现在的Linux版本块的大小为1024bytes)
bi: 每秒读取的块数
bo: 每秒写入的块数
系统:
in: 每秒中断数,包括时钟中断。【interrupt】
cs: 每秒上下文切换数。 【count/second】
CPU(以百分比表示):
us: 用户进程执行时间(user time)
sy: 系统进程执行时间(system time)
id: 空闲时间(包括IO等待时间),中央处理器的空闲时间 。以百分比表示。
wa: 等待IO时间
备注:
# 1、如果r经常大于4,id经常少于40,表示cpu的负荷很重。
# 2、如果bi,bo长期不等于0,表示内存不足。
# 3、如果disk经常不等于0,且在b中的队列大于3,表示io性能不好。
Linux在具有高稳定性、可靠性的同时,具有很好的可伸缩性和扩展性,能够针对不同的应用和硬件环境调整,优化出满足当前应用需要的最佳性能。因此企业在维护Linux系统、进行系统调优时,了解系统性能分析工具是至关重要的。
# 显示活跃和非活跃内存
vmstat -a 2 5 【-a 显示活跃和非活跃内存,所显示的内容除增加inact和active】
# 显示从系统启动至今的fork数量,【 linux下创建进程的系统调用是fork】
vmstat -f
2) lsof: используется для просмотра файлов, открытых вашим процессом, процесса, открывшего файл, и портов (TCP, UDP), открытых этим процессом. Получить / восстановить удаленные файлы
# lsof打开的文件可以是:
1.普通文件
2.目录
3.网络文件系统的文件
4.字符或设备文件
5.(函数)共享库
6.管道,命名管道
7.符号链接
8.网络文件(例如:NFS file、网络socket,unix域名socket)
9.还有其它类型的文件,等等
3) dstat -c состояние процессора -d чтение и запись диска -n состояние сети -l отображение загрузки системы -m отображение аналогичного состояния памяти -p отображение информации о системном процессе -r отображение состояния ввода-вывода системы
Примечание. Если команды dstat нет, необходимо скачать (yum -y install dstat)
4) стек стрейс
# 有时我们需要对程序进行优化、减少程序响应时间。除了一段段地对代码进行时间复杂度分析,我们还有更便捷的方法吗?
若能直接找到影响程序运行时间的函数调用,再有针对地对相关函数进行代码分析和优化,那相比漫无目的地看代码,效率就高多了。
将strace和pstack工具结合起来使用,就可以达到以上目的。strace跟踪程序使用的底层系统调用,可输出系统调用被执行的时间点以及各个调用耗时;pstack工具对指定PID的进程输出函数调用栈。
4. Инструмент для определения местоположения JVM
Ряд ценных инструментов командной строки по умолчанию предоставляется в каталоге bin каталога установки JDK. Каждый гаджет в основном имеет небольшой размер, потому что эти инструменты представляют собой простые пакеты jdk\lib\tools.jar.
Среди них наиболее часто используемые команды при поиске и устранении неполадок включают: jps (процесс), jmap (память), jstack (поток), jinfo (параметр) и т. д.
- jps: запрашивать всю информацию о процессе JAVA текущей машины;
- jmap: вывод ситуации с памятью java-процесса (например: эти объекты и числа и т. д.);
- jstack: вывести информацию о стеке потока Java-потока;
- jinfo: используется для просмотра параметров конфигурации jvm.
4.1, джпс
jps используется для вывода всех идентификаторов процессов, запущенных текущим пользователем.При обнаружении неисправности или проблемы в сети можно использовать jps для быстрого поиска соответствующего идентификатора процесса Java.
# jps 命令查询
jps -l -m -m -l -l 参数用于输出主启动类的完整路径
ps -ef | grep tomcat
#我们也能快速获取 tomcat 服务的进程 id。
Конечно, мы также можем использовать команду состояния процесса запроса, предоставляемую Linux, например:
4.2, джмап
map命令是一个可以输出所有内存中对象的工具,甚至可以将VM 中的heap,以二进制输出成文本。
打印出某个java进程(使用pid)内存内的,所有‘对象’的情况(如:产生那些对象,及其数量)。
# 输出当前进程 JVM 堆新生代、老年代、持久代等请情况,GC 使用的算法等信息
jmap -heap pid
# 输出当前进程内存中所有对象包含的大小
jmap -histo:live {pid} | head -n 10
# 以二进制输出档当前内存的堆情况,然后可以导入 MAT 等工具进行
jmap -dump:format=b,file=/usr/local/logs/gc/dump.hprof {pid}
# jmap(Java Memory Map) 可以输出所有内存中对象的工具 , 甚至可以将 VM 中的 heap, 以二进制输出成文本。
jmap -heap pid
# 输出当前进程 JVM 堆新生代、老年代、持久代等请情况,GC 使用的算法等信息
jmap -heap pid
using parallel threads in the new generation. ##新生代采用的是并行线程处理方式
using thread-local object allocation.
Concurrent Mark-Sweep GC ##同步并行垃圾回收
Heap Configuration: ##堆配置情况,也就是JVM参数配置的结果[平常说的tomcat配置JVM参数,就是在配置这些]
MinHeapFreeRatio = 40 ##最小堆使用比例
MaxHeapFreeRatio = 70 ##最大堆可用比例
MaxHeapSize = 2147483648 (2048.0MB) ##最大堆空间大小
NewSize = 268435456 (256.0MB) ##新生代分配大小
MaxNewSize = 268435456 (256.0MB) ##最大可新生代分配大小
OldSize = 5439488 (5.1875MB) ##老年代大小
NewRatio = 2 ##新生代比例
SurvivorRatio = 8 ##新生代与suvivor的比例
PermSize = 134217728 (128.0MB) ##perm区 永久代大小
MaxPermSize = 134217728 (128.0MB) ##最大可分配perm区 也就是永久代大小
Heap Usage: ##堆使用情况【堆内存实际的使用情况】
New Generation (Eden + 1 Survivor Space): ##新生代(伊甸区Eden区 + 幸存区survior(1+2)空间)
capacity = 241631232 (230.4375MB) ##伊甸区容量
used = 77776272 (74.17323303222656MB) ##已经使用大小
free = 163854960 (156.26426696777344MB) ##剩余容量
32.188004570534986% used ##使用比例
Eden Space: ##伊甸区
capacity = 214827008 (204.875MB) ##伊甸区容量
used = 74442288 (70.99369812011719MB) ##伊甸区使用
free = 140384720 (133.8813018798828MB) ##伊甸区当前剩余容量
34.65220164496263% used ##伊甸区使用情况
From Space: ##survior1区
capacity = 26804224 (25.5625MB) ##survior1区容量
used = 3333984 (3.179534912109375MB) ##surviror1区已使用情况
free = 23470240 (22.382965087890625MB) ##surviror1区剩余容量
12.43827838477995% used ##survior1区使用比例
To Space: ##survior2 区
capacity = 26804224 (25.5625MB) ##survior2区容量
used = 0 (0.0MB) ##survior2区已使用情况
free = 26804224 (25.5625MB) ##survior2区剩余容量
0.0% used ## survior2区使用比例
PS Old Generation: ##老年代使用情况
capacity = 1879048192 (1792.0MB) ##老年代容量
used = 30847928 (29.41887664794922MB) ##老年代已使用容量
free = 1848200264 (1762.5811233520508MB) ##老年代剩余容量
1.6416783843721663% used ##老年代使用比例
Perm Generation: ##永久代使用情况
capacity = 134217728 (128.0MB) ##perm区容量
used = 47303016 (45.111671447753906MB) ##perm区已使用容量
free = 86914712 (82.8883285522461MB) ##perm区剩余容量
35.24349331855774% used ##perm区使用比例
jmap может просматривать распределение памяти и использование процесса JVM, используемый алгоритм GC и другую информацию.
jmap -histo:live {pid} | head -n 10:
jmap -histo:live {pid} | head -n 10 输出当前进程内存中所有对象包含的大小
输出当前进程内存中所有对象实例数 (instances) 和大小 (bytes), 如果某个业务对象实例数和大小存在异常情况,可能存在内存泄露或者业务设计方面存在不合理之处。
jmap -dump:
jmap -dump:format=b,file=/usr/local/logs/gc/dump.hprof {pid}
-dump:formate=b,file= 以二进制输出当前内存的堆情况至相应的文件,然后可以结合 MAT 等内存分析工具深入分析当前内存情况。
一般我们要求给 JVM 添加参数 -XX:+Heap Dump On Out Of Memory Error OOM 确保应用发生 OOM 时 JVM 能够保存并 dump 出当前的内存镜像。
当然,如果你决定手动 dump 内存时,dump 操作占据一定 CPU 时间片、内存资源、磁盘资源等,因此会带来一定的负面影响。
此外,dump 的文件可能比较大 , 一般我们可以考虑使用 zip 命令对文件进行压缩处理,这样在下载文件时能减少带宽的开销。
下载 dump 文件完成之后,由于 dump 文件较大可将 dump 文件备份至制定位置或者直接删除,以释放磁盘在这块的空间占用。
4.3, стек
printf '%x\n' tid -> идентификатор потока из десятичного в шестнадцатеричный (нативный поток)
Десятичный: jstack pid | grep tid -C 30 –color
Метод ps запрашивает tid текущего потока и продолжительность времени, которое занимает текущий поток: ps -mp 8278 -o THREAD,tid,time | head -n 40
Процесс Java имеет высокую загрузку ЦП, и мы хотим найти поток с максимальной загрузкой ЦП.
(1) 利用 top 命令可以查出占 CPU 最高的线程 pid
top -Hp {pid}
(2) 占用率最高的线程 ID 为 6900,将其转换为 16 进制形式 (因为 java native 线程以 16 进制形式输出)
printf ‘%x\n’ 6900
(3) 利用 jstack 打印出 java 线程调用栈信息
jstack 6418 | grep ‘0x1af4’ -A 50 –color
注意:jstack pid 也可以直接根据进程id查询此进行下所有线程的堆栈情况,但是已经知道问题线程,应该直接定位问题线程。
# grep 参数说明
grep [-acinv] [--color=auto] [-A n] [-B n] '搜寻字符串' 文件名
参数说明:
-a:将二进制文档以文本方式处理
-c:显示匹配次数
-i:忽略大小写差异
-n:在行首显示行号
-A:After的意思,显示匹配字符串后n行的数据
-B:before的意思,显示匹配字符串前n行的数据
-v:显示没有匹配行
--color:以特定颜色高亮显示匹配关键字
4.4. Джинфо
#命令:jinfo pid
#描述:输出当前 jvm 进程的全部参数和系统属性
#命令:jinfo -flag name pid
#描述:输出对应名称的参数,使用该命令,可以查看指定的 jvm 参数的值。如:查看当前 jvm 进程是否开启打印 GC 日志。
# 查看某个 JVM 参数值
jinfo -flag ReservedCodeCacheSize 28461
jinfo -flag MaxPermSize 28461
#命令:jinfo -flag [+|-]name pid
#描述:开启或者关闭对应名称的参数,使用 jinfo 可以在不重启虚拟机的情况下,可以动态的修改 jvm 的参数。尤其在线上的环境特别有用。
#命令:jinfo -flag name=value pid
#描述:修改指定参数的值。
4.5, jstat
# 垃圾回收器统计
jstat -gc pid
S0C:第一个幸存区的大小
S1C:第二个幸存区的大小
S0U:第一个幸存区的使用大小
S1U:第二个幸存区的使用大小
EC:伊甸园区的大小
EU:伊甸园区的使用大小
OC:老年代大小
OU:老年代使用大小
MC:方法区大小
MU:方法区使用大小
CCSC:压缩类空间大小
CCSU:压缩类空间使用大小
YGC:年轻代垃圾回收次数
YGCT:年轻代垃圾回收消耗时间
FGC:老年代垃圾回收次数
FGCT:老年代垃圾回收消耗时间
GCT:垃圾回收消耗总时间
jstat -gcutil `pgrep -u admin java`
#jstat命令可以查看堆内存各部分的使用量,以及加载类的数量。
#命令的格式如下:
jstat [-命令选项] [vmid] [间隔时间/毫秒] [查询次数]
4.6, инструменты VisualVM
VisualVM, способный отслеживать потоки, состояние памяти, просматривать процессорное время методов и объектов в памяти, которые были проверены сборщиком мусора. объект, перевернуть выделенный стек (например, какие объекты выделены для 100 объектов String). VisualVM прост в использовании, практически не имеет конфигурации и имеет богатые функции, почти включая другие встроенные команды JDK. Все функции.
内存信息
? 线程信息
? Dump 堆(本地进程)
? Dump 线程(本地进程)
? 打开堆 Dump。堆Dump可以用jmap来生成。
? 打开线程 Dump
? 生成应用快照(包含内存信息、线程信息等等)
? 性能分析。 CPU分析(各个方法调用时间,检查哪些方法耗时多),内存分析(各类对象占用的内存,检查哪些类占用内存多)
1) Мониторинг удаленного JVM VisualJVM может мониторить не только локальный jvm-процесс, но и удаленный jvm-процесс, который нужно реализовать с помощью технологии JMX.
2) Что такое JMX?
JMX (Java Management Extensions) — это фреймворк для внедрения функций управления приложениями, устройствами, системами и т. д. JMX может гибко разрабатывать плавно интегрированные приложения для управления системами, сетями и службами для ряда гетерогенных платформ операционных систем, системных архитектур и сетевых протоколов передачи.
3) Мониторинг удаленного кота Для мониторинга удаленного кота необходимо настроить JMX на удаленном коте следующим образом:
Сохраните и выйдите, перезапустите tomcat.
4) Используйте VisualJVM для подключения к удаленному коту Добавить удаленный хост: На хосте может быть много jvms, которые нужно отслеживать, поэтому следующим шагом будет добавление тех, которые нужно отслеживать на хосте. JVM:
#在tomcat的bin目录下,修改catalina.sh,添加如下的参数
JAVA_OPTS="‐Dcom.sun.management.jmxremote ‐
Dcom.sun.management.jmxremote.port=9999 ‐
Dcom.sun.management.jmxremote.authenticate=false ‐
Dcom.sun.management.jmxremote.ssl=false"
#这几个参数的意思是:
#-Djava.rmi.server.hostname
#‐Dcom.sun.management.jmxremote :允许使用JMX远程管理
#‐Dcom.sun.management.jmxremote.port=9999 :JMX远程连接端口
#‐Dcom.sun.management.jmxremote.authenticate=false :不进行身份认证,任何用
户都可以连接
#‐Dcom.sun.management.jmxremote.ssl=false :不使用ssl
подключение удалось. Метод использования такой же, как и раньше, вы можете контролировать удаленный процесс tomcat так же, как и локальный процесс jvm.