Web服务端性能提升实践(2)
在Go语言中,应用程序并发处理的部分被称作 goroutines(协程),它可以进行更有效的并发运算.在协程和操作系统线程之间并无一对一的关系:协程是根据一个或多个线程的可用性,映射(多路复用,执行于)在他们之上的;协程调度器在 Go?运行时很好的完成了这个工作.协程是轻量的,比线程更轻.它们痕迹非常不明显(使用少量的内存和资源):使用 4K 的栈内存就可以在堆中创建它们.因为创建非常廉价,必要的时候可以轻松创建并运行大量的协程(在同一个地址空间中 100,000 个连续的协程).并且它们对栈进行了分割,从而动态的增加(或缩减)内存的使用;栈的管理是自动的,但不是由垃圾回收器管理的,而是在协程退出后自动释放.协程可以运行在多个操作系统线程之间,也可以运行在线程之内,让你可以很小的内存占用就可以处理大量的任务.由于操作系统线程上的协程时间片,你可以使用少量的操作系统线程就能拥有任意多个提供服务的协程,而且 Go?运行时可以聪明地意识到哪些协程被阻塞了,暂时搁置它们并处理其他协程.甚至,程序可以在不同的处理器和计算机上同时执行不同的代码段. 我们通常想将一个长计算过程切分成几块,然后让每个goroutine各自负责一块工作,这样对于单一请求的响应时间有成倍的提升. 举个例子,有一个任务分3个阶段,a阶段去数据库a中取数据,b阶段去数据库b中取数据,c阶段合并数据返回.我们启动goroutine以后a、b阶段可以一起进行,极大地缩短了响应时间. 说白了就是部分计算过程由串行转换为并行,一个任务不需要等待其他无关的任务执行完在执行,实际计算中程序的并行执行会更有用处. 关于这部分佐证的数据就不在这边过多叙述了,感兴趣的同学可以自己看一下这方面的资料.比如Web服务端由Ruby切换为Go性能提升15倍的老故事(Ruby使用的是绿色线程,即只有一个CPU得到利用).虽然这个故事可能有点夸大,但是并行带来的性能提升是毫无疑问的.(Ruby切换为Go:http://www.vaikan.com/how-we-went-from-30-servers-to-2-go/). 3. 磁盘I/O对性能的影响(1) 问题磁盘读取数据靠的是机械运动,每次读取数据花费的时间可以分为寻道时间、旋转延迟、传输时间三个部分,寻道时间指的是磁臂移动到指定磁道所需要的时间,主流磁盘一般在5ms以下;旋转延迟就是我们经常听说的磁盘转速,比如一个磁盘7200转,表示每分钟能转7200次,也就是说1秒钟能转120次,旋转延迟就是1/120/2 = 4.17ms;传输时间指的是从磁盘读出或将数据写入磁盘的时间,一般在零点几毫秒,相对于前两个时间可以忽略不计.那么访问一次磁盘的时间,即一次磁盘I/O的时间约等于9ms(5ms+4.17ms)左右,听起来还挺不错的,但要知道一台500 -MIPS的机器每秒可以执行5亿条指令,因为指令依靠的是电的性质,换句话说执行一次I/O的时间可以执行40万条指令,数据库动辄十万百万乃至千万级数据,每次9毫秒的时间,显然是个灾难. (2) 解决办法磁盘I/O对服务器性能的影响没有根本的解决办法,除非你把磁盘扔掉,换成别的东西.我们能在网上搜到各种存储介质的响应速度与价格,如果你有钱,你就可以任性的更换存储介质. 在不更换存储介质的条件下,我们可以减少应用程序对磁盘的访问次数,比如设置缓存,还可以把部分磁盘I/O放到请求周期外,比如用队列和栈来处理数据的I/O等. 4. 优化数据库查询随着业务开发模式的变化,敏捷式开发被越来越多的团队采用,周期越来越短,很多数据库查询语句都是按照业务逻辑来写,时间久了常常就忽略了SQL查询的格式问题,造成数据库压力的增加,使数据库查询的响应变慢.这里简单介绍MySQL数据库中,几条被我们忽略的常见问题和优化方式:
文章来自微信公众号:互联网架构师 (编辑:ASP站长网) |