本人现在计算机专业硕士一年级,菜鸡一枚,结合前段时间面试经历,整理一下java后端面试常见知识点。本文会持续更新
HTTPS 并不是一项新的应用层协议,只是 HTTP 通信接口部分由 SSL 和 TLS 替代而已。通常情况下,HTTP 会先直接和 TCP 进行通信。在使用 SSL 的 HTTPS 后,则会先演变为和 SSL 进行通信,然后再由 SSL 和 TCP 进行通信。也就是说,HTTPS 就是身披了一层 SSL 的 HTTP。(我都喜欢把骚粉留在最后。。。
SSL 是一个独立的协议,不只有 HTTP 可以使用,其他应用层协议也可以使用,比如 SMTP(电子邮件协议)、Telnet(远程登录协议) 等都可以使用。
SSL 即安全套接字层,它在 OSI 七层网络模型中处于第五层,SSL 在 1999 年被 IETF(互联网工程组)更名为 TLS ,即传输安全层,直到现在,TLS 一共出现过三个版本,时,浏览器去到dns服务器获取此url对应的ip,然后客户端连接上服务端的443端口,将此请求发送给到服务端,此时客户端同时将自己支持的加密算法带给服务端;
服务端收到这套加密算法的时候,和自己支持的加密算法进行对比(也就是和自己的私钥进行对比),如果不符合,就断开连接;如果符合,服务端就将CA证书发送给客户端,此证书中包括了数字证书包含的内容:1、证书颁发机构;2、使用机构;3、公钥;4、有效期;5、签名算法;6、签名hash算法;7、指纹算法;8、指纹。
这里服务端发送的东西是用私钥进行加密的,公钥都能解开,并不能保证发送的数据包不被别人看到,所以后面的过程会和客户端商量选择一个对称加密(只能用私钥解开,这里详情请移步非对称、对称加解密相关问题)来对传输的数据进行加密。
(3)客户端验证服务端发来的证书
客户端验证收到的证书,包括发布机构是否合法、过期,证书中包含的网址是否与当前访问网址一致等等。
客户端验证证书无误后(或者接受了不信任的证书),会生成一个随机数,用服务端发过来的公钥进行加密。如此一来,此随机数只有服务端的私钥能解开了。
用证书中的签名hash算法取握手信息的hash值,然后用生成的随机数对[握手信息和握手信息的hash值]进行加密,然后用公钥将随机数进行加密后,一起发送给服务端。其中计算握手信息的hash值,目的是为了保证传回到服务端的握手信息没有被篡改。
(4)服务端接收随机数加密的信息,并解密得到随机数,验证握手信息是否被篡改。
服务端收到客户端传回来的用随机数加密的信息后,先用私钥解密随机数,然后用解密得到的随机数解密握手信息,获取握手信息和握手信息的hash值,计算自己发送的握手信息的hash值,与客户端传回来的进行对比验证。
如果验证无误,同样使用随机字符串加密握手信息和握手信息hash值发回给到客户端。
(5)客户端验证服务端发送回来的握手信息,完成握手
客户端收到服务端发送过来的握手信息后,用开始自己生成的随机数进行解密,验证被随机数加密的握手信息和握手信息hash值。
验证无误后,握手过程就完成了,从此服务端和客户端就开始用那串随机数进行对称加密通信了(常用的对称加密算法有AES)。
(1)修改Linux内核参数
通过修改内核参数,控制队列大小和队满的时候应做什么处理。
超出处理能力时,对新的SYN直接回报RST,丢弃连接:
先看一下syn队列与accept队列是如何工作的:
应用程序过慢时,会导致Accept队列被占满。
受到SYN攻击时,会导致SYN队列被占满
Reactor模式,是基于Java NIO的,在他的基础上,抽象出来两个组件——Reactor和Handler两个组件:
(1)Reactor:负责响应IO事件,当检测到一个新的事件,将其发送给相应的Handler去处理;新的事件包含连接建立就绪、读就绪、写就绪等。
下图十最简单的单Reactor单线程模型,Reactor线程是个多面手,负责多路分离套接字,Accept新连接,并分派请求到Handler处理器中。
当其中某个 handler 阻塞时, 会导致其他所有的 client 的 handler 都得不到执行, 并且更严重的是, handler 的阻塞也会导致整个服务不能接收新的 client 请求(因为 acceptor 也被阻塞了)。 因为有这么多的缺陷, 因此单线程Reactor 模型用的比较少。这种单线程模型不能充分利用多核资源,所以实际使用的不多。
在单线程Reactor模式基础上,做如下改进:
在linux中的Java进程中,默认情况下所有的socket都是blocking IO。在阻塞式 I/O 模型中,应用程序在从IO系统调用开始,一直到到系统调用返回,这段时间是阻塞的。返回成功后,应用进程开始处理用户空间的缓存数据
举个栗子,发起一个blocking socket的read读操作系统调用,流程大概是这样:
(1)当用户线程调用了read系统调用,内核(kernel)就开始了IO的第一个阶段:准备数据。很多时候,数据在一开始还没有到达(比如,还没有收到一个完整的Socket数据包),这个时候kernel就要等待足够的数据到来。
(2)当kernel一直等到数据准备好了,它就会将数据从kernel内核缓冲区,拷贝到用户缓冲区(用户内存),然后kernel返回结果。
(3)从开始IO读的read系统调用开始,用户线程就进入阻塞状态。一直到kernel返回结果后,用户线程才解除block的状态,重新运行起来
所以,blocking IO的特点就是在内核进行IO执行的两个阶段,用户线程都被block了。
在linux系统下,可以通过设置socket使其变为non-blocking。NIO 模型中应用程序在一旦开始IO系统调用,会出现以下两种情况:
(1)在内核缓冲区没有数据的情况下,系统调用会立即返回,返回一个调用失败的信息
(2)在内核缓冲区有数据的情况下,是阻塞的,直到数据从内核缓冲复制到用户进程缓冲。复制完成后,系统调用返回成功,应用进程开始处理用户空间的缓存数据。
举个栗子。发起一个non-blocking socket的read读操作系统调用,流程是这个样子:
(1)在内核数据没有准备好的阶段,用户线程发起IO请求时,立即返回。用户线程需要不断地发起IO系统调用。
(2)内核数据到达后,用户线程发起系统调用,用户线程阻塞。内核开始复制数据。它就会将数据从kernel内核缓冲区,拷贝到用户缓冲区(用户内存),然后kernel返回结果。
(3)用户线程才解除block的状态,重新运行起来。经过多次的尝试,用户线程终于真正读取到数据,继续执行。
优点:每次发起的 IO 系统调用,在内核的等待数据过程中可以立即返回。用户线程不会阻塞,实时性较好。
缺点:需要不断的重复发起IO系统调用,这种不断的轮询,将会不断地询问内核,这将占用大量的 CPU 时间,系统资源利用率较低。
总之,NIO模型在高并发场景下,也是不可用的。一般 Web 服务器不使用这种 IO 模型。一般很少直接使用这种模型,而是在其他IO模型中使用非阻塞IO这一特性。java的实际开发中,也不会涉及这种IO模型。
如何避免同步非阻塞NIO模型中轮询等待的问题呢?这就是IO多路复用模型。
IO多路复用模型,就是通过一种新的系统调用,一个进程可以监视多个文件描述符,一旦某个描述符就绪(一般是内核缓冲区可读/可写),内核kernel能够通知程序进行相应的IO系统调用。
目前支持IO多路复用的系统调用,有 select,epoll等等。select系统调用,是目前几乎在所有的操作系统上都有支持,具有良好跨平台特性。epoll是在linux 2.6内核中提出的,是select系统调用的linux增强版本。
IO多路复用模型的基本原理就是select/epoll系统调用,单个线程不断的轮询select/epoll系统调用所负责的成百上千的socket连接,当某个或者某些socket网络连接有数据到达了,就返回这些可以读写的连接。因此,好处也就显而易见了——通过一次select/epoll系统调用,就查询到到可以读写的一个甚至是成百上千的网络连接。
举个栗子。发起一个多路复用IO的的read读操作系统调用,流程是这个样子:
在这种模式中,首先不是进行read系统调动,而是进行select/epoll系统调用。当然,这里有一个前提,需要将目标网络连接,提前注册到select/epoll的可查询socket列表中。然后,才可以开启整个的IO多路复用模型的读流程。
(1)进行select/epoll系统调用,查询可以读的连接。kernel会查询所有select的可查询socket列表,当任何一个socket中的数据准备好了,select就会返回。
(2)用户线程获得了目标连接后,发起read系统调用,用户线程阻塞。内核开始复制数据。它就会将数据从kernel内核缓冲区,拷贝到用户缓冲区(用户内存),然后kernel返回结果.
(3)用户线程才解除block的状态,用户线程终于真正读取到数据,继续执行。
select的调用复杂度是线性的,即O(n)。举个例子,一个保姆照看一群孩子,如果把孩子是否需要尿尿比作网络IO事件,select的作用就好比这个保姆挨个询问每个孩子:你要尿尿吗?如果孩子回答是,保姆则把孩子拎出来放到另外一个地方。当所有孩子询问完之后,保姆领着这些要尿尿的孩子去上厕所(处理网络IO事件)。
还是以保姆照看一群孩子为例,在epoll机制下,保姆不再需要挨个的询问每个孩子是否需要尿尿。取而代之的是,每个孩子如果自己需要尿尿的时候,自己主动的站到事先约定好的地方,而保姆的职责就是查看事先约定好的地方是否有孩子。如果有小孩,则领着孩子去上厕所(网络事件处理)。因此,epoll的这种机制,能够高效的处理成千上万的并发连接,而且性能不会随着连接数增加而下降。
select本质上是通过设置或检查存放fd标志位的数据结构进行下一步处理。 这带来缺点: - 单个进程可监视的fd数量被限制,即能监听端口的数量有限 单个进程所能打开的最大连接数由FD_SETSIZE宏定义,其大小是32个整数的大小(在32位的机器上,大小就是3232,同理64位机器上FD_SETSIZE为3264),当然我们可以对进行修改,然后重新编译内核,但是性能可能会受到影响,这需要进一步的测试 一般该数和系统内存关系很大,具体数目可以cat
对socket是线性扫描,即轮询,效率较低: 仅知道有I/O事件发生,却不知是哪几个流,只会无差异轮询所有流,找出能读数据或写数据的流进行操作。同时处理的流越多,无差别轮询时间越长 - O(n)。
当socket较多时,每次select都要通过遍历FD_SETSIZE个socket,不管是否活跃,这会浪费很多CPU时间。如果能给 socket 注册某个回调函数,当他们活跃时,自动完成相关操作,即可避免轮询,这就是epoll与kqueue。
select方法本质其实就是维护了一个文件描述符(fd)数组,以此为基础,实现IO多路复用的功能。这个fd数组有长度限制,在32位系统中,最大值为1024个,而在64位系统中,最大值为2048个,这个配置可以调用
select方法被调用,首先需要将fd_set从用户空间拷贝到内核空间,然后内核用poll机制(此poll机制非IO多路复用的那个poll方法,可参加附录)直到有一个fd活跃,或者超时了,方法返回。
select方法返回后,需要轮询fd_set,以检查出发生IO事件的fd。这样一套下来,select方法的缺点就很明显了:
poll本质上和select没有区别,依然需要进行数据结构的复制,依然是基于轮询来实现,但区别就是,select使用的是fd数组,而poll则是维护了一个链表,所以从理论上,poll方法中,单个进程能监听的fd不再有数量限制。但是轮询,复制等select存在的问题,poll依然存在
epoll就是对select和poll的改进了。它的核心思想是基于事件驱动来实现的,实现起来也并不难,就是给每个fd注册一个回调函数,当fd对应的设备发生IO事件时,就会调用这个回调函数,将该fd放到一个链表中,然后由客户端从该链表中取出一个个fd,以此达到O(1)的时间复杂度
所以综合来说,epoll的优点有:
水平触发 :水平触发的意思就是说,只要条件满足,对应的事件就会一直被触发。所以如果条件满足了但未进行处理,那么就会一直被通知
边缘触发:边缘触发的意思就是说,条件满足后,对应的事件只会被触发一次,无论是否被处理,都只会触发一次。
针对这3个特点,Eric Brewer教授在2000年提出了CAP原则,也称为CAP定理。该原则指出,任何分布式系统都不能同时满足3个特点,如图1-6所示。
根据CAP原则,从图1-6中可以看出分布式系统只能满足3种情况。
BASE并非一个英文单词,而是几个英文单词的简写。
IOC即控制反转, 是一种设计思想,而不是一个具体的技术实现。IoC 的思想就是将原本在程序中手动创建对象的控制权,交由 Spring 框架来管理。不过, IoC 并非 Spirng 特有,在其他语言中也有应用。是基于反射来实现的
AOP(Aspect-Oriented Programming:面向切面编程)能够将那些与业务无关,却为业务模块所共同调用的逻辑或责任(例如事务处理、日志管理、权限控制等)封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可拓展性和可维护性。是基于代理来实现的。
AOP最为典型的应用实际就是数据库事务的管控。例如,当我们需要保存一个用户时,可能要连同它的角色信息一并保存到数据库中。于是,可以看到图4-4所示的一个流程图。
这里的用户信息和用户角色信息,我们都可以使用面向对象编程(OOP)进行设计,但是它们在数据库事务中的要求是,要么一起成功,要么一起失败,这样OOP就无能为力了。数据库事务毫无疑问是企业级应用关注的核心问题之一,而使用AOP可以解决这些问题。AOP还可以减少大量重复的工作。在Spring流行之前,我们可以使用JDBC代码实现很多的数据库操作,例如,插入一个用户的信息,我们可以用JDBC代码来实现。
选取可用的Zone,并随机挑选一个Zone出来,然后根据此Zone的名称来获取负载均衡器。
下面展示了一个Bean的构造过程
如上图所示,Bean 的生命周期还是比较复杂的,下面来对上图每一个步骤做文字描述:
用户在编制程序时并不知道主存的使用状况,用户编程时使用的地址就是虚地址或逻辑地址,其对应的空间即徐空间或逻辑空间。而计算机物理内存的访问地址称为实地址或物理地址。程序将虚地址转换为实地址的过程称为程序的再定位。
以页为单位的虚拟存储器,称为页式虚拟存储器。它的虚拟空间跟主存空间都将被划分为相同大小的页。主存中的页,称为实页,虚存中的页,称为虚页。虚拟地址被分为两个字段,虚页号和页内偏移。为了对每个虚拟页的存放位置,存取位置,使用情况,修改情况等等进行等进行说明,操作系统在主存中给每个进程都生成一个页表。因此,每个虚拟页表都对应有一个页表项。页表是一张存放在主存中的,虚拟页与实页对照的映射表。其中存放位置字段用来建立虚拟页与实页之间的映射,进而进行地址转换。有效位用来表示对应页面是否存在。
2. web优化,比如可以把用户请求合并(js、css合并),使用cdn加速静态页访问速度,把图片文档压缩减少带宽传输,
1. 使用简单并且稳定的架构方案
90. 检测某个端口所占用的进程,比如3306
91. 对于linux主机的cpu负载使用,什么情况下user的比例升高,什么情况下system的比
例升高,请联系实际举例。
答案:在Linux系统里面跑的用户安装服务比较忙的时候,会导致user的比例升高,比如mysql服务、php服务等。同样,当进程比较忙,比如php使用非常频繁,子进程非常多的时候,会导致进程切换频繁,system的比例就会升高。
92、在不umount的情况下,如何重新设置mount的参数。
93. 说一下公司多少台服务器,是什么架构
这个指令是指当一个nginx进程打开的最多文件描述符数目,理论值应该是最多打开文件数与进程数相除,现在在linux2.6内核下开启文件打开数为65535,worker_rlimit_nofile就相应应该填写65535。这是因为nginx调度时分配请求到进程并不是那么的均衡,所以假如填写10240,总并发量达到3-4万时就有进程可能超过10240了,这时会返回502错误。
G. client_header_buffer_size 4k;客户端请求头部的缓冲区大小,这个可以根据你的系统分页大小来设置,一般一个请求头的大小不会超过1k,不过由于一般系统分页都要大于1k,所以这里设置为分页大小。
H. open_file_cachemax=65535 inactive=60s;这个将为打开文件指定缓存,默认是没有启用的,max指定缓存数量,建议和打开文件数一致,inactive是指经过多长时间文件没被请求后删除缓存。
95. 提高性能和并发数,需要优化哪些内核参数
net.ipv4.tcp_max_orphans = 262144 //系统中最多有多少个TCP套接字不被关联到任何一个用户文件句柄上。如果超过这个数字,孤儿连接将即刻被复位并打印出警告信息。这个限制仅仅是为了防止简单的DoS攻击,不能过分依靠它或者人为地减小这个值,更应该增加这个值(如果增加了内存之后)。
net.ipv4.tcp_synack_retries = 1 //为了打开对端的连接,内核需要发送一个SYN 并附带一个回应前面一个SYN的ACK。也就是所谓三次握手中的第二次握手。这个设置决定了内核放弃连接之前发送SYN+ACK 包的数量。
A. 抗负载能力强,因为lvs工作方式的逻辑是非常之简单,而且工作在网络4层仅做请求分发之用,没有流量,所以在效率上基本不需要太过考虑。在我手里的 lvs,仅仅出过一次问题:在并发最高的一小段时间内均衡器出现丢包现象,据分析为网络问题,即网卡或linux2.4内核的承载能力已到上限,内存和 cpu方面基本无消耗。
B. 配置性低,这通常是一大劣势,但同时也是一大优势,因为没有太多可配置的选项,所以除了增减服务器,并不需要经常去触碰它,大大减少了人为出错的几率。
C. 工作稳定,因为其本身抗负载能力很强,所以稳定性高也是顺理成章,另外各种lvs都有完整的双机热备方案,所以一点不用担心均衡器本身会出什么问题,节点出现故障的话,lvs会自动判别,所以系统整体是非常稳定的。
D. 无流量,上面已经有所提及了。lvs仅仅分发请求,而流量并不从它本身出去,所以可以利用它这点来做一些线路分流之用。没有流量同时也保住了均衡器的IO性能不会受到大流量的影响。
E. 基本上能支持所有应用,因为lvs工作在4层,所以它可以对几乎所有应用做负载均衡,包括http、数据库、聊天室等等。
另:lvs也不是完全能判别节点故障的,譬如在wlc分配方式下,集群里有一个节点没有配置VIP,会使整个集群不能使用,这时使用wrr分配方式则会丢掉一台机。目前这个问题还在进一步测试中。所以,用lvs也得多多当心为妙。
A. 工作在网络的7层之上,可以针对http应用做一些分流的策略,比如针对域名、目录结构,它的正则规则比HAProxy更为强大和灵活,这也是它目前广泛流行的主要原因之一,Nginx单凭这点可利用的场合就远多于LVS了。
B. Nginx对网络稳定性的依赖非常小,理论上能ping通就就能进行负载功能,这个也是它的优势之一;相反LVS对网络稳定性依赖比较大,这点本人深有体会;
C. Nginx安装和配置比较简单,测试起来比较方便,它基本能把错误用日志打印出来。LVS的配置、测试就要花比较长的时间了,LVS对网络依赖比较大。
D. 可以承担高负载压力且稳定,在硬件不差的情况下一般能支撑几万次的并发量,负载度比LVS相对小些。
E. Nginx可以通过端口检测到服务器内部的故障,比如根据服务器处理网页返回的状态码、超时等等,并且会把返回错误的请求重新提交到另一个节点,不过其中缺点就是不支持url来检测。比如用户正在上传一个文件,而处理该上传的节点刚好在上传过程中出现故障,Nginx会把上传切到另一台服务器重新处理,而LVS就直接断掉了,如果是上传一个很大的文件或者很重要的文件的话,用户可能会因此而不满。
F. Nginx不仅仅是一款优秀的负载均衡器/反向代理软件,它同时也是功能强大的Web应用服务器。LNMP也是近几年非常流行的web架构,在高流量的环境中稳定性也很好。
G. Nginx现在作为Web反向加速缓存越来越成熟了,速度比传统的Squid服务器更快,可以考虑用其作为反向代理加速器。
H. Nginx可作为中层反向代理使用,这一层面Nginx基本上无对手,唯一可以对比Nginx的就只有lighttpd了,不过lighttpd目前还没有做到Nginx完全的功能,配置也不那么清晰易读,社区资料也远远没Nginx活跃。
I. Nginx也可作为静态网页和图片服务器,这方面的性能也无对手。还有Nginx社区非常活跃,第三方模块也很多。
J. Nginx新版本已经支持代理tcp各种协议,不再仅仅局限在代理http、https以及email。
97. zabbix监控哪些项目,模板是不是自己写的,触发报警有哪些,阀值都是多少
监控了CPU使用、系统负载、内存剩余、磁盘使用百分比、mysql主从、mysql队列数量、网站访问量、网卡流量、web状态码,有自己写的自定义监控脚本。触发报警的有系统负载(当高于20报警)、磁盘使用百分比(高于90%报警)、mysql主从是否正常(不正常告警)、mysql队列数量(高于400报警)、网卡流量(高于100M报警)等等。
10. php优化参数有哪些,fastcgi设置是多少,动态还是静态
11. TCP有哪些了解,TCP连接状态中“TIME_WAIT”是什么意思,影响什么
答:关于tcp有点复杂,直接上图吧,更直观
CLOSED: 这个没什么好说的了,表示初始状态。
LISTEN: 这个也是非常容易理解的一个状态,表示服务器端的某个SOCKET处于监听状态,可以接受连接了。
SYN_RCVD: 这个状态表示接受到了SYN报文,在正常情况下,这个状态是服务器端的SOCKET在建立TCP连接时的三次握手会话过程中的一个中间状态,很短暂,基本 上用netstat你是很难看到这种状态的,除非你特意写了一个客户端测试程序,故意将三次TCP握手过程中最后一个ACK报文不予发送。因此这种状态时,当收到客户端的ACK报文后,它会进入到ESTABLISHED状态。
SYN_SENT: 这个状态与SYN_RCVD遥想呼应,当客户端SOCKET执行CONNECT连接时,它首先发送SYN报文,因此也随即它会进入到了SYN_SENT状 态,并等待服务端的发送三次握手中的第2个报文。SYN_SENT状态表示客户端已发送SYN报文。
ESTABLISHED:这个容易理解了,表示连接已经建立了。
FIN_WAIT_1: 这个状态要好好解释一下,其实FIN_WAIT_1和FIN_WAIT_2状态的真正含义都是表示等待对方的FIN报文。而这两种状态的区别 是:FIN_WAIT_1状态实际上是当SOCKET在ESTABLISHED状态时,它想主动关闭连接,向对方发送了FIN报文,此时该SOCKET即 进入到FIN_WAIT_1状态。而当对方回应ACK报文后,则进入到FIN_WAIT_2状态,当然在实际的正常情况下,无论对方何种情况下,都应该马 上回应ACK报文,所以FIN_WAIT_1状态一般是比较难见到的,而FIN_WAIT_2状态还有时常常可以用netstat看到。
FIN_WAIT_2:上面已经详细解释了这种状态,实际上FIN_WAIT_2状态下的SOCKET,表示半连接,也即有一方要求close连接,但另外还告诉对方,我暂时还有点数据需要传送给你,稍后再关闭连接。
TIME_WAIT: 表示收到了对方的FIN报文,并发送出了ACK报文,就等2MSL后即可回到CLOSED可用状态了。如果FIN_WAIT_1状态下,收到了对方同时带 FIN标志和ACK标志的报文时,可以直接进入到TIME_WAIT状态,而无须经过FIN_WAIT_2状态。
CLOSING: 这种状态比较特殊,实际情况中应该是很少见,属于一种比较罕见的例外状态。正常情况下,当你发送FIN报文后,按理来说是应该先收到(或同时收到)对方的 ACK报文,再收到对方的FIN报文。但是CLOSING状态表示你发送FIN报文后,并没有收到对方的ACK报文,反而却也收到了对方的FIN报文。什 么情况下会出现此种情况呢?其实细想一下,也不难得出结论:那就是如果双方几乎在同时close一个SOCKET的话,那么就出现了双方同时发送FIN报 文的情况,也即会出现CLOSING状态,表示双方都正在关闭SOCKET连接。
CLOSE_WAIT: 这种状态的含义其实是表示在等待关闭。怎么理解呢?当对方close一个SOCKET后发送FIN报文给自己,你系统毫无疑问地会回应一个ACK报文给对 方,此时则进入到CLOSE_WAIT状态。接下来呢,实际上你真正需要考虑的事情是察看你是否还有数据发送给对方,如果没有的话,那么你也就可以 close这个SOCKET,发送FIN报文给对方,也即关闭连接。所以你在CLOSE_WAIT状态下,需要完成的事情是等待你去关闭连接。
LAST_ACK: 这个状态还是比较容易好理解的,它是被动关闭一方在发送FIN报文后,最后等待对方的ACK报文。当收到ACK报文后,也即可以进入到CLOSED可用状态了。
500:服务器内部错误,因为服务器上的程序写的有问题,需要打开错误日志,查看日志,分析错误信息。
502:网关错误,服务器作为网关或代理,从上游服务器收到无效响应。Nginx出现最多,出现502要么是nginx配置的不对,要么是php-fpm资源不够,可以分析php-fpm的慢执行日志,优化php-fpm的执行速度。
400:错误请求,服务器不理解请求的语法。这可能是用户发起的请求不合理,需要检查客户端的请求。
403:服务器拒绝请求。检查服务器配置,是不是对客户端做了限制。
404:未找到请求的资源。检查服务器上是否存在请求的资源,看是否是配置问题。
13. 从运维角度讲一下怎么预防cc攻击和ddos攻击
答案:先来说一下什么是cc攻击和ddos攻击。
1) CC主要是用来攻击页面的。大家都有这样的经历,就是在访问论坛时,如果这个论坛比较大,访问的人比较多,打开页面的速度会比较慢,访问的人越多,论坛的页面越多,数据库就越大,被访问的频率也越高,占用的系统资源也就相当可观。
一个静态页面不需要服务器多少资源,甚至可以说直接从内存中读出来发给你就可以了,但是论坛就不一样了,我看一个帖子,系统需要到数据库中判断我是否有读帖子的权限,如果有,就读出帖子里面的内容,显示出来——这里至少访问了2次数据库,如果数据库的数据容量有200MB大小,系统很可能就要在这200MB大小的数据空间搜索一遍,这需要多少的CPU资源和时间?如果我是查找一个关键字,那么时间更加可观,因为前面的搜索可以限定在一个很小的范围内,比如用户权限只查用户表,帖子内容只查帖子表,而且查到就可以马上停止查询,而搜索肯定会对所有的数据进行一次判断,消耗的时间是相当的大。
CC就是充分利用了这个特点,模拟多个用户(多少线程就是多少用户)不停的进行访问(访问那些需要大量数据操作,就是需要大量CPU时间的页面).这一点用一个一般的性能测试软件就可以做到大量模拟用户并发。
防御CC攻击可以通过多种方法,比如,可以分析攻击的请求头信息,分析它的特点,然后针对这些请求做一些限制。也可以分析请求的ip,利用iptables来限制ip。将网站做成静态页面,也可以有效降低服务器资源使用。另外,还可以限制连接数量,修改最大超时时间等。
2) ddos攻击的方式有很多种,最基本的ddos攻击就是利用合理的服务请求来占用过多的服务资源,从而使合法用户无法得到服务的响应。单一的ddos攻击一般是采用一对一方式的,当攻击目标CPU速度低、内存小或者网络带宽小等等各项指标不高的性能,它的效果是明显的。随着计算机与网络技术的发展,计算机的处理能力迅速增长,内存大大增加,同时也出现了千兆级别的网络,这使得DoS攻击的困难程度加大了-目标对恶意攻击包的"消化能力"加强了不少。这时候分布式的拒绝服务攻击手段(ddos)就应运而生了。ddos就是利用更多的傀儡机(肉鸡)来发起进攻,以比从前更大的规模来进攻受害者。
简单的ddos,比如cc,我们可以通过限定ip来解决攻击。但有时候攻击量很大,甚至可以把机房的网络攻击瘫痪,这时候只能临时在上层网络把目标IP封掉,这样牺牲单个ip而保全大局。也可以接入第三方的防ddos攻击的cdn。
2. 简要叙述下列端口锁运行的服务?
3. 列出当前linux服务器所有监听的端口以及进程号。
5. 简述tcp三次握手的过程?
第一次握手:建立连接。客户端发送连接请求报文段,将SYN位置为1,Sequence Number为x;然后,客户端进入SYN_SEND状态,等待服务器的确认;
Number为y;服务器端将上述所有信息放到一个报文段(即SYN+ACK报文段)中,一并发送给客户端,此时服务器进入SYN_RECV状态;
第三次握手:客户端收到服务器的SYN+ACK报文段。然后将Acknowledgment Number设置为y+1,向服务器发送ACK报文段,这个报文段发送完毕以后,客户端和服务器端都进入ESTABLISHED状态,完成TCP三次握手。
7. 如何查看占用端口8080的进程?
9. 你使用过监控软件吗?说说其特点?
答案参考第13套第9题
10.你认为系统调优方面都包括哪些工作,已linux为例,请阐述,并举一些参数为例?
11. 如何查看当前linux系统的状态如cpu使用,内存使用,负载情况,看到swap使用量大时,是不是意味着物理内存已不够用?
答案:top命令就可以看cpu使用、内存使用以及负载情况,当swap使用率大时,不一定是内存不够,如果swap容量固定不变,那内存就不是瓶颈。用vmstat 1命令看,si so两列的数值在不断变化时,内存就不够了。
14. 如何查看PID为29394的进程的环境变量?
15. 请找出 /home下所有5天前以.log结尾的文件列表?
16. linux软链接和硬链接的区别?
答案:软链接相当于windows的快捷方式,源文件删除软链接不可用,硬链接的文件对应同一个inode,源文件删除硬链接的文件可以用。软链接支持目录,硬链接不支持。
17. 当io出现瓶颈时,应该查看哪个参数,为什么?
答案: vmstat 1 查看wa列,wa列表示处于等待状态的cpu百分比,当IO比较慢时,CPU会有大量的wait。
$?最后运行的命令的返回值
$*所有参数列表。如"$*"用「"」括起来的情况、以"$1 $2 … $n"的形式输出所有参数
$@ 所有参数列表。如"$@"用「"」括起来的情况、以"$1" "$2" … "$n" 的形式输出所有参数
删除数据库中重复数据的几个方法
有两个意义上的重复记录,一是完全重复的记录,也即所有字段均重复的记录,二是部分关键字段重复的记录,比如Name字段重复,而其他字段不一定重复或都重复可以忽略。
1、对于第一种重复,比较容易解决,使用
就可以得到无重复记录的结果集。
如果该表需要删除重复的记录(重复记录保留1条),可以按以下方法删除
发生这种重复的原因是表设计不周产生的,增加唯一索引列即可解决。
2、这类重复问题通常要求保留重复记录中的第一条记录,操作方法如下
假设有重复的字段为Name,Address,要求得到这两个字段唯一的结果集
最后一个select即得到了Name,Address不重复的结果集(但多了一个autoID字段,实际写时可以写在select子句中省去此列)
更改数据库中表的所属用户的两个方法
大家可能会经常碰到一个数据库备份还原到另外一台机器结果导致所有的表都不能打开了,原因是建表的时候采用了当时的数据库用户…… --更改某个表
--存储更改全部表
SQL SERVER中直接循环写入数据
没什么好说的了,大家自己看,有时候有点用处
无数据库日志文件恢复数据库方法两则
数据库日志文件的误删或别的原因引起数据库日志的损坏
1.新建一个同名的数据库
3.用原数据库的数据文件覆盖掉这个新建的数据库
5.此时打开企业管理器时会出现置疑,先不管,执行下面的语句(注意修改其中的数据库名)
6.完成后一般就可以访问数据库中的数据了,这时,数据库本身一般还要问题,解决办法是,利用
数据库的脚本创建一个新的数据库,并将数据导进去就行了.
昨天,系统管理员告诉我,我们一个内部应用数据库所在的磁盘空间不足了。我注意到数据库事件日志文件XXX_Data.ldf文件已经增长到了3GB,于是我决意缩小这个日志文件。经过收缩数据库等操作未果后,我犯了一个自进入行业以来的最大最愚蠢的错误:竟然误删除了这个日志文件!后来我看到所有论及数据库恢复的文章上都说道:“无论如何都要保证数据库日志文件存在,它至关重要”,甚至微软甚至有一篇KB文章讲如何只靠日志文件恢复数据库的。我真是不知道我那时候是怎么想的?!
这下子坏了!这个数据库连不上了,企业管理器在它的旁边写着“(置疑)”。而且最要命的,这个数据库从来没有备份了。我唯一找得到的是迁移半年前的另外一个数据库服务器,应用倒是能用了,但是少了许多记录、表和存储过程。真希望这只是一场噩梦!
没有效果的恢复步骤
_Rambo讲过被删除日志文件中不存在活动日志时,可以这么做来恢复:
但是,很遗憾,执行之后,SQL Server质疑数据文件和日志文件不符,所以无法附加数据库数据文件。
不行,无法读取XXX数据库,DTS Wizard报告说“初始化上下文发生错误”。
怡红公子讲过没有日志用于恢复时,可以这么做:
2,重新建立一个log文件
4,把应用数据库设置成单用户模式
6,如果没有什么大问题就可以把数据库状态改回去了,记得别忘了把系统表的修改选项关掉
我实践了一下,把应用数据库的数据文件移走,重新建立一个同名的数据库XXX,然后停掉SQL服务,把原来的数据文件再覆盖回来。之后,按照怡红公子的步骤走。
但是,也很遗憾,除了第2步之外,其他步骤执行非常成功。可惜,重启SQL Server之后,这个应用数据库仍然是置疑!不过,让我欣慰的是,这么做之后,倒是能够Select数据了,让我大出一口气。只不过,组件使用数据库时,报告说:“发生错误:-,未能在数据库 'XXX' 中运行 BEGIN TRANSACTION,因为该数据库处于回避恢复模式。”
最终成功恢复的全部步骤
设置数据库为紧急模式
把应用数据库的数据文件XXX_Data.mdf移走;
重新建立一个同名的数据库XXX;
把原来的数据文件再覆盖回来;
运行以下语句,把该数据库设置为紧急模式;
DBCC 执行完毕。如果 DBCC 输出了错误信息,请与系统管理员联系。
(所影响的行数为 1 行)
运行以下语句,把应用数据库设置为Single User模式;
没有更新 sysdatabases 中的任何行,因为已正确地重置了模式和状态。没有错误,未进行任何更改。
DBCC 执行完毕。如果 DBCC 输出了错误信息,请与系统管理员联系。
重新建立另外一个数据库XXX.Lost;
运行DTS导出向导;
选择“在SQL Server数据库之间复制对象和数据”,试了多次,好像不行,只是复制过来了所有表结构,但是没有数据,也没有视图和存储过程,而且DTS向导最后报告复制失败;
所以最后选择“从源数据库复制表和视图”,但是后来发现,这样总是只能复制一部分表记录;
于是选择“用一条查询指定要传输的数据”,缺哪个表记录,就导哪个;
视图和存储过程是执行SQL语句添加的。
版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。