1. 高并发
说一说高并发是怎么解决的,与多线程有什么关系?
高并发就是多个线程同时运行
用分布式,比如说Nginx负载均衡,实现session共享
Nginx负载均衡,也叫反向代理服务器,相当于多台服务器,每个服务器上面布的应用一样多,而我们的数据库访问的是同一个数据库,一定不是多个数据库,否则会有差异,这就是我们的负载均衡
它请求过来根据我们的权重,比如说ip,把请求给请求最少的服务器,它就是我们写的应用,然后它返回db,然后轮回
比如说张三来请求,第一次请求登录到A服务器上,然后访问然后返回,第二次访问,如果张三不小心请求到B服务器,会娶不到值,需要重新登录,所以我们就需要一个存放session的东西,所以用到负载均衡一定会用到session共享;不需要登录的时候就不需要session共享,
高并发时Tomcat最多承压多少?
400就算死了,达不到500,保险起见一般配300个
并发就是同时访问
测并发用的是压力测试(通过一个软件进行模拟同时多线程请求)
如何实现session共享?
(1)自己实现一个filter (不推荐)
来拦截请求,根据拿到的请求去缓存里拿,如果有就表示登录成功,没有就是登录失败
(2)Tomcat自身的sessionManager自己继承这个接口,tomcat本身对session是有管理的
需要重新写一个类来实现这个接口,然后作为一个插件让tomcat使用,
(3)Httpsession spring 对他做的整合,redis作为缓存,只需要配置三行(包括注解),不需要代码
它也是基于filter插件,用户过来拦截请求,从缓存里去拿,拿到之后再返回
什么时候获取session?
Request.getsession会创建一个session,
什么时候返回一个新的session,什么时候返回已有的session?
这是servlet中的内容,session是一个会话,只有Request.getsession会获取一个session,这样的session一定会返回一个session,这个获取的session一定会返回一个session;
如果tomcat已经存在一个session,那么会返回已经存在的session,如果不存在,则会创建一个新的session,Session里面有一个方法,这个方法接收一个参数布尔型,不写的话默认是一个true,如果是true,没有session也会创建一个session,如果是false,没有session会返回一个null;
如果一个用户过来访问,却没有登录,这时会创建一个新的session,它根据sessionid(就是cookie)来判断有没有session,session(cookie禁用session就失效)是基于cookie(就是key,value,请求器给一个,返回还可以带着)的
如果使用的是默认的方式,请求的时候cookie的值是sessionid,根据sessionid去找session对象,如果找到就是之前存在,如果不在,返回一个新的session,这个sessionid作为cookie的值,所以说用session一般要用cookie开启,如果cookie没有开启,session无法访问,所以session与前端没关系,与前端相关的是cookie,如果浏览器基于cookie,叫做URL重写,意思是请求的时候把sessionid作为URL的一部分传过去,再次请求的时候,同样也带着这个东西;
所以如果让我们写filter的时候,首先去请求,然后请求的时候filter去拦截,request.getsessionid 这个时候默认根据的是cookieid其实就是sessionid去请求,只需要关注的是request.getsession自己会根据cookie的id去找,不管是通过cookie的方式,还是URL重写的方式,这个方法都可以得到,但是不同的是,http://localhost/test;条件。如果URL重写的话,一定是路径下面一个分号,分号下面是sessionid=1,如果写问号的话,tomcat不识别,他会认为这是你的key value传的一个值,不会认为是session;#号是忽略,不往后台提交,所以angular js就是用这个特性做的路由
写一个filter,然后去请求,再用filter去拦截,通过request.getsession获取session,然后session.getid获取到sessionid,然后sessionid作为key放到redis里面去查对象,如果查得出来说明对象存在,否则对象不存在,这时候会创建一个新的session,request.getsession总是会获取到一个session,这时候拿到sessionid,在拿到对象,在持久化一下,再存到redis里面
如果是登陆的话,首先用户请求过来,要获取session,拿到session之后,要从session上获取当前对象存不存在,如果存在就是有效登录,如果不存在,跳转到登录页,这个是与身份认证有关的
Java中有哪些session?
Session指的是一个会话,
不同于hibernate中的session,
容器中的session
httpsession,
数据库里的session
Sqlsession
2.高可用
用的是分布式
用的是负载均衡
微信,能不间断的提供服务
做高可用,首先前端要做负载均衡,要有多台服务器,一台坏掉以后其他可以顶上;后台数据库要做集群,用的是mysql和redis,因为数据库也有可能当掉,redis我们做的是集群加分布式(集群加replication主从复制)。我们公司没有用过mysql的主从复制,我们以前公司是oracle用过,后来用的sqlserver,但是有个特点,sqlserver不支持Linux,因为sqlserver是微软旗下的
最终我们的数据库是要和web应用服务器分开部署的,因为要保证性能,因为数据库负责查询,一般情况下web是用来跑java程序的;所以说数据库也需要做集群。
New 3个user对象,有一个方法是synchronize修饰的,比如说现在有多个线程访问,给了一个set方法,给了一个synchronize修饰,一个线程访问这个,另一个线程访问另一个对象,三个线程分别访问3个对象,这3个对象里的set get方法都是通过synchronize修饰的,它的值会不会发生线程安全问题?
不会。一个对象一个锁,锁与对象有关系,线程之间并不会出现内部问题;如果用static修饰,static默认获取的是大Class对象的锁,大Class对象只有一个,因为大Class在方法区里面,user.Class==user.getClass==user.forname获取到的是同一个对象
怎样让多线程同步,怎样解决高并发?
(1) 通过同步锁
(2) 通过lock
Synchronize和lock的区别?
线程很多的情况下,使用lock性能会高一些,因为lock里面有trylock,里面可以等待一定的时间,当一个线程走完需要手动释放,还要new一个lock对象
线程少的情况下,使用synchronize简单方便,因为它直接加在方法或是代码块上,当一个线程走完这个代码块,会自动释放锁,
Sleep和wait区别?
(1)Sleep睡眠一段时间会自动往下执行,wait会一直等待,
(2)Sleep不会释放锁,wait会释放锁
(3)Sleep可以出现在任何地方,wait只能出现在同步代码块,否则会抛出一个无效的监视锁状态异常
Final和notify和notifyall有什么区别?
Notify是唤醒一个正在等待wait的线程,notifyall是唤醒所有wait的线程
用线程池好处?
节约资源,这个资源包括时间、CPU
哪里用过线程池?
可能有些工具类会用到,实际上我们工作中是没有用到的,所有的解决方案都是有了,就好比定时任务那些都没必要自己实现,spring已经有了;我们用到的处处都有多线程,只不过不用我们自己去编译,框架里面已经有了;所以这个问题我需要设计一下:有一个线程池类,然后里面可以初始化new一个的时候,有好多参数,可以指定,当然我们也可以自己实现一个线程池:new linkedlist,new10个线程放到里面,每次从头部取一个再插到尾部,循环使用亦可以;其实原理是一样的,只是java已经有实现
你熟悉那些数据库连接池?
线程池有什么好处?