说下程序开发中的服务、进程、线程、协程
服务
我们通过阿里云购买了一台Ecs服务器,我们称之为一个服务器实例,我们通过ssh登陆上这个实例,ssh就是这个实例上提供的一个服务,我们再通过systemctl start docker启动docker,就是在这个实例上启动一个docker服务,我们通过编程方式如用nodejs的createServer,或者java的ServerSocket也可以启动一个服务
var http=require('http'); //用来启服务
var fs=require('fs'); //用来读取文件
var root="C:/Users/Administrator/Desktop/notice" //你本地放index.html页面的文件路径
//开启服务
var server=http.createServer(function(req,res){
var url=req.url;
var file = root+url;
fs.readFile(file,function(err,data){
if(err){
res.writeHeader(404,{
'content-type' : 'text/html;charset="utf-8"'
});
res.write('<h1>404错误</h1><p>你要找的页面不存在</p>');
res.end();
}else{
res.writeHeader(200,{
'content-type' : 'text/html;charset="utf-8"'
});
res.write(data);//将index.html显示在客户端
res.end();
}
})
}).listen(8888); //端口号
console.log('服务器开启成功');
可以发现,服务的底层都是通过建立 TCP/UDP 连接与其他服务器或者客户端使用 IP 地址和端口进行通信
进程
进程是GNU/Linux 操作系统进程中最常见的执行单元。一个任务在一个进程中运行。也可以说一个请求对应一个进程,如果你有管理 PHP-FPM 服务器的经验,你应该知道你不能仅仅通过增加 PHP-FPM 进程数来服务更多的请求。我们通过一个jmeter压力测试来解释进程,我们用jmeter新建了一个任务,并发200,循环次数200,并设置http请求到一个php程序,我们点击开始,然后立即在服务器上运行top命令,可以看到马上显示了很多php-fpm,每个php-fpm就是一个进程,php通过fork多个php-fpm来处理多并发请求
每一个启动都会产生至少一个进程
线程
与进程相比,线程更轻量级。多个线程在一个进程中执行并共享一些全局状态。默认情况下,每个线程都可以在任何时间点访问和修改全局状态。为了保持数据同步,使用锁来防止全局状态被多个线程修改而导致的数据丢失。如果多个线程在没有适当同步的情况下访问同一个可变状态变量,您的程序就会被破坏。众所周知,编写和调试带有线程和锁的高性能并发程序非常困难。我们必须处理死锁、数据竞争等问题。一些现代编程语言如 Node.js 和 PHP 甚至没有线程的概念,但线程的好处也是想而易见,在java的多任务和大数据量处理中非常常见。
我们通过top可以查看到进程,同样,我们也可以通过htop命令(yum install -y htop)查看线程。我们先在服务器端输入htop,然后按来进入htop的设置菜单。选择“设置”栏下面的“显示选项”,然后开启“树状视图”和“显示自定义线程名”选项。按退出设置,我们再jmeter跑一下任务。这时可以观察到线程
为什么是php-fpm而不是php呢,因为php没有多线程的功能,多线程/进程都交由php-fpm来做了。
我们换成测试swoole程序看看有什么不同
可以看到挂载进程下面的很多php线程,说明swoole实现了原来php没有的进程/线程机制
协程
The word “coroutine” is composed of two words: “co” (cooperative) and “routines” (functions) "coroutine "这个词由两个词组成:"co"(合作)和 "routines"(函数)。
协程可以简单理解为轻量级的线程,只不过这个线程是用户态的,不需要操作系统参与,创建销毁和切换的成本非常低,和线程不同的是协程没法利用多核 CPU 的,想利用多核 CPU 需要依赖 Swoole 的多进程模型我个人的理解是:协程就是通过控制函数间的合作,而不需要操作系统参与,用同步的代码来达到异步的效果
下面用一段代码来举例协程
<?php
use Swoole\Coroutine;
use function Swoole\Coroutine\run;
echo "main start\n";
run(function () {
echo "coro " . Coroutine::getcid() . " start\n";
Coroutine::create(function () {
echo "coro " . Coroutine::getcid() . " start\n";
Coroutine::sleep(.2);
echo "coro " . Coroutine::getcid() . " end\n";
});
echo "coro " . Coroutine::getcid() . " do not wait children coroutine\n";
Coroutine::sleep(.1);
以上php代码运行将输出
/*
main start
coro 1 start
coro 2 start
coro 1 do not wait children coroutine
coro 1 end
coro 2 end
end
*/
发表评论