让程序的性能提高10倍[转]

公司有一个Web Service,访问量不大, 但也不算小, 天天几百万的量级。正常状况下, 平均每一个请求响应的时间在200毫秒左右。php

 

天天几百万的访问量, 那么程序每秒请求处理数量在几十个左右, 高峰期也就上百, 而服务器上php处理请求的进程数是大于这个数的,所以, 服务器的处理能力勉强能知足当前量级的请求, 除了少数时候高峰期会出现不稳定的情况, 大多数时候也算是相安无事, 可是从服务器失败请求的数量来看应该离服务器处理能力极限的临界点不远了。java

 

这个Web Service有一个特色, 它并非面向终端的 , 而是为另外一套Web Service提供底层数据用, 那套Web Service会进行数据缓存,不会把全部数据请求转发到咱们这里,它替咱们挡掉了大部份压力。然而, 天有不测风云,某一天高峰期那套Web Service的缓存机制坏掉了, 全部数据请求全都转发到咱们的Web Service上, 结果, 咱们Web Service访问量成倍增加,服务器超出了承受能力的范围而没法正常响应,而后用户各类投诉,领导各类不满,压力天然而然就到了个人身上。golang

 

我分析了一下问题的缘由,Web Service 每一个请求的响应时间为200毫秒上下, 服务器的并发处理能力并非很高, 也就是说在每一个200毫秒内,服务器处理请求数量是有极限的, 当每200毫秒的请求量大于这个极限的时候, 后面进来的请求就不能被及时处理, 只能排队等待,这就跟堵车一下,车的数量远大于马路的吞吐量时,天然是越堵越多。堵车没有时间限制, 反正早晚能开走, 只是花点时间等待而已。 而服务器处理请求就不同了,若是指定的时间范围内没法及时处理请求,那么这些请求就会坏掉, 也就是咱们一般看到的502或者504。咱们的服务器也是由于这个缘由而出现了大量的坏掉的请求,致使业务受到影响。数据库

 

整个Web Service大约有百分之八十流量是流向其中五个接口(页面)的,所以我只要集中优化这五个接口,将它们的响应时间降下来,那么服务器并发请求的处理能力将会获得提高。apache

 

这个Web Service是由php实现,近一年内也不断的在优化其性能,但老是没法完全解决问题, 虽然服务器的并发处理能力获得了必定程度的提高, 可是, 每一个请求的响应时长老是降不下去。 被逼无奈, 我决定以换技术从新实现的方式尝试着解决问题,毕竟高性能服务器的编写并不是php所擅长的, 而golang彷佛更加适合作这件事。缓存

 

我仔细的看过这个Web Service的每一行php代码, 发现存在如下影响性能的问题服务器

 

  1. 没有数据库链接池, 也没有单例, 每一次读写数据库都会简单粗暴的执行openconnection和close connection网络

  2. 使用memcached。我以为memcached也影响性能,由于会有网络开销,若是不是多个程序共享内存须要, 根本没有必要使用, 但在php中却没法避免,由于php没法直接操做内存多线程

  3. 没有多线程,没有办法并行处理问题, 如只能经过串行的方式从多个数据库中读取数据并发

  4. 编写代码时没有考虑到时间复杂度问题, 各类无心义的foreach太多

 

除了代码中存在的问题, php技术自己也有性能痛点存在, 如

 

  1. 解释执行代码, 但也没有像java同样的即时编译机制

  2. 请求必须经过apache和phpfpm服务器中转, 而后再交由php自身

 

而golang正好克服了这些问题

 

  1. 很是方便的使用数据库链接池

  2. 直接操纵内存, 不使用第三方缓存软件

  3. goroutine, 多线程中的战斗机

  4. 纯编译型语言, 跟C相似编译出来的就是最低层的机器码

  5. 程序自己就有Web服务器的功能, 不依赖第三方Web服务器

 

所以, 从理论上来说, golang在性能方面完胜php。

 

由于只须要重写Web Service中的5个接口, 工做量并不算太大, 总共大概只花了2天的工做量就彻底成了重写的工做,而且将旧的php版本中存在的问题全都避免掉。

 

将程序部署至生产环境后,我对两个版本的程序在性能上作了大体的对比

php

golang

php

golang

从图中能够看出,一样的功能, 一样的数据, 可是在请求的时间上却确差了许多倍。

 

在并发量处理方面, 我写了一段Java程序,开100个线程去请求测试环境下的接口, 代码大概长这个样子

php实现的版本, 在这段程序运行20秒左右的时间后,服务器就出现没法响应的情况,大体状况应该与以前线上服务事故缘由相同,车太多, 路过小, 堵住了。

 

而golang的版本, 无论程序开多久, 都一直稳定的运行着, 程序的进程对于服务器资源也没有太大的消耗,所以能够判定,在真实的生产环境下golang写的版本的表现确定将优于php版本。

 

如今, 使用golang新实现的版本还在测试当中, 须要确保接口返回的数据与php版本接口的返回的数据没有一毫误差才能够正式切换服务。

 

系统尚未真式使用, 重写所带来的效果也尚未体现, 可是我仍是义无反顾将这件事提早发在公众号上, 这充分的说明了, 我对于此次重写有足够的自信,对golang的表现也有充足的信心,让程序性能提高10是能够实现的。

相关文章
相关标签/搜索