所谓的无法正常运行是指运行的时间长度和单进程是一致的。另外,进程数设为2所用的时间最短,不知道为什么。。。 单进程 # -*- coding: utf-8 -*- """ Created on Wed Sep 11 15:02:37 2019 @author: Administrator """ from 多进程 # -*- coding: utf-8 -*- """ Created on Tue Sep 10 14:35:04 2019 @author: Administrator """ ###krichahzi 上为单进程,下为多进程,我暂时没懂到底是哪里存在不足,需要优化
那么单应用多进程架构,究竟有哪些好处呢?简单的说,我可以列举下面一些: 偷内存。 内存是按照进程来进行分配的,也是通过进程来进行统计的,开辟新的进程,将为自己的应用偷偷拿到一大块内存,降低被LMK Kill的风险。 互不影响。即使新开的进程崩溃,也不会导致主应用的进程受到影响。 主应用的进程即使退出,新的进程依然可以存活,从而可以继续为应用服务,这就是推送进程最常用的方式。 虽然多进程看上去好像很美,但是,单应用多进程的架构,也会给你的程序带来很多负面影响,简单的说,我也列举下面一些: Application的多次初始化。 Android Studio是针对单进程的调试,如果要进行多进程的调试,虽然可以通过附加进程的方式来做,但在调试过程中,还是非常麻烦的,而且很容易出错。 数据、方法调用困难。
虽然在容器里看不见宿主机上的其他进程,但归根结底它还只是一个运行在宿主机上的进程,所以就不具备操作系统的进程管理能力。 每个容器里只运行一个进程这个说法其实不太准确,因为像Nginx在启动后主进程会再开启若干个Worker进程负责请求的处理,Apache更是会为每个请求创建一个进程。 容器的"单进程模型",并不是指容器里只能运行"一个"进程,而是指容器没有管理多个进程的能力。这是因为容器里的主进程(PID=1 的进程)就是应用本身,其他的进程都是这个主进程的子进程。 可是,当这个 Nginx进程异常退出的时候,主进程sh是感知不到的,也就没法对Nginx进行重启。 Docker只能识别主进程的状态,如果主进程正常,Docker的状态就是Running所以在容器里不推荐跑多个进程。 所以更确切的说法是每个容器应该只有一个关注点,只有一个单一的功能。
单进程:一个时间段只能执行一个进程,例如,要听歌就写不了文档 多进程:一个时间段能同时执行多个进程,例如,终于能同时听歌写文档了 多线程:让一个进程能同时执行一段代码的技术,用起来感觉类似于多进程,但区别在于线程与线程间共享资源 ,所以比多进程节省了系统资源,例如,一个浏览器可以同时打开两个网页。 并发:一个“时间段”有多个程序同时执行,多线程并发和多进程并发应该都算并发,你可以说多进程和多线程是一种技术,并发是一种状态。
单进程管理Process 既然我们的服务应用已经提供了多进程的运行模式,那么我们可以直接自己来操作进程吗?答案当然是没问题的。 僵尸进程与回收 由于父子进程是一个异步过程,就像上面的示例一样,父进程退出了子进程依旧还是在执行。但我们通常在应用多子进程的时候,都会启动一个挂起的父进程,然后通过子进程来工作,实现并行处理的能力。 ➜ source git:(main) ✗ php 3.3单进程管理Process.php Parent #43188 exit Child Process #43189start and sleep ($obj) { $obj->child2 = 1; var_dump($obj); }))->start(); // [root@localhost source]# php 3.3单进程管理 source]# php 3.3单进程管理Process.php // array(1) { // [0]=> // object(Swoole\Process)#1 (6) { /
不管在容器中还是虚拟机中都有一个一号进程,虚拟机中是 systemd 进程,容器中是 entrypoint 启动进程,然后所有的其他线程都是一号进程的子进程,或者子进程的子进程,递归下去。 孤儿进程 前面说到如果子进程先于父进程退出,并且父进程没有对子进程残留的资源进行回收的话将会产生僵尸进程。这里引申另外一种情况,父进程先于子进程退出的话,那么子进程的资源谁来回收呢? 父进程先于子进程退出,这个时候我们一般将还在运行的子进程称为孤儿进程,但是实际上孤儿进程并没有一个明确的定义,他的状态还是处于上面讨论的几种进程状态中。那么孤儿进程的资源谁来回收呢? 单进程模型的本质 看完上面两节大家应该知道了虚拟机或者一个完整的 OS 是如何避免僵尸进程的。 进而就会导致容器中在孤儿进程这种异常场景下僵尸进程无法彻底处理的窘境。 所以说,容器的单进程模型的本质其实是容器中的 1 号进程并不具有管理多进程、多线程等复杂场景下的能力。
模型,模型,多进程单线程 单进程多线程 多进程单线程 master进程管理worker进程: 接收来自外界的信号 向各worker进程发送信号 监控woker进程的运行状态 当woker进程退出后 (异常情况下),会自动重新启动新的woker进程 友情提示:nodejs属于这一种好不好,不是只能单核 单进程多线程 单进程多线程 主线程负责监听客户端的连接请求,workers 线程负责处理已经建立好的连接的读写等事件 单进程多线程 单进程多线程肯定比多进程单线程快一些 多进程单线程与单进程多线程的目的都是想尽可能的利用CPU,减少CPU的空闲时间,特别是多核环境 也就是说,你有4核,在某个时刻要么是CPU同时在4个进程做任务(多进程单线程),要么是CPU同时在4个线程上做任务(单进程多线程)。 不过,单进程多线程肯定比多进程单线程快一些。 这是因为,多进程单线程的CPU切换,是从一个进程到另一个进程,而单进程多线程的CPU切换则只在一个进程内,每个进程|线程都有自己的上下文堆栈保存,进程间的切换消耗更大一些。
一,问题背景 很多时候,我们需要确保进程只有一个实例运行。 相比 普通的基于文件系统的 unix socket,abstract namespace unix socket : 没有磁盘文件 进程挂了以后自动删除,无残留文件 无需担心与 文件系统上的文件冲突,不需要关心文件系统上的绝对路径是否存在的问题 让 x 进程等待 y 进程执行完 yyy 操作后,才能执行 xxx 操作。 特点: 多进程/线程 并发安全。 当持有的进程被 kill ,OS自动释放,无残留。
我们这里以单进程启动为例 nginx.c中的main 函数调用ngx_single_process_cycle 这个函数回循环调用 ngx_process_cycle.c 中的 for ( ;; ) {
Supervisor 介绍 1、基本概念 Supervisor 是一个基于 Python 开发的进程管理工具,主要用于监控、控制 Linux 操作系统上的多个进程,通过将命令行进程转变为后台守护进程, Supervisor 采用 C/S(客户端/服务端)架构来实现进程管理: 服务端:即主进程 supervisord supervisord 启动时会生成配置文件中定义的子进程,并监控子进程的状态,当子进程异常退出时对其进行自动重启 、停止、重启、查看状态等操作 2、主要作用 管理进程:Supervisor 可以启动、停止、重启和监控多个进程,确保进程异常退出后能够自动重启 记录日志:Supervisor 可以记录子进程的标准输出和错误输出 作为主进程启动,并置于守护进程模式 Supervisord 根据配置文件中的设置,逐一启动子进程 Supervisord 通过操作系统信号机制,实时监控子进程的运行状态 Supervisord 在子进程状态异常时接收到控制信号 [program:test-server] # command:进程启动命令 # process_name:进程名称 # user:进程启动用户 # directory:启动命令执行前切换到的目录 #
多进程服务器 为了可以处理多个客户的请求,我们之前一直使用多进程TCP并发服务器,socket()监听一个套接口,accept()多个用户,父进程监听listenfd,子线程们在connfd上进行应答处理 单进程服务器 通过使用select函数,我们可以在单进程服务器的前提下,处理多客户的请求,而无需为每个客户派生一个子进程。下面描述此模型下的处于不同阶段的服务器状态。 /tcpservselect01 查看服务端进程情况 可以看到目前主机上有一个服务器进程 [root@VM_0_6_centos ~]# ps -la F S UID PID PPID C /tcpcli01 150.*.*.* hello hello 再次查看服务端进程情况 可以看到此时仍然只有一个进程。 30506 30352 0 80 0 - 1595 poll_s pts/0 00:00:00 tcpservselect01 这个服务器程序较为复杂,但是它避免了为每个连接的客户创建一个新的进程
生产者/消费者问题也称缓存绑定问题(bounded- buffer),是一个经典的、多进程同步问题。 问题描述: 有两个进程:一组生产者进程和一组消费者进程共享一个初始为空、固定大小为n的缓存(缓冲区)。 不完善的解决方案会造成“死锁”,即两个进程都在“睡觉”等着对方来“唤醒”。 只有生产者和消费者两个进程,正好是这两个进程存在着互斥关系和同步关系。那么需要解决的是互斥和同步PV操作的位置。 若生产者进程已经将缓冲区放满,消费者进程并没有取产品,即 empty = 0,当下次仍然是生产者进程运行时,它先执行 P(mutex)封锁信号量,再执行 P(empty)时将被阻塞,希望消费者取出产品后将其唤醒 轮到消费者进程运行时,它先执行 P(mutex),然而由于生产者进程已经封锁 mutex 信号量,消费者进程也会被阻塞,这样一来生产者进程与消费者进程都将阻塞,都指望对方唤醒自己,陷入了无休止的等待。
理论上能用于进程间同步的内核对象比如事件和互斥量等都能用于实现此功能,此处使用互斥量 Mutex 举例。
了解大佬更多信息:https://blog.csdn.net/force_eagle f-stack nginx 单进程模式启动流程分析 本文主要对 f-stack nginx 单进程模式启动流程做基本梳理 , 单进程模式主要调用函数 ngx_single_process_cycle , 配置单进程启动 nginx.conf: daemon off; master_process off;
理论上能用于进程间同步的内核对象比如事件和互斥量等都能用于实现此功能,此处使用互斥量 Mutex 举例。
采用网上的一个利用复制文件来检测多进程和单进程差异的例子。但是例子中许多关键的解释并未给出,反而给入门新手造成了很多不必要的困扰和门槛。 第一个问题的解答:首先,创建两个工程文件,一个是单进程,一个是多进程。其中多进程无法使用选中部分代码然后ctrl+enter的方式运行,必须运行全部代码,在工程文件上方的运行按钮运行。 ? ),速度慢的目的是为了检验多进程速度比单进程快,为什么呢? 因为 1, time.sleep相当于暂停,单进程复制50个文件,暂停了50次,而多进程复制只有暂停了12.5次,所以速度快了。 2,文件复制属于io密集型处理,不是多进程擅长的,如果把 time.sleep去掉,单进程的速度会比多进程快。 以上大致就是为什么加 time.sleep来测试多进程的原因。
在UNIX环境高级编程(APUE)中提到了守护进程的创建方法,思路很清晰,所以这里通过代码具体研究下。 1 完整程序:单实例守护进程 根据APUE的介绍,创建守护进程基本需要如下7个步骤。 3 创建第一个守护进程 如下图所示,程序先执行第178行main函数中的打印语句,输出当前第一个进程的PID值为25872;然后由于在daemonize函数中第一个进程(PID:25872)退出,所以它的子进程 )打开标准输入/输出/错误流,最后该子进程成为由Linux系统init进程托管的孤儿进程,没有终端terminal,这也就是守护进程。 其中使用ps -axj|head -n 1; ps -axj|grep daemon_process命令发现子进程(PID:25874)的父进程为1进程(init进程),终端TTY为空。 接着使用命令pstree -pul查看当前用户的所有进程情况,如下图所示,再次说明守护进程(PID:25874)创建成功了。 4 创建第二个守护进程 如果尝试再次创建一个同样的守护进程,如下图所示。
但这种设计模式有局限:只能在一个进程内生效。但项目开发中又难免会出现开启多个进程的情况。这个时候,原本设计的单例,在整个应用的范围来看,变成了两个单例。 两个进程内的单例的内部状态(变量的取值)也就无法同步了,这也是这个问题的核心(单例的行为(方法)在不同进程是一致的,内部状态会影响到行为的结果)。 依旧是最简单的解决思路: 为每个单例的调用都封装一层(实际是两层,一层给业务,一层是AIDL,用于跨进程调用) 在调用的时候,封装层里判断当前调用的执行环境,如果在单例所在的进程,则调用单例的对应方法, 这个解决思路里,大部分是体力活: 把单例里定义的方法添加到AIDL文件里 实现AIDL文件里的方法(跨进程调用的封装) 添加封装层(if (在单例的进程) { 调用单例的方法; } else { 发起跨进程调用 后续添加新的单例,只需要: 定义单例的AIDL 实现单例 在InstanceCarrier里添加序列化和反序列化的两行代码 如果添加了进程,需要在那个进程添加一个BaseService的派生类 如果是新增接口的话
但毕竟还是有一些人会去这样思考的,这周微信上有人问,Nginx是多进程单线程,Tomcat是单进程多线程,为什么它们会这样设计。 是呀,为什么会这样设计呢。 我当时是这么回答的。 另外他们俩担负的责任也不同,代理一版都是比较轻型,Tomcat毕竟要担负起处理负责业务逻辑的职责,多个进程恐怕不好协同哈,跨进程共享变量,那就成了分布式了。 多进程单线程模型,一个master进程,多个work进程,另外work进程可以绑定到独立的CPU上,这样避免了进程的切换成本。每个进程内部由一个线程来处理请求,负责请求的吞吐。 多进程单线程的模型中,没有了线程的切换,因此性能上能减少很多不必要的消耗,所以Nginx这样的代理服务的系统性能也能够提升很多。 单进程就好比一条流水线只有一个机械手,切换时间片时暂停状态就可以,不用交接信息,减少无用功,所以效率高。 上下文切换的成本来自哪里。
(3)该版本是单进程(线程)的,必须要一个领导爬取完之后才能进行下一个领导的爬取,效率较低,特别是留言较多的领导耗时很长,可以考虑使用多进程或多线程进行优化。