2 TCP 与 UDP
网络层:IP 协议,ICMP 协议,ARP 协议,RARP 协议和 BOOTP 协议;
传输层:TCP 协议与 UDP 协议;
应用层:FTP,HTTP,TELNET,SMTP,DNS 等协议;
HTTP 是应用层协议,其传输都是被包装成 TCP 协议传输.可以用 SOCKET 实现 HTTP.
Socket 是一组接口,可以实现 TCP,也可以实现 UDP.在设计模式中,Socket 其实就是一个门面模式,它把复杂的 TCP/UDP 协议族隐藏在 Socket 接口后面,对用户来说,一组简单的接口就是全部,让 Socket 去组织数据,以符合指定的协议.
TCP --- 传输控制协议,提供的是面向连接,可靠的字节流服务.当客户和服务器彼此交换数据前,必须先在双方之间建立一个 TCP 连接,之后才能传输数据.TCP 提供超时重发,丢弃重复数据,检验数据,流量控制等功能,保证数据能从一端传到另一端. 理想状态下,TCP 连接一旦建立,在通信双方中的任何一方主动关闭连接前,TCP 连接都将被一直保持下去.断开连接时服务器和客户端均可以主动发起断开 TCP 连接的请求.
UDP --- 用户数据报协议,是一个无连接的简单的面向数据报的运输层协议.UDP 不提供可靠性,它只是把应用程序传给 IP 层的数据包发送出去,但是并不能保证它们能到达目的地.由于 UDP 在传输数据包前不用在客户和服务器之间建立一个连接,且没有超时重发等机制,故而传输速度很快.
TCP 连接的三次握手:要了解 TCP,一定要知道 "三次握手,四次拜拜" 所谓的三次握手,就是发送数据前必须建立的连接叫三次握手,握手完了才开始发的,这也就是面向连接的意思.
第一次握手:客户端发送 syn 包 (syn=j) 到服务器,并进入 SYN_SEND 状态,等待服务器确认;
第二次握手:服务器收到 syn 包,必须确认客户的 SYN(ack=j+1),同时自己也发送一个 SYN 包(syn=k),即 SYN+ACK 包,此时服务器进入 SYN_RECV 状态;
第三次握手:客户端收到服务器的 SYN+ACK 包,向服务器发送确认包 ACK(ack=k+1),此包发送完毕,客户端和服务器进入 ESTABLISHED 状态,完成三次握手.
3 Java Thread
程序:是一段静态代码,它是应用软件执行的蓝本.
进程:是程序运行时的一个实例,对应了从代码加载,执行的一个完整过程,此过程也对应进程产生,发展到消亡的过程.
线程:比进程更小的执行单位,一个进程在其执行过程中,可以产生多个执行线程,即每个线程也有它的产生,发展到消亡的过程.是一个动态概念.
粒度层次不同,是两个不同层次上的概念.进程是由操作系统来管理的,而线程则是由进程来管理.
共享资源不同,不同进程的代码,内部数据和状态都是完全独立的,而一个进程内的多线程是共享进程空间资源的,有可能互相影响.
切换效率不同,线程本身的数据通常只有寄存器数据,以及一个进程执行时使用的堆栈,所以线程比进程切换负担小.
3.1 Thread 生命周期及状态模型
3.2 Thread 常用方法
Thread:
public static Thread currentThread( ):返回当前线程对象,是一个静态的方法.
public static void sleep(long millis):使当前线程进入睡眠状态,参数设定其等待时间,不会释放锁,静态方法.
public static void yield():使当前线程放弃执行,切换到其它线程,是一个静态方法.
Thread Instance:
public void start():启动线程,JVM 将调用此线程的 run 方法,结果是将同时运行两个线程,当前线程和执行 run 方法的线程.
public void run():Thread 的子类应该重写此方法,内容应为该线程应执行的任务.
public void stop():停止线程运行,并退出可执行状态. [已过时]
public void resume():将暂停的线程继续执行.[已过时]
public void suspend():使线程暂停执行,不退出可执行态.[已过时]
public void interrupt():中断线程.
public void join():在当前线程中加入调用 join 方法的线程 A,直到线程 A 死亡才能继续执行当前线程.
public void join(long millis):在当前线程中加入调用 join 方法的线程 A,直到到达参数指定的毫秒数或线程 A 死亡才能继续执行当前线程.
public void setPriority(int newPriority):设置线程优先级.
public void setDaemon(boolean on):设置是否为后台线程.如果当前运行线程均为后台线程则 JVM 停止运行.该方法必须在 start() 方法之前使用.
public final void checkAccess():判断当前线程是否有权力修改调用此方法的线程.
public boolean isAlive():判断线程是否处于执行状态.返回值 true 表示处于运行状态,false 表示已停止.
Object:
public void wait():在其他线程调用此对象的 notify() 方法或 notifyAll() 方法前,使当前线程进入等待状态,会释放锁.
public void notify(): 唤醒在此对象监视器上等待的单个线程.
public void notifyAll():唤醒在此对象监视器上等待的所有线程.
3.3 main() 主线程与子线程
主线程:Java 应用程序总是从主类的 main() 方法开始执行.当 JVM 加载代码,发现 main 方法之后,启动的线程称作" 主线程 ",该线程负责执行 main 方法.
子线程:在 main 方法的执行中再创建的线程.
如果 main 方法中又创建了子线程,那么 JVM 就要在主线程和子线程之间轮流切换,main 方法即使执行完最后的语句,JVM 也不会结束程序,JVM 一直要等到程序中的所有线程都结束之后,才结束我们的 Java 应用程序.
3.4 Thread 线程创建两种方法
Thread 类:Thread 类的子类创建线程对象,子类重写 Thread 类中的 run() 方法; 在 Java 程序中创建多线程的方法之一是继承 Thread 类,从 Thread 类派生一个子类,并创建这个子类的对象,就可以产生一个新的线程.这个子类应该重写 Thread 类的 run 方法,在 run 方法中写入需要在新线程中执行的语句段.这个子类的对象需要调用 start 方法来启动,新线程等待 CPU 调度将自动进入 run 方法.当前线程将同时继续往下执行. 当创建子类的多个线程对象时,其成员变量和 run() 方法中局部变量都是互不干扰的.
Runnable 接口:使用 Thread 类直接创建线程对象,但需要传入实现 Runable 接口的目标对象. 在编写复杂程序时相关的类可能已经继承了某个基类,而 Java 不支持多继承,在这种情况下,便需要通过实现 Runnable 接口来生成多线程. 使用 Thread 创建线程对象时,通常使用的构造方法是:Thread(Runnable target),该构造方法中的参数是一个 Runnable 类型的接口,因此,在创建线程对象时必须向构造方法的参数传递一个实现 Runnable 接口类的实例,该实例对象称作所创线程的目标对象. 当线程调用 start 方法后,一旦轮到它来享用 CPU 资源,目标对象就会自动调用接口中的 run 方法(接口回调). 对于使用同一目标对象的线程,目标对象的成员变量自然就是这些线程的共享数据单元.不同 run() 方法中的局部变量互不干扰.
3.5 Thread 同步
synchronized -- 线程同步关键字
把需要修改数据的方法用关键字 synchronized 来修饰,用于指定需要同步的代码段或方法,也就是监视区.
当一个线程 A 使用一个 synchronized 修饰的方法时,其他线程想使用这个方法时就必须等待,直到线程 A 使用完该方法 (除非线程 A 使用 wait 主动让出 CUP 资源).
当被 synchronized 限定的代码段执行完,就释放对象锁(信号量).
3.6 Thread 通信
为了更有效地协调不同线程的工作,需要在线程间建立沟通渠道,通过线程间的 "对话" 来解决线程间的同步问题.
java.lang.Object 类的一些方法为线程间的通讯提供了有效手段.
一个线程在使用的同步方法中时,可能根据问题的需要,必须使用 wait() (挂起) 方法使本线程等待,暂时让出 CPU 的使用权,并允许其它线程使用这个同步方法.其它线程如果在使用这个同步方法时如果不需要等待,那么它用完这个同步方法的同时,应当执行 notify(), notifyAll()(恢复)方法通知所有的由于使用这个同步方法而处于等待的线程结束等待.
3.7 Thread 调度机制
每个 Java 线程都有一个优先级,其范围都在 1 和 10 之间. 默认情况下,每个线程的优先级都设置为 5.
在线程 A 运行过程中创建的新的线程对象 B,初始状态具有和线程 A 相同的优先级.可在线程创建之后的任何时候,通过 setPriority(int priority) 方法改变其原来的优先级.
基于线程优先级的线程调度:
具有较高优先级的线程比优先级较低的线程优先执行;
对具有相同优先级的线程,Java 的处理是随机的;
底层操作系统支持的优先级可能要少于 10 个,这样会造成一些混乱.因此,只能将优先级作为一种很粗略的工具使用.最后的控制可以通过明智地使用 yield() 函数来完成;
假设某线程正在运行,则只有出现以下情况之一,才会使其暂停运行:
一个具有更高优先级的线程变为就绪状态(Ready);
由于输入 / 输出(或其他一些原因),调用 sleep,wait,yield 方法使其发生阻塞;
对于支持时间分片的系统,时间片的时间期满;
通常,我们在一个线程内部插入 yield() 语句,这个方法会使正在运行的线程暂时放弃执行,这时具有同样优先级的线程就有机会获得调度开始运行,但较低优先级的线程仍将被忽略不参加调度;
3.8 Thread 挂起与恢复
挂起 有时候两个线程并不是同步的,即不涉及都需要调用一个同步方法,但线程也可能需要暂时的挂起.所谓挂起一个线程就是让线程暂时让出 CPU 的使用权限,暂时停止执行,但停止执行的持续时间不确定,因此不能使用 sleep 方法暂停线程.挂起一个线程需使用 wait 方法,即让准备挂起的线程调用 wait 方法,主动让出 CPU 的使用权限.
恢复 为了恢复该线程,其它线程在占有 CUP 资源期间,让挂起的线程的目标对象执行 notifyAll() 方法,使得挂起的线程继续执行;如果线程没有目标对象,为了恢复该线程,其它线程在占有 CPU 资源期间,让挂起的线程调用 notifyAll() 方法,使挂起的线程继续执行.
4 Java 数据结构
线性表结构一般分为三种:顺序线性表,单链表,双链表;特征:
一个特定的线性表,应该是用来存放特定的某一个类型的元素的( 元素的 "同一性");
除第一个元素外,其他每一个元素 有且仅有一个直接前驱;除最后一个元素外,其他每一个元素 有且仅有一个直接后继( 元素的 "序偶性");
元素在线性表中的 "下标" 唯一地确定该元素在表中的相对位置( 元素的 "索引性");
二叉树是树形结构的一个重要类型.许多实际问题抽象出来的数据结构往往是二叉树的形式,即使是一般的树也能简单地转换为二叉树,而且二叉树的存储结构及其算法都较为简单,因此二叉树显得特别重要. 二叉树 (BinaryTree) 是 n(n≥0)个结点的有限集,它或者是空集(n=0),或者由一个根结点及两棵互不相交的,分别称作这个根的左子树和右子树的二叉树组成.这个定义是递归的.由于左,右子树也是二叉树, 因此子树也可为空树. 二叉树遍历:由于被访问的结点必是某子树的根,所以 N(Node),L(Left subtlee)和 R(Right subtree)又可解释为根,根的左子树和根的右子树.NLR,LNR 和 LRN 分别又称为 先根遍历,中根遍历和后根遍历.
队列是一个常用的数据结构,是一种 先进先出(First In First Out, FIFO) 的结构,也就是说只能在表头进行删除,在表尾进行添加.
栈是一种 后进先出(Last In First Out,LIFO) 的数据结构.
5 JDK 命令行工具
jps : 只用于列出 java 的进程.
jstat :可用于观察 Java 应用程序运行时信息的工具.
jinfo :可用于查看正在运行的 Java 应用程序的扩展参数,甚至支持在运行时修改部分参数.
jmap :生成 Java 应用程序的堆快照和对象的统计信息.jmap -histo 2972 > heap.log
jhat :用于分析 Java 应用程序的堆快照内容文件.jhat heap.log
jstack : 用于导出 Java 应用程序的线程堆栈. jstack -l 2348 > jstack.log
6 静态代理和动态代理
静态代理:由程序员创建或工具生成代理类的源码,再编译代理类.所谓静态也就是在程序运行前就已经存在代理类的字节码文件,代理类和委托类的关系在编译期就确定了.
动态代理:动态代理类的源码是在程序运行期间由 JVM 根据反射等机制动态的生成,所以不存在代理类的字节码文件.代理类和委托类的关系是在程序运行期确定.
7 Http 基础
7.1 HTTP 协议
一种通信协议,它允许将超文本标记语言 (html) 文档从 web 服务器传送到客户端的浏览器. 一个属于应用层的面向对象的协议,由于其简捷,快速的方式,适用于分布式超媒体信息系统.
HTTP 协议的主要特点如下:
支持客户 / 服务器模式,基于 TCP 实现;
简单快速:客户向服务器请求服务时,只需传送请求方法和路径.请求方法常用的有 GET,POST,DELETE,PUT.每种方法规定了客户与服务器联系的类型不同.由于 HTTP 协议简单,使得 HTTP 服务器的程序规模小,因而通信速度很快;
灵活:HTTP 允许传输任意类型的数据对象.正在 传输的类型由 Content-Type 加以标记;
短连接:短连接的含义是限制每次连接只处理一个请求.服务器处理完客户的请求,并收到客户的应答后,即断开连接.采用这种方式可以节省传输时间.
无状态:HTTP 协议是无状态协议.无状态是指协议对于事务处理没有记忆能力.缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大.另一方面,在服务器不需要先前信息时它的应答就较快.
7.2 CGI 是什么
CGI(Common Gateway Interface), 通用网关接口, 它是一段程序, 运行在服务器上如:HTTP 服务器,提供同客户端 HTML 页面的接口.利用程序的标准输入输出流,完成 HTTP 通信.HTTP 是文本协议,每次请求的文本以标准输入流的形式进入服务器端 CGI 程序,创建进程;然后进程的标准输出流作为响应.
CGI 程序可以是 Python 脚本,PERL 脚本,SHELL 脚本,C 或者 C++ 程序等. 所有服务器端 HTTP 处理都是类 CGI 的原理,接受符合协议的标准输入文本流,从标准输出流输出同样符合协议的文本,也就是 "请求" 和 "响应".
7.3 负载均衡,分布式集群
在负载均衡的思路下,多台服务器为对等方式,每台服务器都具有同等的地位,可以单独对外提供服务而无须其他服务器的辅助.通过负载分担技术,将外部发送来的请求按一定规则分配到对称结构中的某一台服务器上,而接收到请求的服务器都独立回应客户机的请求.
常用负载均衡技术:反向代理负载均衡 (如 Apache+JK2+Tomcat 这种组合),使用代理服务器可以将请求转发给内部的 Web 服务器,让代理服务器将请求均匀地转发给多台内部 Web 服务器之一上,从而达到负载均衡的目的.这种代理方式与普通的代理方式有所不同,标准代理方式是客户使用代理访问多个外部 Web 服务器,而这种代理方式是多个客户使用它访问内部 Web 服务器,因此也被称为反向代理模式.
客户系统一般采用 Apache httpd 作为 web 服务器,即作为 Tomcat 的前端处理器,根据具体情况而定,有些情况下是不需要 Apache httpd 作为 web 服务器的,如系统展现没有静态页面那就不需要 Apache httpd,那时可以直接使用 Tomcat 作为 web 服务器来使用.使用 Apache httpd 主要是它在处理静态页面方面的能力比 Tomcat 强多了.
会话亲和:就是表示来自同会话的所有请求都由相同的 Tomcat 实例来处理,这种情况下,如果 Tomcat 实例或所执行的服务器机器失效,也会丧失 Servlet 的会话数据.即使在集群系统中执行更多的 Tomcat 实 例,也永远不会复制会话数据.这样是提高集群性能的一种方案,但不具备有容错能力了.
会话复制:只配置负载均衡还不行,还要 session 复制,也就是说其中任何一个 tomcat 的添加的 session ,是要同步复制到其它 tomcat , 集群内的 tomcat 都有相同的 session,使用会话复制,则当一个 Tomcat 实例宕掉时,由于至少还有另一个 Tomcat 实例保有一份会话状态数据,因而数据不会丧失.但性能会 有所降低.
其实无论是分布式,数据缓存,还是负载均衡,无非就是改善网站的性能瓶颈,在网站源码不做优化的情况下,负载均衡可以说是最直接的手段了.其实抛开这个名词,放开了说,就是希望用户能够分流,也就是说把所有用户的访问压力分散到多台服务器上,也可以分散到多个 tomcat 里,如果一台服务器装多个 tomcat,那么即使是负载均衡,性能也提高不了太多,不过可以提高稳定性,即容错性.当其中一个主 tomcat 当掉,其他的 tomcat 也可以补上,因为 tomcat 之间实现了 Session 共享.待 tomcat 服务器修复后再次启动,就会自动拷贝所有 session 数据,然后加入集群.这样就可以不间断的提供服务.如果要真正从本质上提升性能,必须要分布到多台服务器.
8 Linux 基础
8.1 Linux 启动原理
CMOS:记录 各项硬件参数且嵌入在主板上面的存储器; BIOS:一个写入到主板上的一个韧体(韧体就是写入到硬件上的一个程序).BIOS 就是在开机的时候计算机系统会主动执行的第一个程序了.
首先加载 BIOS 程序,通过 BIOS 程序去 加载 CMOS 信息,取得主机的各项硬件配置,并开始进行开机自检,依据设置取得第一个可启动的设备;
加载执行第一个启动设备内 MBR 的 Boot Loader;
依据 Boot Loader 的 设置加载 Kernel,Kernel 会开始检测硬件与加载驱动程序;
在硬件驱动成功后, Kernel 会主动调用 init 进程,而 init 会取得 run-level 信息;
init 执行 /etc/rc.d/rc.sysinit 文件来准备软件执行的操作环境(如网络,时区等);
init 执行 run-level 的各个服务启动(script 方式);
init 执行 /etc/rc.d/rc.local 文件;
init 执行 终端模拟程序 mingetty 来启动 login 进程,最后就等待用户登录;
8.2 Linux 命令行工具
top : 实时显示系统中各个进程的资源占用状况.前半部分是系统统计信息,后半部分是进程占用资源状况信息.
sar : 周期性地对内存和 CPU 使用情况进行采样.查看 CPU 使用情况:sar -u 1 3;查看内存使用情况:sar -r 1 3;查看 I/O 使用情况:sar -b 1 3
vmstat : 周期性地统计 CPU 内存 swap 使用情况等信息.vmstat 1 3
iostat : 周期性查看 I/O 信息.iostat 1 2
pidstat:功能强大的性能检测工具, 不仅可以监视进程的 CPU,I/O,内存资源,也可以监视线程的性能情况.
查看 CPU 使用情况: pidstat -p 1187 -u 1 3[-t 参数将系统性能的监控细化到线程级别]
查看内存使用情况: pidstat -p 1187 -r 1 3 [-t 参数将系统性能的监控细化到线程级别]
查看 I/O 使用情况: pidstat -p 1187 -d 1 3 [-t 参数将系统性能的监控细化到线程级别]
netstat:用于查看各种网络相关信息,如网络连接,路由表,接口状态 (Interface Statistics),masquerade 连接,多播成员 (Multicast Memberships) 等等.
netstat -na 来显示所有连接的端口并用数字表示.
mpstat:用于获取 CPU 相关统计信息.mpstat -P ALL 5 2 显示了系统中 CPU 的各种统计信息.-P ALL 选项指示该命令显示所有 CPU 的统计信息.参数 5 2 指示该命令每隔 5 秒运行一次,共运行 2 次.
pmap:report memory map of a process(查看进程的内存映像信息).
pmap -d 1
-x extended Show the extended format. 显示扩展格式
-d device Show the device format. 显示设备格式
-q quiet Do not display some header/footer lines. 不显示头尾行
-V show version Displays version of program. 显示版本
来源: https://juejin.im/post/5a657ed1f265da3e3304726a