文档章节

高性能服务器本质论

码代码的小司机
 码代码的小司机
发布于 07/22 09:11
字数 1925
阅读 3
收藏 0

一 服务器分类
从软件性能角度,高性能服务器分:cpu密集型服务器/IO密集型服务器
(1)CPU密集型:该类服务器没有对io的访问/没有同步点,性能瓶颈在于对cpu的充分利用。
典型的如转发服务器/代理服务器/协议转换类服务器/分布式总线服务器等。
(2)IO密集型:该类服务器存在对cache/db/硬盘等的同步访问,或者对fcgi/其他服务器等的同步访问。
简单说有同步访问点的均归属此类服务器。当前硬件基础下,有同步操作的服务器,性能瓶颈均在同步点的返回快慢上,而非cpu。
二 网络层机制
对 上述两类服务器,均需要同样高效的网络层机制。当前高效的网络层也就是大家熟知的iocp/epoll/kqueue/port/dev.poll等,在 各个os下使用宿主os推荐的高效网络层机制,任何通过其他机制绕过这些机制的做法都不可能达到最好性能。这里推荐下boost.asio,文档齐全,示 例丰富,学习曲线平缓。
三 CPU密集型服务器设计
(1)单进程单线程是改类服务器的本质特征。
整个进程只存在一个线程,所有代码均运行在同一个线程中,均顺序执行,任何地方不需要加锁。由于网络线程的存在,实际上该类程序的唯一线程就是网络线程,以linux为例,就是epoll线程。
在多核情况下,fork和cpu个数相同的进程数并且如果可能使用sched_setaffinity类函数将进程和cpu绑定。以充分利用多核性能。
该类服务器的代表:tuxedo/nginx.
(2)单进程多线程,但多线程均完成同样的功能,彼此之间互不依赖/互不影响 ,这是该类服务器的变体。
单 进程单线程无疑是该类服务器最理想最完美的实现。但有时候为了简化部署,简化业务上报,业务自检,统一日志,尤其是统计类日志/配置动态生效等附加功能考 虑,不得已牺牲少许性能而将上述“单进程单线程,fork多个充分利用多核”方案改造为“独立多线程充分利用多核”方案。
该方案中,多线程中的各个线程仍然是顺序执行,任何地方不需要加锁,均为独立的网络线程。
相对方案(1), 该方案编程更复杂,而linux下线程调度又不如进程高效,整体看为方便性牺牲了少许性能。
该类服务器的代表:我们的协议转换网关/分布式总线服务器等。
(3)高效算法
优化耗时较多算法/挑选合适容器,完成固定任务,尽量减少cpu的运算量。
(4)错误设计:区分网络线程/业务线程,将业务线程根据业务特点划分各个线程阶段。
对 cpu密集型的服务器来说,关键在于充分利用cpu,尽量减少无用代码的执行。引如中间处理线程,意味着引入锁切换/内存复制/更多无效代码,不可否认, 在已有协议栈情况下,根据业务特点化分线程可以简化编程。单纯的单一线程意味着更复杂的编码,尤其是涉及到更多中间状态时。
在该场景下,有位牛人,对线程的点评:“线程是给那些不能将程序执行序转换成状态机的笨人用的” 这句话真是再合适不过了。
四 IO密集型服务器设计
(1)网络层多线程,中间线程按照业务特点设定,同步点操作使用多线程
同 步点使用多线程是该类服务器的本质特征。在同步操作的返回时间不能由本服务器控制的前提下,本服务器所能做的也就只能是加多线程数,提供同步并发数。线程 数的最优配置取决于网络层入口并发数以及同步操作返回的时间。简单划分可以网络线程数=cpu个数/2.同步点线程数还取决于同步操作的代价,若为廉价的 cache操作,则可适当增多,若为昂贵的db操作,则要根据可以分配的连接数决定。
(2)减少人为产生的同步点
尽量减少访问其他系统使用同步接口。
(3)优化同步点
根据同步操作的特点优化: 异步/增大缓存/批量等。

五 内存操作/锁机制/内核态用户态切换/日志操作
(1)内存操作
内存申请:减少内存动态分配,推荐tcmalloc
内存复制:CPU密集型,必须的内存复制:(a)网络读:处从内核态复制到用户态,仅1次 (b)网络写:异步内存复制/用户态到内核态 ,仅2次
                    IO密集型,内存复制非关键点。
(2)锁机制 CPU密集型:尽量无锁. IO密集型: 非关键点
(3)内核态用户态切换
两类服务器均相同,尽量减少内核态/用户态互相切换:每次调用系统调用尽可能读取更多字符/仅可能减少不必要的系统调用(去除不必要的调用/通过缓存机制减少调用次数)。
(4)日志操作 略

六 进程vs线程vs协程
进程和线程(略)
协程:和进程/线程这种cpu调度单元不同,它更多是线程内对象之间一种调度理念的优化。协程对象有自己的堆栈,可以通过直接跳转直接转换执行点,减少了内存寻址操作。它特别适合用来优化线程内的某些基础组件,包括:状态机/调停者模式(或者线程内队列)。

在CPU密集型服务器的设计中,说道“线程是给那些不能将程序执行序转换成状态机的笨人用的”,而有了协程,我们有了一种新的简化编程的方法。将协程用于网络层,可以手动实现类似select的功能,用于多对象参与的复杂中间状态,可以简化编程。
但从整体性能角度看,协程则是鸡肋的存在,从几年前出现boost.Coroutine,到现在该项目停止开发,boost引入更多其他方案asio/mpl/statechart,协程一路蹒跚。
七 总结
在当前硬件体系架构下,服务器性能的关键仍然是传统的cpu/io/memory.
cpu密集型的服务器,需要最大限度充分利用所有cpu,以及尽量少的进行内存申请/内存复制。
IO密集型服务器,需要最大限度提高io能力,为达到该目的,可以在非同步线程牺牲对cpu的利用率/牺牲对memory的高效使用,一切为提高io并发能力服务。

本文转载自:https://www.cnblogs.com/lchb/articles/3533618.html

共有 人打赏支持
码代码的小司机
粉丝 23
博文 86
码字总数 52351
作品 0
杭州
高级程序员
福利丨技术芳菲四月天,送你一份书单静享春光

今天,人人皆言敏捷,可你的团队是否真的敏捷高效?你的软件开发能力是否过硬?为此,小编联合@图灵教育 给大家推荐两本热门书籍:《学习敏捷:构建高效团队》、《软件开发本质论》,送书福利...

DBAplus社群
2017/04/27
0
0
消息系统本质论

烟雾信号、快递服务、信鸽和信号量这些都是通讯的一种方式,你可能会立马想到消息。人类总是有相互联系的需求,同时总是去寻找新的通信方式去战胜距离带来的挑战。现代的通讯科技已经有了很大...

Float_Luuu
2016/01/16
1K
3
高性能平台-Web服务器缓存(1)

/** * web服务器缓存响应结果 * 1.web服务器本质就是URL映射 模拟场景: 当Browser(浏览器)==》WebServer 发送请求后 WebServer的(剥开很多实际过程进入到本质)工作: 1.解析URL 2.完成URL...

小洋哥
2014/06/06
0
0
关于传说中的拒绝服务攻击CC

近来经常听到圈子里的朋友跟我提到CC这种攻击 见不到虚假ip 见不到特别大的流量 但无法进行正常连接 传说一条adsl 足以搞掂一台高性能服务器 据可靠消息 重庆电信的很多游戏服务器虽在黑洞之...

红薯
2009/05/05
238
0
编程大牛推荐书籍

云风(中国游戏编程先行者,前网易游戏部门资深程序员,简悦创始人): C++编程思想 Effective C++ 深度探索C++对象模型 C++语言的设计和演化 C专家编程 C陷阱与缺陷 C语言接口与实现 Lua程序...

nop4ss
2015/10/10
34
0

没有更多内容

加载失败,请刷新页面

加载更多

Generator-ES6

基本概念 Generator 函数是 ES6 提供的一种异步编程解决方案,语法行为与传统函数完全不同。 Generator 函数有多种理解角度。语法上,首先可以把它理解成,Generator 函数是一个状态机,封装...

简心
20分钟前
2
0
FullCalendar日历插件说明文档

普通显示设置 属性 描述 默认值 header 设置日历头部信息。 如果设置为false,则不显示头部信息。包括left,center,right左中右三个位置,每个位置都可以对应以下不同的配置: title: 显示当...

ada_young
20分钟前
0
0
Redis知识总结--string的内部实现

SDS(Simple Dynamic String) String的数据结构是一个字节数组,但简单的获取数组长度的时间复杂度就是O(n),这对于单线程的redis来讲是不能接受的,因此string在redis中的实现是SDS类,SDS类...

looqy
31分钟前
1
0
SpringBoot开发案例之整合Dubbo分布式服务

前言 在 SpringBoot 很火热的时候,阿里巴巴的分布式框架 Dubbo 不知是处于什么考虑,在停更N年之后终于进行维护了。在之前的微服务中,使用的是当当维护的版本 Dubbox,整合方式也是使用的 ...

Java干货分享
37分钟前
2
0
美团团购订单系统优化记

团购订单系统简介 美团团购订单系统主要作用是支撑美团的团购业务,为上亿美团用户购买、消费提供服务保障。2015年初时,日订单量约400万~500万,同年七夕订单量达到800万。 目标 作为线上S...

Skqing
40分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部