实时警报通知:微信告警通知的重要性解析
858
2022-12-20
本文目录一览:
网店管理的工具一般有以下几种:
1、阿里指数
阿里指数是阿里巴巴诚信通用户都普遍使用的数据分析工具,主要给大家展示的是供货商的数据,里面可以看到很多的商品排行榜也可以看关键词。
2、意参谋
这是淘宝旗下的一款官方工具,可以全面展示店铺经营全链路的各项核心数据。
3、千牛
千牛工作台一款专用于商务沟通的软件,简单说就是淘宝、天猫购物平台的交流工具。千牛卖家版可以帮你管理店铺、查看交易信息,上传宝贝和发货等等。
4、淘货源
淘货源简单讲就是当有一天你们在淘宝网看到同类似宝贝或者是某一款产品不错的情况下你想找货源,记住你们一定不要去把这个图片扒了之后直接去找,最好的方式就是通过淘货源匹配到当前1688商家里面最便宜的货源,然后你把它找下来,这是新手卖家的福利。
5、店查查
可以提供淘宝数据统计、店铺关注、宝贝价格关注、直通车选词、标题优化、销售数据分析,让运营者对店铺数据一目了然。
阿里云服务器ECS如何选择?很多新手用户并不知道PTS是什么,如果你不知道如何选择阿里云服务器ECS产品,性能测试PTS可以很好的帮助你快速对云服务器进行压力测试,从而助你选择适合自己的阿里云服务器ECS,下面是性能测试PTS详解!
阿里云开发者社区最近推出了一个“ ECS 选款利器!PTS助您快速上云 ”活动,PTS性能压测包仅需0.99/月起,真实模拟,免去繁琐的搭建和维护成本!现在您可以只支付10块钱不到的试用成本,即可体验使用 PTS 来帮助 ECS 进行容量规划选择合适规格的整个流程!
完成动手实验的同学,即可参与抽奖活动,小米手环 6、蓝牙键盘、掌上游戏机、笔记本支架、 数据线、优惠券等丰富奖品等您来拿!限量 1500 份,抽奖即得,百分百中奖哦!
性能测试PTS(Performance Testing Service)是具备强大的分布式压测能力的SaaS压测平台,可模拟海量用户的真实业务场景,全方位验证业务站点的性能、容量和稳定性。
PTS旨在简化性能压测本身的工作。
PTS目标是将性能压测本身的工作持续简化,使您可以将更多的精力回归到关注业务和性能问题本身。在PTS平台上,您可以用较低的人力和资源成本,构造出最接近真实业务场景的复杂交互式流量,快速衡量系统的业务性能状况,为性能问题定位、容量配比、全链路压测的流量构造提供最好的帮助。进而提升用户体验,促进业务发展,最大程度实现企业的商业价值。
业务场景
PTS广泛应用于各种压力测试和性能测试场景,包括但不限于以下场景:
PTS孵化于服务阿里巴巴全生态五年以上的单链路、全链路压测平台,是阿里巴巴内部最佳实践的输出。该平台对内除了支持日常的外部流量压测之外,同时支持了大大小小的促销活动,如天猫双11、双12和年货节等。
压测流程
PTS提供全面高效的压测流程:
压测流程说明:
1.在PTS控制台上,准备压测API数据,构造压测场景,定义压测模式、量级等;支持随时启停压测,压测过程中可调速。
2.压测启动后,PTS后台的压测控制中心将自动调度压测数据、压测任务和压测引擎。
3.通过随机调度全国上百个城市和运营商的内容分发网络CDN (Content Delivery Network)节点,发起压测流量。保证从虚拟用户并发量、压测流量的分散度等维度都接近真正的用户行为,压测结果更加全面和真实可信。
4.通过压测引擎向您指定的业务站点发起压测。
5.压测过程中,通过集成云监控、ARMS(应用实时监控服务)产品,结合PTS自有的监控指标,实时采集压测数据。
6.在PTS控制台,实时展现压测数据,进行过程监控;压测结束后,生成压测报告。基于整个压测场景的性能表现,定位性能问题、发现系统瓶颈。
压测创建方式
PTS支持以下4种方式创建压测场景(或称压测用例),如下图所示:
说明:
方式一:PTS自研零编码可视化编排,使用自研强大引擎压测。
方式二: 使用PTS自研云端录制器,零侵入录制业务请求并导入1中的自研交互中进行进一步设置。
方式三: 将导入脚本压测 1中的PTS自研交互中,使用PTS自研引擎。
方式四:JMeter压测并使用原生JMeter引擎进行压测,PTS提供自定义的压力构造和监控数据汇聚等产品服务。
其中,方式一、二、三由于使用了PTS的自研引擎,具备RPS(Requests per Second)吞吐量压测模式、秒级启动、实时控制、定时压测和流量遍布全国运营商网络的差异化能力。
方式一是PTS最核心的一种压测场景创建方式,所有资源包均可使用。其他几种创建方式面向不同规格资源包开放。
适用于多业务场景
不论您处于哪个行业,在以下业务场景(但不限于),PTS都是您值得信赖的性能测试工具。
适用行业广泛
PTS应用行业广泛,涉及电商、多媒体、金融保险、物流快递、广告营销、社交等等。
PTS服务阿里巴巴全生态多年,支持了天猫双11、双12、年货节等大促活动。植根于电商行业的PTS,对电商的典型业务模型支持得更友好,压测来源更广泛,脉冲能力和流量掌控能力更强。
PTS自商业版发布以来,吸引了来自多媒体、金融保险、政务等众多行业的用户,以其强大的压测场景编排能力和报表能力,帮助用户快速发现问题,进行针对性地调优,提升了系统承压能力。
适用于多种网络环境
不论您的业务位于公有云、专有云、混合云或者自建IDC中,只要能够通过公网访问,PTS都能够通过遍布全国上百个城市和各运营商的CDN节点发起压测流量,最大程度地模拟真实业务场景。
适用于使用HTTP/HTTPS/WebSocket等协议的客户端
PTS本身的GUI模式支持HTTP/HTTPS协议的压测,无论您的客户端是自研的App、移动端网页、PC端网页、微信小程序还是C/S结构的软件,都可以使用PTS进行压测。PTS同时集成了开源JMeter,支持更多的协议和场景,例如您可以通过“JMeter + WebSocket插件”的方式,对使用WebSocket协议的客户端进行压测(在PTS上传相应的插件JAR文件即可),其他协议以此类推。
下面以电商典型业务场景为例,为您介绍如何在PTS中编排压测场景。
什么是压测场景
要发起一次性能压测,首先需要创建一个压测场景。压测场景中包含一个或多个并行的业务,每个业务包含一个或多个串行的请求。
示例
淘宝网需要对产品A和B相关的页面(即存在多个API)进行压测,假设其主要业务场景为:
业务A:浏览产品A。
业务B:购买产品B(登录 → 浏览产品B → 加入购物车 → 提交订单)。
那么在压测场景中的设置如下。
串联链路1:浏览产品A 和串联链路2:购买产品B是并行关系。
根据业务逻辑,一部分用户在浏览产品A,另一部分用户在进行购买产品B的一系列操作,即两个业务是同时发生的,所以将它们设置为两个串联链路,压测中会并行发起请求。
串联链路中的多个API是串行关系。
根据业务逻辑,串联链路2:购买产品B中的一系列用户行为是存在先后顺序的,所以将这些存在先后关系的API添加到一个串联链路中,PTS压测中会按照顺序发起压测。
综合来看,在压测中,示例中的浏览产品A的API和登录的API,会同时发起压测流量。更多性能测试PTS场景示例,可参考阿里云帮助资料: 性能测试 PTS最佳实践
背景
随着计算技术的不断发展,3纳米制程芯片已进入试产阶段,摩尔定律在现有工艺下逐渐面临巨大的物理瓶颈,通过多核处理器技术来提升服务器的性能成为提升算力的主要方向。
在服务器领域,基于java构建的后端服务器占据着领先地位,因此,掌握java并发编程技术,充分利用CPU的并发处理能力是一个开发人员必修的基本功,本文结合线程池源码和实践,简要介绍了线程池和线程变量的使用。
线程池概述
线程池是一种“池化”的线程使用模式,通过创建一定数量的线程,让这些线程处于就绪状态来提高系统响应速度,在线程使用完成后归还到线程池来达到重复利用的目标,从而降低系统资源的消耗。
总体来说,线程池有如下的优势:
线程池的使用
在java中,线程池的实现类是ThreadPoolExecutor,构造函数如下:
可以通过 new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory,handler)来创建一个线程池。
在构造函数中,corePoolSize为线程池核心线程数。默认情况下,核心线程会一直存活,但是当将allowCoreThreadTimeout设置为true时,核心线程超时也会回收。
在构造函数中,maximumPoolSize为线程池所能容纳的最大线程数。
在构造函数中,keepAliveTime表示线程闲置超时时长。如果线程闲置时间超过该时长,非核心线程就会被回收。如果将allowCoreThreadTimeout设置为true时,核心线程也会超时回收。
在构造函数中,timeUnit表示线程闲置超时时长的时间单位。常用的有:TimeUnit.MILLISECONDS(毫秒)、TimeUnit.SECONDS(秒)、TimeUnit.MINUTES(分)。
在构造函数中,blockingQueue表示任务队列,线程池任务队列的常用实现类有:
在构造函数中,threadFactory表示线程工厂。用于指定为线程池创建新线程的方式,threadFactory可以设置线程名称、线程组、优先级等参数。如通过Google工具包可以设置线程池里的线程名:
在构造函数中,rejectedExecutionHandler表示拒绝策略。当达到最大线程数且队列任务已满时需要执行的拒绝策略,常见的拒绝策略如下:
ThreadPoolExecutor线程池有如下几种状态:
线程池提交一个任务时任务调度的主要步骤如下:
核心代码如下:
Tomcat 的整体架构包含连接器和容器两大部分,其中连接器负责与外部通信,容器负责内部逻辑处理。在连接器中:
Tomcat为了实现请求的快速响应,使用线程池来提高请求的处理能力。下面我们以HTTP非阻塞I/O为例对Tomcat线程池进行简要的分析。
在Tomcat中,通过AbstractEndpoint类提供底层的网络I/O的处理,若用户没有配置自定义公共线程池,则AbstractEndpoint通过createExecutor方法来创建Tomcat默认线程池。
核心部分代码如下:
其中,TaskQueue、ThreadPoolExecutor分别为Tomcat自定义任务队列、线程池实现。
Tomcat自定义线程池继承于java.util.concurrent.ThreadPoolExecutor,并新增了一些成员变量来更高效地统计已经提交但尚未完成的任务数量(submittedCount),包括已经在队列中的任务和已经交给工作线程但还未开始执行的任务。
Tomcat在自定义线程池ThreadPoolExecutor中重写了execute()方法,并实现对提交执行的任务进行submittedCount加一。Tomcat在自定义ThreadPoolExecutor中,当线程池抛出RejectedExecutionException异常后,会调用force()方法再次向TaskQueue中进行添加任务的尝试。如果添加失败,则submittedCount减一后,再抛出RejectedExecutionException。
在Tomcat中重新定义了一个阻塞队列TaskQueue,它继承于LinkedBlockingQueue。在Tomcat中,核心线程数默认值为10,最大线程数默认为200, 为了避免线程到达核心线程数后后续任务放入队列等待,Tomcat通过自定义任务队列TaskQueue重写offer方法实现了核心线程池数达到配置数后线程的创建。
具体地,从线程池任务调度机制实现可知,当offer方法返回false时,线程池将尝试创建新新线程,从而实现任务的快速响应。TaskQueue核心实现代码如下:
Tomcat中通过自定义任务线程TaskThread实现对每个线程创建时间的记录;使用静态内部类WrappingRunnable对Runnable进行包装,用于对StopPooledThreadException异常类型的处理。
Executors常用方法有以下几个:
Executors类看起来功能比较强大、用起来还比较方便,但存在如下弊端 :
使用线程时,可以直接调用 ThreadPoolExecutor 的构造函数来创建线程池,并根据业务实际场景来设置corePoolSize、blockingQueue、RejectedExecuteHandler等参数。
使用局部线程池时,若任务执行完后没有执行shutdown()方法或有其他不当引用,极易造成系统资源耗尽。
在工程实践中,通常使用下述公式来计算核心线程数:
nThreads=(w+c)/c*n*u=(w/c+1)*n*u
其中,w为等待时间,c为计算时间,n为CPU核心数(通常可通过 Runtime.getRuntime().availableProcessors()方法获取),u为CPU目标利用率(取值区间为[0, 1]);在最大化CPU利用率的情况下,当处理的任务为计算密集型任务时,即等待时间w为0,此时核心线程数等于CPU核心数。
上述计算公式是理想情况下的建议核心线程数,而不同系统/应用在运行不同的任务时可能会有一定的差异,因此最佳线程数参数还需要根据任务的实际运行情况和压测表现进行微调。
为了更好地发现、分析和解决问题,建议在使用多线程时增加对异常的处理,异常处理通常有下述方案:
为了实现优雅停机的目标,我们应当先调用shutdown方法,调用这个方法也就意味着,这个线程池不会再接收任何新的任务,但是已经提交的任务还会继续执行。之后我们还应当调用awaitTermination方法,这个方法可以设定线程池在关闭之前的最大超时时间,如果在超时时间结束之前线程池能够正常关闭则会返回true,否则,超时会返回false。通常我们需要根据业务场景预估一个合理的超时时间,然后调用该方法。
如果awaitTermination方法返回false,但又希望尽可能在线程池关闭之后再做其他资源回收工作,可以考虑再调用一下shutdownNow方法,此时队列中所有尚未被处理的任务都会被丢弃,同时会设置线程池中每个线程的中断标志位。shutdownNow并不保证一定可以让正在运行的线程停止工作,除非提交给线程的任务能够正确响应中断。
ThreadLocal线程变量概述
ThreadLocal类提供了线程本地变量(thread-local variables),这些变量不同于普通的变量,访问线程本地变量的每个线程(通过其get或set方法)都有其自己的独立初始化的变量副本,因此ThreadLocal没有多线程竞争的问题,不需要单独进行加锁。
ThreadLocal的原理与实践
对于ThreadLocal而言,常用的方法有get/set/initialValue 3个方法。
众所周知,在java中SimpleDateFormat有线程安全问题,为了安全地使用SimpleDateFormat,除了1)创建SimpleDateFormat局部变量;和2)加同步锁 两种方案外,我们还可以使用3)ThreadLocal的方案:
Thread 内部维护了一个 ThreadLocal.ThreadLocalMap 实例(threadLocals),ThreadLocal 的操作都是围绕着 threadLocals 来操作的。
从JDK源码可见,ThreadLocalMap中的Entry是弱引用类型的,这就意味着如果这个ThreadLocal只被这个Entry引用,而没有被其他对象强引用时,就会在下一次GC的时候回收掉。
EagleEye(鹰眼)作为全链路监控系统在集团内部被广泛使用,traceId、rpcId、压测标等信息存储在EagleEye的ThreadLocal变量中,并在HSF/Dubbo服务调用间进行传递。EagleEye通过Filter将数据初始化到ThreadLocal中,部分相关代码如下:
在EagleEyeFilter中,通过EagleEyeRequestTracer.startTrace方法进行初始化,在前置入参转换后,通过startTrace重载方法将鹰眼上下文参数存入ThreadLocal中,相关代码如下:
EagleEyeFilter在finally代码块中,通过EagleEyeRequestTracer.endTrace方法结束调用链,通过clear方法将ThreadLocal中的数据进行清理,相关代码实现如下:
在某权益领取原有链路中,通过app打开一级页面后才能发起权益领取请求,请求经过淘系无线网关(Mtop)后到达服务端,服务端通过mtop sdk获取当前会话信息。
在XX项目中,对权益领取链路进行了升级改造,在一级页面请求时,通过服务端同时发起权益领取请求。具体地,服务端在处理一级页面请求时,同时通过调用hsf/dubbo接口来进行权益领取,因此在发起rpc调用时需要携带用户当前会话信息,在服务提供端将会话信息进行提取并注入到mtop上下文,从而才能通过mtop sdk获取到会话id等信息。某开发同学在实现时,因ThreadLocal使用不当造成下述问题:
【问题1:权益领取失败分析】
在权益领取服务中,该应用构建了一套高效和线程安全的依赖注入框架,基于该框架的业务逻辑模块通常抽象为xxxModule形式,Module间为网状依赖关系,框架会按依赖关系自动调用init方法(其中,被依赖的module 的init方法先执行)。
在应用中,权益领取接口的主入口为CommonXXApplyModule类,CommonXXApplyModule依赖XXSessionModule。当请求来临时,会按依赖关系依次调用init方法,因此XXSessionModule的init方法会优先执行;而开发同学在CommonXXApplyModule类中的init方法中通过调用recoverMtopContext()方法来期望恢复mtop上下文,因recoverMtopContext()方法的调用时机过晚,从而导致XXSessionModule模块获取不到正确的会话id等信息而导致权益领取失败。
【问题2:脏数据分析】
权益领取服务在处理请求时,若当前线程曾经处理过权益领取请求,因ThreadLocal变量值未被清理,此时XXSessionModule通过mtop SDK获取会话信息时得到的是前一次请求的会话信息,从而造成脏数据。
【解决方案】
在依赖注入框架入口处AbstractGate#visit(或在XXSessionModule中)通过recoverMtopContext方法注入mtop上下文信息,并在入口方法的finally代码块清理当前请求的threadlocal变量值。
若使用强引用类型,则threadlocal的引用链为:Thread - ThreadLocal.ThreadLocalMap - Entry[] - Entry - key(threadLocal对象)和value;在这种场景下,只要这个线程还在运行(如线程池场景),若不调用remove方法,则该对象及关联的所有强引用对象都不会被垃圾回收器回收。
若使用static关键字进行修饰,则一个线程仅对应一个线程变量;否则,threadlocal语义变为perThread-perInstance,容易引发内存泄漏,如下述示例:
在上述main方法第22行debug,可见线程的threadLocals变量中有3个threadlocal实例。在工程实践中,使用threadlocal时通常期望一个线程只有一个threadlocal实例,因此,若不使用static修饰,期望的语义发生了变化,同时易引起内存泄漏。
如果不执行清理操作,则可能会出现:
建议使用try...finally 进行清理。
我们在使用ThreadLocal时,通常期望的语义是perThread,若不使用static进行修饰,则语义变为perThread-perInstance;在线程池场景下,若不用static进行修饰,创建的线程相关实例可能会达到 M * N个(其中M为线程数,N为对应类的实例数),易造成内存泄漏(https://errorprone.info/bugpattern/ThreadLocalUsage)。
在应用中,谨慎使用ThreadLocal.withInitial(Supplier<? extends S supplier)这个工厂方法创建ThreadLocal对象,一旦不同线程的ThreadLocal使用了同一个Supplier对象,那么隔离也就无从谈起了,如:
总结
在java工程实践中,线程池和线程变量被广泛使用,因线程池和线程变量的不当使用经常造成安全生产事故,因此,正确使用线程池和线程变量是每一位开发人员必须修炼的基本功。本文从线程池和线程变量的使用出发,简要介绍了线程池和线程变量的原理和使用实践,各开发人员可结合最佳实践和实际应用场景,正确地使用线程和线程变量,构建出稳定、高效的java应用服务。
关于全链路压测工具有哪些和网络压测工具的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站。 全链路压测工具有哪些的介绍就聊到这里吧,感谢你花时间阅读本站内容,更多关于网络压测工具、全链路压测工具有哪些的信息别忘了在本站进行查找喔。发表评论
暂时没有评论,来抢沙发吧~