[Design] 后端程序的高并发与异步
既然涉及到高并发这个概念,就少不了先谈这么几个概念,并发数、多进程、多线程、协程、负载均衡。
操作系统上讲的并发是操作系统上有几个程序在同时执行,单核CPU在微观上是由CPU调度执行,非同时执行,多核CPU在微观上才是真正的并行。
互联网产品的并发通常是指并发连接数,用户同时访问数量,哪些因素能影响到并发能力,既有编程模型,也有服务器负载能力。
PHP 依赖多进程解决并发数,是最原始和耗费资源的一种方式。
以 8G 内存服务器为例,一个PHP进程占用20M内存,最多也就开几百个进程,假如任务比较耗时且并发很高,那么新请求很快就得不到响应了。
对于并发访问 PHP 提供 curl_multi_* 系列函数,纯接口的并发调用就不需要自己写多进程、多线程程序了。
Java是多线程模型,每个进程可以创建多个线程,线程使用进程的上下文,每个线程只需要小部分运行资源,所以比进程轻量许多。
进程和线程都是依赖操作系统的系统调用支持的,所以这部分调度开销是难以避免的。
协程是程序级的调度模型,最轻量,好比框架级实现像操作系统一样能自由对程序中断、调度,比如借助于 C 的 setjmp 系列函数就能做到中断。
不管编程模型多先进,单机总会达到并发上限,要想突破限制就必须引入负载均衡,通过横向扩展解决问题。
上面所提到的编程模型优劣,本质上还都是语言层面的,短期内并不能真正解决问题,下面就延伸出从应用层面的考虑:
为什么高性能都离不开异步,比如 Swoole ? 目的就是提升响应时间,提高Qps。
在我们通常的业务开发过程中,逻辑代码一般是同步阻塞模式,一方面它容易理解,另一方面也方便进行一些测试。
这些优势再加上大部分业务场景对并发并没有较高的要求,所以是可以接受的。
但是对于一个大型网站,以及对响应速度和并发要求高的场景,这时候就需要做些优化了,尽量把阻塞操作给异步化。
通过消息队列来做异步有哪些场景?
加速响应:比如注册后的提醒邮件,注册操作成功后将发消息交给队列,直接返回信息给用户,写入队列的速度非常快,然后由订阅的异步任务处理邮件发送。
应用解耦:比如用户发帖之后要给他的粉丝推送帖子,这时候实时性要求并不高,可以将新帖的消息写入队列,然后由队列处理程序操作。
流量削峰:比如秒杀活动,我们不需要实时处理一些购买逻辑,只要将用户请求写入消息队列,长度达到限制就提示用户已结束,后续程序再对队列内容处理。
日志收集:日志一般都需要进行写磁盘操作,大访问量会对 I/O 造成压力,降低程序性能;此时可以将日志写入消息队列,由处理程序订阅该队列进行消费。
广播聊天:用户通过订阅频道来获得最新发布的消息。
实例演示
<?php
/**
* Pub.php
*
* @author ercom
*/ // 1.连接并选择数据库
$redis = new \Redis(); $bool = $redis->connect('127.0.0.1', 6379, 2.5, null, 100); if (! $bool) {
die('连接失败');
} $bool = $redis->select(0); // 此处是模拟将一个任务放置队列中, 并发布
//$phone = 13199999999;
//$redis->lpush('sms-signin', $phone);
//$redis->publish('sms-signin', $phone);
// // 2.模拟生成批量数据 for ($i = 0; $i < 10; $i++) {
$phone = mt_rand(10000000000, 99999999999); echo $phone . PHP_EOL; // 使用 publish 代替下面模拟的每个任务 100ms 的耗时操作,在 subscribe 中处理
//echo $phone . PHP_EOL;
//usleep(100000); $redis->publish('signin-sms', $phone);
}
如果不将消息写入队列,而是每次都自己执行,响应时间很长,用户体验不好。
通过订阅程序异步处理任务,用户无感知,并且体验会很好。
<?php
/**
* Sub.php
*
* @author ercom
*/ // 1.连接并选择数据库
$redis = new \Redis(); $bool= $redis->connect('127.0.0.1', 6379, 2.5, null, 100); if (! $bool) {
die('连接失败');
}
// * 阻止 redis read timeout
$redis->setOption(Redis::OPT_READ_TIMEOUT, -1); // 2.订阅耗时任务并处理
// 如果这个订阅的任务比较重要,将对可用性有要求,日志收集等可以采用。
$redis->subscribe(['signin-sms', 'signin-mail', 'crawler-task-1'], function($redis, $chan, $msg) {
switch ($chan) {
case 'signin-sms': // 耗时1s, 发送并记录数据库
sleep(1);
echo "{$msg} 发注册短信\n"; break; case 'signin-mail': break; case 'crawler-task-1':
// 其他耗时任务,通过 $msg 传递参数来执行
break;
}
});
其它常见的消息队列产品有 RabbitMQ、ZeroMQ、ActiveMQ、Kafka ..
Link:https://www.cnblogs.com/farwish/p/9513100.html
[Design] 后端程序的高并发与异步的更多相关文章
- 配置开发支持高并发TCP连接的Linux应用程序全攻略
http://blog.chinaunix.net/uid-20733992-id-3447120.html http://blog.chinaunix.net/space.php?uid=16480 ...
- [转载] Linux下高并发socket最大连接数所受的各种限制
原文: http://mp.weixin.qq.com/s?__biz=MzAwNjMxNjQzNA==&mid=207772333&idx=1&sn=cfc8aadb422f ...
- Linux下高并发socket最大连接数所受的各种限制
http://blog.csdn.net/guowake/article/details/6615728 1.修改用户进程可打开文件数限制 在Linux平台上,无论编写客户端程序还是服务端程序,在进行 ...
- Linux配置支持高并发TCP连接(socket最大连接数)
Linux配置支持高并发TCP连接(socket最大连接数) Linux配置支持高并发TCP连接(socket最大连接数)及优化内核参数 2011-08-09 15:20:58| 分类:LNMP&a ...
- Linux下高并发socket最大连接数
http://soft.chinabyte.com/os/285/12349285.shtml (转载时原文内容做个修改) 1.修改用户进程可打开文件数限制 在Linux平台上,无论编写客户端程序还是 ...
- nginx、swoole高并发原理初探
阅前热身 为了更加形象的说明同步异步.阻塞非阻塞,我们以小明去买奶茶为例. 同步与异步 同步与异步的重点在消息通知的方式上,也就是调用结果通知的方式. 同步:当一个同步调用发出去后,调用者要一直等待调 ...
- 高并发情况下Linux系统及kernel参数优化
众所周知在默认参数情况下Linux对高并发支持并不好,主要受限于单进程最大打开文件数限制.内核TCP参数方面和IO事件分配机制等.下面就从几方面来调整使Linux系统能够支持高并发环境. Iptabl ...
- Linux下高并发socket最大连接数各种限制的调优
1.修改用户进程可打开文件数限制 在Linux平台上,无论编写客户端程序还是服务端程序,在进行高并发TCP连接处理时,最高的并发数量都要受到系统对用户单一进程同时可打开文件数量的限制(这是因为系统为每 ...
- Linux下高并发socket最大连接数所受的各种限制(转)
1.修改用户进程可打开文件数限制在Linux平台上,无论编写客户端程序还是服务端程序,在进行高并发TCP连接处理时,最高的并发数量都要受到系统对用户单一进程同时可打开文件数量的限制(这是因为系统为每个 ...
随机推荐
- maven+eclipse+jboss+oracle 12c+memcached+AngularJS
Maven 参考梁总的: Eclipse Java EE IDE for Web Developers集成的Maven 3 指向自己安装的 Maven Maven下载.安装和配置(二) 在本地配置ma ...
- java中增删改查(CRUD)总结
对于User表增删改查:1:save(保存方法) view(查询所有记录) update(更新方法) delete(删除方法) 通过method这个参数进行判断执行不同的操作 2: 具体的实现: ...
- HQL详解
HQL查询:Criteria查询对查询条件进行了面向对象封装,符合编程人员的思维方式,不过HQL(Hibernate Query Lanaguage)查询提供了更加丰富的和灵活的查询特性,因此 Hib ...
- Oracle 动态SQL 注意细节 ORA-00911: 无效字符
随笔 - 46 文章 - 92 评论 - 5 lv_sql:=' insert into ETL_SUCESS_AMOUNT select SEQ_OS_ETL_AMOUNTID.NEXT ...
- 使用iframe方式获得svg中的DOM元素,和svg 的 contentDocument 返回 null
碰到这个的相关问题,百度找了好久,找到了个解决方法,原址 https://segmentfault.com/q/1010000009001758 var iframe = document.getEl ...
- TypeScript: this bind 和 回调的正确用法
TypeScript 中如果传递了 而且在回调函数中用了this 的话, 就要小心了, 这个this 不一定是指向当前类对象了,如果想确保指向的还是那个对象的话, 需要在传递那个方法的时候, 先调用b ...
- 前端-JavaScript2-1——JavaScript基础复习及上次作业答案
昨天讲解的JS是编程最最简单的一些基础知识,复习一下: JavaScript书写环境,<script>标签 1 <script type=”text/javascript”&g ...
- 20175227张雪莹 2018-2019-2 《Java程序设计》第八周学习总结
20175227张雪莹 2018-2019-2 <Java程序设计>第八周学习总结 教材学习内容总结 第十五章 泛型与集合框架 泛型:主要目的是可以建立具有类型安全的集合框架,如链表.散列 ...
- 洛谷P1040 加分二叉树(树形dp)
加分二叉树 时间限制: 1 Sec 内存限制: 125 MB提交: 11 解决: 7 题目描述 设一个n个节点的二叉树tree的中序遍历为(l,2,3,...,n),其中数字1,2,3,...,n ...
- 基于fastadmin快速搭建后台管理
FastAdmin是一款基于ThinkPHP5+Bootstrap的极速后台开发框架:开发文档 下面对环境搭建简要概述,希望后来者能少走弯路: 1. 百度搜索最新版wampserver, 安装并启动 ...