计算机网络

计算机网络

关于HTTPS的SSL/TLS的安全加密

![ScreenShot2022-09-02at19.07.54](https://gitee.com/JiaChengCC/u-pic-chart-bed/raw/master/uPic/Screen Shot 2022-09-02 at 19.07.54.png)

nginx实现 反向代理

第几层?其实是第七层,所以一个缺点就是需要为所以就必须为每一种应用服务专门开发一个反向代理服务器。

所以我开的每一个微服务都需要进行反向代理,不对,我是直接代理给了网关的,网关进行转发的。

然后网关转发,反向代理,到底哪里出了问题?怎么调试出来?我用了tcpdum抓取回环包dump到cap文件,然后用wireshark查看,看是ip:端口怎么转发的,然后看哪一步中断了,可能就是哪里有问题了。

二、NIO、BIO、AIO,注意这是网络模型IO

自己写的:

同步指的是第二段,读取数据的时候,是回调告诉完成,还是等待完成。
阻塞指的是,第一阶段的时候,阻塞等待知道有数据,还是比如没有就返回一个标志而不是等待。阻塞指的是调用者是否会挂起等待。

面试官:“你能说一下网络IO模型吗?”

我:“网络IO模型有BIO、NIO、AIO ”。

面试官:“他们分别代表什么,有什么区别吗?”

BIO:同步阻塞IO。
NIO:同步非阻塞IO。
AIO:异步非阻塞IO。

面试官:“BIO为什么是同步阻塞IO,他阻塞的是谁跟谁之间的关联?”。

首先在网络编程中,客户端给服务端发送消息大约分为两个个步骤。
1、发起连接。
2、发送数据。

在BIO中每一个连接都需要分配一个线程来执行,假如A客户端连接了服务器,但是还没有发送消息,这个时候B客户端向服务器发送连接请求,这个时候服务器是没有办法处理B客户端的连接请求的。

img

因为一个线程处理了一个客户端的连接后就阻塞住,并等待处理该客户端发送过来的数据。处理完该客户端的数据后才能处理其他客户端的连接请求。

img

面试官:“那你这个是只有一个线程的时候,那我弄多个线程不就好了,来一个请求连接我弄一个线程”。

我:“那假如有一万个连接请求同时过来,那你开启一万个线程服务端不就崩了嘛。”

面试官:“那我弄一个线程池呢,我最大线程数最多弄500呢?”。

我:“那假如有500线程只请求连接,并不发送数据呢,那你这个线程池不也一样废了吗。这500个请求连接上了还没有发送数据,那么线程池的500个线程就没办法去处理别的请求,这样照样废废了。”

面试官:“那咋办呢?”。

我:“别慌,哥有办法,可以使用NIO同步非阻塞,这样就不需要很多线程,一个线程也能处理很多的请求连接和请求数据。”

面试官:NIO他是怎么实现一个线程处理多个连接请求和多个请求数据的呢?”。

我:“NIO会将获取的请求连接放入到一个数组中,然后再遍历这个数据查看这些连接有没有数据发送过来。”

img

面试官:“这招高啊”。

我:“那必须滴。”

面试官:“但是有个问题啊,如果B和C只连接了,但是一直没有发送数据,那每次还循环判断他俩有没有发送数据的请求是不是有点多余了,能不能在我知道B和C肯定发送了数据的情况下再去遍历他呢?”。

我:“那你让客户B和客户C发送数据的时候给你打一个电话不就行了,然后你就只遍历他俩。”

面试官:“他们也不能够给我打呀,你再想一个别的办法”。

我:“可以引入Epoll,在JDK1.5开始引入了epoll通过事件响应来优化NIO,原理是客户端的每一次连接和每一次发送数据都看作是一个事件,每次发生事件会注册到服务端的一个集合中去,然后客户端只需要遍历这个集合就可以了。”

面试官:“那AIO有什么特点呢?”

我:“AIO是异步非阻塞,他对于客户端的连接请求和发送数据请求是用不同的线程来处理的,他是通过回调来通知服务端程序去启动线程处理,适用于长连接的场景。”

Java IO模型详解

![ScreenShot2022-09-12at08.47.15](https://gitee.com/JiaChengCC/u-pic-chart-bed/raw/master/uPic/Screen Shot 2022-09-12 at 08.47.15.png)

[网络坦白局] TCP粘包 数据包:我只是犯了每个数据包都会犯的错 |硬核图解

粘包这个问题的根因是由于开发人员没有正确理解 TCP 面向字节流的数据传输方式,本身并不是 TCP 的问题,是开发者的问题。

  • TCP 不管发送端要发什么,都基于字节流把数据发到接收端。这个字节流里可能包含上一次想要发的数据的部分信息。接收端根据需要在消息里加上识别消息边界的信息。不加就可能出现粘包问题。
  • TCP 粘包跟Nagle算法有关系,但关闭 Nagle 算法并不解决粘包问题。
  • UDP 是基于数据报的传输协议,不会有粘包问题。
  • IP 层也切片,但是因为不关心消息里有啥,因此有不会有粘包问题。
  • TCP 发送端可以发 10 次字节流数据,接收端可以分 100 次去取;UDP 发送端发了 10 次数据报,那接收端就要在 10 次收完。

RPC的底层原理

1、RPC框架一般使用长链接,不必每次通信都要3次握手,减少网络开销。
2、RPC框架一般都有注册中心,有丰富的监控管理。发布、下线接口、动态扩展等,对调用方来说是无感知、统一化的操作协议私密,安全性较高
3、RPC 协议更简单内容更小,效率更高,服务化架构、服务化治理,RPC框架是一个强力的支撑。

具体步骤:

  1. 服务消费者(client客户端)通过本地调用的方式调用服务。
  2. 客户端存根(client stub)接收到请求后负责将方法、入参等信息序列化(组装)成能够进行网络传输的消息
    体。
  3. 客户端存根(client stub)找到远程的服务地址,并且将消息通过网络发送给服务端。
  4. 服务端存根(server stub)收到消息后进行解码(反序列化操作)。
  5. 服务端存根(server stub)根据解码结果调用本地的服务进行相关处理。
  6. 本地服务执行具体业务逻辑并将处理结果返回给服务端存根(server stub)。
  7. 服务端存根(server stub)将返回结果重新打包成消息(序列化)并通过网络发送至消费方。
  8. 客户端存根(client stub)接收到消息,并进行解码(反序列化)。
  9. 服务消费方得到最终结果。

涉及到的技术

  1. 动态代理:生成Client Stub(客户端存根)和Server Stub(服务端存根)的时候需要用到java动态代理技术。
  2. 序列化 在网络中,所有的数据都将会被转化为字节进行传送,需要对这些参数进行序列化和反序列化操作。目前主流高效的开源序列化框架有Kryo、fastjson、Hessian、Protobuf等。
  3. NIO通信:Java 提供了 NIO 的解决方案,Java 7 也提供了更优秀的 NIO.2 支持。可以采用Netty或者mina框架来解决NIO数据传输的问题。开源的RPC框架Dubbo就是采用NIO通信,集成支持netty、mina、grizzly。
  4. 服务注册中心:通过注册中心,让客户端连接调用服务端所发布的服务。主流的注册中心组件:Redis、Zookeeper、Consul、Etcd。Dubbo采用的是ZooKeeper提供服务注册与发现功能。
  5. 负载均衡:在高并发的场景下,需要多个节点或集群来提升整体吞吐能力。
  6. 健康检查:健康检查包括,客户端心跳和服务端主动探测两种方式。

RPC框架的零拷贝应用

Netty零拷贝主要体现在三个方面:

1、Netty的接收和发送ByteBuffer是采用DIRECT BUFFERS,使用堆外的直接内存(内存对象分配在JVM中堆以外的内存)进行Socket读写,不需要进行字节缓冲区的二次拷贝。如果采用传统堆内存(HEAP BUFFERS)进行Socket读写,JVM会将堆内存Buffer拷贝一份到直接内存中,然后写入Socket中。
2、Netty提供了组合Buffer对象,也就是CompositeByteBuf 类,可以将 ByteBuf 分解为多个共享同一个存储区域的 ByteBuf,避免了内存的拷贝。

3、Netty的文件传输采用了FileRegion 中包装 NIO 的 FileChannel.transferT o() 方法,它可以直接将文件缓冲区的数据发送到目标Channel,避免了传统通过循环write方式导致的内存拷贝问题。

零拷贝带来的作用就是避免没必要的 CPU 拷贝,减少了 CPU 在用户空间与内核空间之间的上下文切换,从而提升了网络通信效率与应用程序的整体性能。

题外话:如何优化持久化?或者说如何写入磁盘更快?

1 Kafka顺序写入,而不是随机写入,所以更快一点。

2 或者说同时发消息的时候先缓存,然后批量发送等等。

3 然后就是零拷贝处理啊什么的

有了 HTTP 协议,为什么还要有 RPC ?

  • 纯裸 TCP 是能收发数据,但它是个无边界的数据流,上层需要定义消息格式用于定义 消息边界 。于是就有了各种协议,HTTP 和各类 RPC 协议就是在 TCP 之上定义的应用层协议。
  • RPC 本质上不算是协议,而是一种调用方式,而像 gRPC 和 Thrift 这样的具体实现,才是协议,它们是实现了 RPC 调用的协议。目的是希望程序员能像调用本地方法那样去调用远端的服务方法。同时 RPC 有很多种实现方式,不一定非得基于 TCP 协议
  • 从发展历史来说,HTTP 主要用于 B/S 架构,而 RPC 更多用于 C/S 架构。但现在其实已经没分那么清了,B/S 和 C/S 在慢慢融合。 很多软件同时支持多端,所以对外一般用 HTTP 协议,而内部集群的微服务之间则采用 RPC 协议进行通讯。
  • RPC 其实比 HTTP 出现的要早,且比目前主流的 HTTP1.1 性能要更好,所以大部分公司内部都还在使用 RPC。
  • HTTP2.0HTTP1.1 的基础上做了优化,性能可能比很多 RPC 协议都要好,但由于是这几年才出来的,所以也不太可能取代掉 RPC。

阿里终面:怎么用 UDP 实现 TCP?

UDP 和 TCP 的区别,以及 UDP 缺什么功能,需要怎么去弥补才能实现 TCP 的功能。

面向连接、可靠、基于字节流

面向连接

顺序问题

丢包问题

流量控制

拥塞控制,如果包丢弃了或者网络环境不好了,就会根据网络情况自行控制自己的行为,看下是发快点还是发慢点。

有状态服务,TCP记录了哪些发送了,哪些没有发送,哪些接收到了,哪些没接收到,应该接收哪个了,一点差错都不行。TCP 干的事情可真多!

面向连接,三次握手、四次挥手

顺序问题和丢包问题可以利用确认重发的机制。

**流量控制,调整发送方和接收方的速率不匹配的问题,利用的是滑动窗口。

拥塞控制主要用来避免包丢失和超时重传,如果出现了这两种现象,就说明发的速率太快了。那最开始怎么知道发送速率呢?其实开始时只发送一个报文段数据,如果收到一个确认,则倍增报文段,依次类推。当发现超时重传时,就又回到只发送一个报文段的情况,这个就是慢启动,这种方式不合适。其实还有一种快速重传算法,简单来说就是拥塞窗口减半,后续线性增速。针对于算法怎么实现的,这里就不展开讲述了。

流量控制解决的是发送方和接收方速率不匹配的问题;

拥塞控制解决的是避免网络资源被耗尽的问题。

流量控制是通过滑动窗口来实现的;

拥塞控制是通过拥塞窗口来实现的。

Author: Jcwang

Permalink: http://example.com/2022/09/02/%E5%85%AB%E8%82%A1%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C/