1. OSI七层和TCP/IP四层
OSI/RM:开放系统互联基本参考模型(open system interconnection reference model),为了各种计算机在世界范围内互连成网的标准框架,国际标准化组织ISO于1977年成立了专门机构研究该问题。
OSI七层/TCPIP四层/五层协议(综合OSI和TCP/IP的优点):
物理层:物理层上传送的数据单位是比特,发送方发送1/0时,接收方应当受到1/0而不是0/1,因此物理层要考虑用多大的电压表示1/0,以及接收方如何识别发送方发出的比特;物理层还要确定连接电缆的插头有几根引脚以及如何连接;定义物理设备标准,例如网线的接口类型、光线的接口类型、各种传输介质的传输速率等。他的主要作用是传入比特流(就是由1、0转化为电流强弱来进行传输,到达目的地后再转化为1、0,也就是我们通常所说的数模转换与模数转换)。这一层的数据叫做比特流。
数据链路层:定义了如何让数据格式化进行传输,将网络层下来的数据报组装成帧,还提供了错误检测和纠正,以保证数据的可靠传输。
网络层:在位于不同地理位置的网络中的两个主机之间提供连接和路径选择。将运输层产生的报文段或者用户数据包封装成包;Internet的发展使得从世界各站点访问信息的用户数大大增加,而网络层正是管理这种连接的层。
运输层:定义了一些传输数据的协议和端口号(WWW端口80等),主要是将从下层的接收的数据进行分段和传输,到达目的地后再进行传输。常常把这一层数据叫做段。
应用层:应用进程间通信与交互的规则,如HTTP协议(万维网应用)、SMTP(电子邮件)、FTP(文件传输)等,数据单位为报文
2.TCP,UDP,HTTP的报文格式(1个字节=8位)
(TCP、UDP是在运输层的协议,HTTP是在应用层的协议)
UDP报文格式:两个部分,UDP数据字段和首部字段(8个字节源端口2、目的端口2、长度2、校验和2),12 字节的伪首部是为了计算检验和临时添加的。
TCP报文格式:两个部分,TCP报文段数据部分和首部(源端口2、目的端口2、序号4、确认号4、数据偏移4位、保留6位、URG/ACK/PSH/RST/SYN/FIN6位标志位、窗口大小2、校验和2、紧急指针2、选项),首部的前20字节是确定的,选项长度可变,最长可达40字节
HTTP协议:定义了浏览器如何向万维网服务器请求万维网文档,以及服务器如何将文档传送给浏览器的,是面向事务的应用层协议
HTTP报文格式:有两种报文,请求报文和响应报文
请求报文和响应报文都是由三个部分组成:
开始行:区分是请求还是响应,请求是:URL+CRLF回车换行,响应是:状态行
首部行:说明浏览器、服务器、报文主题的信息
实体主体:请求中一般不用,响应中可能不用
3.TCP,UDP的区别:
- TCP:传输控制协议TCP,面向连接,传输效率低,可靠性强,点对点,用于传输可靠性要求高,数据量大的数据
- UDP:用户数据报协议UDP,与TCP特性恰恰相反,面向报文,无连接的(不需要数据双方建立连接),尽最大努力交付,没有拥塞控制(实时视频会议、IP电话等允许丢失一些数据,以恒定的速率发送数据),支持一对一、一对多、多对一、多对多,用于传输可靠性要求不高、数据量小的数据,如QQ聊天数据就是通过这种方式传输的
相同之处:都是传输层协议
为什么TCP是安全的:
TCP具有三次握手的双向机制,每次都需要建立一个可以双方互相信任的链接才开始传输数据,而且如果传输过程中发生校验失败、丢包、延时会发生重传;TCP还有拥塞控制和流量控制(窗口和计时器,窗口指明最大数据量)
拥塞控制4个核心算法:
当主机开始发送数据时,如果立即将较大的发送窗口的全部数据字节都注入网络,由于不清楚网络的状况,可能会引发网络拥塞
① 慢启动:由小到大逐渐增加拥塞窗口数值,如果接收方返回确认无延迟,发送方拥塞窗口加倍(为防止拥塞窗口cwnd增大过大引起网络拥塞,还要这是一个慢开始门限ssthresh,如果cwnd < ssthresh,则慢开始,如果>则拥塞避免)
② 拥塞避免:将TCP连接初始化,cwnd设置为1,cwnd加1而不是翻倍,发生网络拥塞时将ssthresh设置为拥塞前的一半
③ 快重传:快重传要求接收方在收到一个失序的报文段后就立即发出重复确认(为的是使发送方及早知道有报文段没有到达对方),当出现丢失,发送下一个时候,接收方会重复发送丢失数据上的上一个完整数据,当发送方连续收到三个重复确认时,立即重传对方尚未收到的报文
④ 快恢复:当发送方连续收到三个重复确认时,就执行“乘法减小”算法,把sstresh门限减半(乘法减小)。考虑到如果网络出现拥塞的话就不会收到好几个重复的确认,所以发送方现在认为网络可能没有出现拥塞,所以此时不执行慢开始算法(cwnd不设置为1),而是把cwnd设置为sstresh减半后的数值,开始拥塞避免算法(加法增大)
TCP三次握手四次挥手:
三次握手:发送数据建立连接
SYN:请求建立连接,ACK确认号是否有效,FIN希望断开连接,seq=x ,seq=y 是选择的初始序列号,
第一次握手:建立连接时,客户端发送syn包(syn=序列号)到服务器,并进入SYN_SENT状态,等待服务器确认;SYN:同步序列编号(Synchronize Sequence Numbers)。
第二次握手:服务器收到syn包,必须确认客户的SYN(ack=序列号+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;
第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED(TCP连接成功)状态,完成三次握手。
四次挥手:停止发送数据关闭连接
1)客户端进程发出连接释放报文,并且停止发送数据。释放数据报文首部,FIN=1,其序列号为seq=u(等于前面已经传送过来的数据的最后一个字节的序号加1),客户端进入FIN-WAIT-1(终止等待1)状态。 TCP规定,FIN报文段即使不携带数据,也要消耗一个序号。
2)服务器收到连接释放报文,发出确认报文,ACK=1,ack=u+1,并且带上自己的序列号seq=v,此时,服务端就进入了CLOSE-WAIT(关闭等待)状态。TCP服务器通知高层的应用进程,客户端向服务器的方向就释放了,这时候处于半关闭状态,即客户端已经没有数据要发送了,但是服务器若发送数据,客户端依然要接受。这个状态还要持续一段时间,也就是整个CLOSE-WAIT状态持续的时间。
3)客户端收到服务器的确认请求后,此时,客户端就进入FIN-WAIT-2(终止等待2)状态,等待服务器发送连接释放报文(在这之前还需要接受服务器发送的最后的数据)。
4)服务器将最后的数据发送完毕后,就向客户端发送连接释放报文,FIN=1,ack=u+1,由于在半关闭状态,服务器很可能又发送了一些数据,假定此时的序列号为seq=w,此时,服务器就进入了LAST-ACK(最后确认)状态,等待客户端的确认。
5)客户端收到服务器的连接释放报文后,必须发出确认,ACK=1,ack=w+1,而自己的序列号是seq=u+1,此时,客户端就进入了TIME-WAIT(时间等待)状态。注意此时TCP连接还没有释放,必须经过2MSL(最长报文段寿命)的时间后,当客户端撤销相应的TCB后,才进入CLOSED状态。
(MSL指一个片段在网络中最大的存活时间,2MSL就是一个发送和一个回复所需的最大时间。如果直到2MSL,Client都没有再次收到FIN,那么Client推断ACK已经被成功接收,则结束TCP连接。)
6)服务器只要收到了客户端发出的确认,立即进入CLOSED状态。同样,撤销TCB后,就结束了这次的TCP连接。可以看到,服务器结束TCP连接的时间要比客户端早一些。
4. HTTP的长连接是怎么做的
HTTP的长连接,本质上是TCP的连接,HTTP是应用层的协议,TCP才是真正的传输层的协议(快递单子和实际送货过程),http1.1是长连接
如何实现? 通过设置connection为keep-alive实现
为了干什么? 为了复用TCP连接,长连接情况下,多个HTTP请求可以复用同一个TCP连接,节省了很多TCP连接建立和断开的消耗
平时普通的Web应用使用长连接有什么好处? 长连接可以省去较多的TCP建立和关闭的操作,减少浪费,节约时间。对于频繁请求资源的客户来说,较适用长连接。节约TCP连接和断开的消耗。
长连接的问题:在长连接的应用场景下,client端一般不会主动关闭它们之间的连接,Client与server之间的连接如果一直不关闭,客户端连接越来越多,server早晚有扛不住的时候,这时候server端需要采取一些策略,如关闭一些长时间没有读写事件发生的连接,这样可 以避免一些恶意连接导致server端服务受损。
5. JVM内存分布
JVM是什么:JVM(Java Virtual Machine,Java虚拟机)
Java程序的跨平台特性主要是指字节码文件可以在任何具有Java虚拟机的计算机或者电子设备上运行,Java虚拟机中的Java解释器负责将字节码文件解释成为特定的机器码进行运行。因此在运行时,Java源程序需要通过编译器编译成为.class文件。JVM是JRE的一部分。它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。JVM有自己完善的硬件架构,如处理器、堆栈、寄存器等,还具有相应的指令系统。Java语言最重要的特点就是跨平台运行。使用JVM就是为了支持与操作系统无关,实现跨平台。所以,JAVA虚拟机JVM是属于JRE的,而现在我们安装JDK时也附带安装了JRE(当然也可以单独安装JRE)。
JVM内存分布:
堆:堆是Java虚拟机管理的内存中最大的一块区域,Java堆是所有线程共享的区域,在虚拟机启动的时候创建,堆的作用是用来存放几乎所有的对象实例,Java堆是垃圾器管理的主要区域,因此也被称为GC(garbage collect)堆。当要给新的实例分配内存空间的时候,堆空间不足会抛出OOM异常。
方法区:方法区也是用于线程共享的区域,用来存储已经被加载的类信息,常量、静态变量、即时编译器编译后的代码数据
虚拟机栈:每个线程都有一个自己的虚拟机栈,虚拟机栈是线程私有的,虚拟机栈执行方法的时候,会为每一个方法创建一个栈帧,用于存放局部变量、操作数栈、动态链接、方法出口等信息。每一个方法的调用过程,在虚拟机中就是一个栈帧的一次入栈出栈。所以在用递归的方法来处理量很大的数据的时候,就会 导致StackOverFlowError。
本地方法栈:功能和虚拟机栈作用非常相似,虚拟机栈执行的是Java字节码,而本地方法栈执行的是Native方法。
程序计数器:程序计数器是一小块内存区域,也是线程私有的。用来储存当前线程执行的字节码的行号。Java多线程是通过线程轮流切换并分配给处理器执行的方式实现的。所以如果当前线程切换后,要想恢复到正确的位置,就需要程序计数器了。如果当前线程执行的方法是Java方法,那程序计数器保存的就是字节码指令的地址,如果执行的是Native方法,计数器的值就为空(Undefind)。
6. Java的set,list,map(线程安全的map,map怎么实现之类的)
Java中的集合包括三大类,分别是set list map,他们都处于java.util包中,set list map都是接口,它们有各自的实现类;LIST SET继承自Collection接口,Map不是(Collection是所有集合类的接口)
- Set(集) 实现类主要有HashSet和TreeSet,不能含有重复的元素
- List(列表) 实现类主要有ArrayList,LinkedList,Vector(安全,多了个同步化机制),以特定次序存储元素
- Map(映射)实现类主要有HashMap和TreeMap,HashTable(安全,比hashmap多了线程安全
collection和map的区别:
Collection类型者,每个位置只有一个元素。Map类型者,持有 key-value pair,像个小型数据库。
Collection、List、Set、Map都是接口,不能实例化。继承自它们的 ArrayList, Vector, HashTable, HashMap是具象class,这些才可被实例化。
7. 线程创建,线程池参数
为什么要使用线程池?
线程池做的工作主要是控制运行的线程的数量,处理过程中将任务放入队列,然后在线程创建后启动这些任务,如果线程的数量超过最大数量,超过数量的线程将排队等候,等其他线程执行完毕,再从队列中取出任务来执行
特点:线程复用,控制最大并发数,管理线程
- 降低资源消耗,通过重复利用已创建的线程降低线程创建和销毁造成的消耗
- 提高响应速度,当任务到达时,任务可以不需要的等到线程创建就能够立刻执行
- 提高线程的可管理性,线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,
- 还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控。
线程创建四大方法:
① 继承Thread类
② 实现Runnable接口
③ 使用Callable创建线程
④ 使用线程池创建线程
线程池七大参数:
① .corePoolSize:线程池中的常驻核心线程数,在创建了线程池后,当有请求任务进来之后,就会安排池中的线程去执行请求任务,近似理解为今日当值线程,当线程池中的线程数目达到corePoolSize后,就会把到达的任务放入缓存队列中。
② .maximumPoolSize:线程池能够容纳同时执行的最大线程数,此值必须大于等于1
③ .keepAliveTime:多余的空闲线程的存活时间。当前线程池数量超过corePoolSize时,当空闲时间达到keepAliveTime值时,多余空闲线程会被销毁直到只剩下corePoolSize个线程为止,默认情况下,只有当线程池中的线程数大于corePoolSize时,keepAliveTime才会起作用,直到线程池找那个的线程数不大于corePoolSize。
④ .unit:keepAliveTime的单位
⑤ .workQueue:任务队列,被提交但尚未被执行的任务
⑥ .threadFactory:表示生成线程池中工作线程的线程工厂,用于创建线程一般默认即可
⑦ .handler:拒绝策略,表示当队列满了并且工作线程大于等于线程池最大线程数(maximumPoolSize)时如何处理
8. Udp数据报丢失怎么处理,在应用层处理的具体实现,选择udp而不是tcp的原因是什么?
UDP因为自身特性,尽最大可能传输,但是不保证数据的准确性,会有一定的数据丢失
选择UDP的情况:
当对网络通讯质量要求不高的时候,要求网络通讯速度能尽量的快,这时就可以使用UDP。
比如,日常生活中,常见使用UDP协议的应用如下:QQ语音、QQ视频
9.部署在公网环境用udp是否可以?可以
10.如何解决粘包?加长度 具体的回答,说一下思路。(跳过)
第二范式在第一范式的基础之上更进一层。第二范式需要确保数据库表中的每一列都和主键相关,而不能只与主键的某一部分相关(主要针对联合主键而言)。也就是说在一个数据库表中,一个表中只能保存一种数据,不可以把多种数据保存在同一张数据库表中。
订单信息表:
这样就产生一个问题:这个表中是以订单编号和商品编号作为联合主键。这样在该表中商品名称、单位、商品价格等信息不与该表的主键相关,而仅仅是与商品编号相关。所以在这里违反了第二范式的设计原则。而如果把这个订单信息表进行拆分,把商品信息分离到另一个表中,把订单项目表也分离到另一个表中,就非常完美了。如下所示。
这样设计,在很大程度上减小了数据库的冗余。如果要获取订单的商品信息,使用商品编号到商品信息表中查询即可。
第三范式需要确保数据表中的每一列数据都和主键直接相关,而不能间接相关。
比如在设计一个订单数据表的时候,可以将客户编号作为一个外键和订单表建立相应的关系。而不可以在订单表中添加关于客户其它信息(比如姓名、所属公司等)的字段。如下面这两个表所示的设计就是一个满足第三范式的数据库表。
这样在查询订单信息的时候,就可以使用客户编号来引用客户信息表中的记录,也不必在订单信息表中多次输入客户信息的内容,减小了数据冗余。