分散的面试问题
# 分散的面试问题
# 一、Cookie和Session有什么区别?
当Tomcat服务器第一次接收到客户端的请求信息时,会开辟一个新的Session空间,创建一个新的Session对象,生成一个Session id。然后放在响应头发送给客户端。客户端收到之后就会存放在浏览器的Cookie中。以后用户的每次请求,都会在请求头附带这个Session id,这样服务器就可以返回上次的会话内容,如登陆状态。
# 二、当服务端从单机扩展为分布式后,cookie和session如何扩展?
首先如果服务器是在多机分布式的场景下,session id只会在其中一个服务器当中,如果第二次请求在另一个服务器,就会失去上次会话信息。扩展方法如下:
1.可以让客户端把所有请求发送到拥有该session id的Tomcat实例中。但是存在的问题在于,如果这个服务端实例挂了之后,请求就会被转发到其他的服务端Tomcat实例中,session id就会丢失。
2.让Tomcat实例把session id同步复制到其它的Tomcat实例上,来保证无论请求由哪一个Tomcat实例来响应,都有session id。问题在于,服务器端同步session id开销大,而且容易丢失。
3.服务端的session都存在一个redis进行共享。
# 三、如何实现分布式锁
1.Redis:setnx key value +过期时间。如果执行失败,说明key已经存在了锁被占用,保证互斥性。而如果成功,就会再给这个锁设置一个过期时间,让key自动删除释放锁,防止该进程还未主动释放锁就挂了。
2.Zookeeper:利用znode子节点命名唯一和临时顺序编号节点。首先每个想申请锁的客户端现在znode节点下创建一个新的临时顺序编号节点,这时候Zookeeper会给他从小到大进行编号,然后客户端查看自己的编号是不是最小的,如果是他就可以获得锁资源。如果不是,则说明序号排在前面的客户端占有了锁,并对比它序号小1的节点进行监听,一旦状态改变说明前面一个客户端已经释放锁可以占用。每个客户端执行完事务后断开连接,那么节点就会自己删除。
3.MySQL:利用表中主键索引或者是唯一索引只能有一条数据。这个key可以设置为要竞争的id,比如商品id。加锁的形式是通过向一张表插入一个数据。如果一条插入成功,那么其它相同key的数据插入就会失败。
# 四、什么是SYN泛洪攻击?如何防范?
1.黑客端会发送大量的SYN请求给服务端建立TCP连接,这时候服务端就会不断发送ack给对方,对方一直不回应服务端就会一直发送(以为是自己的报文超时),直到资源耗尽。
2.解决方法①可以设置一个较短的SYN过期延时,过期后服务器就会抛弃这个SYN半连接。
②设置SYN cookie,服务器发现接受到某个重复IP的大量请求时,就认为收到了攻击。
# 五、查找学生表中年龄最大的一条记录?
①select * from student where age=(select max(age) from student)
②select TOP 1 * from stude nt order by age desc 返回表中前一行数据
③select * from student order by age desc limit 1
# 六、TCP和UDP区别?
1.从报文上看,UDP报文首部只有四个字段,包括ip,端口,总长度,检验。
而TCP头部除此之外,还有序号,期望号,窗口大小,FIN和SYN等等字段。
2.UDP,没有重传和拥塞控制机制。
TCP有重传机制(冗余ACK,超时),流量控制(点对点,基于滑动窗口,通过min(拥塞窗口,接收方窗口)来对发送方进行限制),拥塞控制(慢开始,拥塞避免算法,拥塞处理)
3.UDP无连接不可靠,用于广播。
TCP面向连接可靠,可靠数据传输。
# 七、分布式内存缓存memcached
1.memcache:分布式内存对象缓存系统,能在内存中做缓存。支持数据类型简单。数据100k以上性能比redis好。一致性基于CAS实现。
2.memcached服务器之间互不通信,各自独立存取数据,因此服务器不具有分布式功能,memcached分布式主要依赖于客户端的实现.每台memcached存储的数据都是不一样的。
查询时需要通过两次hash。第一次哈希根据key来找到数据所在的memcached服务器,在那个memcached服务器内再通过第二次哈希来找到真正的数据。
3.不适用guava的原因:guava实现是本地缓存(缓存和应用进程在同一台机器上),轻量快速,生命周期随jvm销毁而结束。因此在分布式场景下,每个实例的本地缓存可能存在不一致情况。
适用于数据量小,改动少,访问多的数据。
# 八、Linux删除文件原理?
使用rm删除文件实际上是在父目录中删除该文件的名字,从而使文件名消失,无法指向该文件的inode节点。当没有文件名指向该inode节点时,才会删除该文件的inode和block。
创建文件的硬链接时,删除会减少文件的引用计数i_count和文件名到inode的链接i_link,只有当前文件没有被其它进程调用时引用计数才会减少为0,这时候会正式删除文件。
软链接类似于快捷方式,是通过源文件的地址进行引用,因此直接删除不影响。
# 九、Spring循环依赖
# 如何解决循环依赖
让我们初始化A bean时,如果它的初始化依赖于B bean,而B的初始化又依赖于A那么就会有循环依赖的问题。Spring是通过三级缓存来解决循环依赖:
1.首先实例化A对象,然后把A对象放入到第三级缓存中,把他的引用暴露出来,接着进行属性注入。
2.A发现依赖于B,那么此时会去三级缓存查看是否有B对象,没有则重新创建B对象,跟A实例化步骤一致。
3.这时候发现B依赖于A,getBean(A)时可以在第三级缓存找到A引用,直接返回完成B的属性注入,进而成功创建B的Bean对象,然后返回去给A,A也创建成功。
# 为什么使用三级而非二级解决IOC问题
使用三级是出于AOP考虑,如果只使用二级缓存,在AOP情形下,可以先创建代理对象,再进行初始化一系列工作。但是这样就和Spring的AOP设计原理相悖,一般应该是Bean实例化初始化后再创建AOP对象。因此需要第三级缓存来保存产生的代理对象。
# 十、输入URL后页面解析过程?
1.首先通过DHCP协议动态获取本机IP地址。
DHCP是基于UDP实现的,大致过程如下:主机先广播discover报文,其中包含有主机的MAC地址;所有DHCP服务器接收到之后,向主机通过广播或者单播(通过discover报文中的MAC地址进行单播)的方式发送offer报文;主机收到后一般会响应最先收到的那个,并广播request报文,表示接受使用该DHCP服务器提供的ip地址;DHCP收到会发送确认报文。
2.通过DNS域名解析获取URL对应的ip地址。
首先浏览器先查看自己的DNS缓存,若没有则搜索操作系统缓存,若没有则查看本地host文件是否有该域名的映射,都没有则进行DNS查询。
先对本地域名服务器进行递归查询,本地域名服务器会查询自己的缓存,如果没有则会依次向根域名服务器,顶级域名服务器,权限域名服务器等等进行迭代查询。最后本地域名服务器得到ip地址后返回给浏览器。
3.获得目的ip地址后,传输层会进行TCP三次握手建立传输链路。
4.网络层首先是在路由表中,根据目的ip地址查找下一条路由器的地址,其中如果本机在局域网中,还可能涉及本地路由器的NAT转换,将本机的私有IP地址转化为路由器的公网IP。
再者还需要通过ARP协议获取目的ip对应的MAC地址,主机将包含目的ip的ARP请求广播到局域网上的所有主机,并接受消息以确认目标MAC地址。
5.建立完连接后开始传输数据。客户端会根据HTTP协议生成HTTP请求报文。服务器接收到http请求后,就会把客户端请求的web资源通过HTTP响应报文发给客户端。客户端接收到响应后,进行四次挥手来与服务器关闭连接。
6.浏览器就会进行解析和渲染,呈现给我们看到的页面。
# 十一、HTTP请求报文,描述HTTP和HTTPS区别?
HTTP请求报文包括:第一部分请求行(包括请求方法get/post,请求的相对路径,还有HTTP版本),第二部分请求头,第三部分请求实体。
1.HTTP是互联网上一种应用广泛的网络通信协议,基于TCP实现的。传输时先建立TCP连接,再进行资源传输。分给持久连接和非持久连接,持久连接只需建立一次TCP连接,后续访问数据传输不需要建立新的连接;而非持久连接中每次访问资源都需要建立一次新的TCP连接建立通道。
HTTPS可以认为是HTTP+SSL,他在HTTP基础上增加了一系列安全机制,一方面在保证数据传输的安全性以外,另一方面还对访问者增加了验证机制。
2.HTTP免费的,而HTTPS需要申请证书,证书需要收费。
HTTP默认80端口,而HTTPS默认443端口。
HTTPS握手协议比较耗时,除了三次握手之外,还增加了对证书的验证过程,因此比较影响服务的响应速度和吞吐量。并且证书体系也不是完全安全的,对于DDOS(分布式拒绝访问攻击)甚至会起到反作用。
# 十二、什么是TCP的序号和期望号?TCP握手三次握手和四次挥手必要性?2MSL?
1.TCP是面向连接可靠的传输层协议,而UDP是无连接不可靠的传输层协议。
2.TCP会对数据字节编号,序号seq是当前报文的第一个字节号,期望号ack等于收到对方报文的最后一个数据号加一,表示期望收到对方下一个报文的序号。TCP规定携带SYN字段的报文即使不携带数据,也要消耗一个序号;而对于没有SYN的报文不携带数据,就不消耗序号。
3.两次握手的问题在于,A和B建立TCP连接,如果A第一次发送过程中如果因为网络堵塞超时了,A会重新发送TCP连接报文给B,B发确认报文给A然后两者进行数据传输。当A和B断开连接时,如果这时候B才收到了之前A第一次发送的超时的TCP连接报文,那么B会认为A此时要创建新的TCP连接,于是B会给A发送确认报文,数据运输通路建立完成(假设两次即可),而A收到后不予理睬,因此会导致B一直等待A的数据,造成资源的浪费。而如果时三次握手的话上述情况,B因为没有收到A发送的第三个报文而不会建立连接。
4.如果是三次挥手,则B发完数据后,发送第三个断开连接报文给A后B关闭连接,A收到B的第三次挥手后也会关闭连接。但是问题在于,当网络堵塞时,如果B发送的第三次挥手报文丢失,那么A会一直等待B发送关闭连接报文,而此时B已经关闭。
5.A发送给B第四次确认时,如果不等待2MSL时长就立即关闭,当网络阻塞B收不到第四个报文时,B会一直重传,一直处于最后确认状态而无法关闭。
# 十三、HTTP1.0,1.1和HTTP2.0区别?
1.HTTP1.0中客户端只和服务器保持非持久连接,每一个新的请求都是需要建立TCP连接,服务器完成响应之后就会立即断开TCP连接。
2.HTTP1.1中,默认支持持久连接,在一个TCP连接上可以进行多个请求响应。同时还允许客户端不用等待就收上次请求的响应,就可以发送下一次请求。(但是服务器需要按序响应)
3.HTTP2.0中,性能和特性有了很大的提升:
①多路复用,客户端和服务器都可以同时发送或者接受多个请求响应报文,不需要按序接收。
②HTTP2.0传输数据分割为帧,并采用二进制编码。相比之前1.1的文本格式编码解析起来更加高效。
③首部压缩:通过使用维护一个首部表,来跟踪存储之前每次发送时的键值对。有两个请求,如果它们的状态行和头部大部分内容相同的话,那么第二请求头只需要发送不同的差异数据,这样就可以减少在头部的重复开销。
④服务推送。允许服务器在响应报文外,发送其它客户端需要的资源给客户端,避免客户端再发送一次请求的开销。比如加载静态资源。
# 十四、什么是CSRF攻击?
CSRF是跨站请求伪造攻击。因为用户的浏览器中,会有携带有用户session id的cookie,第二次请求用户就可以带上cookie让服务端返回相关会话信息。这时候如果在浏览器另打开一个tab页,那么它也可以正常获得浏览器的id。黑客就可以利用此cookie进行攻击。
比如在一个银行系统,用户通过get方法转账,其中url暴露用户的账户和转账金额;这时候黑客就可以在另外一个tab页进行附带一个新链接,其中账户是黑客自己的账户。当用户不小心点进去后,就会发送一个带有cookie的请求后,服务器就会受理转账给黑客用户。
解决方案:①尽量使用post方法提交表单,少用get方法。攻击者不容易伪造。
②用户在请求中,加入一个黑客无法获得的识别字段。