精华内容
下载资源
问答
  • RAM随机存取存储器

    千次阅读 2010-09-25 20:37:00
    存储单元的内容可按需随意取出或存入,且存取速度与存储单元的位置无关的存储器。这种存储器在断电时将丢失其存储内容,故主要用于存储短时间使用的程序。 按照存储信息的不同,随机存储器又分为静态随机存储器...

    随机存取存储器

    RAM(随机存取存储器)RAM -random access memory 随机存储器。存储单元的内容可按需随意取出或存入,且存取的速度与存储单元的位置无关的存储器。这种存储器在断电时将丢失其存储内容,故主要用于存储短时间使用的程序。 按照存储信息的不同,随机存储器又分为静态随机存储器(Static RAM,SRAM)和动态随机存储器(Dynamic RAM,DRAM)。


    随机存取

    所谓“随机存取”,指的是当存储器中的消息被读取或写入时,所需要的时间与这段信息所在的位置无关。相对的,读取或写入顺序访问(Sequential Access)存储设备中的信息时,其所需要的时间与位置就会有关系(如磁带)。


    易失性

    当电源关闭时RAM不能保留数据。如果需要保存数据,就必须把它们写入

      

     

    静态随机存取存储器

    一个长期的存储设备中(例如硬盘)。RAM和ROM相比,两者的最大区别是RAM在断电以后保存在上面的数据会自动消失,而ROM不会。


    高访问速度

    现代的随机存取存储器几乎是所有访问设备中写入和读取速度最快的,取存延迟也和其他涉及机械运作的存储设备相比,也显得微不足道。


    需要刷新

    现代的随机存取存储器依赖电容器存储数据。电容器充满电后代表1(二进制),未充电的代表0。由于电容器或多或少有漏电的情形,若不作特别处理,数据会渐渐随时间流失。刷新是指定期读取电容器的状态,然后按照原来的状态重新为电容器充电,弥补流失了的电荷。需要刷新正好解释了随机存取存储器的易失性。


    对静电敏感

    正如其他精细的集成电路,随机存取存储器对环境的静电荷非常敏感。静电会干扰存储器内电容器的电荷,引致数据流失,甚至烧坏电路。故此触碰随机存取存储器前,应先用手触摸金属接地。

     

    区别


    随机存储器

    rom -read only memory 只读存储器

    ①简单地说,在计算机中,RAM 、ROM都是数据存储器。RAM 是随机存取存

      

     

    动态随机存取存储器

    储器,它的特点是易挥发性,即掉电失忆。ROM 通常指固化存储器(一次写入,反复读取),它的特点与RAM 相反。ROM又分一次性固化、光擦除和电擦除重写两种类型。举个例子来说也就是,如果突然停电或者没有保存就关闭了文件,那么ROM可以随机保存之前没有储存的文件但是RAM会使之前没有保存的文件消失。


    内存

    在计算机的组成结构中,有一个很重要的部分,就是存储器。存储器是用来存储程序和数据的部件,对于计算机来说,有了存储器,才有记忆功能,才能保证正常工作。存储器的种类很多,按其用途可分为主存储器和辅助存储器,主存储器又称内存储器(简称内存),辅助存储器又称外存储器(简称外存)。外存通常是磁性介质或光盘,像硬盘,软盘,磁带,CD等,能长期保存信息,并且不依赖于电来保存信息,但是由机械部件带动,速度与CPU相比就显得慢的多。内存指的就是主板上的存储部件,是CPU直接与之沟通,并用其存储数据的部件,存放当前正在使用的(即执行中)的数据和程序,它的物理实质就是一组或多组具备数据输入输出和数据存储功能的集成电路,内存只用于暂时存放程序和数据,一旦关闭电源或发生断电,其中的程序和数据就会丢失。

    从一有计算机开始,就有内存。内存发展到今天也经历了很多次的技术改进,从最早的DRAM一直到FPMDRAM、EDODRAM、SDRAM等,内存的速度一直在提高且容量也在不断的增加。今天,服务器主要使用的是什么样的内存呢?目前,IA架构的服务器普遍使用的是REGISTERED

      

     

    快速周期随机存取存储器

    ECCSDRAM。

    既然内存是用来存放当前正在使用的(即执行中)的数据和程序,那么它是怎么工作的呢?我们平常所提到的计算机的内存指的是动态内存(即DRAM),动态内存中所谓的“动态”,指的是当我们将数据写入DRAM后,经过一段时间,数据会丢失,因此需要一个额外设电路进行内存刷新操作。具体的工作过程是这样的:一个DRAM的存储单元存储的是0还是1取决于电容是否有电荷,有电荷代表1,无电荷代表0。但时间一长,代表1的电容会放电,代表0的电容会吸收电荷,这就是数据丢失的原因;刷新操作定期对电容进行检查,若电量大于满电量的1/2,则认为其代表1,并把电容充满电;若电量小于1/2,则认为其代表0,并把电容放电,藉此来保持数据的连续性。

     

    源文档 <http://baike.baidu.com/view/3558.htm>

     

    展开全文
  • 路径链接法是将图像文件保存在固定的路径下,数据库中只存储图像文件的路径和名称,此方法数据库容量小,存取速度快,但安全性较差;内存流法是将二进制数据直接存储在数据库中,此方法对数据的共享非常方便,安全性...

    在数据库应用项目开发中,经常会使用一些二进制的图像数据,存储和读取显示图像数据主要采用的是路径链接法和内存流法。路径链接法是将图像文件保存在固定的路径下,数据库中只存储图像文件的路径和名称,此方法数据库容量小,存取速度快,但安全性较差;内存流法是将二进制数据直接存储在数据库中,此方法对数据的共享非常方便,安全性相对较高,常用于图像容量不是很大的时候。

    本文主要讨论通过SQL Server 2008使用内存流法如何实现二进制图像数据的存储。

    1 VARBINARY(MAX)数据类型简介

      在SQL Server 2000和更早的版本中,如果每条记录的数据量远远超过了一个单独记录的8K,我们常用IMAGE数据类型以二进制存储该数据,在使用IMAGE数据类型时,数据是不和普通数据存储在一起的。一个被称作指针的很小的二进制值,和普通数据存储在一起,这个二进制值指向数据文件里的数据实际存储的位置。对IMAGE数据进行读取、插入数据时需要使用READTEXT[1]及WRITETEXT命令,这两个命令需使用TEXTPTR函数来获得正确的二进制指针,这个二进制指针用于定位物理文件中的数据,使用起来较麻烦。

      虽然在SQL Server 2008中依然提供IMAGE数据类型,但微软计划在未来的SQL Server版本中删除IMAGE数据类型, 用VARBINARY(MAX)数据类型来代替,在该版本下不应当使用IMAGE这种类型。

      VARBINARY(MAX) 为可变长度二进制数据,不限最大长度,常用于数据超出 8,000 字节时,可以直接使用insert命令添加数据,使用起来较简单。

    2 使用T-SQL语句将图像文件直接读入VARBINARY(MAX)字段

      首先在SQL Server 2008的查询窗口中创建测试数据库ImageDB,并建立ImageTable表来存储图像数据:

     然后使用Insert命令将其插入到ImageTest表中(此处图像文件为C:\aa.jpg),OPENROWSET函数包含访问OLE DB数据源中的远程数据所需的全部连接信息,内置的 BULK 访问接口支持大容量操作,实现的代码为:

    运行Select * from ImageTable语句将会看到该图像的二进制编码,但SQL Server 2008不提供直接查看图片的方法,为了查看图片,我们需要创建应用程序,本文第4部分介绍其实现的方法。

    3 在SQL Server中将二进制数据复制到图像文件

      在SQL Server 2008中将二进制数据复制到图像文件,要对Windows的文件进行操作,我们需要用到xp_cmdshell扩展存储过程,在使用之前我们需获得执行该命令的权限:

     通过执行xp_cmdshell将二进制数据复制到图像文件:

    可以看到C盘下增加了一个图像文件bb.jpg。

    4 使用C#.NET存取SQL Server 2008中的图像数据

      为在2中创建的ImageTable表添加一个ImagePath字段,用于记录图像的路径及文件名。

    在窗体上添加一个按钮,用于实现将图像文件读入SQL Server,实现的基本过程是先通过openFileDialog控件选择要读入的图像文件,将图像文件转换成二进制流,连接数据库后使用insert命令将二进制流数据存储到SQL Server,实现的代码如下:

        再添加一个按钮,用于实现将SQL Server中二进制数据显示为图像,连接数据库后将ImageTable表的记录绑定到dataGridView控件,虽然dataGridView控件可以将二进制数据显示为图片,但行列间距太小,不好看,所以同时还将图像显示在pictureBox控件中,实现的代码如下:

    展开全文
  • 微服务:全链路压测和容量规划

    千次阅读 2019-08-25 18:16:44
    什么是全链路压测?...全链路压测是一个模拟线上环境的完整闭环,由5核心要素组成: 压测环境:对应用户真实的线上环境,具备数据与流量隔离能力的生产环境; 原则:能够用中间件解决的问题,绝不...

    什么是全链路压测?

    基于实际的生产业务场景、系统环境,模拟海量的用户请求和数据对整个业务链进行压力测试,并持续调优的过程

    主要特征:

    • 真实流量
    • 线上环境
    • 实时监控和过载保护

    全链路压测组成

    单链路指一个业务线。

    全链路压测是一个模拟线上环境的完整闭环,由5大核心要素组成:

    1. 压测环境:对应用户真实的线上环境,具备数据与流量隔离能力的生产环境; 原则:能够用中间件解决的问题,绝不对业务系统进行改造,系统所需做的是升级中间件,这一原则极大提高了工作效率。
    2. 压测基础数据:构造满足高峰场景的核心基础相关数据,影子库里构造相同量级的数据; 真实线上数据筛选脱敏。
    3. 压测流量(模型、数据):成百上千的接口组合,到复杂的接口之间的参数传递,复杂的条件判断来构造精准的全局流量模型,和真实业务情况保持一致;
      > 压测引擎的三层结构:
      • 协议支持
      • 请求发送:CGroup资源隔离,异步Reactor模型发送请求,链路间线程池隔离
      • 集群协作: Master,Slave长连接; Cristian算法同步网络延迟,Slave动作一致;
    4. 流量发起:模拟全国各地真实的用户请求访问,探测站点能力;
    5. 问题定位:多维度的监控和报表,服务端可通过其他生态产品协助定位。

    翻译构造能力的体现:便捷的构造全局业务场景和流量数据的能力。

    原子因素:链路(被压测的最小单位) 指令: 思考时间、集合点、条件跳转、cookie存取、全局准备、并发用户限制等

    原子因素->串行链路->场景

    全链路压测解决什么问题?

    • 验证峰值流量下服务的稳定性和伸缩性
    • 验证新上线功能的稳定性
    • 进行降级、报警等故障演练
    • 对线上服务进行更准确的容量评估

    什么时机下需要?

    • 业务发展速度
    • 在可以预期的一段时间(最好是半年,一个季度有点晚)内,业务会有较快速的发展,线上机器必须要大幅度扩容
    • 扩容有的时候并不是线性的,从两台扩展到四台,你得服务能力或者能提高两倍
    • 继续扩容服务能力就有可能提高不上去了,因为要受限于其他的模块,比如 DB、公共组建、中间件等

    ps:业务的不断发展,依赖的模块不断增多。需要找出短板来进行解决

    • 链路的复杂程度在扩张
    • 一般而言,随着业务的发展,我们的接口会越来越多,系统会逐渐的做分布式
    • 业务线内部的模块越抽象越多,业务线跟其他业务线的交互也越来越多
    • 我们无法单纯的根据自己系统的处理能力来评估接口的服务能力

    ps:接口的服务能力取决于模块中最低的那个—木桶理论

    • 对单机压测结果越来越没有自信
      • 一个很好的指标,一般而言,我们都会压一下我们自己的模块
      • 单机的压测不代表真实的线上场景,内心会越来越虚,这个时候,就要考虑全链路了

    如何展开全链路压测?

     

    压力测试方式的几个阶段

    • 对线上的单机或集群发起服务调用
    • 将线上流量进行录制,然后在单台机器上进行回放
    • 通过修改权重的方式进行引流压测
    • 全链路压测

     

    梳理核心链路和边界

    • 核心链路是一个业务的核心,这一块应该可以很快梳理清楚
    • 难点在于梳理清楚链路的边界
    • 千万不要污染正常数据:认真梳理数据处理的每一个环节,确保 mock 数据的处理结果不会写入到正常库里面
    • 在核心链路的基础上,我们会有很多的分支业务,而这些分支业务有的可以参与压测,有的不能参与压测
      • 比如给用户下放 push 消息
      • 短信 / 支付 / 微信 Oauth 授权

    首先应该明确的是:全链路压测针对的是现代越来越复杂的业务场景和全链路的系统依赖。所以首先应该将核心业务和非核心业务进行拆分,确认流量高峰针对的是哪些业务场景和模块,针对性的进行扩容准备,而不是为了解决海量流量冲击而所有的系统服务集群扩容几十倍,这样会造成不必要的成本投入。

    数据模型构建

    • 数据的真实性和可用性:可以从生产环境完全移植一份当量的数据包,作为压测的基础数据,然后基于基础数据,通过分析历史数据增长趋势,预估当前可能的数据量
    • 数据脱敏:基于生产环境的全链路压测,必须考虑的一点是不能产生脏数据,以免对生产造成影响,影响用户体验等,因此在数据准备时需要进行数据脱敏
    • 数据隔离:千万不要污染正常数据:认真梳理数据处理的每一个环节,可以考虑通过压测数据隔离处理,落入影子库,mock 对象等手段,来防止数据污染

    流量平台搭建

    • jmeter、Ngrinder、locust,提供分布式压测的方式(饿了么 的流量平台是基于 jmeter 改造的)、压测机中的机器数据能够实时的收集查看到、可以随时停止压测、一定时间内实时错误率达到阈值自动熔断。考虑到压测量较大的情况下回传测试结果会对 agent 本身造成一定资源占用,可以考虑异步上传,甚至事务补偿机制。
    • 业务代码改造:压测请求上会打上特殊的标记,这个标记会随着请求的依赖调用一直传递下去。写请求写到影子区域(比如header头中做标记,存储、缓存、消息、日志等一系列的状态数据)、依赖的外部服务做 mock 处理(短信、邮件、push 等等)

    全链路压测应对的都是海量的用户请求冲击,可以使用分布式压测的手段来进行用户请求模拟,目前有很多的开源工具可以提供分布式压测的方式,比如jmeter、Ngrinder、locust等。

    可以基于这些压测工具进行二次开发,由Contorller机器负责请求分发,agent机器进行压测,然后测试结果上传Contorller机器。

    考虑到压测量较大的情况下回传测试结果会对agent本身造成一定资源占用,可以考虑异步上传,甚至事务补偿机制。

    • 真实流量蓄水池,分批释放
    • 逐步压测

    全链路压测核心功能

    数据构造

    回放业务高峰期产生的流量

    • HTTP: Nginx Access Log分析
    • RPC:对部分机器录制

    通过以上两种方式生成压测词表(词表分片处理,方便后续批量加载)

     压测隔离

    • 添加压测标识,各服务和中间件依据标识来进行压测服务的分组和影子表方案的实施。
    • 在请求头添加特殊标识,但需要保证线程间和跨服务间透传。
    • 链路诊断功能方便定位问题。

    服务隔离

    • 通常选择深夜低峰压测,同时隔离正常流量和测试流量。 隔离策略:基于IP,机器数,百分比

    数据隔离

    • 影子表(阿里):使用线上同一个数据库,包括共享数据库中的内存资源,只在写入数据时写进另一个影子表。 KV的处理类似,MQ则选择生产端或消费端忽略消息。

    调度中心

    资源计算预估

    • 压测期望到达的QPS
    • 压测请求的平均响应时间和请求/响应体大小
    • 压测的词表大小、分片数
    • 压测类型

    事件注入机制

    根据系统的实际情况对压力进行相应调整。

    • 调整QPS
    • 触发熔断
    • 开启事故注入
    • 开启代码级性能分析

    代码设计:观察者模式(会触发的事件)和责任链模式(执行事件)

    熔断保护机制

    客户端熔断: 根据业务自定义的熔断阈值,实时分析监控数据,当达到熔断阈值时,任务调度器会向压测引擎发送降低QPS或者直接中断压测的指令,防止系统被压挂。

     

    容量规划

    为什么需要容量规划

    容量规划的目的在于让每一个业务系统能够清晰地知道:什么时候该加机器、什么时候应该减机器?双11等大促场景需要准备多少机器,既能保障系统稳定性、又能节约成本

    ps:什么时候增减机器、保障系统稳定性、节约成本

    容量规划四步走

    1. 业务流量预估阶段:通过历史数据分析未来某一个时间点业务的访问量会有多大
    2. 系统容量评估阶段:初步计算每一个系统需要分配多少机器
    3. 容量的精调阶段:通过全链路压测来模拟大促时刻的用户行为,在验证站点能力的同时对整个站点的容量水位进行精细调整
    4. 流量控制阶段:对系统配置限流阈值等系统保护措施,防止实际的业务流量超过预估业务流量的情况下,系统无法提供正常服务流量控制阶段:对系统配置限流阈值等系统保护措施,防止实际的业务流量超过预估业务流量的情况下,系统无法提供正常服务

    获取单台机器的服务能力

    为了精准地获取到单台机器的服务能力,压力测试都是直接在生产环境进行,这有两个非常重要的原因:单机压测既需要保证环境的真实性,又要保证流量的真实性

    生产环境进行单台机器压力测试的 4 个方法

    模拟请求:通过对生产环境的一台机器发起模拟请求调用来达到压力测试的目的

    工具:apache ab、webbench、httpload、jmeter、loadrunner

    适用场景:新系统上线或者访问量不大的系统采用这种方式来进行单机压测

    缺点:模拟请求和真实业务请求之间存在的差异,会对压力测试的结果造成影响 另一个缺点在于写请求的处理比较麻烦,因为写请求可能会对业务数据造成污染,这个污染要么接受、要么需要做特殊的处理(比如将压测产生的数据进行隔离)

    ps:和真实请求有差异、写请求需要处理、适合新系统上线或访问量不大的

    复制请求:通过将一台机器的请求复制多份发送到指定的压测机器

    适用场景:系统调用量比较小的场景

    优点:为了使得压测的请求跟真实的业务请求更加接近,在压测请求的来源方式上,我们尝试从真实的业务流量进行录制和回放,采用请求复制的方式来进行压力测试

    缺点:同样也面临着处理写请求脏数据的问题 另外一个缺点复制的请求必须要将响应拦截下来,所以被压测的这台机器需要单独提供,且不能提供正常的服务(不能把响应给到真实的用户了,比如涉及到发短信邮件之类的)

    请求转发将分布式环境中多台机器的请求转发到一台机器

    适用场景:系统调用量比较大的场景

    优点:请求的引流转发方式不仅压测结果非常精准、不会产生脏数据、而且操作起来也非常方便快捷,在阿里巴巴也是用的非常广泛的一种单机压测方式,这种方式怎么测试出当前系统最大能抗的流量是多少呢?

    调整负载均衡修改负载均衡设备的权重,让压测的机器分配更多的请求

    适用场景:系统调用量比较大的场景

    优点:调整负载均衡方式活的的压测结果非常准确、并且不会产生脏数据

    ps:单机压测可以基于上面的4种压测方式基础上,构件一套自动化的压测系统,可以配置定时任务定期对系统进行压测,也可以在任意想压测的时间点手动触发一次压测

    在进行压测的同时,实时探测压测机器的系统负载,一旦系统负载达到预设的阈值即立刻停止压测,同时输出一份压测报告 通过单机压测获取的单机服务能力值也是容量规划一个非常重要的参考依据

    最小机器数 = 预估的业务访问量 / 单机能力

    单机压测问题

    系统可用性问题

    经常由下面一些不确定性因素引起:

    • 系统容量
    • 业务性能
    • 基础设施瓶颈
    • 中间件瓶颈
    • 系统直接的依赖影响

    传统线上单机与单系统压测的四种方式

    • 模拟调用者压测生产环境:读请求+写请求(需要特定处理)
    • 流量录制和回放:快速率回放对单机压测

    从流量分配的角度,将流量集中到某台机器(这两种方式要求访问流量不能太小):

    • 请求流量转发
    • 改变负载均衡的权重

    单系统压测的问题

    • 在做单个系统的容量规划时,所有的依赖环节能力是无限的,进而使得我们获取的单机能力值是偏乐观的;
    • 采用单系统规划时,无法保证所有系统均一步到位,大多数精力都集中核心少数核心系统;
    • 部分问题只有在真正大流量下才会暴露,比如网络带宽等等。

     

    流程举例

    • 业务中需要区分流量(正常流量/压测流量)
      • 压测时需要在 http header 里加入 X-Shadow 的key ,值为 true 的代表压测,key 不存在或者 key 值不等于 true 代表非压测流量
    • 接收和发送 http / grpc 等请求时
      • 在向下游服务发起请求时,如果是压测流量把 header 头中的标记字段往下透传,下游继续在业务中往下透传
      • 接收到如果是压测流量,使用相应的压测数据
    • 依赖的模块
      • MySQL 使用影子表,将压测流量对 MySQL 的读写打到影子表上。即正常的业务表名为A,则影子表名为Ashadow
        • 所有涉及到的业务表都需要建一份影子表
        • 便于事后数据的清理
      • MongoDB 使用影子 collection ,将压测流量对 MongoDB 的读写打到影子表上。即正常的业务表名为A,则影子表名为 Ashadow
        • 同 MySQL
      • Redis 使用影子 key ,将压测流量对 redis 的读写打到影子 key 上。 如 set key value 会变成 set key_shadow value
        • 同 MySQL
      • kafka 使用影子 topic,key 后拼接 _shadow
        • 同 MySQL
    • 不需要参与压测的做 mock 处理
      • 给用户发push、短信、支付、微信 Oauth 授权

    全链路压测应用

    1 阿里分享

    2013年为了双11提前预演而诞生,该服务已提供在阿里云PTS铂金版。

    2 京东分享

    ForgeBot, 2016年开发

    京东全链路压测军演系统(ForceBot)架构解密

    最早基于开源的NGrinder,能胜任单业务压测。Controller功能耦合重,支持的Agent数量有限。 之后开发了ForgeBot。

    2.1 主要功能模块

    • Controller:任务分配
    • Task Service:负载任务下发,支持横向扩展。提供任务交互和注册服务。(gRPC:HTTP2+protobuf3)
    • Agent:注册心跳,拉取任务、更新任务状态、 执行和停止worker process(采用Docker容器部署)
    • Monitor Service:接受并转发压测数据给JMQ
    • DataFlow:对压测数据做流式计算(输出TPS,TP999,TP99,TP90,TP50,MAX,MIN),将计算结果存到DB(ES)

    在管理端创建测试场景,Controller扫描发现场景,寻找空闲Agent资源。

    任务分配时,Controller计算每个间隔的执行时间点和递增的虚拟用户数,由Agent动态加压减压。

    在多个组件使用了gRPC框架通讯

    分读压测和写压测

    2.2 一些解决问题的思路

    问题:如何模拟在某一个瞬间压力达到峰值?
    解决方案:通过集合点功能实现,提前开启峰值所需足够数量的线程,通过计算确定各个时间点上不需要执行任务的线程数量,通过条件锁让这些线程阻塞。当压力需要急剧变化时,我们从这些阻塞的线程中唤醒足够数量的线程,使更多的线程在短时间进入对目标服务压测的任务。

    问题:为了计算整体的 TPS,需要每个Agent把每次调用的性能数据上报,会产生大量的数据,如果进行有效的传输?
    解决方案:对每秒的性能数据进行了必要的合并,组提交到监控服务

    3 饿了么分享

    饿了么全链路压测平台的实现与原理

    3.1 业务模型的梳理

    • 是否关键路径
    • 业务的调用关系
    • 业务的提供的接口列表
    • 接口类型(http、thrift、soa等)
    • 读接口还是写接口?
    • 各接口之间的比例关系

    3.2 数据模型的构建

    3.2.1 写请求

    压测方法:

    • 用户、商户、菜品等在数量上与线上等比例缩放;
    • 对压测流量进行特殊标记;
    • 根据压测标记对支付,短信等环节进行mock;
    • 根据压测标记进行数据清理;

      读请求

      压测方法:拉取线上日志,根据真实接口比例关系进行回放

    3.2.2 无日志服务

    压测方法:

    • 构建压测数据使缓存命中率为0%时,服务接口性能,数据库性能;
    • 缓存命中率为100%时,服务接口性能;
    • 缓存命中率达到业务预估值时,服务接口性能;

    3.3 压测工具

    定制JMeter

    3.4 压测指标监控和收集

    • 应用层面
    • 服务器资源
    • 基础服务:中间件和数据库

    要点:

    • 响应时间不要用平均响应时间,关注95线;
    • 吞吐量和响应时间挂钩
    • 吞吐量和成功率挂钩

    3.5 具体实现

    SpringBoot+AngularJS.

    测试期间产生的冷数据(用例数据、结果数据)持久化至MongoDB,热数据(实时数据)持久化至InfluxDB并定期清理。

    分布式测试:重新实现JMeter的分布式调度
    测试状态流转:各种流程形成闭环,要考虑各种异常。
    主要流程:配置 -> 触发 -> 运行 -> 结果收集 -> 清理。

    整个状态流转的实现,采用异步Job机制实现了类似状态机的概念,状态属性持久化到数据库中,便于恢复。

    3.6 安全保障

    由于是在线上真实环境,需要避免测试引起的服务不可用和事故。

    • 权限管理:用户权限分级管理,不能随意触发他人的测试用例,同时高峰期和禁止发布期,不允许执行任何测试。
    • 停止功能:这是面向用户的手动停止功能,用户可以随时点击运行状态下的测试用例上的停止按钮,后台会直接kill掉所有运行该测试用例的测试机上的JMeter进程。
    • 熔断功能:系统会根据实时信息中的错误率进行判断,当一定时间内的实时错误率达到或超过某个阈值时,该次测试将被自动熔断,无需用户干预。
    • 兜底脚本:最极端的情况,当整个系统不可用,而此时需要停止测试时,我们提供了一份外部脚本直接进行停止。

    相关链接:

    阿里全链路压测

    有赞全链路压测

    京东全链路压测

    饿了么全链路压测

    滴滴全链路压测解决之道

    美团全链路压测自动化实践

    逻辑思维在全链路压测方面的实践

    http://xulizhao.com/blog/meituan-load-test-note/

    展开全文
  • java的八基本类型

    万次阅读 多人点赞 2018-09-04 16:30:15
    Java基本类型共有八种,基本类型可以分为三类,字符类型char,布尔类型boolean以及数值类型byte、short、int、long、float、double。数值类型又可以分为整数类型byte、short、int、long和浮点数类型float、double。...

    1. Java的简单类型及其封装器类

    Java基本类型共有八种,基本类型可以分为三类,字符类型char,布尔类型boolean以及数值类型byte、short、int、long、float、double。数值类型又可以分为整数类型byte、short、int、long和浮点数类型float、double。JAVA中的数值类型不存在无符号的,它们的取值范围是固定的,不会随着机器硬件环境或者操作系统的改变而改变。实际上,JAVA中还存在另外一种基本类型void,它也有对应的包装类 java.lang.Void,不过我们无法直接对它们进行操作。8 中类型表示范围如下:

    byte:8位,最大存储数据量是255,存放的数据范围是-128~127之间。

    short:16位,最大数据存储量是65536,数据范围是-32768~32767之间。

    int:32位,最大数据存储容量是2的32次方减1,数据范围是负的2的31次方到正的2的31次方减1。

    long:64位,最大数据存储容量是2的64次方减1,数据范围为负的2的63次方到正的2的63次方减1。

    float:32位,数据范围在3.4e-45~1.4e38,直接赋值时必须在数字后加上f或F。

    double:64位,数据范围在4.9e-324~1.8e308,赋值时可以加d或D也可以不加。

    boolean:只有true和false两个取值。

    char:16位,存储Unicode码,用单引号赋值。

    Java决定了每种简单类型的大小。这些大小并不随着机器结构的变化而变化。这种大小的不可更改正是Java程序具有很强移植能力的原因之一。下表列出了Java中定义的简单类型、占用二进制位数及对应的封装器类。

    简单类型

    boolean

    byte

    char

    short

    Int

    long

    float

    double

    void

    二进制位数

    1

    8

    16

    16

    32

    64

    32

    64

    --

    封装器类

    Boolean

    Byte

    Character

    Short

    Integer

    Long

    Float

    Double

    Void

       对于数值类型的基本类型的取值范围,我们无需强制去记忆,因为它们的值都已经以常量的形式定义在对应的包装类中了。如:

    基本类型byte 二进制位数:Byte.SIZE最小值:Byte.MIN_VALUE最大值:Byte.MAX_VALUE

    基本类型short二进制位数:Short.SIZE最小值:Short.MIN_VALUE最大值:Short.MAX_VALUE

    基本类型char二进制位数:Character.SIZE最小值:Character.MIN_VALUE最大值:Character.MAX_VALUE

    基本类型double 二进制位数:Double.SIZE最小值:Double.MIN_VALUE最大值:Double.MAX_VALUE

    注意:float、double两种类型的最小值与Float.MIN_VALUE、 Double.MIN_VALUE的值并不相同,实际上Float.MIN_VALUE和Double.MIN_VALUE分别指的是 float和double类型所能表示的最小正数。也就是说存在这样一种情况,0到±Float.MIN_VALUE之间的值float类型无法表示,0 到±Double.MIN_VALUE之间的值double类型无法表示。这并没有什么好奇怪的,因为这些范围内的数值超出了它们的精度范围。

    Float和Double的最小值和最大值都是以科学记数法的形式输出的,结尾的"E+数字"表示E之前的数字要乘以10的多少倍。比如3.14E3就是3.14×1000=3140,3.14E-3就是3.14/1000=0.00314。

    Java基本类型存储在栈中,因此它们的存取速度要快于存储在堆中的对应包装类的实例对象。从Java5.0(1.5)开始,JAVA虚拟机(JavaVirtual Machine)可以完成基本类型和它们对应包装类之间的自动转换。因此我们在赋值、参数传递以及数学运算的时候像使用基本类型一样使用它们的包装类,但这并不意味着你可以通过基本类型调用它们的包装类才具有的方法。另外,所有基本类型(包括void)的包装类都使用了final修饰,因此我们无法继承它们扩展新的类,也无法重写它们的任何方法。

    基本类型的优势:数据存储相对简单,运算效率比较高

    包装类的优势:有的容易,比如集合的元素必须是对象类型,满足了java一切皆是对象的思想

     

    2.Java中的常量

    十六进制整型常量:以十六进制表示时,需以0x或0X开头,如0xff,0X9A。

    八进制整型常量:八进制必须以0开头,如0123,034。

    长整型:长整型必须以L作结尾,如9L,342L。

    浮点数常量:由于小数常量的默认类型是double型,所以float类型的后面一定要加f(F)。同样带小数的变量默认为double类型。

    如:float f;

        f=1.3f;//必须声明f。

    字符常量:字符型常量需用两个单引号括起来(注意字符串常量是用两个双引号括起来)。Java中的字符占两个字节。一些常用的转义字符:

    ①\r表示接受键盘输入,相当于按下了回车键;

    ②\n表示换行;

    ③\t表示制表符,相当于Table键;

    ④\b表示退格键,相当于Back Space键;

    ⑤\'表示单引号;

    ⑥\''表示双引号;

    ⑦\\表示一个斜杠\。

     

    3. 数据类型之间的转换

    1).简单类型数据间的转换,有两种方式:自动转换和强制转换,通常发生在表达式中或方法的参数传递时。

    自动转换

    具体地讲,当一个较"小"数据与一个较"大"的数据一起运算时,系统将自动将"小"数据转换成"大"数据,再进行运算。而在方法调用时,实际参数较"小",而被调用的方法的形式参数数据又较"大"时(若有匹配的,当然会直接调用匹配的方法),系统也将自动将"小"数据转换成"大"数据,再进行方法的调用,自然,对于多个同名的重载方法,会转换成最"接近"的"大"数据并进行调用。这些类型由"小"到"大"分别为 (byte,short,char)--int--long--float—double。这里我们所说的"大"与"小",并不是指占用字节的多少,而是指表示值的范围的大小

    ①下面的语句可以在Java中直接通过:

    byte b;int i=b; long l=b; float f=b; double d=b;

    ②如果低级类型为char型,向高级类型(整型)转换时,会转换为对应ASCII码值,例如

    char c='c'; int i=c;

    System.out.println("output:"+i);输出:output:99;

    ③对于byte,short,char三种类型而言,他们是平级的,因此不能相互自动转换,可以使用下述的强制类型转换。

    short i=99 ; char c=(char)i; System.out.println("output:"+c);输出:output:c;

    强制转换

    将"大"数据转换为"小"数据时,你可以使用强制类型转换。即你必须采用下面这种语句格式: int n=(int)3.14159/2;可以想象,这种转换肯定可能会导致溢出或精度的下降。

    2)表达式的数据类型自动提升, 关于类型的自动提升,注意下面的规则。

    ①所有的byte,short,char型的值将被提升为int型;

    ②如果有一个操作数是long型,计算结果是long型;

    ③如果有一个操作数是float型,计算结果是float型;

    ④如果有一个操作数是double型,计算结果是double型;

    例, byte b; b=3; b=(byte)(b*3);//必须声明byte。

    3)包装类过渡类型转换

    一般情况下,我们首先声明一个变量,然后生成一个对应的包装类,就可以利用包装类的各种方法进行类型转换了。例如:

    ①当希望把float型转换为double型时:

    float f1=100.00f;

    Float F1=new Float(f1);

    double d1=F1.doubleValue();//F1.doubleValue()为Float类的返回double值型的方法

    ②当希望把double型转换为int型时:

    double d1=100.00;

    Double D1=new Double(d1);

    int i1=D1.intValue();

    简单类型的变量转换为相应的包装类,可以利用包装类的构造函数。即:Boolean(boolean value)、Character(char value)、Integer(int value)、Long(long value)、Float(float value)、Double(double value)

    而在各个包装类中,总有形为××Value()的方法,来得到其对应的简单类型数据。利用这种方法,也可以实现不同数值型变量间的转换,例如,对于一个双精度实型类,intValue()可以得到其对应的整型变量,而doubleValue()可以得到其对应的双精度实型变量。

    4)字符串与其它类型间的转换

    其它类型向字符串的转换

    ①调用类的串转换方法:X.toString();

    ②自动转换:X+"";

    ③使用String的方法:String.volueOf(X);

    字符串作为值,向其它类型的转换

    ①先转换成相应的封装器实例,再调用对应的方法转换成其它类型

    例如,字符中"32.1"转换double型的值的格式为:new Float("32.1").doubleValue()。也可以用:Double.valueOf("32.1").doubleValue()

    ②静态parseXXX方法

    String s = "1";

    byte b = Byte.parseByte( s );

    short t = Short.parseShort( s );

    int i = Integer.parseInt( s );

    long l = Long.parseLong( s );

    Float f = Float.parseFloat( s );

    Double d = Double.parseDouble( s );

    ③Character的getNumericValue(char ch)方法

    5)Date类与其它数据类型的相互转换

    整型和Date类之间并不存在直接的对应关系,只是你可以使用int型为分别表示年、月、日、时、分、秒,这样就在两者之间建立了一个对应关系,在作这种转换时,你可以使用Date类构造函数的三种形式:

    ①Date(int year, int month, int date):以int型表示年、月、日

    ②Date(int year, int month, int date, int hrs, int min):以int型表示年、月、日、时、分

    ③Date(int year, int month, int date, int hrs, int min, int sec):以int型表示年、月、日、时、分、秒

    在长整型和Date类之间有一个很有趣的对应关系,就是将一个时间表示为距离格林尼治标准时间1970年1月1日0时0分0秒的毫秒数。对于这种对应关系,Date类也有其相应的构造函数:Date(long date)。

    获取Date类中的年、月、日、时、分、秒以及星期你可以使用Date类的getYear()、getMonth()、getDate()、getHours()、getMinutes()、getSeconds()、getDay()方法,你也可以将其理解为将Date类转换成int。

    而Date类的getTime()方法可以得到我们前面所说的一个时间对应的长整型数,与包装类一样,Date类也有一个toString()方法可以将其转换为String类。

    有时我们希望得到Date的特定格式,例如20020324,我们可以使用以下方法,首先在文件开始引入,

    import java.text.SimpleDateFormat;

    import java.util.*;

    java.util.Date date = new java.util.Date();

     

    //如果希望得到YYYYMMDD的格式

    SimpleDateFormat sy1=new SimpleDateFormat("yyyyMMDD");

    String dateFormat=sy1.format(date);

     

    //如果希望分开得到年,月,日

    SimpleDateFormat sy=new SimpleDateFormat("yyyy");

    SimpleDateFormat sm=new SimpleDateFormat("MM");

    SimpleDateFormat sd=new SimpleDateFormat("dd");

    String syear=sy.format(date);

    String smon=sm.format(date);

    String sday=sd.format(date);

    总结:只有boolean不参与数据类型的转换

    (1).自动类型的转换:a.常数在表数范围内是能够自动类型转换的

    b.数据范围小的能够自动数据类型大的转换(注意特例)

    int到float,long到float,long到double 是不会自动转换的,不然将会丢失精度

    c.引用类型能够自动转换为父类的

    d.基本类型和它们包装类型是能够互相转换的

    (2).强制类型转换:用圆括号括起来目标类型,置于变量前

     

    4.Java引用类型

    Java有 5种引用类型(对象类型):类 接口 数组 枚举 标注

    引用类型:底层结构和基本类型差别较大

    JVM的内存空间:(1). Heap 堆空间:分配对象 new Student()

    (2). Stack 栈空间:临时变量 Student stu

    (3).Code 代码区 :类的定义,静态资源 Student.class

    eg:Student stu = new Student(); //new 在内存的堆空间创建对象

    stu.study(); //把对象的地址赋给stu引用变量

    上例实现步骤:a.JVM加载Student.class 到Code区

         b.new Student()在堆空间分配空间并创建一个Student实例;

         c.将此实例的地址赋值给引用stu, 栈空间;

    -----------------------------------------  个人总结 -----------------------------------------

    1、如果小数类型,并且小数比较小,比如四位小数,建议使用 BigDecimal 如果 是 double 类型会有失精度,有的时候会用科学记数法表示;

    比如 0.0001 会变成 1.0E-4,试问谁能看懂,如果偏要用 double 还要对类型进行转换。

    2、int double 都是有包装类型的,建议使用包装类型,包装类型能区分 null 和 0,就像在spring-mvc接收时使用 int 类型接收值,如果这个属性不传值,ajax 请求会报 400 错误,而且不能区分这个值是否是空;

    3、for 循环中如果要对字符串进行拼接,建议使用 StringBuffer ,如果没有线程安全问题,直接使用 StringBuilder,原因StringBuffer的所有操作是保证线程安全的,可以理解成使用了 synchronized 关键字,对性能是有影响的。

    4、最后对所有包装类型进行操作(比如 toString())要进行空指针判断,我们并不能保证这个值是有的。

    5、 数据类型的转换

    数据类型的转换,分为自动转换和强制转换。自动转换是程序在执行过程中 “ 悄然 ” 进行的转换,不需要用户提前声明,一般是从位数低的类型向位数高的类型转换;强制类型转换则必须在代码中声明,转换顺序不受限制。

    自动数据类型转换

    具体地讲,当一个较"小"数据与一个较"大"的数据一起运算时,系统将自动将"小"数据转换成"大"数据,再进行运算。而在方法调用时,实际参数较"小",而被调用的方法的形式参数数据又较"大"时(若有匹配的,当然会直接调用匹配的方法),系统也将自动将"小"数据转换成"大"数据,再进行方法的调用,自然,对于多个同名的重载方法,会转换成最"接近"的"大"数据并进行调用。这些类型由"小"到"大"分别为 (byte,short,char)--int--long--float—double。这里我们所说的"大"与"小",并不是指占用字节的多少,而是指表示值的范围的大小。

    自动转换按从低到高的顺序转换。不同类型数据间的优先关系如下: 

    低 ---------------------------------------------> 高 

    byte,short,char-> int -> long -> float -> double

    运算中,不同类型的数据先转化为同一类型,然后进行运算,转换规则如下:

    操作数 1 类型

    操作数 2 类型

    转换后的类型

    byte 、 short 、 char

    int

    int

    byte 、 short 、 char 、 int

    long

    long

    byte 、 short 、 char 、 int 、 long

    float

    float

    byte 、 short 、 char 、 int 、 long 、 float

    double

    double

    强制数据类型转换

    强制转换的格式是在需要转型的数据前加上 “( )” ,然后在括号内加入需要转化的数据类型。有的数据经过转型运算后,精度会丢失,而有的会更加精确

     

    参考:https://blog.csdn.net/u014266877/article/details/54374867

     

    展开全文
  • 引用类型和基本类型区别

    万次阅读 2011-12-20 22:34:35
    今天明白了一个困扰很久的问题:引用类型和基本类型的区别与联系 要明白这个问题,首先需要理解堆栈的概念。那什么又是堆栈,有什么区别和联系呢? 堆:首先堆是动态分配的,JVM并不会自动释放这部分内存。只用...
  • Java 八基本数据类型

    万次阅读 多人点赞 2018-09-11 14:59:48
    Java基本类型存储在栈中,因此它们的存取速度于存储在堆中的对应包装类的实例对象。从Java5.0(1.5)开始,JAVA虚拟机( Java Virtual Machine)可以完成基本类型和它们对应包装类之间的自动转换。因此我们在...
  • 硬件学习--不同硬盘类型速度对比

    千次阅读 2014-09-03 11:09:36
      SATA:串行ATA总线  SCSI:小型电脑输入输出接口  SAS:希捷研究出来的取代SCSI技术的接口  接口速度是 SAS > SCSI > SATA
  • java八基本数据类型及其封装类

    万次阅读 多人点赞 2019-01-05 16:52:19
    Java基本类型共有八种,基本类型可以分为三类,字符类型char,布尔类型boolean以及数值类型byte、short、int、long、float、double。数值类型又可以分为整数类型byte、short、int、long和浮点数类型float、double。...
  • 分析了嵌入式环境中YAFFS/YAFFS2文件系统的优点,提出YAFFS2不仅支持小容量的NAND flash,对大容量NAND flash更具有优势。并介绍了YAFFS/YAFFS2文件系统结构。着重将YAFFS2文件系统在嵌入式Linux系统中的实现过程...
  •  双极型结构SRAM:功耗较存取速度更加。  2.动态存储单元(DRAM)  静态存储单元存在静态功耗,集成度做不高,所以,存储容量也做不大。动态存储单元,利用了栅源间的MOS电容存储信息。其静态...
  • 基本数据类型(详解)

    千次阅读 2020-03-06 18:29:11
    Java基本类型存储在栈中,因此它们的存取速度于存储在堆中的对应包装类的实例对象。从Java5.0(1.5)开始,JAVA虚拟机(JavaVirtual Machine)可以完成基本类型和它们对应包装类之间的自动转换。因此我们在赋值...
  • Laxcus是Laxcus大数据实验室全体系自主设计研发的用户集群大数据管理系统,支持一到百万台级节点,提供零至EB量级数据存储、计算能力,集运行、开发、部署、维护为一体的平台。现在已经在地部署和投入运营。逐...
  • 8086芯片 ...容量小,存取速度快 典型 SRAM 芯片HM6116 DRAM动态随机存储器。特点:电容组成,需要刷新电路,容量大,存取速度慢。常用类型 DSRAM Intel 2164 只读存储器(ROM) * ...
  • 基本类型,或者叫做内置类型,是JAVA中不同于类的特殊类型。它们是我们编程中使用最频繁的类型。java是一种强类型语言,第一次申明变量必须说明数据类型,第一次变量赋值称为变量的初始化。 1. Java的简单类型及其...
  • 存储器的类型

    千次阅读 2018-05-03 23:24:07
      主要有两种类型的存储器:RAM和ROM。 1. RAM   随机存取存储器(RAM)(Random Access Memory)是计算机中主存的主要组成部分。在随机存取设备中,可以使用存储单元地址来随机存取一个数据项,而不需要存取...
  • 只不过是一项加快硬盘读取的技术而已,众所周知硬盘在大容量存储方面和传输速度方面性能优越,但是在随机读取方面却不如闪盘,而这项技术不过是把一些原来保存在硬盘上的存取的东西放在闪盘上,读取时优先查找闪盘里...
  • 如何计算系统容量

    千次阅读 2013-08-27 16:54:57
    因此需要预先估计系统的容量,作为产品推广、放量的依据;并且预先知道系统的瓶颈在哪、需要优先优化的方向、硬件需求取向、扩容的时机和规模。 典型的系统架构会有三层,分别是接入层、逻辑处理层、存储层。对于...
  • Flash 芯片类型介绍

    千次阅读 2019-04-28 20:35:09
    ** 一、 IIC EEPROM ** IIC EEPROM,采用的是 IIC 通信协议;...一种电可擦除可编程只读存储器,掉电后数据不丢失,由于芯片能够支持单字节擦写,且支持擦除 的次数非常之,一个地址位可重复擦写...
  • Java基本类型和包装类型总结

    万次阅读 多人点赞 2017-07-19 12:36:40
    1.Java的基本类型及其对应的包装器类Java有8种基本类型:大致分为3类:字符,布尔,数值类型(在java中数值是不存在无符号的,这一点不像C/C++,他们的取值范围是固定的,不会随着机器硬件的环境或者操作系统的改变...
  • Java基本数据类型&引用类型总结

    万次阅读 2016-10-15 22:01:08
    Java基本类型共有八种,基本类型可以分为三类,字符类型char,布尔类型boolean以及数值类型byte、short、int、long、float、double。数值类型又可以分为整数类型byte、short、int、long和浮点数类型float、double。...
  • C语言数据类型

    万次阅读 多人点赞 2018-09-12 15:10:25
    数据类型包括原始类型、多元组、记录单元、代数数据类型、抽象数据类型、参考类型以及函数类型。本文主要以51单片机中的数据类型为中心而展开的话题。  在keil C51或者iar for c8051编译器下:  int 占两个字节 ...
  • # 打开查询缓冲可以极的提高服务器速度, 如果你有大量的相同的查询并且很少修改表. # 查看 “Qcache_lowmem_prunes” 状态变量来检查是否当前值对于你的负载来说是否足够高. # 注意: 在你表经常变化的情况下或者...
  • 为了提高CPU 访问存储器的速度,可以采用双端口存储器、模块存储器等技术,它们同属并行技术,前者为空间并行,后者为时间并行。 一、双端口存储器 双端口RAM 是指同一个存储器有左、右两个独立的端口,分别具有...
  • 大数据是以容量大类型多存取速度快、应用价值高为主要特征的数据集合,正快速发展为对数量巨大、来源分散、格式多样的数据进行采集、存储和关联分析,从中发现新知识、创造新价值、提升新能力的新一代信息技术和...
  • 常见的硬盘类型介绍

    千次阅读 2019-07-31 21:56:00
    部分人选择硬盘都是会先看厂家,然后才是容量、材质等信息,常见的硬盘厂家主要有: 希捷Seagate 西部数据Western Digital 三星SAMSUNG 闪迪SanDisk 金士顿Kingston … 按照硬盘材质分为两类 HDD(Hard...
  • 由于不必须按顺序存储,链表在插入的时候可以达到O(1)的复杂度,比另一种线性表顺序表,但是查找一个节点或者访问特定编号的节点则需要O(n)的时间,而线性表和顺序表相应的时间复杂度分别是O(logn)和O(1)。...
  • 块存储和文件存储是我们比较熟悉的两种主流的存储类型,而对象存储(Object-based Storage)是一种新的网络存储架构,基于对象存储技术的设备就是对象存储设备(Object-based Storage Device)简称OSD。  首先...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 31,859
精华内容 12,743
关键字:

容量大类型多存取速度快