计算机网络知识回顾

#计算机网络知识回顾

OSI七层模型:

被一些大公司甚至一些国家政府支持的OSI失败的原因:

1)OSI的专家缺乏实际经验,他们在完成OSI标准时缺乏商业驱动力

2)OSI的协议实现起来过分复杂,而且运行效率很低

3)OSI制定标准的周期太长,占领市场失败,使得按OSI标准生产的设备无法及时进入市场(20世纪90年代初期,虽然整套的OSI国际标准都已经制定出来,但基于TCP/IP的互联网已经抢先在全球相当大的范围成功运行了)OSI的层次划分不太合理,有些功能在多个层次中重复出现

###OSI七层结构:

  • 应用层
  • 表示层
  • 会话层
  • 运输层
  • 网络层
  • 数据链路层
  • 物理层

###TCP\IP四层协议:

  • 应用层(各种应用层协议TELNET,SMTP,FTP)
  • 运输层(TCP UDP)
  • 网际层(IP)
  • 网络接口层

###五层协议体系结构:

  • 应用层
  • 运输层(TCP\UDP)
  • 网络层(IP)
  • 数据链路层
  • 物理层

应用层

应用程序间的网络通信交互规则

应用层的任务是通过应用进程间的交互来完成特定网络应用。应用层协议定义的是应用进程(进程:主机中正在运行的程序)间的通信和交互的规则。对于不同的网络应用需要不同的应用层协议。在互联网中应用层协议很多,如域名系统DNS,支持万维网应用的HTTP协议,支持电子邮件的SMTP协议等等。我们把应用层交互的数据单元称为报文。

DNS(Domain Name System)

域名系统是因特网的一项核心服务,它作为可以将域名和IP地址相互映射的一个分布式数据库,能够使人更方便的访问互联网,而不用去记住能够被机器直接读取的IP数串。(百度百科)例如:一个公司的Web网站可看作是它在网上的门户,而域名就相当于其门牌地址,通常域名都使用该公司的名称或简称。

HTTP协议

超文本传输协议(HTTP,HyperText Transfer Protocol)是互联网上应用最为广泛的一种网络协议。

传输层

传递应用层报文

运输层的主要任务就是负责向两台主机进程之间的通信提供通用的数据传输服务。应用进程利用该服务传送应用层报文。“通用的”是指并不针对某一个特定的网络应用,而是多种应用可以使用同一个运输层服务。由于一台主机可同时运行多个线程,因此运输层有复用和分用的功能。所谓复用就是指多个应用层进程可同时使用下面运输层的服务,分用和复用相反,是运输层把收到的信息分别交付上面应用层中的相应进程。

-传输控制协议TCP(Transmisson Control Protocol)–提供面向连接的,可靠的数据传输服务。
-用户数据协议UDP(User Datagram Protocol)–提供无连接的,尽最大努力的数据传输服务(不保证数据传输的可靠性)。

网络层

打包报文段或用户数据,并找寻合适的路由,进而找到目标主机

网络层负责为分组交换网上的不同主机提供通信服务。在发送数据时,网络层把运输层产生的报文段或用户数据报封装成分组和包进行传送。在TCP/IP体系结构中,由于网络层使用IP协议,因此分组也叫IP数据报,简称数据报。

数据链路层

两台主机之间的数据传输,总是在一段一段的链路上传送的,这就需要使用专门的链路层的协议。

在两个相邻节点之间传送数据时,数据链路层将网络层交下来的IP数据报组装程帧,在两个相邻节点间的链路上传送帧。每一帧包括数据和必要的控制信息(如同步信息,地址信息,差错控制等)。

在接收数据时,控制信息使接收端能够知道一个帧从哪个比特开始和到哪个比特结束。这样,数据链路层在收到一个帧后,就可从中提出数据部分,上交给网络层.

物理层

在物理层上所传送的数据单位是比特。实现相邻计算机节点之间比特流的透明传送,尽可能屏蔽掉具体传输介质和物理设备的差异。

计算机网络相关问题

计算机网络相关问题

①TCP三次握手和四次挥手

三次握手(创建)

1)客户端–发送带有SYN标志的数据包–一次握手–服务端
2)服务端–发送带有SYN/ACK标志的数据包–二次握手–客户端
3)客户端–发送带有带有ACK标志的数据包–三次握手–服务端

第二次握手中,服务端为何要传回SYN(发起一个新链接)?

接收端传回发送端所发送的SYN是为了告诉发送端,我接收到的信息确实就是你所发送的信号了。

双方通信无误必须是两者互相发送信息都无误。传了SYN,证明发送方到接收方的通道没有问题,但是接收方到发送方的通道还需要ACK信号来进行验证。

四次挥手(断开)

1)客户端-发送一个FIN,用来关闭客户端到服务器的数据传送
2)服务器-收到这个FIN,发回一个ACK,确认序号为收到的序号加1。和SYN一样,一个FIN将占用一个序号
3)服务器-关闭与客户端的连接,发送一个FIN给客户端
4)客户端-发回ACK报文确认,并将确认序号设置为收到序号加1

②在浏览器中输入url地址->>显示主页的过程(完整描述)

域名解析 –> 发起TCP的3次握手 –> 建立TCP连接后发起http请求 –> 服务器响应http请求,浏览器得到html代码 –> 浏览器解析html代码,并请求html代码中的资源(如js、css、图片等) –> 浏览器对页面进行渲染呈现给用户

③HTTP和HTTPS的区别

④TCP、UDP协议的区别

UDP:

UDP在传送数据之前不需要先建立连接,远地主机在收到UDP报文后,不需要给出任何确认。虽然UDP不提供可靠交付,但在某些情况下UDP确是一种最有效的工作方式(一般用于即时通信),比如: QQ语音 QQ视频 、直播等等

1)无连接
2)尽力交付,不保证可靠
3)面向报文
4)没有拥塞控制(网络出现拥塞不会使源主机的发送速率降低,对实时应用很有用)
5)支持一对一,一对多,多对多交互通信
6)UDP的首部开销小,只有8个字节,比TCP的20个字节的首部要短。

TCP:

TCP提供面向连接的服务。在传送数据之前必须先建立连接,数据传送结束后要释放连接。TCP不提供广播或多播服务。由于TCP要提供可靠的,面向连接的运输服务(TCP的可靠体现在TCP在传递数据之前,会有三次握手来建立连接,而且在数据传递时,有确认、窗口、重传、拥塞控制机制,在数据传完后,还会断开连接,四次挥手,用来节约系统资源),这一难以避免增加了许多开销,如确认,流量控制,计时器以及连接管理等。这不仅使协议数据单元的首部增大很多,还要占用许多处理机资源。TCP一般用于文件传输、发送和接收邮件、远程登录等场景。

1)面向连接(就好像打电话一样,通话前需要先拨号建立连接,通话结束后要挂机释放连接)
2)TCP连接只能是点对点的(一对一)
3)可靠(通过TCP连接传送的数据,无差错、不丢失、不重复、并且按序到达)
4)TCP提供全双工通信。TCP允许通信双方的应用进程在任何时候都能发送数据。TCP连接的两端都设有发送缓存和接收缓存,用来临时存放双方通信的数据
5)面向字节流。TCP中的“流”(stream)指的是流入进程或从进程流出的字节序列。“面向字节流”的含义是:虽然应用程序和TCP的交互是一次一个数据块(大小不等),但TCP把应用程序交下来的数据仅仅看成是一连串的无结构的字节流。

⑤常见的状态码

1XX informational(信息性状态码) 请求正在处理

2XX Success(成功状态码) 请求正常处理完毕

3XX Redirection(重定向状态码) 需要进行附加操作才能完成请求

4XX Client Error(客户端错误状态码) 服务无法处理请求

5XX Server Error(服务端错误状态码) 服务端处理请求出错

sass sass-loader

window下无法安装sass sass-loader

node-sass安装失败的原因是网络限制导致无法下载.node文件

推荐方法:使用淘宝镜像

1
npm set sass_binary_site=https://npm.taobao.org/mirrors/node-sass/

or

1
2
npm install -g cnpm --registry=https://registry.npm.taobao.org
cnpm install node-sass sass-loader -S

其他翻墙、手动导入文件的方式不推荐。

JVM相关问题

JVM相关问题

1.JVM内存模型,GC机制和原理。

2.GC分两种,Minor GC和 Full GC有什么区别?什么时候会触发Full GC?分别采用什么算法?

3.JVM里有几种classloader,为什么会有多种?

4.什么是双亲委派机制?介绍一些运作过程,双亲委派模式的好处?

5.什么情况下我们需要破坏双亲委派模型?

6.常见的JVM调优有哪些?可以具体到那个参数,调成什么值?

7.JVM虚拟机内存划分、类加载器、垃圾收集算法、垃圾收集器、class文件结构是如何解析的?

Zookeeper通知机制

Zookeeper通知机制

客户端注册监听(watch)它关心的目录节点,当目录节点发生变化(数据改变、被删除、子目录节点增加删除)时,zookeeper会通知客户端。

Zookeeper做了什么?

1.命名服务 2.配置管理 3.集群管理 4.分布式锁 5.队列管理

命名服务

在zookeeper的文件系统里创建一个目录,即有唯一的path。在我们使用tborg无法确定上游程序的部署机器时即可与下游程序约定好path,通过path即能互相探索发现。

命名服务是分布式系统中比较常见的一类场景。在分布式系统中,被命名的实体通常可以是集群中的机器、提供的服务地址或远程对象等——这些我们都可以统称它们为名字(Name),
其中较为常见的就是一些分布式服务框架(如RPC、RMI)中的服务地址列表,通过使用命名服务,客户端应用能够根据指定名字来获取资源的实体、服务地址和提供者的信息等。

Java中的JNDI便是一种典型的命名服务。JNDI是Java命名与目录接口(Java Naming and Directory Interface)的缩写,是J2EE体系中重要的规范之一,标准的J2EE容器都提供了对JNDI规范的实现。
因此,在实际开发中,开发人员常常使用应用服务窗口自带的JNDI实现来完成数据源的配置与管理。
使用JNDI方式后,开发人员可以完全不需要关心数据库相关的任何信息,包括数据库类型、JDBC驱动类型及数据库账户等。

ZooKeeper的命名服务有两个应用方向:

  1. ZooKeeper提供类似JNDI服务,都能够帮助应用系统通过一个资源引用的方式来实现对资源的定位与实用。
  2. 利用ZooKeeper顺序节点的特性,制作分布式的ID生成器。

配置管理

程序总是需要配置的,如果程序分散部署在多台机器上,要逐个改变配置就变得困难。现在把这些配置全部放到zookeeper上去,保存在 Zookeeper 的某个目录节点中,
然后所有相关应用程序对这个目录节点进行监听,一旦配置信息发生变化,每个应用程序就会收到 Zookeeper 的通知,然后从 Zookeeper 获取新的配置信息应用到系统中就好。

集群管理

所谓集群管理无在乎两点:是否有机器退出和加入、选举master。

对于第一点,所有机器约定在父目录GroupMembers下创建临时目录节点,然后监听父目录节点的子节点变化消息。一旦有机器挂掉,该机器与 zookeeper的连接断开,其所创建的临时目录节点被删除,所有其他机器都收到通知:某个兄弟目录被删除,于是,所有人都知道:它上船了。
新机器加入也是类似,所有机器收到通知:新兄弟目录加入,highcount又有了。

对于第二点,我们稍微改变一下,所有机器创建临时顺序编号目录节点,每次选取编号最小的机器作为master就好。

Zookeeper分布式锁

有了zookeeper的一致性文件系统,锁的问题变得容易。锁服务可以分为两类,一个是保持独占,另一个是控制时序。

对于第一类,我们将zookeeper上的一个znode看作是一把锁,通过createznode的方式来实现。所有客户端都去创建 /distribute_lock 节点,最终成功创建的那个客户端也即拥有了这把锁。用完删除掉自己创建的distribute_lock 节点就释放出锁。

对于第二类, /distribute_lock 已经预先存在,所有客户端在它下面创建临时顺序编号目录节点,和选master一样,编号最小的获得锁,用完删除,依次方便。

队列管理

两种类型的队列:

1、同步队列,当一个队列的成员都聚齐时,这个队列才可用,否则一直等待所有成员到达。

2、队列按照 FIFO 方式进行入队和出队操作。

第一类,在约定目录下创建临时目录节点,监听节点数目是否是我们要求的数目。

第二类,和分布式锁服务中的控制时序场景基本原理一致,入列有编号,出列按编号。

BIO,NIO,AIO 总结

BIO,NIO,AIO IO模型总结

Java 中的 BIO、NIO和 AIO 理解为是 Java 语言对操作系统的各种 IO 模型的封装。
程序员在使用这些 API 的时候,不需要关心操作系统层面的知识,也不需要根据不同操作系统编写不同的代码。
只需要使用Java的API就可以了。

同步与异步

同步:

同步就是发起一个调用后,被调用者未处理完请求之前,调用不返回。

异步:

异步就是发起一个调用后,立刻得到被调用者的回应表示已接收到请求,但是被调用者并没有返回结果,此时我们可以处理其他的请求,
被调用者通常依靠事件,回调等机制来通知调用者其返回结果。

同步和异步的区别最大在于异步的话调用者不需要等待处理结果,被调用者会通过回调等机制来通知调用者其返回结果。

阻塞和非阻塞

阻塞:

阻塞就是发起一个请求,调用者一直等待请求结果返回,也就是当前线程会被挂起,无法从事其他任务,只有当条件就绪才能继续。

非阻塞:

非阻塞就是发起一个请求,调用者不用一直等着结果返回,可以先去干其他事情。

1
2
3
4
5
举个生活中简单的例子,你妈妈让你烧水,

小时候你比较笨啊,在那里傻等着水开(同步阻塞)。
等你稍微再长大一点,你知道每次烧水的空隙可以去干点其他事,然后只需要时不时来看看水开了没有(同步非阻塞)。
后来,你们家用上了水开了会发出声音的壶,这样你就只需要听到响声后就知道水开了,在这期间你可以随便干自己的事情,你需要去倒水了(异步非阻塞)。

BIO (Blocking I/O)

同步阻塞I/O模式,数据的读取写入必须阻塞在一个线程内等待其完成。

传统 BIO

BIO通信(一请求一应答)

采用 BIO 通信模型 的服务端,通常由一个独立的 Acceptor 线程负责监听客户端的连接。
我们一般通过在while(true) 循环中服务端会调用 accept() 方法等待接收客户端的连接的方式监听请求,
请求一旦接收到一个连接请求,就可以建立通信套接字在这个通信套接字上进行读写操作,此时不能再接收其他客户端连接请求,
只能等待同当前连接的客户端的操作执行完成, 不过可以通过多线程来支持多个客户端的连接

如果要让 BIO 通信模型能够同时处理多个客户端请求,就必须使用多线程
(主要原因是socket.accept()、socket.read()、socket.write() 涉及的三个主要函数都是同步阻塞的),
也就是说它在接收到客户端连接请求之后为每个客户端创建一个新的线程进行链路处理,处理完成之后,
通过输出流返回应答给客户端,线程销毁。这就是典型的 一请求一应答通信模型 。
我们可以设想一下如果这个连接不做任何事情的话就会造成不必要的线程开销,不过可以通过线程池机制改善,
线程池还可以让线程的创建和回收成本相对较低。使用FixedThreadPool 可以有效的控制了线程的最大数量,
保证了系统有限的资源的控制,实现了N(客户端请求数量):M(处理客户端请求的线程数量)的伪异步I/O模型(N 可以远远大于 M)

我们再设想一下当客户端并发访问量增加后这种模型会出现什么问题?

1
2
3
4
Java 虚拟机中,线程是宝贵的资源,线程的创建和销毁成本很高,除此之外,线程的切换成本也是很高的。
尤其在 Linux 这样的操作系统中,线程本质上就是一个进程,创建和销毁线程都是重量级的系统函数。
如果并发访问量增加会导致线程数急剧膨胀可能会导致线程堆栈溢出、创建新线程失败等问题,最终导致进程宕机或者僵死,
不能对外提供服务。

Demo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
public class IOClient {

public static void main(String[] args) {
// TODO 创建多个线程,模拟多个客户端连接服务端
new Thread(() -> {
try {
Socket socket = new Socket("127.0.0.1", 3333);
while (true) {
try {
socket.getOutputStream().write((new Date() + ": hello world").getBytes());
Thread.sleep(2000);
} catch (Exception e) {
}
}
} catch (IOException e) {
}
}).start();

}

}



public class IOServer {

public static void main(String[] args) throws IOException {
// TODO 服务端处理客户端连接请求
ServerSocket serverSocket = new ServerSocket(3333);

// 接收到客户端连接请求之后为每个客户端创建一个新的线程进行链路处理
new Thread(() -> {
while (true) {
try {
// 阻塞方法获取新的连接
Socket socket = serverSocket.accept();

// 每一个新的连接都创建一个线程,负责读取数据
new Thread(() -> {
try {
int len;
byte[] data = new byte[1024];
InputStream inputStream = socket.getInputStream();
// 按字节流方式读取数据
while ((len = inputStream.read(data)) != -1) {
System.out.println(new String(data, 0, len));
}
} catch (IOException e) {
}
}).start();

} catch (IOException e) {
}

}
}).start();

}

}

伪异步 IO

为了解决同步阻塞I/O面临的一个链路需要一个线程处理的问题,后来有人对它的线程模型进行了优化一一一
后端通过一个线程池来处理多个客户端的请求接入,
形成客户端个数M:线程池最大线程数N的比例关系,其中M可以远远大于N.
通过线程池可以灵活地调配线程资源,设置线程的最大值,防止由于海量并发接入导致线程耗尽。

采用线程池和任务队列可以实现一种叫做伪异步的 I/O 通信框架

当有新的客户端接入时,将客户端的 Socket 封装成一个Task(该任务实现java.lang.Runnable接口)投递到后端的线程池中
进行处理,JDK 的线程池维护一个消息队列和 N 个活跃线程,对消息队列中的任务进行处理。由于线程池可以设置消息队列的大小
和最大线程数,因此,它的资源占用是可控的,无论多少个客户端并发访问,都不会导致资源的耗尽和宕机。

伪异步I/O通信框架采用了线程池实现,因此避免了为每个请求都创建一个独立线程造成的线程资源耗尽问题。
不过因为它的底层仍然是同步阻塞的BIO模型,因此无法从根本上解决问题。

总结

在活动连接数不是特别高(小于单机1000)的情况下,这种模型是比较不错的,可以让每一个连接专注于自己的 I/O
并且编程模型简单,也不用过多考虑系统的过载、限流等问题。线程池本身就是一个天然的漏斗,可以缓冲一些系统处理不了的
连接或请求。但是,当面对十万甚至百万级连接的时候,传统的 BIO 模型是无能为力的。因此,我们需要一种更高效的 I/O
处理模型来应对更高的并发量。

NIO (New I/O)

NIO是一种同步非阻塞的I/O模型,对应 java.nio 包,提供了 Channel , Selector,Buffer等抽象。

NIO中的N可以理解为Non-blocking,不单纯是New。它支持面向缓冲的,基于通道的I/O操作方法。
NIO提供了与传统BIO模型中的 Socket 和 ServerSocket 相对应的 SocketChannel 和 ServerSocketChannel 两种不同的套接字通道
实现,两种通道都支持阻塞和非阻塞两种模式。

阻塞模式使用就像传统中的支持一样,比较简单,但是性能和可靠性都不好;
非阻塞模式正好与之相反。

对于低负载、低并发的应用程序,可以使用同步阻塞I/O来提升开发速率和更好的维护性;
对于高负载、高并发的(网络)应用,应使用 NIO 的非阻塞模式来开发。

区别:(关键)

1) Non-blocking IO(非阻塞IO)
Java IO流:
阻塞的。这意味着,当一个线程调用 read() 或 write() 时,该线程被阻塞,
直到有一些数据被读取,或数据完全写入。该线程在此期间不能再干任何事情了。

NIO流:
不阻塞的。Java NIO使我们可以进行非阻塞IO操作。
比如说,单线程中从通道读取数据到buffer,同时可以继续做别的事情,当数据读取到buffer中后,
线程再继续处理数据。写数据也是一样的。另外,非阻塞写也是如此。一个线程请求写入一些数据到某通道,
但不需要等待它完全写入,这个线程同时可以去做别的事情。

2)Buffer(缓冲区)
IO 面向流(Stream oriented),而 NIO 面向缓冲区(Buffer oriented)。
Buffer是一个对象,它包含一些要写入或者要读出的数据。在NIO类库中加入Buffer对象,体现了新库与原I/O的一个重要区别。
Java NIO Buffers用于和NIO Channel交互。 我们从Channel中读取数据到buffers里,从Buffer把数据写入到Channels;
Buffer本质上就是一块内存区;

一个Buffer有三个属性是必须掌握的,分别是:capacity容量、position位置、limit限制。

IO:
在面向流的I/O中·可以将数据直接写入或者将数据直接读到 Stream 对象中。
虽然 Stream 中也有 Buffer 开头的扩展类,但只是流的包装类,还是从流读到缓冲区,
而 NIO 却是直接读到 Buffer 中进行操作。

NIO流:
在NIO厍中,所有数据都是用缓冲区处理的。在读取数据时,它是直接读到缓冲区中的;
在写入数据时,写入到缓冲区中。任何时候访问NIO中的数据,都是通过缓冲区进行操作。
最常用的缓冲区是 ByteBuffer,一个 ByteBuffer 提供了一组功能用于操作 byte 数组。
除了ByteBuffer,还有其他的一些缓冲区,事实上,每一种Java基本类型(除了Boolean类型)都对应有一种缓冲区。

3)Channel (通道)
NIO 通过Channel(通道) 进行读写。

通道是双向的,可读也可写,而流的读写是单向的。无论读写,通道只能和Buffer交互。因为 Buffer,通道可以异步地读写。

4)Selector (选择器)
NIO有选择器,而IO没有。

选择器用于使用单个线程处理多个通道。因此,它需要较少的线程来处理这些通道。线程之间的切换对于操作系统来说是昂贵的。
因此,为了提高系统效率选择器是有用的。

NIO 包含下面几个核心的组件:

Channel (通道)
Buffer (缓冲区)
Selector(选择器)

AIO (Asynchronous I/O)

AIO 也就是 NIO 2。在 Java 7 中引入了 NIO 的改进版 NIO 2,它是异步非阻塞的IO模型。
异步 IO 是基于事件和回调机制实现的,也就是应用操作之后会直接返回,不会堵塞在那里,当后台处理完成,
操作系统会通知相应的线程进行后续的操作。

AIO 是异步IO的缩写,虽然 NIO 在网络操作中,提供了非阻塞的方法,但是 NIO 的 IO 行为还是同步的。
对于 NIO 来说,我们的业务线程是在 IO 操作准备好时,得到通知,接着就由这个线程自行进行 IO 操作,IO操作本身是同步的。

SpringCloud 服务调用

SpringCloud 服务调用

目前,在Spring cloud 中服务之间通过restful方式调用有两种方式

  • restTemplate + Ribbon
  • feign

Ribbon

Ribbon 是一个基于 HTTP 和 TCP 客户端的负载均衡器,它可以在客户端配置 ribbonServerList(服务端列表),然后轮询请求以实现均衡负载
它在联合 Eureka 使用时ribbonServerList 会被 DiscoveryEnabledNIWSServerList 重写,扩展成从 Eureka 注册中心获取服务端列表,同时它也会用 NIWSDiscoveryPing 来取代 IPing,
它将职责委托给 Eureka 来确定服务端是否已经启动。

Feign

Spring Cloud Netflix 的微服务都是以 HTTP 接口的形式暴露的,所以可以用 Apache 的 HttpClient 或 Spring 的 RestTemplate 去調用, 而 Feign 是一個使用起來更加方便的 HTTP 客戶端,它用起來就好像調用本地方法一樣,完全感覺不到是調用的遠程方法

总结起来就是

发布到注册中心的服务方接口,是 HTTP 的,也可以不用 Ribbon 或者 Feign,直接浏览器一样能够访问
只不过 Ribbon 或者 Feign 调用起来要方便一些,最重要的是:它俩都支持软负载均衡

注意:spring-cloud-starter-feign 里面已经包含了 spring-cloud-starter-ribbon(Feign 中也使用了 Ribbon)

从实践上看,采用feign的方式更优雅(feign内部也使用了ribbon做负载均衡)。

如何理解客户端Ribbon

zuul也有负载均衡的功能,它是针对外部请求做负载,那客户端ribbon的负载均衡又是怎么一回事?

客户端ribbon的负载均衡,解决的是服务发起方(在Eureka注册的服务)对被调用的服务的负载,比如我们查询商品服务要调用显示库存和商品明细服务,通过商品服务的接口将两个服务组合,可以减少外部应用的请求,比如手机App发起一次请求即可,可以节省网络带宽,也更省电。

ribbon是对服务之间调用做负载,是服务之间的负载均衡,zuul是可以对外部请求做负载均衡。

Zookeeper分布式协调服务

Zookeeper分布式协调服务

分布式特点:

  • 凡是分布式就有路由
  • 凡是路由就有负载
  • 凡是有负载就一定会有宕机
  • 凡是分布式就有链接
  • 凡是链接就有安全

分布式、开源、分布式应用程序协调服务。包括配置维护、域名服务、分布式同步、组服务等。

单机模式:

Mode: standalone
C/S架构
Znode 称为zk节点数据

对节点基本操作

create /monkey xxx 创建节点
set /monkey xxxxa 更新节点
get /zk_test 获取节点
delete /zk_test 一般删除(若里面不为空,无法删除)
rmr /zk_test 递归删除

节点类型:

  • 持久节点
  • 持久有序
  • 临时节点
  • 临时有序

watcher(监听作用)

get /zk_test watch 监听节点数据,一旦发生改变,可以通知

源码分析

jps 查看进程号 ===》 查看方法名

1
2
3
4
5
C:\Users\Administrator>jps
1748 Bootstrap
4788 QuorumPeerMain
2424 ZooKeeperMain
3116 Jps

ZooKeeperMain客户端入口
QuorumPeerMain服务端源码

通过源码发现:
help 帮助
history 历史

create -s /monkey xxxxx

  • 持久: 当客户端断开时,znode节点不会被删除
  • 临时: 当客户端断开时,znode节点自动删除

利用Watch机制实现 》》》 分布式配置中心

利用临时有序节点(失效删除,自增等特点) 》》》分布式任务调度

》》》分布式服务注册与订阅

znode节点属性:
cZxid = 0x2
ctime = Tue Jun 04 23:21:32 CST 2019
mZxid = 0x2
mtime = Tue Jun 04 23:21:32 CST 2019
pZxid = 0xa
cversion = 1
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 0
numChildren = 1

集群模式 (选举)

zk一般部署奇数个

zoo.cfg文件修改,2888端口,添加集群机器
server.1=196.128.3.1:2888:3888
server.2=196.128.3.2:2888:3888
server.3=196.128.3.3:2888:3888

选举模式 ==> 过半选举(过半原则)
Mode: leader
Mode: follower

查看状态:
sh zkServer.sh status

Spring源码

#Spring源码

spring-jcl日志源码分析

1.spring的基本应用和spring源码的编译

2.java混乱的日志系统,JUL,JCL,log4j,slf4j

spring aop源码分析

1.AspectJ和spring AOP, aspectj的静态织入

2.JDK动态代理的源码分析,JDK如何操作字节码

3.spring通过cglib完成AOP,cglib如何完成方法拦截

4.AnnotationAwareAspectJAutoProxyCreator是如何实现代理织入的

spring IOC、AOP、MVC源码分析

1.BeanDefinition作用,如何改变bean的行为

2.BeanDefinitionRegistry的作用,源码分析

3.BeanNameGenerator如何改变beanName的生成策略

4.BeanPostProcessor在bean实例化过程中可以做什么?经典应用场景有哪些?

Spring Boot 介绍

Spring Boot 介绍

Spring Boot 提供了一组工具只需要极少的配置就可以快速的构建并启动基于 Spring 的应用程序。解决了传统 Spring 开发需要配置大量配置文件的痛点,同时 Spring Boot 对于第三方库设置了合理的默认值,可以快速的构建起应用程序。当然 Spring Boot 也可以轻松的自定义各种配置,无论是在开发的初始阶段还是投入生成的后期阶段。

Spring Boot 优点

1.快速的创建可以独立运行的 Spring 项目以及与主流框架的集成。

2.使用嵌入式的 Servlet 容器,用于不需要打成war包。

3.使用很多的启动器(Starters)自动依赖与版本控制。

4.大量的自动化配置,简化了开发,当然,我们也可以修改默认值。

5.不需要配置 XML 文件,无代码生成,开箱即用。

6.准生产环境的运行时应用监控。

7.与云计算的天然集成。