当前位置: 首页 > news >正文

nginx 进程模型

文章目录

    • nginx运行模式与进程模式
    • 进程模式流程图
      • 默认初始化运行模式与进程模式(宏展开)
      • cpu_affinity多CPU绑定合理性判定
      • Nginx的daemon创建(os/unix/ngx_daemon.c)
      • 运行模式、进程模式启动
    • 多进程模式下master处理流程
      • 设置进程信号、初始化信号掩码、屏蔽相关信号
      • 调用ngx_start_worker_processes函数派生Worker进程
      • 创建cache进程,用于缓存管理
      • 进入主循环,通过sigsuspend使进程等待信号
    • 调用ngx_start_worker_processes函数派生Worker进程
      • ngx_pass_open_channel函数
      • ngx_write_channel函数
    • 讨论

nginx运行模式与进程模式

nginx有守护(daemon)模式与非守护(非daemon)模式两种模式,两种模式在运行后的区别在于:

  • 守护模式:nginx启动后直接回到命令提示符界面,不接受任何的输入和输出,其父进程为Linux的init进程;启动nginx进程后,会使用fork创建子进程进行后续操作,启动进程会自动结束。
  • 非守护模式:nginx启动后没有回到命令提示符界面,当nginx有输出时,会直接在终端输出,其父进程为bash。

进程模式分为单进程模式和多进程模式

进程模式流程图

在这里插入图片描述

默认初始化运行模式与进程模式(宏展开)

static char *ngx_core_module_init_conf(ngx_cycle_t *cycle, void *conf)//函数中(core/nginx.c文件中):
{	………ngx_conf_init_value(ccf->daemon, 1);    //守护进程,daemon守护方式ngx_conf_init_value(ccf->master, 1); //多进程模式………ngx_conf_init_value(ccf->worker_processes, 1);    //默认一个worker………//worker进程绑定CPU设置合理性判断,用户名,文件锁等初始化return NGX_CONF_OK;
}//宏定义展开如下
#define NGX_CONF_UNSET       -1
………
#define ngx_conf_init_value(conf, default)  \   if (conf == NGX_CONF_UNSET) {           \      conf = default;                         \   }
………static char *ngx_core_module_init_conf(ngx_cycle_t *cycle, void *conf)//函数中(core/nginx.c文件中):
{………//ngx_conf_init_value(ccf->daemon, 1)按宏展开;if (ccf->daemon == -1) {//守护进程,daemon守护方式ccf->daemon = 1;                                        }//以下ngx_conf_init_value宏类似展开………return NGX_CONF_OK;
}

cpu_affinity多CPU绑定合理性判定

进行绑定时,必须cpu数目与worker进程数目相等,否则不好绑定

#if (NGX_HAVE_CPU_AFFINITY)   //支持多CPU绑定if (!ccf->cpu_affinity_auto       //非自动&& ccf->cpu_affinity_n       //非0 && ccf->cpu_affinity_n != 1      //非1  && ccf->cpu_affinity_n != (ngx_uint_t) ccf->worker_processes)   //与工作进程数相等 {        //错误处理及记录;}
#endif

Nginx的daemon创建(os/unix/ngx_daemon.c)

  1. 创建一个子进程,自己(父进程)关闭结束;.
  2. 创建新的会话;
  3. 设置进程的umask为0;
  4. daemon模式下,没有输入输出;
  5. 返回
//创建新的会话
………
switch (fork()) 
{  case -1:     ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "fork() failed");  return NGX_ERROR;    case 0:       break;    //子进程default:       exit(0);  //父进程退出,结束}
………//在守护模式下没有输出,nginx采用重定向的方式对输出进行重定向
………
fd = open("/dev/null", O_RDWR);    
if (fd == -1) {       //错误记录处理, return NGX_ERROR;  
}    
if (dup2(fd, STDIN_FILENO) == -1) {     //错误记录处理, return NGX_ERROR;  }   //将标准输入重定位到fd,即null设备
if (dup2(fd, STDOUT_FILENO) == -1) {//错误记录处理, return NGX_ERROR;  } //将标准输出重定位到fd,即null设备
………
ngx_int_t  ngx_daemon(ngx_log_t *log)  //汇总与总结
{//定义变量;//创建一个子进程,自己(父进程)关闭结束;ngx_parent = ngx_pid;   //ngx_pid为全局变量 ngx_pid = ngx_getpid();    if (setsid() == -1) {    //创建新的会话 //错误处理与记录后返回;}   umask(0);//设置掩码为0//daemon模式下,关闭标准输入与输出;
}

运行模式、进程模式启动

在Nginx的main函数最后,一切准备就绪后,根据ngx_process 值的指示,判定单/多进程模式

int ngx_cdecl  main(int argc, char *const *argv) 
{………//前期内存池等各种准备if (ngx_process == NGX_PROCESS_SINGLE) {     //为0  ngx_single_process_cycle(cycle);   //单进程模式} else  //不为0{       ngx_master_process_cycle(cycle);    //多进程模式}return 0;
}

多进程模式下master处理流程

在这里插入图片描述

  1. 设置进程信号、初始化信号掩码屏蔽相关信号。
  2. 调用ngx_start_worker_processes函数派生Worker进程;
  3. ngx_start_cache_manager_processes函数派生cache manager进程以及cache loader进程; cache进程用于缓存管理;
  4. 进入主循环,通过sigsuspend使进程等待信号;
  5. 待收到信号后进入ngx_signal_handler进行信号处理

设置进程信号、初始化信号掩码、屏蔽相关信号

//Nginx定义的几个常见信号
#define NGX_SHUTDOWN_SIGNAL      QUIT  //终端退出
#define NGX_TERMINATE_SIGNAL     TERM  //软件终止
#define NGX_NOACCEPT_SIGNAL      WINCH  //窗口大小改变
#define NGX_RECONFIGURE_SIGNAL   HUP  //终端挂起或终端控制进程结束
  • nginx信号解析
#define ngx_signal_helper(n)     SIG##n // 表示前后两个字符串合并(宏)
#define ngx_signal_value(n)      ngx_signal_helper(n) //程序中使用的宏ngx_signal_value (NGX_RECONFIGURE_SIGNAL)//,经过宏展开后 
1. ngx_signal_value ( HUP ),经过宏展开后 
2. ngx_signal_helper( HUP ),再经过宏展开后 
3. SIGHUP  这正是Linux的信号………//定义局部临时变量
sigemptyset(&set);  
sigaddset(&set, SIGCHLD);  //Linux信号标准名字
sigaddset(&set, SIGALRM); //Linux信号标准名字
sigaddset(&set, SIGIO); //Linux信号标准名字
sigaddset(&set, SIGINT); //Linux信号标准名字
sigaddset(&set, ngx_signal_value(NGX_RECONFIGURE_SIGNAL));   //Linux信号别名
sigaddset(&set, ngx_signal_value(NGX_REOPEN_SIGNAL));   
sigaddset(&set, ngx_signal_value(NGX_NOACCEPT_SIGNAL));   
sigaddset(&set, ngx_signal_value(NGX_TERMINATE_SIGNAL));   
sigaddset(&set, ngx_signal_value(NGX_SHUTDOWN_SIGNAL));   
sigaddset(&set, ngx_signal_value(NGX_CHANGEBIN_SIGNAL));
if (sigprocmask(SIG_BLOCK, &set, NULL) == -1) {   //若新增屏蔽(搁置)信号集合set 失败   //错误处理并记录
}
sigemptyset(&set);//清空信号集,以便后面使用
………

调用ngx_start_worker_processes函数派生Worker进程

………
ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);    
ngx_start_worker_processes(cycle, ccf->worker_processes,                              NGX_PROCESS_RESPAWN);
………

创建cache进程,用于缓存管理

………
ngx_start_cache_manager_processes(cycle, 0);
………

进入主循环,通过sigsuspend使进程等待信号

………
for(;;){………//设置时钟sigsuspend(&set);        ngx_time_update();//更新时钟………
}

调用ngx_start_worker_processes函数派生Worker进程

多进程模式下Worker进程的作用(os/unix/ ngx_process_cycle.c)

  1. 读取请求、解析请求、处理请求,产生结果后,返回给客户,最后断开连接。
  2. 一个请求在一个且仅在该worker内处理完成;
  3. ngx_start_worker_processes函数调用ngx_spawn_process函数派生worker进程.

ngx_start_worker_processes函数的主要功能及其过程如下:

  1. 局部临时变量定义。如创建一个ngx_channel_t 变量ch,并将ch的command置为NGX_CMD_OPEN_CHANNEL;表示新建一个进程;
  2. 循环创建n个worker进程;
  3. 调用ngx_spawn_process创建一个worker进程,设置ngx_process_slot 值;
  4. 为了ngx_processes数组的值同步,设置好ch的其它字段的值,
  5. 调用ngx_pass_open_channel广播,使得以前创建的进程,更新ngx_processes数据;
  6. 重复,3~5,直至n个worker创建完成。
//第三个参数type
#define NGX_PROCESS_NORESPAWN     -1   //子进程退出,父进程不重启
#define NGX_PROCESS_JUST_SPAWN    -2 //区分刚建的子进程与其它子进程
#define NGX_PROCESS_RESPAWN       -3//子进程退出,父进程重启
#define NGX_PROCESS_JUST_RESPAWN  -4//区分刚建的子进程与其它子进程,子进程退出,父进程重启
#define NGX_PROCESS_DETACHED      -5   //新派生进程与父进程脱离关系//第二个参数n :创建worker进程的总数
static voidngx_start_worker_processes(ngx_cycle_t *cycle, ngx_int_t n, ngx_int_t type)struct ngx_cycle_s {   void                  ****conf_ctx;   //保持所有模块的配置结构体ngx_pool_t               *pool; //内存池ngx_log_t                *log; //日志信息ngx_log_t                 new_log;  ngx_uint_t                log_use_stderr;  /* unsigned  log_use_stderr:1; */    ngx_connection_t        **files;   //文件句柄ngx_connection_t         *free_connections;  //可用连接池ngx_uint_t                free_connection_n;//可用连接池总数ngx_module_t            **modules;   //模块信息ngx_uint_t                modules_n;  ngx_uint_t                modules_used;    /* unsigned modules_used:1; */    ngx_queue_t               reusable_connections_queue;    //再利用连接队列ngx_uint_t                reusable_connections_n;   //再利用连接数ngx_array_t               listening;    //被监听端口ngx_array_t               paths;    //操作目录ngx_array_t               config_dump;   ngx_rbtree_t              config_dump_rbtree;  ngx_rbtree_node_t         config_dump_sentinel;   ngx_list_t                open_files;   //打开文件ngx_list_t                shared_memory;    //共享文件ngx_uint_t                connection_n;   //当前进程中所有连接对象的总数ngx_uint_t                files_n;//代开文件个数ngx_connection_t         *connections;   //指向当前进程中的所有连接对象 ngx_event_t              *read_events;   //读事件ngx_event_t              *write_events; //写事件ngx_cycle_t              *old_cycle;  //old cycle指针ngx_str_t                 conf_file;  //配置文件ngx_str_t                 conf_param;   //配置参数ngx_str_t                 conf_prefix;   //配置前缀ngx_str_t                 prefix;   //前缀ngx_str_t                 lock_file;   //用于进程间同步的文件锁ngx_str_t                 hostname;//主机名
};

ngx_channel_t结构体

//ngx_channel_t 的command
#define NGX_CMD_OPEN_CHANNEL   1 //新建
#define NGX_CMD_CLOSE_CHANNEL  2 //关闭
#define NGX_CMD_QUIT           3 //退出
#define NGX_CMD_TERMINATE      4  //终止
#define NGX_CMD_REOPEN         5  //重新打开(重启)
typedef struct {   ngx_uint_t  command; //命令ngx_pid_t   pid;   //进程号ngx_int_t   slot;  // ngx_processes 数组中worker进程下标ngx_fd_t    fd;//保存用于socketpair全双工的socket
} ngx_channel_t;

ngx_processes数组
作用有以下几个方面:
(1)保存创建进程的有关信息;
(2)便于worker进程间通信;
(3)便于worker进程与master进程间通信;

ngx_process_t    ngx_processes[NGX_MAX_PROCESSES];typedef struct {    ngx_pid_t           pid;  //worker进程的PIDint                 status;  //状态ngx_socket_t        channel[2]; //worker与master之间通信的socketpair ngx_spawn_proc_pt   proc;   //回调函数void               *data;   // proc回调函数的参数char               *name;    //worker子进程的名字unsigned            respawn:1;   //是否重启unsigned            just_spawn:1;  //是否刚创建unsigned            detached:1;   //是否脱离unsigned            exiting:1;    unsigned            exited:1;
} ngx_process_t;
static voidngx_start_worker_processes(ngx_cycle_t *cycle, ngx_int_t n, ngx_int_t type){
………// 创建并初始化ngx_channel_t结构体类型ch;
ngx_channel_t  ch;
ch.command = NGX_CMD_OPEN_CHANNEL;  
for (i = 0; i < n; i++) {    //依次创建n个worker进程ngx_spawn_process(cycle, ngx_worker_process_cycle,  (void *) (intptr_t) i, "worker process", type);//调用 ngx_spawn_process函数,创建worker进程,其信息ngx_processes数组ngx_process_slot 元素的中;   ch.pid = ngx_processes[ngx_process_slot].pid;    ch.slot = ngx_process_slot;     ch.fd = ngx_processes[ngx_process_slot].channel[0]; //刚创建进程的写端给其它进程,便于后续通信ngx_pass_open_channel(cycle, &ch);    //调用ngx_pass_open_channel广播(这是有linux的进程机制决定的,fork时父子进程会共享内存,当进程对内存内容进行修改时,内核会复制一份数据到另一片内存时,这时前后的内容会不一致,所以才需要广播)
}
}

ngx_spawn_process函数

  1. 在ngx_processes数组中找到一个保存worker进程信息的元素下标s;①如果respawn大于0, respawn就是s;②如果不大于0,从ngx_processes数组中找到其元素的pid成员为-1的(空闲)元素,该元素就是的数组下标就是s;但该s不能超过最大worker范围。
if (respawn >= 0) 
{     s = respawn;   // ①} 
else 
{       // ②,遍历ngx_processes数组,确定sfor (s = 0; s < ngx_last_process; s++) {         if (ngx_processes[s].pid == -1)  {      break;    }   }      if (s == NGX_MAX_PROCESSES) {     //最大为1024       //超过最大worker数限制,错误处理并记录return NGX_INVALID_PID;     } 
}
  1. 如果respawn不是NGX_PROCESS_DETACHED,即派生子进程与父进程不是非脱离关系,①创建通信socketpair, ②以非阻塞方式设置读写端, ③将写端设置为异步写, ④并将写端的SIGIO以及SIGURG信号的属主设为父进程; ⑤设置Master、worker进程执行exec()函数后,关闭socket。
①创建通信socketpair,if (respawn != NGX_PROCESS_DETACHED) {//2,如果非关系成立if (socketpair(AF_UNIX, SOCK_STREAM, 0, ngx_processes[s].channel) == -1) // ①{//错误处理并记录;return NGX_INVALID_PID;       }②以非阻塞方式设置读写端,if (ngx_nonblocking(ngx_processes[s].channel[0]) == -1) {  //设置写端 //错误处理并记录;return NGX_INVALID_PID;    }③将写端设置为异步写,on = 1;    if (ioctl(ngx_processes[s].channel[0], FIOASYNC, &on) == -1) {   // ③      // 错误处理并记录;return NGX_INVALID_PID;   }④并将写端的SIGIO以及SIGURG信号的属主设为ngx_pid(父进程);if (fcntl(ngx_processes[s].channel[0], F_SETOWN, ngx_pid) == -1) { // ④   // 错误处理并记录;return NGX_INVALID_PID;     }⑤设置Master、worker进程执行exec()函数后,关闭socket。
if (fcntl(ngx_processes[s].channel[1], F_SETFD, FD_CLOEXEC) == -1) {  // ⑤       // 错误处理并记录;return NGX_INVALID_PID;    }//以下设置当前子进程的socket,Master进程用于监听
ngx_channel = ngx_processes[s].channel[1];//给全局变量ngx_channel 赋值
}
  1. 如果respawn是NGX_PROCESS_DETACHED,设置该worker的通信通道都为-1;
else//是2的if的else分支,否则,则是NGX_PROCESS_DETACHED脱离关系{       ngx_processes[s].channel[0] = -1;   //创建的是master,通信pair置为-1     
ngx_processes[s].channel[1] = -1;  }
  1. fork派生worker进程;
//为ngx_start_worker_processes函数记下ngx_process_slot 值ngx_process_slot = s; //ngx_process_slots是全部变量pid = fork();    //派生子进程
  1. worker子进程执行回调proc;
switch (pid) {   case -1:       错误处理并记录;return NGX_INVALID_PID;   case 0:     //5,子进程执行回调函数procngx_parent = ngx_pid;     ngx_pid = ngx_getpid();     proc(cycle, data);     break;   default:        break;  //父进程往后执行}
  1. 父进程填充worker子进程的信息到ngx_processes数组s元素中;
 ngx_processes[s].pid = pid;   //ngx_processes[s].exited = 0;    
f (respawn >= 0) {    //如果是重启子进程,返回return pid;   }

在这里插入图片描述

ngx_spawn_process(cycle, ngx_worker_process_cycle,                          (void *) (intptr_t) i, "worker process", type);1.第一个参数: cycle, ngx_start_worker_processes函数
2.第二个参数:回调函数ngx_worker_process_cycle,该函数在os/unix/    ngx_process_cycle.c中定义;
3.第三个参数:i,即第几个worker
4.第四个参数:worker进程名字
5.第五个参数:类型,来自ngx_start_worker_processes函数的形参

ngx_pass_open_channel函数

遍历ngx_processes数组广播,对每个worker子进程发送信息。
static void ngx_pass_open_channel(ngx_cycle_t *cycle, ngx_channel_t *ch):

  1. 对每个非刚创建、不存在进程以及父进程socket关闭的子进程;
  2. 调用ngx_write_channel发送消息内容;
typedef struct {   ngx_uint_t  command; //命令,见下页ngx_pid_t   pid;   //进程号ngx_int_t   slot;  // ngx_processes 数组中worker进程下标ngx_fd_t    fd;//保存用于socketpair全双工的socket
} ngx_channel_t;
static void ngx_pass_open_channel(ngx_cycle_t *cycle, ngx_channel_t *ch)
{for (i = 0; i < ngx_last_process; i++) {      //过滤刚建的子进程、不存在的子进程以及关闭socket的子进程if (i == ngx_process_slot            ||   //刚刚创建的ngx_processes[i].pid == -1            ||   //没有进程数据的数组元素ngx_processes[i].channel[0] == -1)    //无法通信了{            continue;        }   ..........    //给每个子进程的父进程发送刚建进程的worker信息ngx_write_channel(ngx_processes[i].channel[0], ch, sizeof(ngx_channel_t), cycle->log);  }
}

ngx_write_channel函数

  1. 构造struct msghdr 类型msg;//Linux系统层次接口
  2. 调用sendmsg发送msg;//Linux系统层次接口
ngx_int_tngx_write_channel(ngx_socket_t s, ngx_channel_t *ch, size_t size,    ngx_log_t *log)
{ssize_t             n;  //声明所需变量ngx_err_t           err;    struct iovec        iov[1];    struct msghdr       msg;
……iov[0].iov_base = (char *) ch;   //构造msgiov[0].iov_len = size;  msg.msg_name = NULL; msg.msg_namelen = 0;    msg.msg_iov = iov;  msg.msg_iovlen = 1;   n = sendmsg(s, &msg, 0);//发送msg,Linux编程接口……//错误处理等return NGX_OK;
}

讨论

  • 为什么nginx使用的是进程不是线程

是因为 Nginx 要保证高可用性,多线程之间会共享地址空间,当某一个第三方模块引发了一个段错误时,就会导致整个 Nginx 进程挂掉。而采用多进程模型不会出现这个问题

相关文章:

nginx 进程模型

文章目录 nginx运行模式与进程模式进程模式流程图默认初始化运行模式与进程模式(宏展开)cpu_affinity多CPU绑定合理性判定Nginx的daemon创建&#xff08;os/unix/ngx_daemon.c&#xff09;运行模式、进程模式启动 多进程模式下master处理流程设置进程信号、初始化信号掩码、屏蔽…...

TypeScript - 枚举类型 -字符型枚举

什么是枚举 枚举就是有固定的元素的一个对象。 对象的元素可以直接列举出来。 什么是字符型枚举 字符型枚举&#xff0c;就是元素的值是字符串。 就这么简单。 定义一个我看看 来&#xff0c;让我们实际看一下字符型的枚举。 // 定义字符型枚举 enum COLOR2{RED red,BLUE blu…...

分布式锁-Redis红锁解决方案

一 分布式锁的概念 1&#xff1a;概念 分布式锁&#xff08;多服务共享锁&#xff09; 在分布式的部署环境下&#xff0c;通过锁机制来让多客户端互斥的对共享资源进行访问控制分布式系统不同进程共同访问共享资源的一种锁的实现。如果不同的系统或同一个系统的不同主机之间共…...

【Ubuntu 终端终结者Ctrl shift e无法垂直分页解决办法】

Ubuntu 终端终结者Ctrl shift e无法垂直分页解决办法 错误原因解决办法 错误原因 这是因为ibus输入法有一个快捷键占用了这个终端终结者的快捷键 解决办法 打开命令行输入 ibus-setup进入到如下页面随后将其中的表情注释的快捷键删除即可...

Error: error:0308010C:digital envelope routines::unsupported

Error: error:0308010C:digital envelope routines::unsupported 问题描述&#xff1a; 使用 npm run dev 或者 yarn run dev 时 报错&#xff1a;Error: error:0308010C:digital envelope routines::unsupported PS D:\Project\dlspeed_all\GS-IMS\ruoyi-ui> npm run de…...

RTMP在智能眼镜行业应用方案有哪些?

方案示例 视频直播&#xff1a;智能眼镜通常具有摄像头和显示屏&#xff0c;可以实时拍摄和显示视频。RTMP协议可以用于将智能眼镜拍摄的视频传输到服务器&#xff0c;以便其他用户可以实时观看。远程协作&#xff1a;智能眼镜可以用于远程协作&#xff0c;例如在医疗、建筑等…...

【每日一题】合并两个有序数组

链接奉上&#xff1a;合并两个有序数组 目录 直接合并后排序&#xff1a;思路&#xff1a;代码实现&#xff1a; 双指针思路&#xff1a;代码实现&#xff1a; 直接合并后排序&#xff1a; 思路&#xff1a; 将nums2直接合并到nums1后边&#xff0c;并进行排序 代码实现&…...

MySQL---表的增查改删(CRUD进阶)

文章目录 数据库约束表的设计一对一一对多多对多 新增查询聚合查询分组查询联合查询内连接外连接自连接子查询合并查询 数据库约束 数据库约束就是指&#xff1a;程序员定义一些规则对数据库中的数据进行限制。这样数据库会在新增和修改数据的时候按照这些限制&#xff0c;对数…...

《HelloGitHub》第 91 期

兴趣是最好的老师&#xff0c;HelloGitHub 让你对编程感兴趣&#xff01; 简介 HelloGitHub 分享 GitHub 上有趣、入门级的开源项目。 github.com/521xueweihan/HelloGitHub 这里有实战项目、入门教程、黑科技、开源书籍、大厂开源项目等&#xff0c;涵盖多种编程语言 Python、…...

jvm线上异常排查流程

1. Linux命令 jps 找出当前运行实例 2. jinfo -flags pid&#xff08;java运行id) 打印出当前设置的jvm内存参数情况 3.jstat -gcutil pid 1000 10 每秒打印一次当前jvm的gc运行情况&#xff0c;一共打印10次 4.将gc日志下载进行分析&#xff1a;到底是因为什么原因导致一直…...

python项目之酒店客房入侵检测系统的设计与实现

项目简介 酒店客房入侵检测系统的设计与实现实现了以下功能&#xff1a; 1、控制台&#xff1a; 控制台是整个系统的首页面。在控制台中&#xff0c;酒店的客房管理人员能够在该页面中查看到当前的空余客房数量、当前在店的客房人数、当前的已用客房数量、当前酒店全部的客房…...

C++ 学习系列 -- 标准库常用得 algorithm function

一 前言 c 标准库中提供了许多操作数据结构&#xff1a;vector、list、deque、map、set 等函数&#xff0c;学习并了解这些常用函数对于我们理解 c 的一些设计模式有着重要的作用。 二 常用的 algorithm function 源码 源代码位置&#xff1a; bits/stl_algo.h 1. accumu…...

[论文笔记]E5

引言 今天又带来一篇文本匹配/文本嵌入的笔记:Text Embeddings by Weakly-Supervised Contrastive Pre-training。中文题目是 基于弱监督对比预训练计算文本嵌入。 本篇工作提出了E5模型(EmbEddings from bidirEctional Encoder rEpresentations)。该模型以带弱监督信号的对…...

k8s 1.28版本:使用StorageClass动态创建PV,SelfLink 问题修复

k8s中提供了一套自动创建 PV 的机制&#xff0c;就是基于 StorageClass 进行的&#xff0c;通过 StorageClass 可以实现仅仅配置 PVC&#xff0c;然后交由 StorageClass 根据 PVC 的需求动态创建 PV。 问题&#xff1a;   使用 k8s 1.28版本&#xff0c;通过 kubectl get pv…...

漏洞复现-dedecms文件上传(CVE-2019-8933)

dedecms文件上传_CVE-2019-8933 漏洞信息 Desdev DedeCMS 5.7SP2版本中存在安全漏洞CVE-2019-8933文件上传漏洞 描述 ​ Desdev DedeCMS&#xff08;织梦内容管理系统&#xff09;是中国卓卓网络&#xff08;Desdev&#xff09;公司的一套基于PHP的开源内容管理系统&#x…...

vue分片上传

<template><div><input type"file" id"input" /><button click"uploadFile">上传</button></div> </template><script lang"ts" setup> let chunkSize1024 * 1024,index0; const upl…...

【大数据Hive】hive 表数据优化使用详解

目录 一、前言 二、hive 常用数据存储格式 2.1 文件格式-TextFile 2.1.1 操作演示 2.2 文件格式 - SequenceFile 2.2.1 操作演示 2.3 文件格式 -Parquet 2.3.1 Parquet简介 2.3.2 操作演示 2.4 文件格式-ORC 2.4.1 ORC介绍 2.4.2 操作演示 三、hive 存储数据压缩优…...

京东平台数据分析(京东销量):2023年9月京东吸尘器行业品牌销售排行榜

鲸参谋监测的京东平台9月份吸尘器市场销售数据已出炉&#xff01; 根据鲸参谋电商数据分析平台的相关数据显示&#xff0c;今年9月&#xff0c;京东吸尘器的销量为19万&#xff0c;环比下滑约12%&#xff0c;同比下滑约25%&#xff1b;销售额为1.2亿&#xff0c;环比下滑约11%&…...

基于springboot实现休闲娱乐代理售票平台系统项目【项目源码+论文说明】计算机毕业设计

基于springboot实现休闲娱乐代理售票平台系统演示 摘要 网络的广泛应用给生活带来了十分的便利。所以把休闲娱乐代理售票管理与现在网络相结合&#xff0c;利用java技术建设休闲娱乐代理售票系统&#xff0c;实现休闲娱乐代理售票的信息化。则对于进一步提高休闲娱乐代理售票管…...

jvm对象内存划分

写此篇博客源于面试问到内存分配的细节&#xff0c;然后不明白问的是什么。回过头发现以前看过这块内容&#xff0c;只是有些印象&#xff0c;但是无法描述清楚。 额外概念了解 jvm内存空间是逻辑上连续的虚拟地址空间&#xff08;虚拟内存中的概念&#xff09;映射到物理内存…...

大型活动交通拥堵治理的视觉算法应用

大型活动下智慧交通的视觉分析应用 一、背景与挑战 大型活动&#xff08;如演唱会、马拉松赛事、高考中考等&#xff09;期间&#xff0c;城市交通面临瞬时人流车流激增、传统摄像头模糊、交通拥堵识别滞后等问题。以演唱会为例&#xff0c;暖城商圈曾因观众集中离场导致周边…...

cf2117E

原题链接&#xff1a;https://codeforces.com/contest/2117/problem/E 题目背景&#xff1a; 给定两个数组a,b&#xff0c;可以执行多次以下操作&#xff1a;选择 i (1 < i < n - 1)&#xff0c;并设置 或&#xff0c;也可以在执行上述操作前执行一次删除任意 和 。求…...

【SQL学习笔记1】增删改查+多表连接全解析(内附SQL免费在线练习工具)

可以使用Sqliteviz这个网站免费编写sql语句&#xff0c;它能够让用户直接在浏览器内练习SQL的语法&#xff0c;不需要安装任何软件。 链接如下&#xff1a; sqliteviz 注意&#xff1a; 在转写SQL语法时&#xff0c;关键字之间有一个特定的顺序&#xff0c;这个顺序会影响到…...

DIY|Mac 搭建 ESP-IDF 开发环境及编译小智 AI

前一阵子在百度 AI 开发者大会上&#xff0c;看到基于小智 AI DIY 玩具的演示&#xff0c;感觉有点意思&#xff0c;想着自己也来试试。 如果只是想烧录现成的固件&#xff0c;乐鑫官方除了提供了 Windows 版本的 Flash 下载工具 之外&#xff0c;还提供了基于网页版的 ESP LA…...

NFT模式:数字资产确权与链游经济系统构建

NFT模式&#xff1a;数字资产确权与链游经济系统构建 ——从技术架构到可持续生态的范式革命 一、确权技术革新&#xff1a;构建可信数字资产基石 1. 区块链底层架构的进化 跨链互操作协议&#xff1a;基于LayerZero协议实现以太坊、Solana等公链资产互通&#xff0c;通过零知…...

MySQL用户和授权

开放MySQL白名单 可以通过iptables-save命令确认对应客户端ip是否可以访问MySQL服务&#xff1a; test: # iptables-save | grep 3306 -A mp_srv_whitelist -s 172.16.14.102/32 -p tcp -m tcp --dport 3306 -j ACCEPT -A mp_srv_whitelist -s 172.16.4.16/32 -p tcp -m tcp -…...

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

使用 SymPy 进行向量和矩阵的高级操作

在科学计算和工程领域&#xff0c;向量和矩阵操作是解决问题的核心技能之一。Python 的 SymPy 库提供了强大的符号计算功能&#xff0c;能够高效地处理向量和矩阵的各种操作。本文将深入探讨如何使用 SymPy 进行向量和矩阵的创建、合并以及维度拓展等操作&#xff0c;并通过具体…...

Mobile ALOHA全身模仿学习

一、题目 Mobile ALOHA&#xff1a;通过低成本全身远程操作学习双手移动操作 传统模仿学习&#xff08;Imitation Learning&#xff09;缺点&#xff1a;聚焦与桌面操作&#xff0c;缺乏通用任务所需的移动性和灵活性 本论文优点&#xff1a;&#xff08;1&#xff09;在ALOHA…...

Redis的发布订阅模式与专业的 MQ(如 Kafka, RabbitMQ)相比,优缺点是什么?适用于哪些场景?

Redis 的发布订阅&#xff08;Pub/Sub&#xff09;模式与专业的 MQ&#xff08;Message Queue&#xff09;如 Kafka、RabbitMQ 进行比较&#xff0c;核心的权衡点在于&#xff1a;简单与速度 vs. 可靠与功能。 下面我们详细展开对比。 Redis Pub/Sub 的核心特点 它是一个发后…...