Java相关的经典问题及解答

微博和知乎中的 feed 流是如何实现的?
https://www.jianshu.com/p/1d8345c3404d

在浏览器地址栏输入URL,按下回车后究竟发生了什么?
https://www.jianshu.com/p/c5425486e90c

java实现在线文档编辑
https://www.jianshu.com/p/0163cda737ce

高并发设计方案二(秒杀架构)
https://www.jianshu.com/p/37209226d04d

支付高并发
https://www.jianshu.com/p/b5924730d5a9

高并发的架构该如何设计,一张图让你彻底明白,俗语讲的你肯定懂
https://www.jianshu.com/p/11787c73be6d

缓存穿透,缓存击穿,缓存雪崩解决方案分析
https://www.jianshu.com/p/b29d06f16d2b

使用Mutex实现线程安全的链表功能
https://www.jianshu.com/p/ac5bc209b463

应用服务器性能优化
https://www.jianshu.com/p/4a3257cac8af

每个程序员要注意的 9 种反模式
https://www.jianshu.com/p/7e12152c5bfe

性能分析之-- JAVA Thread Dump 分析综述
https://www.jianshu.com/p/dc24f52e9832

三个实例演示 Java Thread Dump 日志分析
https://www.jianshu.com/p/cd17d417342a

  1. 用一句话概括 Web 编程的特点
  2. Google是如何在一秒内把搜索结果返回给用户
  3. 哪种依赖注入方式你建议使用,构造器注入,还是 Setter方法注入
  4. 树(二叉或其他)形成许多普通数据结构的基础。请描述一些这样的数据结构以及何时可以使用它们
  5. 线上系统突然变得异常缓慢,你如何查找问题
  6. 新浪微博是如何实现把微博推给订阅者
  7. 简要介绍下从浏览器输入 URL 开始到获取到请求界面之后 Java Web 应用中发生了什么
  8. 高并发下,如何做到安全的修改同一行数据
  9. 12306网站的订票系统如何实现,如何保证不会票不被超卖
  10. 聊了下曾经参与设计的服务器架构
  11. 请思考一个方案,实现分布式环境下的 countDownLatch
  12. 请思考一个方案,设计一个可以控制缓存总体大小的自动适应的本地缓存
  13. 在你的职业生涯中,算得上最困难的技术挑战是什么
  14. 如何写一篇设计文档,目录是什么
  15. 大写的O是什么?举几个例子
  16. 编程中自己都怎么考虑一些设计原则的,比如开闭原则,以及在工作中的应用
  17. 解释一下网络应用的模式及其特点
  18. 设计一个在线文档系统,文档可以被编辑,如何防止多人同时对同一份文档进行编辑更新
  19. 说出数据连接池的工作机制是什么
  20. 怎么获取一个文件中单词出现的最高频率
  21. 描述一下你最常用的编程风格
  22. 如果有机会重新设计你们的产品,你会怎么做
  23. 如何搭建一个高可用系统
  24. 如何启动时不需输入用户名与密码
  25. 如何在基于Java的Web项目中实现文件上传和下载
  26. 如何实现一个秒杀系统,保证只有几位用户能买到某件商品。
  27. 如何实现负载均衡,有哪些算法可以实现
  28. 如何设计一个购物车?想想淘宝的购物车如何实现的
  29. 如何设计一套高并发支付方案,架构如何设计
  30. 如何设计建立和保持 100w 的长连接
  31. 如何避免浏览器缓存。
  32. 如何防止缓存雪崩
  33. 如果AB两个系统互相依赖,如何解除依赖
  34. 如果有人恶意创建非法连接,怎么解决
  35. 如果有几十亿的白名单,每天白天需要高并发查询,晚上需要更新一次,如何设计这个功能
  36. 如果系统要使用超大整数(超过long长度范围),请你设计一个数据结构来存储这种超大型数字以及设计一种算法来实现超大整数加法运算)
  37. 如果要设计一个图形系统,请你设计基本的图形元件(Point,Line,Rectangle,Triangle)的简单实现
  38. 如果让你实现一个并发安全的链表,你会怎么做
  39. 应用服务器与WEB 服务器的区别?应用服务器怎么监控性能,各种方式的区别?你使用过的应用服务器优化技术有哪些
  40. 大型网站在架构上应当考虑哪些问题
  41. 有没有处理过线上问题?出现内存泄露,CPU利用率标高,应用无响应时如何处理的
  42. 最近看什么书,印象最深刻的是什么
  43. 描述下常用的重构技巧
  44. 你使用什么版本管理工具?分支(Branch)与标签(Tag)之间的区别在哪里
  45. 你有了解过存在哪些反模式(Anti-Patterns)吗
  46. 你用过的网站前端优化的技术有哪些
  47. 如何分析Thread dump
  48. 你如何理解AOP中的连接点(Joinpoint)、切点(Pointcut)、增强(Advice)、引介(Introduction)、织入(Weaving)、切面(Aspect)这些概念
  49. 你是如何处理内存泄露或者栈溢出问题的
  50. 你们线上应用的 JVM 参数有哪些
  51. 怎么提升系统的QPS和吞吐量
1. 用一句话概括 Web 编程的特点

由ASP,PHP,JAVASCRIPT,JAVA,CGI等计算机脚本语言编写出来的执行灵活的互联网网页程序

2. Google是如何在一秒内把搜索结果返回给用户

参考链接

1、用户发出搜索请求。谷歌搜索质量工程师 PatrickRiley 说:在大多数搜索中,你的搜索处于多个并行的控制过程或谷歌实验室的创新项目组过程中,可以说每一个查询请求都会参与一些谷歌的创意实验。我们都是小白鼠?
2、谷歌会对用户输入的关键词提供一些建议。
3、谷歌会用同义词匹配与你的搜索关键词语义相近的查询结果。
4、生成初步的查询结果,虽然谷歌宣称可以找到成千上万的相关结果,但一般只显示不到1000条,同时查询结果将被进行本地化处理,本土站点在查询结果中优先出现。

搜索结果将如何被优化?
1、对查询结果按权威性和 PageRank 进行排序,重复的查询结果被剔除。此时的查询结果已接近最终形态,在这一基础上,有两个进程将分开进行–查询结果优化和为其匹配相应的广告。我们先来看查询结果优化。

对查询结果进行过滤处理
2、对查询结果进行过滤处理。包括以下几点:
2.1、对通常的查询,谷歌会把相关的专题性垂直搜索结果(比如新闻、购物、视频、书籍、地图等)也加到返回的查询结果中。
2.2、个性化,用户访问过的网站在查询结果列表中会更靠上
2.3、大量使用锚点的网站有可能被从查询结果中删除
2.4、如果网页被其他高 PageRank 的网站引用,则网页的重要性会大大提高。
2.5、趋势分析:对搜索流量爆增或有大量新闻的搜索关键词,谷歌会在新的查询结果中增加额外的 PageRank 权值。
2.6、同一个域名下的多个网页如果具有相同的 PageRank 会被归为一组。
2.7、查询结果最终形成(将与广告一同显示)

用户所搜索的内容如何与广告相结合?
1、Google 根据关键词、广告类型、用户所处位置找出相关的被竞价拍卖的关键词广告
1.1、关键词广告必须遵守当地法律条文。广告业主的非法广告将被取缔,如果关键词的搜索流量过低或关键词广告点击量偏低,则会被自动禁用,出于商业策略,像亚马逊这样的客户会给予优惠折扣。
1.2、关键词相关广告按收益潜力排序。
1.3、对广告业主来说广告内容一般是固定的,但有时使用动态关键词使关键词广告与搜索关键词相关度更高。一些广告允许增加附属信息,比如网站链接、电话号码、产品链接、地址等。
1.4、如果广告拥有相当高的点击率,则会显示在搜索结果列表的上方,以使其更显眼。
1.5、其余的广告依序显示在页面右侧

经过上述一系列复杂的信息处理过程,最终返回给用户的是一个个性化的、具备地理位置特征的、布局简洁的查询结果页面,当然还精确匹配了广告,所有这些步骤在总共不到1秒的时间内完成,每天3亿次的点击量给 Google 带来了超过200亿美元的年收入

3. 哪种依赖注入方式你建议使用,构造器注入,还是 Setter方法注入

Setter
setter方法设定依赖关系显得更加直观,更加自然。
如果依赖关系(或继承关系)较为复杂,那么构造函数也会相当庞大(我们需要在构造函数中设定所有依赖关系)
对于某些第三方类库而言,可能要求我们的组件必须提供一个默认的构造函数(如Struts中的Action),此时构造的依赖注入机制就体现出其局限性,难以完成我们期望的功能。

4. 树(二叉或其他)形成许多普通数据结构的基础。请描述一些这样的数据结构以及何时可以使用它们

HashMap:java8改成数组+链表+红黑树的数据结构

TreeMap实现SortedMap接口,底层红黑树数据结构,能够把它保存的记录根据键排序,默认是按键值的升序排序,也可以指定排序的比较器

TreeSet:树集,底层通过TreeMap实现,有序非同步集合,用红黑树数据结构,每次添加到树中时,都会添加到正确位置,迭代器可以按排好的顺序访问每个元素,比散列表插入慢,查询快

priority queue:优先级队列,可以任意顺序插入,但是按排序顺序检索,数据结构用堆(heap)自我调整的二叉树,add和remove操作会把最小的元素移动到根,非线程安全。

二叉树:(遍历按根节点遍历顺序分前中后)
前序遍历:根节点->左子树->右子树
中序遍历:左子树->根节点->右子树
后序遍历:左子树->右子树->根节点
特点:排序二叉树虽然可以快速检索,但在最坏的情况下:如果插入的节点集本身就是有序的,要么是由小到大排列,要么是由大到小排列,那么最后得到的排序二叉树将变成链表:所有节点只有左节点(如果插入节点集本身是大到小排列);或所有节点只有右节点(如果插入节点集本身是小到大排列)。在这种情况下,排序二叉树就变成了普通链表,其检索效率就会很差。

红黑树,一种二叉查找树,但在每个结点上增加一个存储位表示结点的颜色,可以是Red或Black。
通过对任何一条从根到叶子的路径上各个结点着色方式的限制,红黑树确保没有一条路径会比其他路径长出俩倍,因而是接近平衡的。
红黑树能够以O(log2 n) 的时间复杂度进行搜索、插入、删除操作。此外,由于它的设计,任何不平衡都会在三次旋转之内解决。

5. 线上系统突然变得异常缓慢,你如何查找问题
  1. 首先就是想看日志,后来想想看日志确实不太可行,并发量太大的情况下,查日志会很慢,(看日志,pstack strace gdb)。
  2. 应该从上到下看。----网络,系统,应用。任何一个环节都有可能有问题,首先看网络监控情况,然后看系统(内存,cpu,负载 )情况。
  3. 把线程dump出来,用jstack dump 线程调用链,看线程卡到哪里了。然后定位代码,看看赌在哪个函数,是不是调用了重函数。当然先定位到具体应用,再dump。
  4. 看接口故障率,然后看数据库有没有锁。
  5. 先看日志,排除了磁盘满了,网络慢,然后看进程,具体到当时几个线程,堵在哪儿。
  6. 分布式服务一般都是服务治理的,可以看整个调用链的时间图。
  7. 看监控,监控只是能找到问题 但是不能找到问题原因,什么请求、返回、错误、慢速,这些都是要监控的,告警也要配置好,有问题第一时间知道。
  8. 假如是网络问题那就找临近的防火墙看对应服务器的并发连接数是否新建连接/半开连接超高,或者有突发流量挤占了资源。同时查对应服务器的磁盘I/O情况和对应那个应用的进程内存占用曲线是否有突发。高并发应用我理解上日志肯定是没法去看的,因为日志量太巨大了。
  9. 集群或多主机的系统,需要根据监控 看各个主机的CPU 内存 接口IO等,这些能分析一些,如果能得出具体的主机 再分析哪个应用的CPU 内存 异常dump 等。如果涉及到接口机 可以看接口的失败率,应用的话需要排查log了,有时候主机空间不足 内存不足、硬件故障也会导致问题。
  10. 例子:在银行做安全运维时候,那帮服务器的和网银的一天到晚就说这是网络问题,这绝对网络瘫了。。然后查一圈发现他们一个什么java的问题,说是有个印度小哥把java runtime装了最高版本。但是系统不支持,必须重新装回低版本,就好了。
  11. 如果是分布式部署多台机器,别的机器没问题,但这台机器有问题。那么更有可能是因为网络或者磁盘导致的,一般这些资源都有zabbix这样的监控。看日志是肯定要的。
  12. 如果这些机器都是虚拟机的话也有可能是控制器系统的问题。
  13. 扩展:
    阿里,负载均衡和流量清洗系统强大,每年网购高峰期和那几个“节”一过0点的突发流量,很考验负载均衡系统的部署策略。高峰限流是关键,不能冲垮系统,但高峰一限流。。购物车就无法结账了。(异步结帐)
    京东,双12 的时候。负载均衡也会出问题。有时候,负载不均衡的情况出现,有针对应用的限流和熔断的,也有针对URL的限流和熔断机制。
    另外:DDOS攻击、负载均衡算法没设计好、CDN、DNS等都有可能
6. 新浪微博是如何实现把微博推给订阅者

这个链接写的很详细,就不复制在这里了:
微博和知乎中的 feed 流是如何实现的?
https://www.jianshu.com/p/1d8345c3404d

7. 简要介绍下从浏览器输入 URL 开始到获取到请求界面之后 Java Web 应用中发生了什么

参考链接

  1. 首先嘛,你得在浏览器里输入要网址:
  2. 浏览器查找域名的IP地址
  3. 浏览器给web服务器发送一个HTTP请求
  4. 服务的永久重定向响应
  5. 浏览器跟踪重定向地址
  6. 服务器“处理”请求
  7. 服务器发回一个HTML响应
  8. 浏览器开始显示HTML
  9. 浏览器发送获取嵌入在HTML中的对象
  10. 浏览器发送异步(AJAX)请求
8. 高并发下,如何做到安全的修改同一行数据
  1. 将库存字段number字段设为unsigned,当库存为0时,因为字段不能为负数,将会返回false
  2. 悲观锁
  3. 使用MySQL的事务,锁住操作的行
  4. FIFO队列思路
  5. 使用非阻塞的文件排他锁
  6. 乐观锁,采用带版本号(Version)更新
9. 12306网站的订票系统如何实现,如何保证不会票不被超卖
  1. 一个是java的对象锁,用于线程同步;
  2. 另外一个是数据库的锁;这里只能用数据库端的锁来实现。
    采用乐观锁即可解决此问题。乐观锁意思是不锁定表的情况下,利用业务的控制来解决并发问题,这样即保证数据的并发可读性又保证保存数据的排他性,保证性能的同时解决了并发带来的脏数据问题。
    可以使用版本号实现乐观锁。
10. 聊了下曾经参与设计的服务器架构


电商系统架构,Saas多租户系统架构,企业信息系统架构(EIP)

11. 请思考一个方案,实现分布式环境下的 countDownLatch

CountDownLatch是一个同步的辅助类,它可以允许一个或多个线程等待,直到一组在其它线程中的操作执行完成。
一个CountDownLatch会通过一个给定的count数来被初始化。其中await()方法会一直阻塞,直到当前的count被减到0,而这个过程是通过调用countDown()方法来实现的。在await()方法不再阻塞以后,所有等待的线程都会被释放,并且任何await()的子调用都会立刻返回。
使用zookeeper实现分布式共享锁,使用缓存实现countDownLatch

12. 请思考一个方案,设计一个可以控制缓存总体大小的自动适应的本地缓存

设计一个可以控制缓存总体大小的自动适应的本地缓存

13. 在你的职业生涯中,算得上最困难的技术挑战是什么

Spring系统底层的运行逻辑。
JVM的底层
系统的安全

14. 如何写一篇设计文档,目录是什么
  1. 引言
    1.1 编写目的
    1.2 背景
    1.3 定义
    1.4 参考资料
  2. 程序系统的结构
  3. 程序设计说明
    3.1 程序描述
    3.2 功能
    3.3 性能
    3.4 输入项
    3.5 输出项
    3.6 算法
15. 大写的O是什么?举几个例子

大写的O描述的是,就数据结构中的一系列元素而言,一个算法的性能。Collection类就是实际的数据结构,我们通常基于时间、内存和性能,使用大写的O来选择集合实现。比如:
例子1:ArrayList的get(index i)是一个常量时间操作,它不依赖list中元素的数量。所以它的性能是O(1)。
例子2:一个对于数组或列表的线性搜索的性能是O(n),因为我们需要遍历所有的元素来查找需要的元素。

16. 编程中自己都怎么考虑一些设计原则的,比如开闭原则,以及在工作中的应用

参考链接
对扩展开放、对修改关闭
策略模式、简单工厂、工厂方法、抽象工厂、建造者模式、桥梁模式、外观模式、中介模式、迭代模式

  1. 抽象约束
    第一,通过接口或者抽象类约束扩展,对扩展进行边界限定,不允许出现在接口或抽象类中不存在的public方法;
    第二,参数类型、引用对象尽量使用接口或者抽象类,而不是实现类;
    第三,抽象层尽量保持稳定,一旦确定即不允许修改。
  2. 元数据(metadata)控制模块行为
    元数据就是用来描述环境和数据的数据,通俗地说就是配置参数,参数可以从文件中获得,也可以从数据库中获得。
    Spring容器就是一个典型的元数据控制模块行为的例子,其中达到极致的就是控制反转(Inversion of Control)
  3. 制定项目章程
    在一个团队中,建立项目章程是非常重要的,因为章程中指定了所有人员都必须遵守的约定,对项目来说,约定优于配置。
  4. 封装变化
    对变化的封装包含两层含义:
    第一,将相同的变化封装到一个接口或者抽象类中;
    第二,将不同的变化封装到不同的接口或抽象类中,不应该有两个不同的变化出现在同一个接口或抽象类中。
17. 解释一下网络应用的模式及其特点

典型的网络应用模式大致有三类:B/S、C/S、P2P。其中B代表浏览器(Browser)、C代表客户端(Client)、S代表服务器(Server),P2P是对等模式,不区分客户端和服务器。

B/S应用模式中可以视为特殊的C/S应用模式,只是将C/S应用模式中的特殊的客户端换成了浏览器,因为几乎所有的系统上都有浏览器,那么只要打开浏览器就可以使用应用,没有安装、配置、升级客户端所带来的各种开销。

P2P应用模式中,成千上万台彼此连接的计算机都处于对等的地位,整个网络一般来说不依赖专用的集中服务器。网络中的每一台计算机既能充当网络服务的请求者,又对其它计算机的请求作出响应,提供资源和服务。
通常这些资源和服务包括:信息的共享和交换、计算资源(如CPU的共享)、存储共享(如缓存和磁盘空间的使用)等,这种应用模式最大的阻力是安全性、版本等问题。
目前有很多应用都混合使用了多种应用模型,最常见的网络视频应用,它几乎把三种模式都用上了。

补充:此题要跟"电子商务模式"区分开,因为有很多人被问到这个问题的时候马上想到的是B2B(如阿里巴巴)、B2C(如当当、亚马逊、京东)、C2C(如淘宝、拍拍)、C2B(如威客)、O2O(如美团、饿了么)。

18. 设计一个在线文档系统,文档可以被编辑,如何防止多人同时对同一份文档进行编辑更新

java实现在线文档编辑
剩下的就是锁的问题了。
https://www.jianshu.com/p/0163cda737ce

19. 说出数据连接池的工作机制是什么

参考链接

数据库连接池在初始化时将创建一定数量的数据库连接放到连接池中,这些数据库连接的数量是由最小数据库连接数来设定的。无论这些数据库连接是否被使用,连接池都将一直保证至少拥有这么多的连接数量。连接池的最大数据库连接数量限定了这个连接池能占有的最大连接数,当应用程序向连接池请求的连接数超过最大连接数量时,这些请求将被加入到等待队列中。

数据库连接池的最小连接数和最大连接数的设置要考虑到下列几个因素:

  1. 最小连接数是连接池一直保持的数据库连接,所以如果应用程序对数据库连接的使用量不大,将会有大量的数据库连接资源被浪费;
  2. 最大连接数是连接池能申请的最大连接数,如果数据库连接请求超过此数,后面的数据库连接请求将被加入到等待队列中,这会影响之后的数据库操作。
  3. 如果最小连接数与最大连接数相差太大,那么最先的连接请求将会获利,之后超过最小连接数量的连接请求等价于建立一个新的数据库连接。不过,这些大于最小连接数的数据库连接在使用完不会马上被释放,它将被放到连接池中等待重复使用或是空闲超时后被释放。
20. 怎么获取一个文件中单词出现的最高频率

Linux命令参考链接
使用linux命令或者shell实现:文件words存放英文单词,格式为每行一个英文单词(单词可以重复),统计这个文件中出现次数最多的前10个单词。
cat words.txt | sort | uniq -c | sort -k1,1nr | head -10

Java算法的思路是:

  1. 从头到尾遍历文件,从文件中读取遍历到的每一个单词。
  2. 把遍历到的单词放到hashmap中,并统计这个单词出现的次数。
  3. 获取最高频率算法:
    (1)遍历hashmap,将遍历到的单词的出现次数放到优先级队列中。当优先级队列的元素个数超过k个时就把元素级别最低的那个元素从队列中取出,这样始终保持队列的元素是k个。遍历完hashmap,则队列中就剩下了出现次数最多的那k个元素。
    (2)最简单的方法,冒泡或选择排序,求出最大的k个元素,时间复杂度在O(kn);
    (3)基于快排的选择排序,在随机化的情况下,时间复杂度在O(n);
    (4)局部淘汰法1,取前k个元素,建立一个数组,然后遍历所有元素,依次与数组中最小的元素比较,若大于,则替换。这种方法时间复杂度为O(kn);
    (5)局部淘汰法2,取前k个元素,维护一个小根堆,遍历所有元素,依次与堆顶元素进行比较,若大于,则替换并重新使其为小根堆,这种方法的时间复杂度为O(nlgk)
21. 描述一下你最常用的编程风格

最常用的编程风格

22. 如果有机会重新设计你们的产品,你会怎么做

略,平时可以多想想

23. 如何搭建一个高可用系统
  1. 主备/集群模式,防止单点
  2. 限流,削峰,防止后端压力过大
  3. 熔断机制,类似与限流
  4. 容灾机制,多机房/异地部署

减少单点 – 去单点首先要识别整个系统所有主链路的单点,如机房(同城异地双机房),应用服务器,DNS服务器,SFTP服务器,LBS,缓存服务器,数据库,消息服务器,代理服务器和专线等,如系统通过专线调用对方服务,需要考虑同时拉联通和电信的专线,联通或电信的专线还是有一定概率会出现问题的,但是同时出问题的概率会小非常多。优先使用软负载,使用硬负载兜底。

减少依赖 – 减少DNS依赖,减少远程服务依赖,DNS依赖可以尝试设置本地host,用工具给所有服务器推送最新的域名映射关系,通过本地缓存或近端服务减少RPC调用。

限制循环 – 避免无限死循环,导致CPU利用率百分百,可以设置for循环的最大循环次数,如最大循环1000次。

控制流量 – 避免异常流量对应用服务器产生影响,可以对指定服务设置流量限制,如QPS,TPS,QPH(每小时总请求量)和QPD(每天总请求量)。

精准监控 – 对CPU利用率,load,内存,带宽,系统调用量,应用错误量,PV,UV和业务量进行监控,避免内存泄露和异常代码对系统产生影响,配置监控一定要精准,如平时内存利用率是50%,监控可以配置成60%进行报警,这样可以提前感知内存泄露问题,避免应用无响应。

无状态 – 服务器不能保存用户状态数据,如在集群环境下不能用static变量保存用户数据,不能长时间把用户文件存放在服务器本地。服务器有状态会难以扩容,且出现单点问题。

容量规划 – 定期对容量进行评估。如大促前进行压测和容量预估,根据需要进行扩容。

功能开关 – 打开和关闭某些功能,比如消息量过大,系统处理不了,把开关打开后直接丢弃消息不处理。上线新功能增加开关,如果有问题关闭新功能。

设置超时 – 设置连接超时和读超时设置,不应该太大,如果是内部调用连接超时可以设置成1秒,读超时3秒,外部系统调用连接超时可以设置成3秒,读超时设置成20秒。

重试策略 – 当调用外部服务异常时可以设置重试策略,每次重试时间递增,但是需要设置最大重试次数和重试开关,避免对下游系统产生影响。

隔离 – 应用隔离,模块隔离,机房隔离和线程池隔离。可以按照优先级,不变和变几个维度来隔离应用和模块,如抽象和不变的代码放在一个模块,这个模块的代码几乎不会修改,可用性高,经常变的业务逻辑放在一个模块里,这样就算有问题,也只会影响到某一个业务。不同的业务使用不同的线程池,避免低优先级任务阻塞高优先级,或高优先级任务过多时影响低优先级任务永远不会执行。

异步调用 – 同步调用改成异步调用,解决远程调用故障或调用超时对系统的影响。

热点缓存 – 对热点数据进行缓存,降低RPC调用。如B系统提供名单服务,B系统可以提供一个client SDK提供近端缓存服务,定期去服务器端取数据,减少RPC调用。

缓存容灾 – 当数据库不可用时可以使用缓存的数据。并设置分级缓存,如优先读本地缓存,其次读分布式缓存。

分级缓存 – 优先读本地缓存,其次读分布式缓存。通过推模式更新本地缓存。

系统分级 – 对系统进行分级,如ABC三个等级,高级别系统不依赖于低级别系统,并且高级别系统比底级别系统高可用率要高。

服务降级 – 如果系统出现响应缓慢等状况,可以关闭部分功能,从而释放系统资源,保证核心服务的正常运行。需要识别哪些服务可以降级,比如突然有大量消息流入,导致服务不可用,我们会把消息直接丢弃掉。或通过设置流控,拒绝为低级别系统提供服务。

流量蓄洪 – 当流量陡增时,可以将请求进行蓄洪,如把请求保存在数据库中,再按照指定的QPS进行泄洪,有效的保护下游系统,也保证了服务的可用性。当调用对方系统,对方系统响应缓慢或无响应时,可采取自动蓄洪。

服务权重 – 在集群环境中,可自动识别高性能服务,拒绝调用性能低的服务。如在集群环境中,对调用超时的服务器进行权重降低,优先调用权重高的服务器。

依赖简化 – 减少系统之间的依赖,比如使用消息驱动,A和B系统通过消息服务器传递数据,A和B系统使用数据库进行读写分离,A系统负责往数据库中写数据,B系统负责读数据,因为数据存放在数据库中,当A不可用时,短时间内不影响B系统提供服务。

弹性扩容 – 根据资源的使用率自动或手动进行扩容。如带宽不够用时,快速增加带宽。

灰度和回滚 – 发布新功能只让部分服务器生效,且观察几天逐渐切流,如果出现问题只影响部分客户。出现问题快速回滚,或者直接下线灰度的机器。

减少远程调用 – 优先调用本地JVM内服务,其次是同机房服务,然后是同城服务,最后是跨城服务。如A调用B,B调用互联网的C系统获取数据,B系统可以把数据缓存起来,并设置数据的保鲜度,减少B对C的依赖。配置中心把注册服务的地址推送到调用服务的系统本地。参数中心把参数配置信息推送到系统的本地内存,而不是让系统去远程服务器获取参数信息。

熔断机制 – 增加熔断机制,当监控出线上数据出现大幅跌涨时,及时中断,避免对业务产生更大影响。如我们做指标计算时,指标可以计算慢,但是不能算错,如果发现某个用户的指标环比或同比增长一倍或跌零,会考虑保存所有消息,并中止该用户的指标计算。

运行时加载模块 – 我们会把经常变的业务代码变成一个个业务模块,使用Java的ClassLoader在运行时动态加载和卸载模块,当某个模块有问题时候,可以快速修复。

代码扫描 – 使用IDEA代码分析等工具进行代码扫描,识别出程序中的BUG,如空指针异常,循环依赖等。

自动备份 – 程序,系统配置和数据定期进行备份。可使用linux命令和shell脚本定时执行备份策略,自动进行本地或异地。出现问题时能快速重新部署。

线上压测 – 系统的对外服务需要进行压测,知道该服务能承受的QPS和TPS,从而做出相对准确的限流。

24. 如何启动时不需输入用户名与密码

(weblogic)修改服务启动文件,增加 WLS_USER和WLS_PW项。也可以在boot.properties文件中增加加密过的用户名和密码.

25. 如何在基于Java的Web项目中实现文件上传和下载

在Sevlet3以前,Servlet API中没有支持上传功能的API,因此要实现上传功能需要引入第三方工具从POST请求中获得上传的附件或者通过自行处理输入流来获得上传的文件,我们推荐使用Apache的commons-fileupload。
Sevlet3之后增加了Multipart支持可以直接实现文件的上传和下载

26. 如何实现一个秒杀系统,保证只有几位用户能买到某件商品。

设计这个系统是一个考虑全面的问题,可以发散出很多问题,考察很多方面,不是仅仅回答通过redis的自减操作完成

比如简单的方案:

  1. 页面开启倒计时,要保证不能把下单接口暴露过早暴露出来,防止机器刷下单接口
  2. 前端限流,比如nginx对下单接口限流,命中限流则返回302到秒杀页
  3. 后端单独部署,独立域名和nginx,与线上正常运行的系统隔离开来,避免影响到线上环境
  4. 由于生成订单操作比较耗时,采用队列的方式来解耦下单成功和生成订单,针对进入后端的请求,采用redis自减,针对自减结果>0的请求则认为下单成功,触发一个生成订单的消息,然后立即返回给用户结果
  5. 用户方面,针对秒杀成功有两种处理方式
    a. 用户端收到秒杀成功的结果,则开启提示页面,并进入倒计时,倒计时时间为订单生成的预估时间
    b. 秒杀成功后,给当前用户在redis中生成一个订单生成状态的标识,用户端开启提示页面,loading,并轮询后端订单生成状态,生成成功之后让前端跳转到订单页面
  6. 订单服务订阅下单系统发送的消息,并开始生成订单,生成订单成功之后更新redis中用户秒杀订单的状态为已生成订单

系统应该有页面和接口,页面用于展示用户界面,接口用于获取数据
界面:秒杀页面,秒杀成功页面,秒杀失败页面,命中限流页面(查看订单页面不算秒杀系统的功能)
接口:秒杀下单接口,秒杀成功获取订单生成状态接口

https://www.jianshu.com/p/37209226d04d

27. 如何实现负载均衡,有哪些算法可以实现
  1. 轮询法
    将请求按顺序轮流地分配到后端服务器上,它均衡地对待后端的每一台服务器,而不关心服务器实际的连接数和当前的系统负载。
  2. 随机法
    通过系统的随机算法,根据后端服务器的列表大小值来随机选取其中的一台服务器进行访问。由概率统计理论可以得知,随着客户端调用服务端的次数增多,其实际效果越来越接近于平均分配调用量到后端的每一台服务器,也就是轮询的结果。
  3. 源地址哈希法
    源地址哈希的思想是根据获取客户端的IP地址,通过哈希函数计算得到的一个数值,用该数值对服务器列表的大小进行取模运算,得到的结果便是客服端要访问服务器的序号。采用源地址哈希法进行负载均衡,同一IP地址的客户端,当后端服务器列表不变时,它每次都会映射到同一台后端服务器进行访问。
  4. 加权轮询法
    不同的后端服务器可能机器的配置和当前系统的负载并不相同,因此它们的抗压能力也不相同。给配置高、负载低的机器配置更高的权重,让其处理更多的请;而配置低、负载高的机器,给其分配较低的权重,降低其系统负载,加权轮询能很好地处理这一问题,并将请求顺序且按照权重分配到后端。
  5. 加权随机法
    与加权轮询法一样,加权随机法也根据后端机器的配置,系统的负载分配不同的权重。不同的是,它是按照权重随机请求后端服务器,而非顺序。
  6. 最小连接数法
    最小连接数算法比较灵活和智能,由于后端服务器的配置不尽相同,对于请求的处理有快有慢,它是根据后端服务器当前的连接情况,动态地选取其中当前积压连接数最少的一台服务器来处理当前的请求,尽可能地提高后端服务的利用效率,将负责合理地分流到每一台服务器。
28.如何设计一个购物车?想想淘宝的购物车如何实现的

电子商务网站购物车设计

购物车流程设计:

  1. 淘宝:
    购物车操作规则:未登录无法加入购物车并且无法进入购物车页面,登陆后添加到购物车的商品在退出登录又重新登录之后还存在,
    购物车操作属于纯接口操作。
    流程:列表–详情–加入购物车–选择–结算–确认订单–提交订单弹出支付宝付款界面
  2. 京东:
    购物车操作规则:分为手机购物车和服务端购物车:
    未登录状态下添加到购物车的商品,可以在购物页面显示,在登陆之后会同步到服务端,同步成功之后就会清空本地购物车数据
    流程:列表–详情–加入购物车–选择–去结算–填写订单–提交订单弹出支付页面–不付款选择离开支付页面进入订单列表页面

购买流程设计:

  1. 淘宝:
    列表–详情–立即购买–确认订单–提交订单弹出支付宝付款界面–不付款就进入订单详情(详情页有付款按钮,此订单目前为待付款状态)
    –付款成功进入到支付成功页面–查看订单–订单详情页面
    (购买可以走“立即购买”也可以走“加入购物车”,生成订单的商品就从购物车中自动删除)
  2. 京东:
    列表–详情–加入购物车–购物车–去结算–填写订单–提交订单弹出支付页面–付款成功进入到微信支付成功页面–返回京东到订单支付成功页面–查看订单–订单列表页
    (只有“购物车”一种购买流程,不可以直接购买)

总结:简单点就用纯接口不做本地保存,复杂点就没登录时候存本地,登陆之后做同步并且清空本地数据

29. 如何设计一套高并发支付方案,架构如何设计

参考链接

库分表:以uid为键,使用中间件进行分库分表
订单ID:时间戳+机器号+自增序列,推荐Twitter的Snowflake,可以把分库分表信息放在订单前
数据异构:按业务bid异构数据
读写分离、数据分离,缓存等
其余可参考26
(1) 客户端层:调用方是浏览器或者手机APP
(2) 反向代理层:系统入口,反向代理
(3) 站点应用层:实现核心应用逻辑,返回html或者json
(4) 服务层:如果实现了服务化
(5) 数据-缓存层:缓存加速访问存储
(6) 数据-数据库层:数据库固化数据存储

Java相关的经典问题及解答_第1张图片
image.png
30. 如何设计建立和保持 100w 的长连接

可以使用Netty NIO框架,但需要扩大JVM内存,估计20G以上,JVM内存高了full GC时间会长可能会达到几秒,需要优化GC算法,
可以使用代理服务器来分散连接
负载均衡 +反向代理。

31.如何避免浏览器缓存
  1. Cache-Control/Pragma
    这个HTTP Head字段用于指定所有缓存机制在整个请求/响应链中必须服从的指令,如果知道该页面是否为缓存,不仅可以控制浏览器,还可以控制和HTTP协议相关的缓存或代理服务器。
    Cache-Control请求字段被各个浏览器支持得较好,而且它的优先级也比较高,它和其他一些请求字段(如Expires)同时出现时,Cache-Control会覆盖其他字段。Pragma字段的作用和Cache-Control有点类似,它也是在HTTP头中包含一个特殊的指令,使相关的服务器来遵守,最常用的就是Pragma:no-cache,它和Cache-Control:no-cache的作用是一样的。
  2. Expires
    Expires通常的使用格式是Expires:Sat,25Feb201212:22:17GMT,后面跟着一个日期和时间,超过这个时间值后,缓存的内容将失效,也就是浏览器在发出请求之前检查这个页面的这个字段,看该页面是否已经过期了,过期了就重新向服务器发起请求。
  3. Last-Modified/EtagLast-Modified字段
    一般用于表示一个服务器上的资源的最后修改时间,资源可以是静态(静态内容自动加上Last-Modified字段)或者动态的内容(如Servlet提供了一个getLastModified方法用于检查某个动态内容是否已经更新),通过这个最后修改时间可以判断当前请求的资源是否是最新的。一般服务端在响应头中返回一个Last-Modified字段,告诉浏览器这个页面的最后修改时间,如Last-Modified:Sat,25Feb201212:55:04GMT,浏览器再次请求时在请求头中增加一个If-Modified-Since:Sat,25Feb 201212:55:04GMT字段,询问当前缓存的页面是否是最新的,如果是最新的就返回304状态码,告诉浏览器是最新的,服务器也不会传输新的数据。
  4. Etag字段
    这个字段的作用是让服务端给每个页面分配一个唯一的编号,然后通过这个编号来区分当前这个页面是否是最新的。这种方式比使用Last-Modified更加灵活,但是在后端的Web服务器有多台时比较难处理,因为每个Web服务器都要记住网站的所有资源,否则浏览器返回这个编号就没有意义了。
32.如何防止缓存雪崩

缓存雪崩是指在我们设置缓存时采用了相同的过期时间,导致缓存在某一时刻同时失效,请求全部转发到DB,DB瞬时压力过重雪崩。
缓存失效时的雪崩效应对底层系统的冲击非常可怕。大多数系统设计者考虑用加锁或者队列的方式保证缓存的单线 程(进程)写,从而避免失效时大量的并发请求落到底层存储系统上。这里分享一个简单方案就时讲缓存失效时间分散开,比如我们可以在原有的失效时间基础上增加一个随机值,比如1-5分钟随机,这样每一个缓存的过期时间的重复率就会降低,就很难引发集体失效的事件。

33.如果AB两个系统互相依赖,如何解除依赖

A > B,同时B > A 解除这种双向依赖的话,需要在AB之外增加一个C,用C封装A依赖的B的那部分功能,让A改为依赖C,C依赖B 然后就是这样 A >C,C >B,B >A 不过这样依然存在环路依赖

34.如果有人恶意创建非法连接,怎么解决

参考百度DDos说明

DDos攻击:
分布式拒绝服务(DDoS:Distributed Denial of Service)攻击指借助于客户/服务器技术,将多个计算机联合起来作为攻击平台,对一个或多个目标发动DDoS攻击,从而成倍地提高拒绝服务攻击的威力。通常,攻击者使用一个偷窃帐号将DDoS主控程序安装在一个计算机上,在一个设定的时间主控程序将与大量代理程序通讯,代理程序已经被安装在网络上的许多计算机上。代理程序收到指令时就发动攻击。利用客户/服务器技术,主控程序能在几秒钟内激活成百上千次代理程序的运行。

这种攻击方式可分为以下几种:

  1. 通过使网络过载来干扰甚至阻断正常的网络通讯;
  2. 通过向服务器提交大量请求,使服务器超负荷;
  3. 阻断某一用户访问服务器;
  4. 阻断某服务与特定系统或个人的通讯。

防范:
主机设置
所有的主机平台都有抵御DoS的设置,总结一下,基本的有几种:

  1. 关闭不必要的服务
  2. 限制同时打开的Syn半连接数目
  3. 缩短Syn半连接的time out 时间
  4. 及时更新系统补丁
    网络设置
    网络设备可以从防火墙与路由器上考虑。这两个设备是到外界的接口设备,在进行防DDoS设置的同时,要注意一下这是以多大的效率牺牲为代价的,对你来说是否值得。
  5. 防火墙
    禁止对主机的非开放服务的访问 限制同时打开的SYN最大连接数 限制特定IP地址的访问 启用防火墙的防DDoS的属性 严格限制对外开放的服务器的向外访问 第五项主要是防止自己的服务器被当做工具去害人。
  6. 路由器
    设置SYN数据包流量速率 升级版本过低的ISO 为路由器建立log server
35.如果有几十亿的白名单,每天白天需要高并发查询,晚上需要更新一次,如何设计这个功能

负载均衡,缓存(结合本地缓存和集中式缓存),分库分表,更新数据也按表分,然后再单表乐观锁更新。

36.如果系统要使用超大整数(超过long长度范围),请你设计一个数据结构来存储这种超大型数字以及设计一种算法来实现超大整数加法运算)

参考链接

37.如果要设计一个图形系统,请你设计基本的图形元件(Point,Line,Rectangle,Triangle)的简单实现

Java图形这块略。

38.如果让你实现一个并发安全的链表,你会怎么做

参考链接
这里使用mutex互斥锁实现

39.应用服务器与WEB 服务器的区别?应用服务器怎么监控性能,各种方式的区别?你使用过的应用服务器优化技术有哪些

Apache、Tomcat、JBOSS、Jetty、Nginx

区别

  1. Apache是Web服务器,Tomcat是应用(Java)服务器。
    Tomcat在中小型系统和并发访问用户不是很多的场合下被普遍使用。
    Apache支持静态页,Tomcat支持动态的。
  2. Jetty是由Tomcat内核作为其Servlet容器引擎,并加以审核和调优. 大中型系统可以应用。能够提供数据库连接池服务, 还支持其他Web技术的集成,譬如PHP、.NET两大阵营。
    3, JBoss是一个管理EJB的容器和服务器,但JBoss核心服务不包括支持servlet/JSP的WEB容器,一般与Tomcat或Jetty绑定使用。
  3. Nginx是目前性能最高的HTTP服务器。其特点是占有内存少,并发能力强。Nginx代码完全用C语言从头写成。
    所以:Apache—Nginx;Tomcat—Jetty;JBoss。这三组可以组合了。

性能监控 参考链接

  1. 核心基础设施监控(Core Infrastructure Monitoring,CIM)
  2. 应用级别监控(Application Level Monitoring,ALM)
  3. 微服务监控(Micro Service Monitoring,MSM)
  4. 多租户日志监控(Multitenant Log Monitoring,MLM)

应用服务器性能优化总结 参考链接
分布式缓存、异步操作、使用集群、代码优化(多线程、资源复用、数据结构、数据异构)

40. 大型网站在架构上应当考虑哪些问题

参考链接

  1. 海量数据的处理
  2. 数据并发的处理
  3. 文件存贮的问题
  4. 数据关系的处理
  5. 数据索引的问题
  6. 分布式处理
  7. Ajax的利弊分析
  8. 数据安全性的分析
  9. 数据同步和集群的处理的问题
  10. 数据共享的渠道以及OPENAPI趋势
41. 有没有处理过线上问题?出现内存泄露,CPU利用率标高,应用无响应时如何处理的

有很多,比如:
数据库响应慢,通过服务器查看,有些进程令CPU特别高,有些sql太复杂,子查询太多,导致数据库性能变慢。
应用服务器因为对exception的处理没有到位,导致linux服务器的file open too many错误。
有些单例的模式没有写健壮,导致程序逻辑出错。

42. 最近看什么书,印象最深刻的是什么

看个人了

43. 描述下常用的重构技巧

参考链接

No.1:重复代码的提炼
No.2:冗长方法的分割
No.3:嵌套条件分支的优化(1)
No.4:嵌套条件分支的优化(2)
No.5:去掉一次性的临时变量
No.6:消除过长参数列表
No.7:提取类或继承体系中的常量
No.8:让类提供应该提供的方法
No.9:拆分冗长的类
No.10:提取继承体系中重复的属性与方法到父类

44. 你使用什么版本管理工具?分支(Branch)与标签(Tag)之间的区别在哪里

从svn命令操作的角度,branches和tags是一样的,都是分支标记功能,两者的区别主要在于默认的使用用途。

一般来说:

  1. branches下用于存放“分支”,比如用于测试的分支、用于不同版本开发的分支、用于缺陷处理的分支等等,“分支”下存放的内容是会继续修改的;
  2. tags下用于存放“标记”,比如某个发布版本的标记,“标记”下存放的内容通常来说是固定不变的。

比如:开发进行到1.0版本测试完成,要进行对外软件发布了,同时项目组后续会拆分成两个小组,一个小组负责1.0版本的BUG维护,另一个小组开始在1.0基础上进行2.0版本的开发。此时,就可以把当前版本从trunk拉到tags下一份,标记为release1_0,然后对外发布时就从这个文件夹获取;然后再把当前版本拉到branches下一份,标记为bugfix1_0,负责1.0版维护的小组以后就在这个文件夹下进行修复工作,负责2.0版开发的小组继续在trunk下工作。
从配置管理的角度来看,打基线就是把库中的某些内容打个标记,就是拖到tags文件夹下。

45. 你有了解过存在哪些反模式(Anti-Patterns)吗

反模式(英文:Anti-patterns或pitfalls), 是指用来解决问题的带有共同性的不良方法。它们已经经过研究并分类,以防止日后重蹈覆辙,并能在研发尚未投产的系统时辨认出来。

软件膨胀:随着版本的升级,软件越来越消耗系统资源。
反抽象:需要的功能并不暴露给用户,导致用户要在较高层次重新实现一些功能。
万能类︰在一个类的设计中,聚集了太多的函数。
硬编码(Hard Code):或称写死。在实现某系统用途上设死该系统的运作环境。
超布尔逻辑︰不必要的比较,或是过于抽象的布尔计算。
剪贴编程(Copy-n-paste programming):宁愿拷贝(并修改)现存代码而非创造通用的解决方案。
掩耳盗铃: 假设一个已知的bug不会出现。
DLL地狱:由于动态连接库的版本、存在与否、和重复所造成的种种问题,特别是在Microsoft Windows。

每个程序员要注意的 9 种反模式: 参考链接

  1. 过早优化
  2. 单车车库
  3. 分析瘫痪
  4. 上帝类
  5. 新增类恐惧症
  6. 内部平台效应
  7. 魔法数和字符串
  8. 数字管理
  9. 无用的(幽灵)类
46. 你用过的网站前端优化的技术有哪些

网站前端性能优化常用几种方式

47. 如何分析Thread dump

dump 文件里,值得关注的线程状态有:
死锁,Deadlock(重点关注)
执行中,Runnable
等待资源,Waiting on condition(重点关注)
等待获取监视器,Waiting on monitor entry(重点关注)
暂停,Suspended
对象等待中,Object.wait() 或 TIMED_WAITING
阻塞,Blocked(重点关注)
停止,Parked

参考:
性能分析之-- JAVA Thread Dump 分析综述
三个实例演示 Java Thread Dump 日志分析

48.你如何理解AOP中的连接点(Joinpoint)、切点(Pointcut)、增强(Advice)、引介(Introduction)、织入(Weaving)、切面(Aspect)这些概念
  1. 连接点(Joinpoint):程序执行的某个特定位置(如:某个方法调用前、调用后,方法抛出异常后)。一个类或一段程序代码拥有一些具有边界性质的特定点,这些代码中的特定点就是连接点。Spring仅支持方法的连接点。
  2. 切点(Pointcut):如果连接点相当于数据中的记录,那么切点相当于查询条件,一个切点可以匹配多个连接点。Spring AOP的规则解析引擎负责解析切点所设定的查询条件,找到对应的连接点。
  3. 增强(Advice):增强是织入到目标类连接点上的一段程序代码。Spring提供的增强接口都是带方位名的,如:BeforeAdvice、AfterReturningAdvice、ThrowsAdvice等。很多资料上将增强译为“通知”,这明显是个词不达意的翻译,让很多程序员困惑了许久。
    说明: Advice在国内的很多书面资料中都被翻译成"通知",但是很显然这个翻译无法表达其本质,有少量的读物上将这个词翻译为"增强",这个翻译是对Advice较为准确的诠释,我们通过AOP将横切关注功能加到原有的业务逻辑上,这就是对原有业务逻辑的一种增强,这种增强可以是前置增强、后置增强、返回后增强、抛异常时增强和包围型增强。
  4. 引介(Introduction):引介是一种特殊的增强,它为类添加一些属性和方法。这样,即使一个业务类原本没有实现某个接口,通过引介功能,可以动态的未该业务类添加接口的实现逻辑,让业务类成为这个接口的实现类。
  5. 织入(Weaving):织入是将增强添加到目标类具体连接点上的过程,AOP有三种织入方式:①编译期织入:需要特殊的Java编译期(例如AspectJ的ajc);②装载期织入:要求使用特殊的类加载器,在装载类的时候对类进行增强;③运行时织入:在运行时为目标类生成代理实现增强。Spring采用了动态代理的方式实现了运行时织入,而AspectJ采用了编译期织入和装载期织入的方式。
  6. 切面(Aspect):切面是由切点和增强(引介)组成的,它包括了对横切关注功能的定义,也包括了对连接点的定义。
49.你是如何处理内存泄露或者栈溢出问题的

内存溢出是由于没被引用的对象(垃圾)过多造成JVM没有及时回收,造成的内存溢出。如果出现这种现象可行代码排查:

  1. 是否App中的类中和引用变量过多使用了static修饰 如public static Student s;在类中的属性中使用 static修饰的最好只用基本类型或字符串。如public static int i = 0; //public static String str;
  2. 是否App中使用了大量的递归或无限递归(递归中用到了大量的建新的对象)
  3. 是否App中使用了大量循环或死循环(循环中用到了大量的新建的对象)
  4. 检查App中是否使用了向数据库查询所有记录的方法。即一次性全部查询的方法,如果数据量超过10万多条了,就可能会造成内存溢出。所以在查询时应采用“分页查询”。
  5. 检查是否有数组,List,Map中存放的是对象的引用而不是对象,因为这些引用会让对应的对象不能被释放。会大量存储在内存中。
  6. 检查是否使用了“非字面量字符串进行+”的操作。因为String类的内容是不可变的,每次运行"+"就会产生新的对象,如果过多会造成新String对象过多,从而导致JVM没有及时回收而出现内存溢出。

栈溢出的原因

  1. 是否有递归调用
  2. 是否有大量循环或死循环
  3. 全局变量是否过多
  4. 数组、List、map数据是否过大
  5. 使用DDMS工具进行查找大概出现栈溢出的位置
50.你们线上应用的 JVM 参数有哪些

-Xmx4g
设置JVM最大可用内存为4g。

-Xms4g
设置JVM初始内存为4g。此值可以设置与-Xmx相同,以避免每次垃圾回收完成后JVM重新分配内存。

-XX:NewRatio=2
设置年轻代(包括Eden和两个Survivor区)与年老代的比值(除去持久代)。设置为2,则年轻代与年老代所占比值为1:2,年轻代占整个堆栈的1/3

-XX:SurvivorRatio=4
年轻代中Eden区与两个Survivor区的比值。注意Survivor区有两个。如:4,表示Eden:Survivor=4:2,一个Survivor区占整个年轻代的1/6

-XX:PermSize=256m
设置持久代大小为256m

-XX:MaxPermSize=512m
设置持久代最大为512m

-Xss256k
设置每个线程的堆栈大小。JDK5.0以后每个线程堆栈大小为1M,以前每个线程堆栈大小为256K。更具应用的线程所需内存大小进行调整。在相同物理内存下,减小这个值能生成更多的线程。但是操作系统对一个进程内的线程数还是有限制的,不能无限生成,经验值在3000~5000左右。

-XX:+DisableExplicitGC
关闭System.gc()

-XX:+UseParNewGC
设置年轻代为并行收集,可与CMS收集同时使用,JDK5.0以上,JVM会根据系统配置自行设置,所以无需再设置此值

-XX:ParallelGCThreads=4
并行收集器的线程数,此值最好配置与处理器数目相等 同样适用于CMS

-XX:+UseConcMarkSweepGC
使用CMS内存收集

-XX:+UseCMSCompactAtFullCollection
在FULL GC的时候,对年老代的压缩,CMS是不会移动内存的,因此非常容易产生碎片,导致内存不够用,因此内存的压缩这个时候就会被启用。增加这个参数是个好习惯。可能会影响性能,但是可以消除碎片

-XX:+CMSParallelRemarkEnabled
降低标记停顿

-XX:MaxTenuringThreshold=3
垃圾最大年龄,即对象在Survivor区存在的年龄为3(复制一次年龄+1),如果设置为0的话,则年轻代对象不经过Survivor区,直接进入年老代. 对于年老代比较多的应用,可以提高效率.如果将此值设置为一个较大值,则年轻代对象会在Survivor区进行多次复制,这样可以增加对象再年轻代的存活 时间,增加在年轻代即被回收的概率该参数只有在串行GC时才有效.

-XX:+CMSParallelRemarkEnabled
降低标记停顿(线上配置重复了)

-XX:CMSInitiatingOccupancyFraction=70
使用cms作为垃圾回收,使用70%后开始CMS收集,为了保证不出现promotion failed(见下面介绍)错误,该值的设置需要满足以下公式CMSInitiatingOccupancyFraction计算公式
CMSInitiatingOccupancyFraction值与Xmn的关系公式:
上面介绍了promontion faild产生的原因是EDEN空间不足的情况下将EDEN与From survivor中的存活对象存入To survivor区时,To survivor区的空间不足,再次晋升到old gen区,而old gen区内存也不够的情况下产生了promontion faild从而导致full gc.那可以推断出:eden+from survivor < old gen区剩余内存时,不会出现promontion faild的情况,即:
(Xmx-Xmn)(1-CMSInitiatingOccupancyFraction/100)>=(Xmn-Xmn/(SurvivorRatior+2))
进而推断出:
CMSInitiatingOccupancyFraction <=((Xmx-Xmn)-(Xmn-Xmn/(SurvivorRatior+2)))/(Xmx-Xmn)
100
例如:
当xmx=128 xmn=36 SurvivorRatior=1时 CMSInitiatingOccupancyFraction<=((128.0-36)-(36-36/(1+2)))/(128-36)100 =73.913
当xmx=128 xmn=24 SurvivorRatior=1时 CMSInitiatingOccupancyFraction<=((128.0-24)-(24-24/(1+2)))/(128-24)
100=84.615…
当xmx=3000 xmn=600 SurvivorRatior=1时 CMSInitiatingOccupancyFraction<=((3000.0-600)-(600-600/(1+2)))/(3000-600)*100=83.33
CMSInitiatingOccupancyFraction低于70% 需要调整xmn或SurvivorRatior值。

-XX:CMSFullGCsBeforeCompaction=0
多少次后进行内存压缩,由于并发收集器不对内存空间进行压缩,整理,所以运行一段时间以后会产生"碎片",使得运行效率降低.此值设置运行多少次GC以后对内存空间进行压缩,整理.

-XX:+UseFastAccessorMethods
原始类型的快速优化

-XX:+UseBiasedLocking
锁机制的性能改善

-Dcom.sun.management.jmxremote
使用jvisualvm通过JMX的方式远程监控JVM的运行情况,还要求再配置ssl、port、authenticate等参数,单独配置这个可能没有,或者可以使用默认配置,需要确认???

-Djava.awt.headless=true
有时我们会在我们的J2EE工程中使用一些图表工具如:jfreechart,用于在web网页输出GIF/JPG等流,在winodws环境下,一般我们的app server在输出图形时不会碰到什么问题,但是在linux/unix环境下经常会碰到一个exception导致你在winodws开发环境下图片显 示的好好可是在linux/unix下却显示不出来,因此加上这个参数以免避这样的情况出现.

调试参数:

-verbose:gc
表示输出虚拟机中GC的详细情况

-XX:+PrintGC
加上参数可以在输出日志中可以查看垃圾回收前后堆的大小, 即打印gc日志

-XX:+PrintGCDetails
打印gc日志的更加详细的信息

-XX:+PrintGCDateStamps
(-XX:+PrintGCDateStamps或者-XX:+PrintGCTimeStamps),输出GC发生时,gc发生的时间

-XX:+PrintAdaptiveSizePolicy
打印自适应收集的大小。默认关闭。

-XX:+PrintHeapAtGC
打印GC前后的详细堆栈信息

-XX:+PrintTenuringDistribution
查看每次minor GC后新的存活周期的阈值

-Xloggc:/***/gc.log
把相关日志信息记录到文件以便分析(gc.log)

-XX:ErrorFile=/**/hs_err_pid.log
生成error 文件的路径(hs_err_pid.log)

-XX:HeapDumpPath=/**/java.hprof
指定HeapDump的文件路径或目录(java.hprof)

配置地址:
-Dconfig.home=/**/config

config配置文件路径
-Dlogback.configurationFile=/**/logback.xml
logback配置文件logback.xml文件位置

51. 怎么提升系统的QPS和吞吐量

集群+负载均衡、增加缓存、系统拆分、分库分表、垂直拆分+水平拆分、异步化+MQ。等等技术手段。

原文链接:https://blog.csdn.net/u013898617/java/article/details/78824077

你可能感兴趣的:(Java相关的经典问题及解答)