首页 秋招复盘7.29:Web
文章
取消

秋招复盘7.29:Web

HTTP

HTTP报文内容

img

POST和GET(from 代码随想录)

  1. 作用不同 GET用于从服务端获取资源 POST一般用来向服务器端提交数据
  2. 参数传递方式不同 GET请求的参数一般写在URL中,且只接受ASCII字符 POST请求参数一般放在请求体中,对于数据类型也没有限制
  3. 安全性不同 因为参数传递方式的不同,所以两者安全性不同,GET请求的参数直接暴露在URL中,所以更不安全,不能用来传递敏感信息。
  4. 参数长度限制不同 GET传送的数据量较小,不能大于2KB。 POST传送的数据量较大,一般被默认为不受限制。 HTTP 协议没有 Body 和 URL 的长度限制,对 URL 限制的大多是浏览器和服务器的原因。
  5. 编码方式不同 GET 请求只能进行 URL 编码(application/x-www-form-urlencoded) POST 支持多种编码方式(application/x-www-form-urlencoded 或 multipart/form-data。为二进制数据使用多种编码。)
  6. 缓存机制不同 GET 请求会被浏览器主动cache,而 POST 不会,除非手动设置。 GET 请求参数会被完整保留在浏览器历史记录里,而 POST 中的参数不会被保留。 GET 产生的 URL 地址可以被 保存为书签,而 POST 不可以。 GET 在浏览器回退时是无害的,而 POST 会再次提交请求。
  7. 时间消耗不同 GET 产生一个 TCP 数据包; POST 产生两个 TCP 数据包。 对于 GET 方式的请求,浏览器会把 header 和 data 一并发送出去,服务器响应 200(返回数据);而对于 POST,浏览器先发送 Header,服务器响应 100 continue,浏览器再发送 data,服务器响应 200 ok(返回数据)
  8. 幂等 意思是多次执行相同的操作,结果都是「相同」的。 GET 方法就是安全且幂等的,因为它是「只读」操作,无论操作多少次,服务器上的数据都是安全的,且每次的结果都是相同的。 POST 因为是「新增或提交数据」的操作,会修改服务器上的资源,所以是不安全的,且多次提交数据就会创建多个资源,所以不是幂等的。

websocket的区别

HTTP (HyperText Transfer Protocol) 是一个基于请求/响应模型的无状态协议,它允许客户端向服务器发送请求,并从服务器接收响应。

特点

  1. 无连接:HTTP 请求和响应完成后,服务器主动断开连接。每个请求/响应都会创建新的连接。
  2. 无状态:服务器不会在两个请求之间保持任何数据(状态)。这意味着每次请求都必须包含所有信息,服务器不能从先前的请求中获取任何信息。
  3. 单向通信:通信始终由客户端发起,服务器只能回应客户端的请求,不能主动向客户端发送消息。

WebSocket 是一个全双工通信协议,它在客户端和服务器之间建立持久性的连接,并允许双方通过此连接进行数据交换。

特点

  1. 持久连接:一旦建立了 WebSocket 连接,客户端和服务器可以在连接断开之前任意次数地发送或接收数据。这避免了每次通信时都需要建立和断开连接的开销。
  2. 全双工通信:客户端和服务器可以同时通过同一个连接发送和接收数据。这意味着服务器可以主动向客户端推送消息。
  3. 实时性:由于连接是持久的,因此数据可以实时或接近实时地传输。

HTTP 与 WebSocket 的区别

  1. 连接方式:HTTP 是无连接的,每个请求/响应都会创建一个新的连接;WebSocket 使用持久连接,允许多次数据交换。
  2. 状态:HTTP 是无状态的,服务器不会保留任何请求状态;WebSocket 连接是有状态的,连接被保持打开,直到客户端或服务器决定关闭。
  3. 通信方式:HTTP 是单向通信,只有客户端可以发起请求;WebSocket 是全双工通信,客户端和服务器都可以主动发送消息。
  4. 数据传输性能:由于 HTTP 每个请求/响应都需要建立和断开连接,所以对于实时性要求高的应用,HTTP 的数据传输效率较低;而 WebSocket 由于使用持久连接,所以数据传输效率较高。
  5. 用途:HTTP 适用于传统的客户端-服务器应用,如网页浏览;WebSocket 适用于需要实时数据交换的应用,如在线游戏、聊天应用等。

参考:

WebSocket 教程 - 阮一峰的网络日志 (ruanyifeng.com)

img

传输二进制数据

支持。

常见的Content-Type类型包括:

  1. text/plain:表示纯文本,没有特殊的格式和样式。
  2. text/html:表示HTML文档,可以在Web浏览器中显示。
  3. application/json:表示JSON格式的数据,用于数据交换。
  4. application/xml:表示XML格式的数据,用于数据交换。
  5. application/octet-stream:表示二进制数据,例如图片、音频、视频等。
  6. multipart/form-data:表示表单数据,用于文件上传。
  7. application/x-www-form-urlencoded:表示表单数据,用于提交表单。
  8. text/css:表示CSS样式表,用于网页的样式设计。
  9. application/javascript:表示JavaScript脚本,用于网页的交互操作。

I/O多路复用

水平触发和边缘触发。(from 小林

epoll 支持两种事件触发模式,分别是边缘触发(edge-triggered,ET)和水平触发(level-triggered,LT

  • 使用边缘触发模式时,当被监控的 Socket 描述符上有可读事件发生时,服务器端只会从 epoll_wait 中苏醒一次,即使进程没有调用 read 函数从内核读取数据,也依然只苏醒一次,因此我们程序要保证一次性将内核缓冲区的数据读取完;
  • 使用水平触发模式时,当被监控的 Socket 上有可读事件发生时,服务器端不断地从 epoll_wait 中苏醒,直到内核缓冲区数据被 read 函数读完才结束,目的是告诉我们有数据需要读取;

边缘触发模式一般和非阻塞 I/O 搭配使用,程序会一直执行 I/O 操作,直到系统调用(如 read 和 write)返回错误,错误类型为 EAGAIN 或 EWOULDBLOCK

select/poll 只有水平触发模式,epoll 默认的触发模式是水平触发,但是可以根据应用场景设置为边缘触发模式。

另外,使用 I/O 多路复用时,最好搭配非阻塞 I/O 一起使用,多路复用 API 返回的事件并不一定可读写的,如果使用阻塞 I/O, 那么在调用 read/write 时则会发生程序阻塞,因此最好搭配非阻塞 I/O,以便应对极少数的特殊情况。

数据序列化实现

对二进制序列化,Protocol Buffer。

使用教程:[Protocol Buffer Basics: C++Protocol Buffers Documentation — Protocol Buffer 基础知识:C++协议缓冲区文档 (protobuf.dev)](https://protobuf.dev/getting-started/cpptutorial/)

简要介绍:

Protocol Buffer是一种轻量级的数据交换格式,由Google开发,广泛应用于分布式系统、网络通信、数据存储等领域。与XML和JSON等数据交换格式相比,Protocol Buffer具有更高的效率和更小的数据存储空间。

Protocol Buffer使用一种基于IDL(Interface Description Language)的描述语言,可以定义数据结构和消息格式,并生成对应的代码。在进行数据交换时,可以将数据序列化为二进制格式,并通过网络或文件等方式传输。在接收方,可以将二进制数据反序列化为原始数据,并进行相应的处理。

Protocol Buffer支持多种编程语言,包括C++、Java、Python、Go等,可以在不同平台和应用程序之间进行数据交换。同时,Protocol Buffer还支持版本控制、压缩、加密等功能,可以满足不同场景下的需求。

Protocol Buffer的优点包括:

  1. 高效:Protocol Buffer使用二进制格式,比XML和JSON等文本格式更小、更快,可以大大提高数据传输和存储的效率。
  2. 易用:Protocol Buffer使用IDL语言描述数据结构和消息格式,可以自动生成对应的代码,使用起来相对简单。
  3. 可扩展:Protocol Buffer支持版本控制和字段标记等功能,可以在不破坏现有数据格式的情况下进行升级和扩展。
  4. 跨平台:Protocol Buffer支持多种编程语言,可以在不同平台和应用程序之间进行数据交换。

总之,Protocol Buffer是一种高效、易用、可扩展、跨平台的数据交换格式,广泛应用于分布式系统、网络通信、数据存储等领域。

RPC协议讲解

通用于分布式框架中。

RPC协议详解

RPC (Remote Procedure Call),即远程过程调用,是一种通过网络从远程计算机程序上请求服务,而无需了解底层网络技术的协议。它假定某些传输协议的存在,如TCP或UDP,以便为通信程序接口进行数据传输。在OSI网络通信模型中,RPC跨越了传输层和应用层。RPC使得开发包括网络分布式多程序在内的应用程序更加容易。

RPC工作原理

调用者(Client)在进行远程过程调用时,实际上是在本地调用该过程,然后把这些参数打包后通过网络发送到执行者(Server)那里。执行者接收到请求后,解包提取出参数,然后执行该过程,然后将过程的执行结果返回给调用者。

RPC应用场景

RPC被广泛应用于分布式系统中,例如:

  1. 分布式文件系统:如NFS(Network File System),它使用RPC来实现客户端和服务器之间的通信,从而在客户端系统上访问和操作服务器上的文件。
  2. 分布式数据库系统:在这些系统中,RPC可以用来实现分布式事务处理。
  3. 云计算:RPC在云计算中非常重要,因为它可以实现跨计算机和跨网络的过程调用。

RPC和HTTP协议的区别

RPC和HTTP都是应用层协议,但它们的主要区别在于它们的使用和目标。

  1. 用途:HTTP主要用于Web浏览器和服务器之间的通信,而RPC主要用于分布式系统中的进程间通信。
  2. 信息传输方式:HTTP是无状态的,每次请求都需要重新建立连接。而RPC可以是有状态的,允许请求之间保持某种形式的会话。
  3. 效率:由于HTTP协议的文本性质,其传输效率相对较低。而RPC协议通常使用二进制格式进行数据传输,从而提高了传输效率。
  4. 复杂性:HTTP是一种更简单的协议,可以通过简单的GET和POST请求进行通信。而RPC是一种更复杂的协议,它允许客户端和服务器之间进行更复杂的交互,如调用远程过程。
  5. 兼容性:HTTP协议几乎可以在所有系统和设备上使用,而RPC可能需要特定的库或支持才能使用。

总的来说,选择使用RPC还是HTTP取决于你的应用需求。如果你需要高效的、复杂的进程间通信,可能会选择RPC。如果你正在开发Web应用,那么HTTP可能是一个更好的选择。

K8S和docker的使用

在centOS上制作的一个镜像在Ubuntu中能否使用。

在CentOS上制作的Docker镜像可以在Ubuntu中使用,因为Docker镜像是跨平台的,可以在不同的操作系统和平台之间移植和部署。但是,在不同的操作系统和平台之间使用Docker镜像时,需要保证镜像所依赖的环境和库的兼容性,否则可能会出现错误或运行异常。因此,在使用跨平台Docker镜像时,需要进行充分的测试和验证,以确保其稳定性和可靠性。

Kubernetes(K8S)和Docker都是用于容器化应用程序的常用技术。以下是它们的详细概念解释:

Docker: Docker是一种开源的容器技术,用于打包、交付和运行应用程序。Docker容器是一种轻量级、可移植的封装,包含应用程序和其依赖项,可以在不同的环境中运行,而无需担心环境差异和依赖项问题。Docker使用Dockerfile文件来描述容器的构建过程,并使用Docker镜像来打包和分发应用程序。Docker镜像是一个只读的文件系统,包含应用程序和其依赖项,可以使用Docker容器来运行和管理。

Kubernetes: Kubernetes是一个开源的容器编排和管理平台,用于自动化容器部署、扩展和管理。Kubernetes提供了一套API和工具,用于管理多个Docker容器,并确保它们的健康状态、高可用性和负载均衡。Kubernetes的核心组件包括Master节点和Worker节点,Master节点用于控制和管理集群,而Worker节点用于运行容器和处理请求。Kubernetes使用Pod、Deployment、Service等资源对象来描述和管理容器的部署、扩展和运维。

  • Pod: Pod是Kubernetes中最小的部署单元,表示一个或多个相关的Docker容器的集合。Pod中的容器共享同一个网络和存储空间,可以通过共享本地文件系统和IPC机制来实现容器之间的通信和协作。Pod可以通过Kubernetes的API和工具进行部署、扩展和管理,以实现高可用性和负载均衡。
  • Deployment: Deployment是Kubernetes中用于管理Pod副本的资源对象,用于控制应用程序的部署和更新。Deployment可以指定应用程序的副本数量、容器镜像、存储卷、环境变量等参数,并自动创建和管理Pod的副本。Deployment还支持滚动更新和回滚功能,可以在不中断服务的情况下更新应用程序。
  • Service: Service是Kubernetes中用于公开和访问容器的资源对象,用于实现容器之间的通信和负载均衡。Service可以将多个Pod绑定到一个虚拟IP地址上,提供统一的访问入口,并根据负载均衡算法将请求分发到不同的Pod上。Service还支持服务发现、DNS解析、会话保持等功能,可以提供高可用性和可靠性的服务。

总之,Kubernetes和Docker都是常用的容器化技术,它们可以帮助开发者快速部署、扩展和管理应用程序,提高开发效率和运行效率。在实践中,开发者可以根据具体需求和场景选择合适的技术和工具来实现容器化应用程序。

算法:实现一个share ptr引用计数智能指针

(当场想的太多了,直接存一个int*在不同share ptr之间共享即可)

  • 实现示例

    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
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    
      #include <mutex>
        
      template <typename T>
      class shared_ptr
      {
      public:
          // 构造函数
          shared_ptr() : ptr_(nullptr), ref_count_(nullptr) {}
          shared_ptr(T *ptr) : ptr_(ptr), ref_count_(new int(1)) {}
          shared_ptr(const shared_ptr<T> &other) : ptr_(other.ptr_), ref_count_(other.ref_count_)
          {
              if (ref_count_)
                  increment_ref_count();
          }
        
          // 析构函数
          ~shared_ptr()
          {
              release();
          }
        
          // 赋值操作符
          shared_ptr<T> &operator=(const shared_ptr<T> &other)
          {
              if (this != &other)
              {
                  release();
                  ptr_ = other.ptr_;
                  ref_count_ = other.ref_count_;
                  if (ref_count_)
                      increment_ref_count();
              }
              return *this;
          }
        
          // 获取指针
          T *get() const
          {
              return ptr_;
          }
        
          // 获取引用计数
          int use_count() const
          {
              std::lock_guard<std::mutex> lock(mutex_);
              if (ref_count_)
                  return *ref_count_;
              else
                  return 0;
          }
        
          // 重载解引用操作符
          T &operator*() const
          {
              return *ptr_;
          }
        
          // 重载箭头操作符
          T *operator->() const
          {
              return ptr_;
          }
        
          // 重载布尔操作符
          operator bool() const
          {
              return ptr_ != nullptr;
          }
        
      private:
          T *ptr_;           // 指向被管理的对象
          int *ref_count_;   // 引用计数
          std::mutex mutex_; // 互斥量
        
          // 增加引用计数
          void increment_ref_count()
          {
              std::lock_guard<std::mutex> lock(mutex_);
              ++(*ref_count_);
          }
        
          // 释放资源
          void release()
          {
              std::lock_guard<std::mutex> lock(mutex_);
              if (ref_count_)
              {
                  --(*ref_count_);
                  if (*ref_count_ == 0)
                  {
                      delete ptr_;
                      delete ref_count_;
                  }
                  ptr_ = nullptr;
                  ref_count_ = nullptr;
              }
          }
      };
    
本文由作者按照 CC BY 4.0 进行授权

重装系统

硬件结构