深入了解Nginx(一):Nginx核心原理

news2024/11/20 16:32:23

一、Nginx核心原理

     本节为大家介绍Nginx的核心原理,包含Reactor模型、Nginx的模块化设计、Nginx的请求处理阶段.

(本文源自微博客,且已获得授权)

1.1、Reactor模型

     Nginx对高并发IO的处理使用了Reactor事件驱动模型。Reactor模型的基本组件包含时间收集器、事件发送器、事件处理器3个基本单元,其核心实现四将所有要处理的I/O事件注册到一个中心I/O多路复用器上,同时主线程/进程阻塞在多路复用器上,一旦有I/O时间到来或者准备就绪(文件描述符或Socket可读、写),多路复用器返回并将事先注册的响应I/O事件分发到对应的处理器中。

     在Reactor模式中,时间收集器、事件发送器、事件处理器则3个基本单元的职责分别如下:

  1. 时间收集器:负责收集Worker进程的各种I/O请求
  2. 事件发送器:负责将I/O时间发送到事件处理器
  3. 事件处理器:负责各种时间的响应工作

Nginx的Reactor模型的设计大致如下:

image.png

     时间收集器将各个连接通道的IO事件放入一个待处理时间列,通过事件发送器发送给对应的事件处理器来处理。而时间收集器之所能够同时管理上百万连接通道的事件,是基于操作系统提供的“多路IO复用”技术,常见的包括select、epoll两种模型。

     正是由于Nginx使用了高性能的Reactor模式,因此是目前并发能力很高的Web服务器之一,成为迄今为止使用广泛的工业级Web服务器。当然,Nginx也解决了著名的网络读写是C10K问题。什么是C10K问题呢?网络服务在处理数以万计的客户端连接时,往往出现效率低下甚至完全瘫痪,这类问题就被成为C10K问题。

1.2、Nginx的两类进程

     一般来说,Nginx在启动以后会与daemon方式在后台运行,其后台进程有两种: 一类称为Master进程(相当于管理进程);另一类称为Worker进程(工作进程)。Nginx的进程结构大致如下:
image.png

     Nginx启动方式有两种:

  1. 单进程启动:此时系统中仅有一个进程,该进程既充当Master管理进程角色,又充当Worker工作进程角色
  2. 多进程启动:此时系统有且仅有一个Master管理进程,至少有一个Worker工作进程。
    (有点类似于RocketMQ的模式)

     一般来说,单进程模式用于调试。在生产环境中,一般会配置成多进程模式,并且Worker工作进程的数量和机器CPU核心数配置不一样多。

     了解Worker工作进程之前,首先了解一下Master管理进程的主要工作,主要有以下两点:

  1. Master管理进程主要负责调度Worker工作进程,比如加载配置、启动工作进程、接收来自外界的信号、向各Worker进程发送信号、监控Worker进程的运行状态等。所以Nginx启动以后,我们能看到至少两个Nginx进程
  2. Master负责创建监听套接口,交由Worker进程进行连接监听。

     接下来介绍Nginx的Worker进程。Worker进程主要用来处理网络事件。当一个Worker进程在接受一条连接通道之后,就开始读取请求、解析请求、处理请求,处理完成产生数据以后,再返回给客户端,最后断开连接通道。

     各个Worker进程之间是对等且相互独立的,它们同等竞争来自客户端的请求,一个请求只可能在一个Worker进程中处理。则都是典型的Reactor模型中Worker进程(或者线程)的职能。

     如果启动了多个Worker进程,那么每个Worker子进程独自尝试接受已连接的Socket监听通道,accept操作默认会上锁,优先使用操作系统的共享内存原子锁,如果操作系统不支持,就是用文件上锁。

     经过配置,Worker进程的接受操作也可以不适用锁,在多个进程同时接受时,当一个连接进来的时候多个工作进程同时被唤起,则会导致惊群问题。而在上锁的场景下,只会有一个Worker阻塞在accept上,其他的进程会因为不能获取锁而阻塞,所以上锁的场景不存在惊群问题。

1.3、Nginx模块化设计

     Nginx服务器被分解为多个模块,模块之间严格遵循“高内聚,低耦合”的原则,每个模块都聚焦于一个功能。高度模块化的设计是Nginx的架构基础。

     什么是Nginx模块呢?在Nginx的实现中,一个模块包含一系列命令(cmd)和这些命令相对应的处理函数(cmd→handler)。Nginx的Worker进程在执行过程中会通过配置文件的配置指令定位到对应的功能模块的某个命令(cmd),然后调用命令对应的处理函数来完成相应的处理。

     Nginx的Worker进程首先会调用Nginx的Core核心模块。大家知道,在Reactor模型中会维护一个运行循环(Run-Loop),主要包括事件收集、事件分发、事件处理,这个工作在Nginx中由Core核心模块负责。Core模块负责执行网络请求处理的基础操作,比如网络读写、存储读写、内容传输、外出过滤以及将请求发往上游服务器等。

     Nginx的Core模块是启动时一定会加载的,其他的模块只有在解析配置时遇到了这个模块的命令才会加载对应的模块。Core模块为其他模块构建了基本的运行时环境,并成为其他各模块的协作基础。

     除了Core模块外,Nginx还有Event、Conf、HTTP、Mail等一系列模块,并且可以在编译时加入第三方模块。Nginx的模块结构如图:
image.png

     这里对Nginx的主要模块说明如下:

  1. Core核心模块:核心模块是Nginx服务器正常运行必不可少的模块,提供错误日志记录、配置文件解析、Reactor事件驱动机制、进程管理等核心功能。
  2. 标准HTTP模块:标准HTTP模块提供HTTP协议解析相关的功能,比如端口配置、网页编码设置、HTTP响应头设置等。
  3. 可选HTTP模块:可选HTTP模块主要用于扩展标准的HTTP功能,让Nginx能处理一些特殊的服务,比如Flash多媒体传输、网络传输压缩、安全协议SSL的支持等。
  4. 邮件服务模块:邮件服务模块主要用于支持Nginx的邮件服务,包括对POP3协议、IMAP协议和SMTP协议的支持。
  5. 第三方模块:第三方模块是为了扩展Nginx服务器的功能,定制开发者自定义功能,比如JSON支持、Lua支持等。

     Nginx的非核心模块可以在编译时按需加入,这里不再赘述。
     总之,Nginx通过模块化设计使得大家可以根据需要对功能模块进行适当的选择和修改,编译成具有特定功能的服务器。

1.4、Nginx配置文件上下文结构

     前面介绍到,一个Nginx的功能模块包含一系列的命令(cmd)以及与命令对应的处理函数(cmd→handler)。而Nginx根据配置文件中的配置指令就知道对应到哪个模块的哪个命令,然后调用命令对应的处理函数来处理。

     一个Nginx配置文件包含若干配置项,每个配置项由配置指令和指令参数两部分组成,可以简单认为配置项是一个键-值对。图中有3个简单的Nginx配置项:
image.png

     Nginx配置文件中的配置指令如果包含空格,就需要用单引号或双引号引起来。指令参数如果是由简单的字符串构成的,简单配置项就需要以分号结束;指令参数如果是复杂的多行字符串,配置项就需要用花括号“{}”括起来。

     Nginx配置项的具体功能与其所处的作用域(上下文、配置块)是强相关的。Nginx指令的作用域配置块大致有5种,它们之间的层次关系如图:
image.png

一个标准的Nginx配置文件的上下文结构如下:

nginx
#main全局配置块,例如工作进程数
events { #events事件处理模式配置块,例如IO读写模式、连接数等

}
http #HTTP协议配置块
{
     #HTTP协议的全局配置块
    server #server虚拟服务器配置块一
    {
          #server全局块
         location [PATTERN] #location路由规则配置块一
         {
         
         }
         location [PATTERN] #location路由规则配置块二
         {
         
         }
    }
    server #server虚拟服务器配置块二
    {
    
    }
#其他HTTP协议的全局配置块
}
mail #mail服务配置块
{
 #email相关协议,如SMTP/IMAP/POP3的处理配置
}

对以上作用域(上下文、配置块)说明如下:

1.4.1、main全局配置块

     配置影响Nginx全局的指令,一般有运行Nginx服务器的用户组、Nginx进程PID存放路径、日志存放路径、配置文件引入、允许生成的Worker进程数等。

1.4.2、events事件处理模式配置块

     配置Nginx服务器的IO多路复用模型、客户端的最大连接数限制等。Nginx支持多种IO多路复用模型,可以使用use指令在配置文件中设置IO读写模型。

1.4.3、HTTP协议配置块

     可以配置与HTTP协议处理相关的参数,比如keepalive长连接参数、GZIP压缩参数、日志输出参数、mime-type参数、连接超时参数等。

1.4.4、server虚拟服务器配置块

     配置虚拟主机的相关参数,如主机名称、端口等。一个HTTP协议配置块中可以有多个server虚拟服务器配置块。

1.4.5、location路由规则块

     配置客户端请求的路由匹配规则以及请求过程中的处理流程。一个server虚拟服务器配置块中一般会有多个location路由规则块。

1.4.6、mail服务配置块

     Nginx为email相关协议(如SMTP/IMAP/POP3)提供反向代理时,mail服务配置块负责配置一些相关的配置项。

     提示:以上介绍的Nginx配置块主要针对的是Nginx基本应用程序配置文件,包括基本配置文件在内,Nginx的常用配置文件大致有下面这些:

  1. nginx.conf:应用程序基本配置文件
  2. mime.types:与MIME类型关联的扩展配置文件
  3. fastcgi.conf:与FastCGI相关的配置文件
  4. proxy.conf:与Proxy相关的配置文件
  5. sites.conf:单独配置Nginx提供的虚拟机主机

1.5、Nginx的请求处理流程

     Nginx中HTTP请求的处理流程可以分为4步:

  1. 读取解析请求行
  2. 读取解析请求头
  3. 多阶段处理,也就是执行handler处理器列表
  4. 将结果返回给客户端

Nginx中HTTP请求的处理流程如图:

image.png

     多阶段处理是Nginx的HTTP处理流程中非常重要的一步。Nginx把请求处理划分成了11个阶段,在完成第一步读取请求行和第二步读取请求头之后,Nginx将整个请求封装到一个请求结构体ngx_http_request_t实例中(相当于Java中的一个请求对象),然后进入第三步多阶段处理,也就是执行handler处理器列表。列表中的每个handler处理器都会对请求对象进行处理,例如重写URI、权限控制、路径查找、生成内容以及记录日志等。

     Nginx将HTTP请求处理流程分成了11个阶段,每个阶段都涉及一些handler处理器。HTTP请求到来时,这些组装在一个列表的handler处理器会按组装的先后次序执行。这一点和Netty的处理流水线pipeline在原理上是类同的。

     在Nginx进行多阶段处理时,handler处理器的执行次序除了和配置文件中对应指令的配置顺序相关外,还和指令所处的阶段先后次序相关。

     Nginx请求处理的11个阶段以及阶段与阶段之间的执行次序如图:
image.png

     对HTTP请求进行多阶段处理是Nginx模块化非常关键和重要的功能,第三方模块的处理器都在不同的处理阶段注册,例如:

  1. 用Memcache进行页面缓存的第三方模块
  2. 用Redis集群进行页面缓存的第三方模块
  3. 执行Lua脚本的第三方模块

1.6、HTTP请求处理的11个阶段

     Nginx请求处理的11个阶段介绍如下

1.6.1、post-read阶段

     在完成第一步读取请求行和第二步读取请求头之后就进入多处理阶段,首当其冲的就是post-read阶段。注册在post-read阶段的处理器不多,标准模块的ngx_realip处理器就注册在这个阶段。ngx_realip处理器模块的用途是改写请求的来源地址。

     为何要改写请求的来源地址呢?

     当Nginx处理的请求经过了某个正向代理服务器(Nginx、CDN)的转发后,请求中的IP地址($remote_addr)可能就不是客户端的真实IP了,变成了下游代理服务器的IP。如何获取用户请求的真实IP地址呢?解决办法之一:在下游的正向代理服务器把请求的原始来源地址编码成某个特殊的HTTP请求头,在Nginx中把这个请求头中编码的地址恢复出来,然后传给Nginx自己后头的上游服务器。ngx_realip模块正是用来处理这个需求的。

     下面有一个简单的例子,假定前头的正向代理服务器能将客户端IP编码成某个特殊的HTTP请求头(如X-My-IP),Nginx就可以通过ngx_realip模块的real_ip_header指令将X-My-IP请求头的IP取出,作为请求中的IP地址($remote_addr)。

server {
   listen 8080;
   set_real_ip_from 192.168.0.100;
   real_ip_header X-My-IP;
   location /test {
   	echo "from: $remote_addr ";
   }
}

     这里的配置是让Nginx把来自正向代理服务器192.168.0.100的所有请求的IP来源地址都改写为请求头X-My-IP所指定的值,放在$remote_addr内置标准变量中。

1.6.2、server-rewrite阶段

     server-rewrite阶段,简单地翻译就是server块中的请求地址重写阶段。在进行请求URI与location路由规则匹配之前可以修改请求的URI地址。

     大部分直接配置在server配置块中的配置项都运行在server-rewrite阶段。

server {
   listen 8080;
   set $a hello; #server-rewrite阶段运行
   location /test {
      set $b "$a, world";
      echo $b;
   }
   set $b hello; #server-rewrite阶段运行
}

     其中,两个变量赋值的配置项set a h e l l o 和 s e t a hello和set ahellosetb hello直接写在server配置块中,因此它们就运行在server-rewrite阶段。

1.6.3、find-config

     紧接在server-rewrite阶段后面的是find-config阶段,也叫配置查找阶段,主要功能是根据请求URL地址去匹配location路由表达式。
     find-config阶段由Nginx HTTP Core(ngx_http_core_module)模块全部负责,完成当前请求URL与location配置块之间的配对工作。这个阶段不支持Nginx模块注册处理程序。

     在find-config阶段之前,客户端请求并没有与任何location配置块相关联。因此,对于运行在此之前的post-read和server-rewrite阶段来说,只有server配置块以及更外层作用域中的配置项才会起作用,location配置块中的配置项不起作用。

1.6.4、rewrite

     由于Nginx已经在find-config阶段完成了当前请求与location的匹配,因此从rewrite阶段开始,location配置块中的指令就可以产生作用。
     rewrite阶段也叫请求地址重写阶段,注册在rewrite阶段的指令首先是ngx_rewrite模块的指令,比如break、if、return、rewrite、set等。其次,第三方ngx_lua模块中的set_by_lua指令和rewrite_by_lua指令也能在此阶段注册。

1.6.5、post-rewrite

     请求地址URI重写提交(Post)阶段,防止递归修改URI造成死循环(一个请求执行10次就会被Nginx认定为死循环),该阶段只能由NginxHTTP Core(ngx_http_core_module)模块实现。

1.6.6、preaccess

     访问权限检查准备阶段,控制访问频率的ngx_limit_req模块和限制并发度的ngx_limit_zone模块的相关指令就注册在此阶段。

1.6.7、access

     在访问权限检查阶段,配置指令多是执行访问控制类型的任务,比如检查用户的访问权限、检查用户的来源IP地址是否合法等。在此阶段能注册的指令有:HTTP标准模块ngx_http_access_module的指令、第三方ngx_auth_request模块的指令、第三方ngx_lua模块的access_by_lua指令等。

     比如,deny和allow指令属于ngx_http_access_module模块,它的
使用示例如下:

server {
   #拒绝全部
    location = /denyall {
       deny all;
    }
    #允许来源IP属于192.168.0.0/24网段或127.0.0.1的请求
    #其他来源IP全部拒绝
    location = /allowsome {
       allow 192.168.0.0/24;
       allow 127.0.0.1;
       deny all;
       echo "you are ok";
    }
}

     如果同一个location块配置了多个allow/deny配置项,access阶段的配置项之间是按配置的先后顺序匹配的,匹配成功一个便跳出。上面的例子中,如果客户端源IP是127.0.0.1,则匹配到“allow127.0.0.1;”配置项后就不再匹配后面的“deny all;”,也就是说该请求不会被拒绝。如果这些配置项的指令来自不同的模块,则每个模块会执行一个访问控制类型的指令。

     特别提醒:echo指令用于返回内容,在location上下文中,该指令注册在content生产阶段。由于echo指令不是注册在access阶段,因此在access阶段不执行该指令的配置项。

1.6.8、post-access

     访问权限检查提交阶段。如果请求不被允许访问Nginx服务器,该阶段负责就向用户返回错误响应。在access阶段可能存在多个访问控制模块的指令注册,post-access阶段的satisfy配置指令可以用于控制它们彼此之间的协作方式。下面有一个例子:

#satisfy指令进行协调
location = /satisfy-demo {
   satisfy any;
   access_by_lua "ngx.exit(ngx.OK)";
   deny all;
   echo "hello";
}

     在上面的例子中,deny指令属于HTTP标准模块的ngx_http_access_module访问控制模块,而access_by_lua指令属于第三方ngx_lua模块,两个模块都有自己的计算结果,需要经过最终的结果统一。
     不同访问控制模块的计算结果统一工作,这里由satisfy指令负责,有两种统一的方式:

  1. 逻辑或操作:具体的配置项为“satisfy any;”,表示访问控制模块A、B、C或更多,只要其中任意一个通过验证就算通过。
  2. 逻辑与操作:具体的配置项为“satisfy all;”,表示访问控制模块A、B、C或更多,全部模块都通过验证才能最终通过。

1.6.9、try-files

     如果HTTP请求访问静态文件资源,那么try-files配置项可以使这个请求按顺序访问多个静态文件资源,直到某个静态文件资源符合选取条件。这个阶段只有一个标准配置指令try-files,并不支持Nginx模块注册处理程序。
     try-files指令接收两个以上任意数量的参数,每个参数都指定了一个URI,Nginx会在try-files阶段依次把前N-1个参数映射为文件系统上的对象(文件或者目录),然后检查这些对象是否存在。若Nginx发现某个文件系统对象存在,则查找成功,进而在try-files阶段把当前请求的URI改写为该对象所对应的参数URI(但不会包含末尾的斜杠字符,也不会发生“内部跳转”)。如果前N-1个参数所对应的文件系统对象都不存在,try-files阶段就会立即发起“内部跳转”,跳转到最
后一个参数(第N个参数)所指定的URI。

     下面是一个简单的实例:

root /var/www/; #root指令把“查找文件的根目录”配置为 /var/www/
location = /try_files-demo {
   try_files /foo /bar /last;
}
#对应到前面try_files的最后一个URI
location /last {
  echo "uri: $uri ";
}

     这里try-files会在文件系统查找前两个参数对应的文件/var/www/foo和/var/www/bar所对应的文件是否存在。如果不存在,此时Nginx就会在try-files阶段发起到最后一个参数所指定的URI(/last)的内部跳转,如图:

image.png

1.6.10、content

     大部分HTTP模块会介入内容产生阶段,是所有请求处理阶段中重要的阶段。Nginx的echo指令、第三方ngx_lua模块的content_by_lua指令都注册在此阶段。

     这里要注意的是,每一个location只能有一个“内容处理程序”,因此,当在location中同时使用多个模块的content阶段指令时,只有一个模块能成功注册成为“内容处理器”。例如echo和content_by_lua同时注册,最终只会有一个生效,但具体是哪一个生效,结果是不稳定的。

1.6.11、log

     日志模块处理阶段记录日志。

     最后,总结一下:

  1. Nginx将一个HTTP请求分为11个处理阶段,这样做让每个HTTP模块可以只专注于完成一个独立、简单的功能。而一个请求的完整处理过程由多个HTTP模块共同合作完成,可以极大地提高多个模块合作的协同性、可测试性和可扩展性。
  2. Nginx请求处理的11个阶段中,有些阶段是必备的,有些阶段是可选的,各个阶段可以允许多个模块的指令同时注册。但是,find-config、post-rewrite、post-access、try-files四个阶段是不允许其他模块的处理指令注册的,它们仅注册了HTTP框架自身实现的几个固定的方法。
  3. 同一个阶段内的指令,Nginx会按照各个指令的上下文顺序执行对应的handler处理器方法。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1709668.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

redis数据类型set,zset

华子目录 Set结构图相关命令sdiff key1 [key2]sdiffstore destination key1 [key2...]sinter key1 [key2...]sinterstore destination key1 [key2...]sunion key1 [key2...]sunionstore destination key1 [key2...]smove source destination memberspop key [count]sscan key c…

51驱动DY-SV20F语音播放模块

51驱动DY-SV20F语音播放模块 简介模块特征电气参数工作模式配置原理图代码结果图 简介 DY-SV20F 是一款一对一分段触发控制播放器,支持 MP3,WAV 解码格式; 可分段触发 9 首曲目;低电平触发;3.7-5VDC 宽电压供电,直驱 …

【安装笔记-20240520-Windows-自定义 WSL2 安装位置】

安装笔记-系列文章目录 安装笔记-20240520-Windows-自定义 WSL2 安装位置 文章目录 安装笔记-系列文章目录安装笔记-20240520-Windows-自定义 WSL2 安装位置 前言一、软件介绍名称:WSL(适用于 Linux 的 Windows 子系统)主页官方介绍 二、安装…

Java面试八股之有哪些线程安全的集合类

Java中有哪些线程安全的集合类 在Java中,并非所有的集合类都是线程安全的,但在多线程环境下,确保集合操作的线程安全性至关重要。以下是几个典型的线程安全集合类: Vector: 类似于ArrayList,但它是线程安全的。它通过…

快团团帮卖团长如何修改供货大团长复制帮卖团的信息?

一、功能说明 在复制帮卖团中,帮卖团长可以选择:①修改团购内容 ②同步大团长的团购内容 二、具体操作步骤 点击“编辑后帮卖”,在团购设置中设置开启/关闭“同步大团长内容” 开启“同步大团长内容”后,大团长修改图文后&#xf…

微信小程序毕业设计-校园综合服务系统项目开发实战(附源码+论文)

大家好!我是程序猿老A,感谢您阅读本文,欢迎一键三连哦。 💞当前专栏:微信小程序毕业设计 精彩专栏推荐👇🏻👇🏻👇🏻 🎀 Python毕业设计…

Incogniton流覽器使用代理詳細教程

作為一款用於多帳戶管理的反檢測流覽器,Incogniton可以與Mac和Windows系統相容並且試用體驗良好。這篇入門級教程會幫你瞭解如何在Incogniton中使用代理。運用Incogniton,你可以通過虛擬流覽器配置檔代替多臺電腦,同時確保數據安全和私密。這…

【JAVA |图书管理系统】JAVA实现图书管理系(附完整代码)

✨✨谢谢大家捧场,祝屏幕前的小伙伴们每天都有好运相伴左右,一定要天天开心哦!✨✨ 🎈🎈作者主页: 🎈丠丠64-CSDN博客🎈 ✨✨ 帅哥美女们,我们共同加油!一起…

天津企业采购云管平台需要考虑哪些?选择哪家好?

随着天津上云企业的增加,云管理需求也逐步增加。因此采购云管平台是非常必要的。那天津企业采购云管平台需要考虑哪些?选择哪家好? 天津企业采购云管平台需要考虑哪些? 【回答】:天津企业采购云管平台需要考虑的因素比…

xcode依赖包package已经安装,但是提示No such module ‘Alamofire‘解决办法

明明已经通过xcode自带的swift包管理器安装好了依赖包,但是却还是提示:No such module,这个坑爹的xcode,我也只能说服气,但是无奈,没办法攻打苹果总部,只能自己想解决办法了 No such module Ala…

企业融资新渠道:一文详解动产抵押

在当今瞬息万变的商业环境中,资金是企业发展的血液。面对融资难题,动产抵押作为一种灵活高效的融资方式,越来越受到企业的青睐。本文将为您全面解析动产抵押的概念、流程、优势及注意事项,助力您的企业解锁融资新途径。 什么是动…

西储大学数据集学习

数据集下载地址:CWRU凯斯西储大学轴承数据数据集——附:下载链接_西储大学轴承数据集下载-CSDN博客 最近研究故障诊断,先对使用比较多的西储大学数据集研究。以资料【1】中的内容展开研究。 1、轴承的结构 轴承分为外圈、内圈、保持架和滚珠…

NiuCloud-Admin-SAAS:引领前端技术革新与SaaS应用快速开发的未来

一、引言 在数字化快速发展的今天,企业对于快速搭建、高效运营的SaaS(Software-as-a-Service)系统的需求日益增长。为满足这一需求,NiuCloud-Admin-SAAS作为一款快速开发SaaS通用管理系统后台框架,凭借其先进的技术栈…

linux安装Java报错cannot execute binary file: Exec format error

uname -a 查看自己jdk版本 下载JDK路径Java Archive Downloads - Java SE 17 下载对应的版本jdk jdk-17.0.10_linux-aarch64_bin.tar.gz jdk-17.0.10_linux-x64_bin.tar.gz

JQuery 入门

一、jQuery 概述 1、JavaScript 库 仓库:可以把很多东西放到这个仓库里面。找东西只需要到仓库里面查找就可以 JavaScript 库:即library,是一个封装好的特定的集合(方法和函数)。从封装一大堆函数的角度理解库,就是在…

Android 项目Gradle文件讲解(Groovy和Kotlin)

Android 项目Gradle文件讲解(Groovy和Kotlin) 前言正文一、Gradle的作用二、Gradle的种类① 工程build.gradle② 项目build.gradle③ settings.gradle④ gradle.properties⑤ gradle-wrapper.properties⑥ local.properties 三、Groovy和Kotlin的语言对比…

数字中国 | 官媒“点名”人大金仓出圈

随着数字化浪潮的不断推进,人大金仓作为数字化转型的先行者,亮相第七届数字中国建设峰会现场,引起了福建媒体的广泛关注。人大金仓以其在数字化领域的卓越成果,成为了媒体报道的焦点,展现了其在推动数字中国建设过程中…

7B2PRO5.4.2主题 wordpress主题开心版免授权源码

这款7B2 PRO主题也是很多小伙伴儿喜欢的一个主题,有伙伴儿反馈说想学习下新版本,这不就来了,免受权开心版本可供学习使用,要运营还是尊重下版权到官网进行购买吧。 下载:7B2PRO5.4.2 wordpress主题免授权直接安装_麦…

CLIP 源码分析:simple_tokenizer.py

tokenizer的含义 from .clip import *引入头文件时为什么有个. 正文 import gzip import html import os from functools import lru_cacheimport ftfy import regex as re# 上面的都是头文件# 这段代码定义了一个函数 default_bpe(),它使用了装饰器 lru_cache()。…

Redis(十四) 主从模式

文章目录 前言什么是分布式系统主从模式实现Redis主从模式主从模式原理nagle 算法拓扑结构主从模式实现的过程psync实时复制 前言 Redis 作为在内存中操作数据的服务器系统,每时都会接收成千上万的请求,如果我们的业务只在单个服务器上面部署了 Redis&a…