首页 文章 精选 留言 我的

精选列表

搜索[高DPI],共10007篇文章
优秀的个人博客,低调大师

王者荣耀高并发背后的故事

“王者荣耀”是一款国民级手机游戏,用户体量巨大,而且一直保持着较高的更新频率。这种业务场景下,突发也变得非常频繁,然而业务体验是至关重要的,使用CDN必不可少。类似地,经常有带宽突发的场景,比如新闻爆点视频、大型直播活动、热门影视剧上线、热门游戏等应用发布。同时,由于家庭带宽和移动网络的快速升级,突发带宽量级越来越大,经常达到Tb级,甚至10Tb 。如何快速、低成本地保障业务突发,成为CDN的一大挑战。 2007年,腾讯自建CDN启用,接入了第一个业务腾讯网。到现在CDN带宽量级,从最早的数十Gb,发展到现在的数十Tb;单业务的带宽也越来越大,大部分业务常量带宽在几百Gb,部分突发业务达到了10Tb。网络的快速升级,移动用户爆发式增长,以及视频类业务包括点播和直播的兴起,使得业务突发越来越频繁,突发带宽越来越高,对CDN的要求也越来越高。 自建CDN得益于腾讯业务的蓬勃发展,先后支持了游戏下载、流媒体视频加速、春节红包等腾讯内部业务;2014年腾讯将CDN全面能力开放,成为腾讯云CDN产品,除承载内部业务外,也开始接入第三方客户,比如快手点播、斗鱼直播等。以上各种业务都有突发场景,也有很强的成本诉求,在如何低成本地保障业务突发,腾讯CDN积累了丰富的经验。接下来就挑战和问题、解决方案、效果三个方面来解析。 一、挑战和问题 下面将从业务特点开始,分析目前存在的挑战和问题。 1、 业务特点和挑战 CDN多样化的场景,注定了突发业务充满挑战。突发业务具有体量大、场景多样化、 无规律等特点。 a) 体量大:突发业务带宽大部分都超过Tb,部分甚至达到了10T ; b) 场景多样化:点播中的热剧和新闻爆点;直播中的LOL/KPL/DOTA2等游戏直播,NBA/世界杯等体育直播,演唱会等综艺直播;应用下载中的王者荣耀等游戏下载;静态网页加速中的红包活动、电商促销等; c) 无规律:部分突发活动无法预知,活动快要开始或已经开始了才知道,比如新闻爆点。 体量大,需要准备更多的资源;场景多样化,需要满足不同的资源需求;无规律性则对我们的扩容效率提了很高的要求。 2、 目前存在的问题 仅仅为了满足业务突发需求而储备大量的资源,成本太高,会造成资源极大的浪费。所以一般会通过复用资源来应对业务突发。但是直接复用资源,存在两个问题: a) 只能复用部分资源:CDN业务,一般按业务类型来区分平台和资源使用,主要原因是不同业务类型对资源需求不同,比如点播类需要更多的存储;有较多https请求的静态页面类,则需要更多CPU资源。这种限制使得资源无法充分利用,加大了资源准备的难度。比如视频突发主要使用视频Buffer,而下载类和网页类Buffer无法直接使用,这限制了Buffer的大小。即使复用同类型资源,因为涉及多个业务资源的协调,准备时间一般会超过两天,无法应对临时突发; b) 无法降低成本:另外针对部分突发业务,比如游戏应用下载,带宽高峰期在上午和中午,如果只使用本平台资源,会导致结算带宽明显上涨,从而增加成本。无法利用同其他业务错峰的特点来降低结算带宽。 二、解决方案 腾讯云CDN通过虚拟化复用现有资源,搭建全业务通用的突发池,所有平台共享Buffer。 突发池中的设备为Docker虚拟机,虚拟机有不同的规格,只要业务有需求,都可以按需使用。突发池中的带宽储备达到了10Tb,基本能满足所有业务突发需求 。任何业务有突发需求,配合自动化上架接口,可在10分钟完成10Tb突发池的扩容。 1、 突发池系统架构 突发池系统架构见图1: 图 1突发池系统架构 (a) 突发池:在各平台物理机的上层,由Docker虚拟机组成的资源池,对CPU/内存/磁盘等使用进行了限制,防止对物理机造成影响。原有业务依然部署在物理机上,不用调整。 (b) 自动化部署和监控系统: 能根据业务实际需求,自动预测需求并扩容 。所有的突发需求,都能在10分钟内扩容完成。针对点播/下载业务,自动分发热点文件,降低回源带宽。 (c) 调度系统:突发业务的突发性和体量大两个特点,使得相比域名调度系统,直通车更占优势。直通车调度更灵活,生效时间快,能达到分钟级。 虚拟机和物理机部署了上报Agent,业务信息和服务器负载每分钟都会上报到监控系统。监控系统会根据历史带宽预测一个值,并与当前带宽比较,如果当前带宽超过预测值的50%,则认为有突发。根据带宽上涨的比例,系统会自动从突发池中扩容相应数据的设备。针对提前准备的突发活动,运维可以指定带宽需求量,之后系统便会自动计算设备需求并扩容。 分钟粒度上报的服务器负载信息则为监控系统做调度决策提供了依据。系统会依据机房剩余带宽、服务器带宽、CPU、IO等综合信息决定虚拟机是否需要从直通车中启用或者禁用。用户访问时先请求直通车调度系统,直通车会根据调度策略返回一个302地址,302地址中为实际CDN资源地址。用户跳转到302地址,并获取实际内容。 2、技术优化 使用虚拟化技术复用资源的重要前提是,不影响现有业务。这就要求对资源有充分的隔离,比如CPU/磁盘,以及对带宽的使用。下面是实现过程中存在的几个问题及解决方案: 精准控制单机负载:负载过高会影响业务质量,需要对单机负载进行精准的控制。 解决方案: (a) 配额系统:直通车中有配额系统,对每个虚拟机可使用的资源做了限制,包括CPU/IO和带宽。监控系统中上报的信息,结合配额系统,可以确保服务器负载被限定在制定的范围内,粒度为分钟级。 (b) 部分请求返回302:对CPU/带宽/IO等做了限制后,应用程序能根据母机当前负载,实时判断是否处理一个请求。如果负载在限制范围内,直接处理;如果负载超出限制,则返回302,使用户跳转到直通车的调度地址,这样能在尽量不影响业务质量的情况对负载做精准控制。程序层面对负载的实时控制,是配额系统的有效补充。 (c) 网卡流量控制:在极端情况下,业务带宽超过设定阈值,这时虚拟网卡会主动丢包,避免对母机造成影响。 限制磁盘大小:Docker在ext3/ext4文件系统中无法对文件/目录级别进行磁盘大小限制。 解决方案: 由于腾讯云CDN业务基本都是使用ext3/ext4文件系统,这种情况下Docker只能对根据用户或用户组对磁盘进行限制,但现网业务都是直接在root环境下使用。这里我们使用loop device来解决磁盘大小限制问题。虚拟机中突发业务使用挂载在loop device上的目录,这样就可以间接限制磁盘大小,防止使用太多磁盘影响其他业务。 CPU绑定:默认是绑定所有CPU,部分单CPU负载高会影响母机业务。 解决方案: 通过脚本每分钟采集一次系统所有单CPU负载,为避免频繁调整和受毛刺数据影响,取15分钟的均值。最后选取负载较低的部分核,并通过配置文件cpuset.cpus来动态绑定,将虚拟机对母机业务影响降低到最小,并且能充分利用资源。 效果 突发池上线后,高效支持了王者荣耀下载、NBA直播、KPL/LPL游戏直播等多次大型突发活动,节约成本2000万。通过共享buffer,搭建突发池能显著提高突发能力和降低成本。 总结 腾讯云CDN通过Docker技术复用资源,搭建Tb级别突发池,能支持直播、点播、静态等各种业务突发,能自动检测到业务突发需求并在10分钟内完成资源扩容,具有发布快,成本低等特点。资源复用能提高资源利用率,为业务提供极大的突发池,但要注意复用业务之间不能相互影响,这需要对服务器进行实时的监控和及时的调度。另外还有一些待改进的地方,比如内核参数基于容器隔离,方便不同业务调优;部分业务客户端不支持302跳转,调度系统需要支持域名调度方式。 原文链接:http://bigdata.evget.com/post/1896.html

优秀的个人博客,低调大师

php 利用pcntl扩展实现高并发

pcntl_fork官方描述:pcntl_fork — 在当前进程当前位置产生分支(子进程)。译注:fork是创建了一个子进程,父进程和子进程 都从fork的位置开始向下继续执行,不同的是父进程执行过程中,得到的fork返回值为子进程 号,而子进程得到的是0。 通过一段代码来理解pcntl_fork如何进行多进程并发执行的 $i = 2; while($i >= 0){ $pid = pcntl_fork(); if($pid > 0){ //当前处于父进程中 }elseif($pid == 0){ //这里是子进程逻辑 exit();//子进程跑完了必须退出。否则子进程会继续执行循环创建新的进程 }else{ //进程创建失败 } 当前进程通过pcntl_fork创建了一个子进程,创建完成后当前进程继续执行,此时$pid为创建子进程的进程id所以会进入pid > 0 的判断区块。同时,当父进程执行pcntl_fork时,php又会重新开启一个进程。该进程会拷贝父进程的变量,并且从pcntl_fork之后开始执行,因为进程为子进程,所以pid为0,会执行pid==0里面的逻辑。子进程逻辑跑完了建议退出,否则会继续执行while循环。 100个号码批量分成10个进程发送示例 //随机取100条数据 $mobileList = ['135***','139***',...,'152*****']; insert($data); function insert(array $phoneList){ $cnt = count($phoneList); //测试数组大小 $slice = 10; //需要调用的进程数量 $master = array_chunk($phoneList,floor($cnt/(10))); $childList = []; echo "进程开始\r\n"; while($slice > 0) { $pid = pcntl_fork(); if($pid > 0){ $childList[$pid] = 1; echo $pid."\r\n"; //$pid>0表示当前还在执行父进程的代码 //这里最好啥都不做,每次执行pcntl_fork都会执行这里的代码。 //这里的代码执行完之后 会将$pid设置为0,然后jump到pcntl_fork代码之后,重新做判断; }elseif($pid == 0){ //这里写我们的逻辑 foreach($master[$slice-1] as $val) { sendMessage();//发送短信 } //子进程执行完之后务必需要关闭; exit(); }else { //程序发生错误也需要关闭程序 exit(); } $slice--; } // 等待所有子进程结束后回收资源 while(!empty($childList)){ $childPid = pcntl_wait($status); if ($childPid > 0){ unset($childList[$childPid]); } } }

优秀的个人博客,低调大师

建立缓存,防高并发代码demo

我在之前的博客中提到过——缓存并发,当一个key过期时,访问这个key的请求量过大,穿透到数据库.解决办法:1,分布式锁,保证每个key同时只有一个线程去查询数据库,其他线程没有获得分布式锁的权限,只需要等待.具体实现如下@Overridepublic AppUser findById(Long id) { if (redisService.exists("user:" + id)) { String appUserStr = redisService.get("user:" + id); return JSONObject.parseObject(appUserStr,AppUser.class); } else { //获取分布式锁 if (RedisTool.tryGetDistributedLock(redisService,"useridlock:" + id,Long.toString(id),180)) { AppUser appUser = appUserDao.findById(id); redisService.set("user:" + id, JSONObject.toJSONString(appUser)); redisService.expire("user:" + id, 864000); //释放分布式锁 RedisTool.releaseDistributedLock(redisService,"useridlock:" + id,Long.toString(id)); return appUser; } else { //无获得分布式锁权限时 try { //当前线程休眠1秒,可根据适当情况调整这个休眠时间 Thread.currentThread().sleep(1000); if (redisService.exists("user:" + id)) { String appUserStr = redisService.get("user:" + id); return JSONObject.parseObject(appUserStr,AppUser.class); }else { return null; } } catch (InterruptedException e) { e.printStackTrace(); return null; } } } }Redis分布式锁的写法可参考本人上一篇博客,谢谢!

优秀的个人博客,低调大师

用栅栏(CyclicBarrier)实现高并发测试

CyclicBarrier 含义: 栅栏允许两个或者多个线程在某个集合点同步。当一个线程到达集合点时,它将调用await()方法等待其它的线程。线程调用await()方法后,CyclicBarrier将阻塞这个线程并将它置入休眠状态等待其它线程的到来。等最后一个线程调用await()方法时,CyclicBarrier将唤醒所有等待的线程然后这些线程将继续执行。CyclicBarrier可以传入另一个Runnable对象作为初始化参数。当所有的线程都到达集合点后,CyclicBarrier类将Runnable对象作为线程执行。 方法 await():使线程置入休眠直到最后一个线程的到来之后唤醒所有休眠的线程 代码实现 原理:设置赛马集合点(线程启动需要一些时间),然后一起赛跑 package org.java; import java.util.concurrent.CyclicBarrier; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import org.junit.Test; public class TestCyclic { @Test public void test01() { int count = 10;//并发线程数 CyclicBarrier cyclicBarrier = new CyclicBarrier(count); ExecutorService executorService = Executors.newFixedThreadPool(count); int n = 0; for (int i = 0; i < count; i++) { executorService.execute(new TestCyclic().new Task(cyclicBarrier, n)); n++; } executorService.shutdown(); // 关闭线程池 // 判断是否所有的线程已经运行完 while (!executorService.isTerminated()) { try { // 所有线程池中的线程执行完毕,执行后续操作 // TODO System.out.println(“==============is sleep============”); Thread.sleep(10000); System.out.println(“==============is wake============”); } catch (InterruptedException e) { e.printStackTrace(); } } } public class Task implements Runnable { private CyclicBarrier cyclicBarrier; int n = 0; public Task(CyclicBarrier cyclicBarrier, int n) { this.cyclicBarrier = cyclicBarrier; this.n = n; } @Override public void run() { try { // 等待所有任务准备就绪 System.out.println(“赛马” + n + “到达栅栏前”); cyclicBarrier.await(); System.out.println(“赛马” + n + “开始跑”); // 测试内容 System.out.println(“hello: ” + n); } catch (Exception e) { e.printStackTrace(); } } } } 运行代码结果如下: ==============is sleep============ 赛马0到达栅栏前 赛马1到达栅栏前 赛马3到达栅栏前 赛马2到达栅栏前 赛马4到达栅栏前 赛马5到达栅栏前 赛马7到达栅栏前 赛马6到达栅栏前 赛马8到达栅栏前 赛马9到达栅栏前 赛马9开始跑 赛马8开始跑 hello: 8 赛马6开始跑 hello: 6 赛马7开始跑 hello: 7 赛马0开始跑 hello: 0 赛马5开始跑 hello: 5 赛马4开始跑 hello: 4 赛马2开始跑 hello: 2 赛马3开始跑 hello: 3 赛马1开始跑 hello: 1 hello: 9 ==============is wake============ 原文发布时间为:2018-07-12本文作者:HARRIES本文来自云栖社区合作伙伴“Java杂记”,了解相关信息可以关注“Java杂记”

资源下载

更多资源
腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册