测试开发面试题

测试开发面试刷题



测试设计

测试方法

黑盒测试:等价类划分法、边界值分析法、错误推测法、因果图法、判断表驱动法、功能图法、正交试验法
白盒测试的测试方法有代码检查法、静态结构分析法、静态质量度量法、逻辑覆盖法、基本路径测试法、域测试、符号测试、路径覆盖和程序变异

微信红包的测试用例

功能
  1、在红包钱数和红包个数的输入框中只能输入数字;
  2、红包最多最少的输入钱数200、0.01;
  3、拼手气红包最多可以发多少个红包
  4、超过最大拼手气红包是否有提醒;
  5、当红包钱数超过最大范围是否有提醒;
  6、余额不足时,红包发送失败,或者会不会匹配切换支付方式;
  7、红包描述里是否可以输入表情汉字英文数字等;
  8、红包描述里最多有多少个字符;
  9、发送的红包别人是否能正常领取;
  10、发送的红包自己可不可以领取;
  11、24小时后别人没有领取的红包是否可以退回原来账户,或者是否还可以领取;
  12、用户是否可以多次抢一个红包;
  13、用户在多人群里发红包是否可以抢自己的红包;
  14、红包金额里的小数位是否有限制;
  15、返回键可以正常取消发红包吗;
  16、断网时,是否可以抢红包;
  17、收发红包界面是否有自己以前收发红包的记录,以及和自己实际收发红包是否匹配;
  18、支付时密码支付和指纹支付是否正常;
  19、支付成功后是否正常返回聊天界面;
  20、是否可以连续发红包。
 性能
  1、网络环境差,发红包的时间;
  2、不同网速时抢红包的时间;
  3、收发红包后跳转时间;
  4、收发红包的耗电量;
  5、退款到账的时间。
 兼容
  1、苹果,安卓系统;
  2、电脑端是否可以抢红包;
  3、不是品牌的手机是否正常使用。
 界面
  1、发红包界面有没有错别字;
  2、抢完红包界面有没有错别字;
  3、收发红包界面排版美观合理;
  4、界面颜色搭配好。
 安全
  1、发送红包领取红包后对应相关的金额是否会变化;
  2、发送失败银行卡或者余额会不会变;
  3、发送成功后是否会受到微信支付的通知。
 易用
  1、支持指纹,人脸识别支付吗;
  2、红包描述可以通过语音输入吗。

其他微信场景参考
一个杯子的测试case

Spring

SpringBoot 框架的优缺点

优点:
1,配置变得简单了
2,springboot内嵌了servlet容器,降低了对环境的要求,机器有java运行环境,可以将项目打包成jar包,通过java命令 java -jar ***.jar 来执行。
3,快速整合第三方框架,无需配置文件
4.代码少了、配置文件少了、不需要对第三方框架烦恼了、项目精简了,对整个团队的开发及维护来说,更大的节约了成本。
5.它避免了编写大量的样板代码,注释和XML配置。
6.Spring Boot应用程序与其Spring生态系统(如Spring JDBC,Spring ORM,Spring Data,Spring Security等)集成非常容易。
缺点:
依赖太多,一个spring boot项目就有很多Maven
缺少服务的注册和发现等解决方案
缺少监控集成方案,安全管理方案

参考

Spring IOC AOP

Spring IOC AOP

操作系统

进程与线程的区别

调度:线程作为调度、分配、运行的基本单位,进程作为拥有资源的基本单位
并发性:不仅进程之间可以并发执行,同一个进程的多个线程之间也可并发执行
拥有资源:进程是拥有资源的一个独立单位,线程不拥有系统资源,但可以访问隶属于进程的资源.
系统开销:在创建或撤消进程时,由于系统都要为之分配和回收资源,导致系统的开销明显大于创建或撤消线程时的开销。
一个线程只能属于一个进程,而一个进程可以有多个线程,但至少有一个线程。
资源分配给进程,同一进程的所有线程共享该进程的所有资源。
处理机分给线程,即真正在处理机上运行的是线程。
线程在执行过程中,需要协作同步。不同进程的线程间要利用消息通信的办法实现同步。线程是指进程内的一个执行单元,也是进程内的可调度实体.

java篇

sleep与wait差异

1、来自不同的类:sleep是Thread的静态类方法,谁调用的谁去睡觉,即使在a线程里调用了b的sleep方法,实际上还是a去睡觉,要让b线程睡觉要在b的代码中调用sleep。
2、有没有释放锁(释放资源)sleep不出让系统资源;wait是进入线程等待池等待,出让系统资源,其他线程可以占用CPU。
3、一般wait不会加时间限制,因为如果wait线程的运行资源不够,再出来也没用,要等待其他线程调用notify/notifyAll唤醒等待池中的所有线程,才会进入就绪队列等待OS分配系统资源。sleep(milliseconds)可以用时间指定使它自动唤醒过来,如果时间不到只能调用interrupt()强行打断。
4、sleep必须捕获异常,而wait,notify和notifyAll不需要捕获异常。

HashMap 和 HashTable 的区别

线程是否安全: HashMap 是非线程安全的,HashTable 是线程安全的,因为 HashTable 内部的方法基本都经过synchronized 修饰。(如果你要保证线程安全的话就使用 ConcurrentHashMap 吧!);
效率: 因为线程安全的问题,HashMap 要比 HashTable 效率高一点。另外,HashTable 基本被淘汰,不要在代码中使用它;
对 Null key 和 Null value 的支持: HashMap 可以存储 null 的 key 和 value,但 null 作为键只能有一个,null 作为值可以有多个;HashTable 不允许有 null 键和 null 值,否则会抛出 NullPointerException。
初始容量大小和每次扩充容量大小的不同 : ① 创建时如果不指定容量初始值,Hashtable 默认的初始大小为 11,之后每次扩充,容量变为原来的 2n+1。HashMap 默认的初始化大小为 16。之后每次扩充,容量变为原来的 2 倍。② 创建时如果给定了容量初始值,那么 Hashtable 会直接使用你给定的大小,而 HashMap 会将其扩充为 2 的幂次方大小(HashMap 中的tableSizeFor()方法保证,下面给出了源代码)。也就是说 HashMap 总是使用 2 的幂作为哈希表的大小,后面会介绍到为什么是 2 的幂次方。
底层数据结构: JDK1.8 以后的 HashMap 在解决哈希冲突时有了较大的变化,当链表长度大于阈值(默认为 8)(将链表转换成红黑树前会判断,如果当前数组的长度小于 64,那么会选择先进行数组扩容,而不是转换为红黑树)时,将链表转化为红黑树,以减少搜索时间。Hashtable 没有这样的机制。
HashMap不能保证随着时间的推移Map中的元素次序是不变的。
HashMap的迭代器(Iterator)是fail-fast迭代器,而Hashtable的enumerator迭代器不是fail-fast的。所以当有其它线程改变了HashMap的结构(增加或者移除元素),将会抛出ConcurrentModificationException,但迭代器本身的remove()方法移除元素则不会抛出ConcurrentModificationException异常。

数组、list与arrayList区别

数组与ArrayList区别
   数组是在内存空间中申请一段连续的内存地址,所以数组的查询速度很快是常量
   ArrayList的大小是按照其中存储的数据来动态扩充与收缩的。所以,我们在声明ArrayList对象时并不需要指定它的长度
List与ArrayList区别
  List类是ArrayList类的泛型等效类
  由于ArrayList可以插入不同类型的数据,因为ArrayList都把他们当作了object来处理。
  在我们使用ArrayList中的数据来处理问题的时候,很可能会报类型不匹配的错误,也就是说ArrayList不是类型安全并且这里涉及了装箱和拆箱导致ArrayList处理性能低
  装箱:将值类型的数据打包到引用类型的实例中
  拆箱:从引用数据中提取值类型
  List继承了Arraylist,在定义时需要加上特定的类型,这样就不会引起强制转换,类型检测也交给编译器进行检测

JDK、JVM、JRE是什么?

JVM
   Java 虚拟机(JVM)是运行 Java 字节码的虚拟机。JVM 有针对不同系统的特定实现(Windows,Linux,macOS),目的是使用相同的字节码,它们都会给出相同的结果。
   在 Java 中,JVM 可以理解的代码就叫做字节码(即扩展名为 .class 的文件),它不面向任何特定的处理器,只面向虚拟机。Java 语言通过字节码的方式,在一定程度上解决了传统解释型语言执行效率低的问题,同时又保留了解释型语言可移植的特点。所以 Java 程序运行时比较高效,而且,由于字节码并不针对一种特定的机器,因此,Java 程序无须重新编译便可在多种不同操作系统的计算机上运行。
JDK
   JDK是 Java Development Kit,它是功能齐全的 Java SDK。它拥有 JRE 所拥有的一切,还有编译器(javac)和工具(如 javadoc 和 jdb)。它能够创建和编译程序。
JRE
   JRE 是 Java 运行时环境。它是运行已编译 Java 程序所需的所有内容的集合,包括 Java 虚拟机(JVM),Java 类库,java 命令和其他的一些基础构件。但是,它不能用于创建新程序。
   如果你只是为了运行一下 Java 程序的话,那么你只需要安装 JRE 就可以了。如果你需要进行一些 Java 编程方面的工作,那么你就需要安装 JDK 了。但是,这不是绝对的。有时,即使您不打算在计算机上进行任何 Java 开发,仍然需要安装 JDK。例如,如果要使用 JSP 部署 Web 应用程序,那么从技术上讲,您只是在应用程序服务器中运行 Java 程序。那你为什么需要 JDK 呢?因为应用程序服务器会将 JSP 转换为 Java servlet,并且需要使用 JDK 来编译 servlet。

数据库

SQL 和MYSQL区别

SQL是一种查询语言,而MYSQL是数据库软件

数据库事务

事务是一个数据库操作序列,由事务开始与事务结束之间执行的全部数据库操作组成,这些操作要么全部执行,要么全部不执行,是一个不可分割的工作单位
1、原子性(Atomicity):事务中的全部操作在数据库中是不可分割的,要么全部完成,要么全部不执行。
2、一致性(Consistency):几个并行执行的事务,其执行结果必须与按某一顺序 串行执行的结果相一致。
3、隔离性(Isolation):事务的执行不受其他事务的干扰,事务执行的中间结果对其他事务必须是透明的。
4、持久性(Durability):对于任意已提交事务,系统必须保证该事务对数据库的改变不被丢失,即使数据库出现故障
使用事务:
步骤1: 开启事务
      set autocommit=0;#或者   
      start transaction;
步骤2: 编写事务中的sql语句(select insert update delete)
语句1;
语句二;
.....
步骤三: 结束事务
	commit;提交事务
	rollback;回滚事务

隔离级别	           脏读	  不可重复读	  幻读        解释
Read uncommitted	√	     √	       √      一个事务可以读取另一个未提交事务的数据
Read committed	    ×	     √	       √      一个事务要等另一个事务提交后才能读取数据
Repeatable read     ×	     ×     	   √      在开始读取数据(事务开启)时,不再允许修改操作
Serializable	    ×	     ×	       ×      事务串行化顺序执行

主键、外键、索引的各自的含义以及区别

主键的关键字primary key ,是由表中的一个或者多个字段构成,主键不能重复,不能为空。主键本身也是一种索引,使用主键,数据库会自动创建主键索引。每个数据表中只有一个主键。
外键的关键字foreign key ,是用来与其他表建立联系的,使数据保持一致性和完整性。建立外键的列必须与主键字段类型相同,只有他表的主键才能作为本表的外键。一个表可以有多个外键,外键数据可以重复,也可以为空。使用外键,数据库会自动创建外键索引。
索引的关键字 index ,可以分为单一索引和复合索引,单一索引是建立在一列上的索引,复合索引是建立在两个或多个列上的索引,索引可以提高查询的效率,但会降低dml操作的效率。所以建立索引时需要权衡。对于dml操作比较频繁的表,索引的个数不宜太多。

主键索引和唯一索引的区别?
1)主键一定会创建一个唯一索引,但是有唯一索引的列不一定是主键;
2)主键不允许为空值,唯一索引列允许空值;
3)一个表只能有一个主键,但是可以有多个唯一索引;
4)主键可以被其他表引用为外键,唯一索引列不可以;
5)主键是一种约束,而唯一索引是一种索引,是表的冗余数据结构,两者有本质的差别
6)主键、外键一定是索引,索引不一定是主键、外键。
7)主键不允许为空值,外键允许为空值,唯一索引列允许空值;

索引

聚集索引一个表只能有一个,而非聚集索引一个表可以存在多个。聚集索引存储记录是物理上连续存在,物理存储按照索引排序,而非聚集索引是逻辑上的连续,物理存储并不连续,物理存储不按照索引排序。
------------------
为什么用B+树做索引,而不用hash表做索引?
1 、模糊查找不支持: 哈希表是把索引字段映射成对应的哈希码然后再存放在对应的位置 , 这样的话, 如果我们要进行模糊查找的话, 显然哈希表这种结构是不支持的, 只能遍历这个 表 。 而 B + 树则可以通过最左前缀原则快速找到对应的数据。
2 、范围查找不支持: 如果我们要进行范围查找, 例如查找 ID 为 100 ~ 400 的人, 哈希表同 样不支持, 只能遍历全表。
3 、 哈希冲突问题: 索引字段通过哈希映射成哈希码, 如果很多字段都刚好映射到相同值的 哈希码的话, 那么形成的索引结构将会是一条很长的链表, 这样的话, 查找的时间就会大大 增加。

MySQL 的优缺点


优点
    a) 99.999%的高可用性
    b) 快速的自动失效切换
    c)灵活的分布式体系结构,没有单点故障
    d)高吞吐量和低延迟
缺点
    a)存在很多限制,比如:不支持外键
    b)部署、管理、配置很复杂
    c)占用磁盘空间大,内存大
    d)备份和恢复不方便
    e)重启的时候,数据节点将数据load到内存需要很长时间 

如何保证分库分表之后ID的全局唯一性

snowflakes 原理 
其核心思想是将64bit的二进制数字分为若干部分,每一部分都存储具有特定含义的数据,比如时间戳、机器ID、序列号等等,最终生成全局唯一的有序ID。它的标准算法如下
一种是嵌入到业务代码里面,也就是分布在业务服务器中
     这种方案的好处是业务代码在使用的时候不需要跨网络调用,性能会好一点。
     缺点需要更多的机器ID位数来支持更多的业务服务器。
     但是由于业务服务器的数量很多,我们很难保证机器ID的唯一性,所以就需要引入zookeeper等分布式一致性组件来保证每次机器重启时都能获得唯一的机器ID
另一种是作为独立的服务器部署,这也是我们常说的发号器服务
     业务在使用发号器的时候需要多一次的网络调用,但是内网的调用对于性能的损耗有限,却可以减少机器ID的位数,如果发号器以主备方式部署,同时运行的只有一个发号器,那么机器ID可以省略,这样可以留更多位数给最后的自增信息位
     即使需要机器ID,因为发号器部署实例数有限,那么就可以把机器ID写在发号器的配置文件里,这样既可以保证机器ID唯一性,也无需引入第三方组件了

优点:Snowflake 算法设计的非常简单且巧妙,性能上也足够高效,同时也能够生成具有全局唯一性、单调递增性和有业务含义的 ID
缺点:
1、依赖于系统的时间戳,一旦系统时间不准,就有可能生成重复的ID,所以如果我们发现系统时钟不准,就可以让发号器暂时拒绝发号,直到时钟准确为止
2、如果请求发号器的QPS不高,如果说发号器每秒只发一个ID,就会造成生成ID的末位永远是1,那么在分库分表的时候如果使用ID作为分区键就会造成库表分配不均匀。解决方法主要有两个:
    时间戳不记录毫秒而是记录秒,这样在一个时间区间里面可以多发出几个号,避免出现分库分表时数据分配不均
    生成的序列号的起始号可以做一下随机,这一秒是 21,下一秒是 30,这样就会尽量的均衡了。

问题:为什么不使用UUID作为主键ID
(UUID是一种通用唯一识别码,是全球唯一的,不会重复,所以可以作为唯一主键使用,而且本机生成不耗费资源,目的是用于分布式环境中唯一生成标志码,是由32个16进制数组成.)
生成的ID最好具有单调递增性,也就是有序的,而UUDI不具备这个特点
UUDI不能作为ID的另一个原因是它不具备业务含义
UUID是由32个16进制数字组成的字符粗,如果作为主键使用比较耗费空间

数据库的范式

第一范式NF:
    数据库表中的字段都是单一属性的,不可再分。简单的说,每一个属性都是原子项,不可分割
第二范式2NF
    数据库表中不存在非关键字段对任一候选关键字段的部分函数依赖,即符合第二范式
第三范式3NF
    数据表中如果不存在非关键字段对任一候选关键字段的传递函数依赖则符合3NF

参考

mysql常用的存储引擎有什么?区别是什么?

常用的存储引擎是:InnoDB,MyISAM
区别在于:
   InnoDB支持事务,而MyISAM不支持事务
   InnoDB支持行级锁,而MyISAM支持表级锁
   InnoDB支持MVC, 而MyISAM不支持
   InnoDB支持外键,而MyISAM不支持
   InnoDB不支持全文索引,而MyISAM支持。
   MyISAM适合查询以及插入为主的应用
   MyISAM的性能更优,占用的存储空间少,所以,选择何种存储引擎,视具体应用而定。

查询速度慢的原因,如何解决

1、没有索引或者没有⽤到索引(这是查询慢最常见的问题,是程序设计的缺陷) 
2I/O吞吐量⼩,形成了瓶颈效应。 
3、没有创建计算列导致查询不优化。 
4、内存不⾜ 
5、⽹络速度慢 
6、查询出的数据量过⼤(可以采⽤多次查询,其他的⽅法降低数据量) 
7、锁或者死锁(这也是查询慢最常见的问题,是程序设计的缺陷) 
8、sp_lock,sp_who,活动的⽤户查看,原因是读写竞争资源。 
9、返回了不必要的⾏和列 
10、查询语句不好,没有优化 
可以通过如下⽅法来优化查询 : 

SQL优化方法

(1)对查询进行优化,尽量避免全表扫描,首先考虑在 WHERE 或 ORDER BY 涉及的列上建立索引; 
(2)尽量避免在 WHERE 子句中对字段进行 NULL 值判断,否则导致引擎放弃使用索引而进行全表扫描(优化:在num上设置默认值0,确保表中num列没有null值) \`SELECT \* FROM test WHERE id IS NULL --> SELECT \* FROM test WHERE id = 0 \` (
(3)应尽量避免在 where 子句中使用!=<>操作符,否则导致引擎放弃使用索引而进行全表扫 
(4)应尽量避免在 where 子句中使用 or 来连接条件,否则导致引擎放弃使用索引而进行全表扫 \` SELECT \* FROM test WHERE id = 10 OR id = 20 --> SELECT \* FROM test WHERE id = 10 UNION ALL SELECT \* FROM TEST WHERE id = 20 \` 
(5)in 和 not in 也要慎用,否则会导致全表扫描 \` SELECT \* FROM test WHERE id in (1, 2, 3) -->(如果是连续值) SELECT \* FROM test WHERE id BETTWEN 1 AND 3 \` 
(6)避免使用模糊查询 LIKE "%xx%",否则会导致全表扫描 
(7)应尽量避免在 where 子句中对字段进行表达式操作,否则会导致引擎放弃索引进行全表扫描 \` SELECT id FROM test WHERE num/2=100 --> SELECT id FROM test WHERE num = 2 \* 100 \` 
(8)应尽量避免在where子句中对字段进行函数操作,这将导致引擎放弃使用索引而进行全表扫描 \` select id from t where substring(name,1,3)='abc'--name以abc开头的id --> select id from t where name like 'abc%' \` 
(9)不要在 where 子句中的“=”左边进行函数、算术运算或其他表达式运算,否则系统将可能无法正确使用索引 
(10)在使用索引字段作为条件时,如果该索引是复合索引,那么必须使用到该索引中的第一个字段作为条件时才能保证系统使用该索引,否则该索引将不会被使用,并且应尽可能的让字段顺序与索引顺序相一致。

TRUNCATE 与 DELETE 区别

*   TRUNCATE 是DDL语句,而 DELETE 是DML语句。   
*   TRUNCATE 是先把整张表drop掉,然后重建该表。而 DELETE 是一行一行的删除,所以 TRUNCATE 的速度肯定比 DELETE 速度快。   
*   TRUNCATE 不可以回滚,DELETE 可以。    
*   TRUNCATE 执行结果只是返回0 rows affected,可以解释为没有返回结果。   
*   TRUNCATE 会重置水平线(自增长列起始位),DELETE 不会。   
*   TRUNCATE 只能清理整张表,DELETE 可以按照条件删除。

网络通信篇

Cookie与Session的区别

cookies 数据保存在客户端,session 数据保存在服务器端;
cookies 可以减轻服务器压力,但是不安全,容易进行 cookies 欺骗;
session 较安全,但占用服务器资源

打开浏览器,从输入 www.baidu.com 到看到浏览器显示页面,这个过程中,都有哪些步骤和环节?

DNS域名解析
TCP三次握手
发生http请求
接受http响应
浏览器解析响应文件(js,css,html)

参考

网络协议,如TCP/UDP的区别?

TCP面向连接(如打电话要先拨号建立连接);UDP是无连接的,即发送数据之前不需要建立连接
TCP提供可靠的服务。也就是说,通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达;UDP尽最大努力交付,即不保证可靠交付
TCP面向字节流,实际上是TCP把数据看成一连串无结构的字节流;UDP是面向报文的UDP没有拥塞控制,因此网络出现拥塞不会使源主机的发送速率降低(对实时应用很有用,如IP电话,实时视频会议等)
每一条TCP连接只能是点到点的;UDP支持一对一,一对多,多对一和多对多的交互通信
TCP首部开销20字节;UDP的首部开销小,只有8个字节
TCP的逻辑通信信道是全双工的可靠信道,UDP则是不可靠信道

post和get请求区别

1、get和post应用上的不同
最直观的区别就是GET把参数包含在URL中,POST通过request body传递参数。包括以下:
1)GET在浏览器回退时是无害的,而POST会再次提交请求。
2)GET产生的URL地址可以被Bookmark,而POST不可以。
3)GET请求会被浏览器主动cache,而POST不会,除非手动设置。
4)GET请求只能进行url编码,而POST支持多种编码方式。
5)GET请求参数会被完整保留在浏览器历史记录里,而POST中的参数不会被保留。
6)GET请求在URL中传送的参数是有长度限制的,而POST么有。
7)对参数的数据类型,GET只接受ASCII字符,而POST没有限制。
8)GET比POST更不安全,因为参数直接暴露在URL上,所以不能用来传递敏感信息。
9)GET参数通过URL传递,POST放在Request body中。
2、get和post本质区别--GET和POST本质上就是TCP链接,并无差别。但是由于HTTP的规定和浏览器/服务器的限制,导致他们在应用过程中体现出一些不同。 
3、get和post重大区别--GET产生一个TCP数据包,POST产生两个TCP数据包:对于GET方式的请求,浏览器会把http header和data一并发送出去,服务器响应200(返回数据);而对于POST,浏览器先发送header,服务器响应100 continue,浏览器再发送data,服务器响应200 ok(返回数据)。

HTTP 状态码 2xx,3xx,4xx,5xx 分别是什么意思?

200 请求已成功,请求所希望的响应头或数据体将随此响应返回。
201 请求已经被实现,而且有一个新的资源已经依据请求的需要而建立,且其 URI 已经随 Location 头信息返回
202 服务器已接受请求,但尚未处理
301 (永久移动) 请求的网页已永久移动到新位置。 服务器返回此响应(对 GET 或 HEAD 请求的响应)时会自动将请求者转到新位置。
302 (临时移动) 服务器目前从不同位置的网页响应请求,但请求者应继续使用原有位置来进行以后的请求。
303 (查看其他位置) 请求者应当对不同的位置使用单独的 GET 请求来检索响应时,服务器返回此代码。
304 (未修改) 自从上次请求后,请求的网页未修改过。 服务器返回此响应时,不会返回网页内容。
305 (使用代理) 请求者只能使用代理访问请求的网页。 如果服务器返回此响应,还表示请求者应使用代理。
307 (临时重定向) 服务器目前从不同位置的网页响应请求,但请求者应继续使用原有位置来进行以后的请求。
401 当前请求需要用户验证。如果当前请求已经包含了 Authorization证书,那么 401 响应代表着服务器验证已经拒绝了那些证书
403 服务器已经理解请求,但是拒绝执行它。与 401 响应不同的是,身份验证并不能提供任何帮助,而且这个请求也不应该被重复提交
404 请求失败,请求所希望得到的资源未被在服务器上发现
500 服务器遇到了一个未曾预料的状况,导致了它无法完成对请求的处理。一般来说,这个问题都会在服务器的程序码出错时出现。
501 服务器不支持当前请求所需要的某个功能。当服务器无法识别请求的方法,并且无法支持其对任何资源的请求。
502 作为网关或者代理工作的服务器尝试执行请求时,从上游服务器接收到无效的响应。
503 由于临时的服务器维护或者过载,服务器当前无法处理请求。这个状况是临时的,并且将在一段时间以后恢复。

HTTPS 和 HTTP 的区别

总的来说: HTTPS=SSL+HTTP
1、https 协议需要到 ca 申请证书,一般免费证书较少,因而需要一定费用。
2、http 是超文本传输协议,信息是明文传输,https 则是具有安全性的 ssl 加 密传输协议。
3、http 和 https 使用的是完全不同的连接方式,用的端口也不一样,前者是 80, 后者是 443(这个只是默认端口不一样,实际上端口是可以改的)
4、http 的连接很简单,是无状态的;HTTPS 协议是由 SSL+HTTP 协议构建的可进 行加密传输、身份认证的网络协议,比 http 协议安全。

性能

QPS = 并发线程数 * ( 1000 / 平均耗时ms )

工作中遇到的性能问题

问题1:grpc线程池被打满
计算密集型:线程数 = 一般设置CPU * 2即可。
IO密集型:线程数 = CPU核心数/(1-阻塞系数) 这个阻塞系数一般为0.8~0.9之间,也可以取0.8或者0.9

针对于阻塞系数,《Programming Concurrency on the JVM Mastering》即《Java 虚拟机并发编程》中有提到一句话:
对于阻塞系数,我们可以先试着猜测,抑或采用一些性能分析工具或java.lang.management API 来确定线程花在系统/IO操作上的时间与CPU密集任务所耗的时间比值。

问题2:MQ消息堆积延迟
消费耗时过长
消费并发度(消费者只有两个实例,消费能力不足)

问题3:接口耗时飙升,grpc线程池被打满,sql耗时飙升
测试数据中的手机号没有打散,触发innodb行锁,导致数据库insert和query耗时飙升。

常见性能瓶颈:

1、吞吐量到上限时系统负载未到阈值:一般是被测服务分配的系统资源过少导致的。测试过程中如果发现此类情况,可以从ulimit、系统开启的线程数、分配的内存等维度定位问题原因
2、CPU的us和sy不高,但wa很高:如果被测服务是磁盘IO密集型型服务,wa高属于正常现象。但如果不是此类服务,最可能导致wa高的原因有两个,一是服务对磁盘读写的业务逻辑有问题,读写频率过高,写入数据量过大,如不合理的数据载入策略、log过多等,都有可能导致这种问题。二是服务器内存不足,服务在swap分区不停的换入换出。
3、同一请求的响应时间忽大忽小:在正常吞吐量下发生此问题,可能的原因有两方面,一是服务对资源的加锁逻辑有问题,导致处理某些请求过程中花了大量的时间等待资源解锁;二是Linux本身分配给服务的资源有限,某些请求需要等待其他请求释放资源后才能继续执行。
4、内存持续上涨:在吞吐量固定的前提下,如果内存持续上涨,那么很有可能是被测服务存在明显的内存泄漏,需要使用valgrind等内存检查工具进行定位

性能瓶颈概率分布:
60%:数据库瓶颈
    数据库服务器 CPU 使用率高(慢查询、SQL 过多、连接数过多)
    抛出连接数过多(连接池设置太小,导致连接排队)
    数据库出现死锁
25%:应用瓶颈
    应用出现内存泄露
    应用出现线程竞争/死锁
    程序代码的算法复杂度
    中间件、第三方应用出现异常
    计算密集型任务引起 CPU 负载高
    I/O 密集型任务引起 I/O 负载高
10%:压测工具瓶颈
  	    JMeter 单机负载能力有限,如果需要模拟的用户请求数超过其负载极限,也会导致 TPS 压不上去
5%:Linux 机器出现异常
	Linux 可用内存无法回收(开销速率大于回收速率)

内存溢出(out of memory):是指程序在申请内存时,没有足够的内存空间供其使用,就会出现out of memory;内存溢出就是你要求分配的内存超出了系统能给你的,系统不能满足需求,于是产生溢出。(程序运行时所需要的内存,超出了它可用的最大内存。)
内存泄露(memory leak):是指程序在申请内存后,无法释放已申请的内存空间。
memory leak会最终会导致out of memory

参考

性能测试指标有哪些?

性能测试外部指标:
1、吞吐量:每秒钟系统能够处理的请求数、任务数。
2、响应时间:服务处理一个请求或一个任务的耗时。
3、错误率:一批请求中结果出错的请求所占比例。
性能测试内部指标:
1、CPU、
2、内存、
3、服务器负载、
4、网络、
5、磁盘IO等

性能测试中什么情况内存过高,但 CPU 使用率不高?

找到内存泄漏的代码,并优化代码
日志打的太多

性能测试中什么情况 CPU 使用率高,但内存占用不高?

计算密集型服务
CPU 高的可能原因:慢 SQL、SQL 语句过多、连接数过多等
确认是否存在慢 SQL
      查看慢查询日志,看看是否有超过预期指标的 SQL 语句,并分析排查:看看执行计划是否准确、索引是否缺失、数据量是否太大等。
      目前案例经过慢查询日志的分析,未存在慢查询。

  确认是否 SQL 语句过多或连接数过多
      使用show full processlist查看当前数据库中正在执行的 SQL 语句及连接池的状态,发现大量 SQL 在等待执行。
      再结合操作过程中的系统日志进行分析,发现每进入一次商城首页,就需要在数据库中执行 19 条查询 SQL。

性能测试-过程以及常见问题定位

悲观锁和乐观锁

乐观锁
乐观锁是一种乐观思想,即认为读多写少,遇到并发写的可能性低,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,采取在写时先读出当前版本号,然后加锁操作(比较跟上一次的版本号,如果一样则更新),如果失败则要重复读-比较-写的操作。
悲观锁
悲观锁是就是悲观思想,即认为写多,遇到并发写的可能性高,每次去拿数据的时候都认为别人会修改,所以每次在读写数据的时候都会上锁,这样别人想读写这个数据就会block直到拿到锁。

中间件

MQ消息丢失、重复、顺序、一致性

如何避免消息堆积和延迟

为了避免在业务使用时出现非预期的消息堆积和延迟问题,您需要在前期设计阶段对整个业务逻辑进行完善的排查和梳理。整理出正常业务运行场景下的性能基线,才能在故障场景下迅速定位到阻塞点。其中最重要的就是梳理消息的消费耗时和消息消费的并发度。
一、梳理消息的消费耗时
通过压测获取消息的消费耗时,并对耗时较高的操作的代码逻辑进行分析。查询消费耗时,请参见获取消息消费耗时。梳理消息的消费耗时需要关注以下信息:
消息消费逻辑的计算复杂度是否过高,代码是否存在无限循环和递归等缺陷。
消息消费逻辑中的I/O操作(如:外部调用、读写存储等)是否是必须的,能否用本地缓存等方案规避。
消费逻辑中的复杂耗时的操作是否可以做异步化处理,如果可以是否会造成逻辑错乱(消费完成但异步操作未完成)。
二、设置消息的消费并发度
逐步调大线程的单个节点的线程数,并观测节点的系统指标,得到单个节点最优的消费线程数和消息吞吐量。
得到单个节点的最优线程数和消息吞吐量后,根据上下游链路的流量峰值计算出需要设置的节点数,节点数=流量峰值/单线程消息吞吐量。

架构

dubbo

dubbo

Dubbo 是一个分布式服务框架,致力于提供高性能和透明化的 RPC 远程服务调用方案,以及 SOA 服务治理方案。简单的说,Dubbo 就是个服务框架,说白了就是个远程服务调用的分布式框架

rpc

RPC是Remote Procedure Call的简称,中文叫远程过程调用

grpc

grpc

算法

蚁群算法

是否知道堆排序及其原理

主要内容:本文详细介绍了一种QRBiLSTM(分位数回归双向长短期记忆网络)的时间序列区间预测方法。首先介绍了项目背景以及模型的优势,比如能够有效利用双向的信息,并对未来的趋势上限和下限做出估计。接着从数据生成出发讲述了具体的代码操作过程:数据预处理,搭建模型,进行训练,并最终可视化预测结果与计算分位数回归的边界线。提供的示例代码可以完全运行并且包含了数据生成环节,便于新手快速上手,深入学习。此外还指出了模型未来发展的方向,例如加入额外的输入特性和改善超参数配置等途径提高模型的表现。文中强调了时间序列的标准化和平稳检验,在样本划分阶段需要按时间序列顺序进行划分,并在训练阶段采取合适的手段预防过度拟合发生。 适合人群:对于希望学习和应用双向长短时记忆网络解决时序数据预测的初学者和具有一定基础的研究人员。尤其适用于有金融数据分析需求、需要做多一步或多步预测任务的从业者。 使用场景及目标:应用于金融市场波动预报、天气状况变化预测或是物流管理等多个领域内的决策支持。主要目的在于不仅能够提供精确的数值预计还能描绘出相应的区间概率图以增强结论置信程度。 补充说明:本教程通过一个由正弦信号加白噪构造而成的简单实例来指导大家理解和执行QRBiLSTM流程的所有关键步骤,这既方便于初学者跟踪学习,又有利于专业人士作为现有系统的补充参考工具
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值