在高性能服务器设计中首先应保持一下几个原则
1. 对线程不是越多越好,原则上应和CPU核数相等,这是为什么呢?线程数超过了CPU核数,执行时的环境切换将耗去不少的CPU资源。
2. 能不用锁最好,即是用,锁锁定的线程越少越好。推存仅在两个线程间使用锁,锁锁定的仅是数据,千万不要去锁定函数,锁定函数锁的作用域无法良好控制。锁锁定的粒度越小越好,锁定的时间越少越好。
3. 对socket使用事件驱动,all-in-one原则,使用异步socket模型,将所有的socket放在同一个线程中处理。也许你会质疑,磁盘IO和网络IO速度的限制,导致你的程序不能全速运行,实质上网络IO不是问题,异步模式的socket已经解决了你的问题,你的问题可能是接收大数据的问题,磁盘IO确实会影响速度,这时你需要将任务分解成多个阶段,在读写数据阶段时交由另外的线程处理。
4. 动态内存分配和对象分配,你无论使用哪种技术都无法有效的解决面临的问题,建议在程序初始化时将所有的资源分配好。尽量限制内存拷贝的发生。
5. 按照以上的原则就能设计出高性能的服务器吗?制约这些的还有服务器的架构,基本的架构如下:
------------------- ------------------- ------------------
| 接入服务器 | ----> | 应用服务器 | ----> | 数据服务器 |
------------------- -------------------- -------------------
为什么会这样呢?首先从客户的诉求说起,当客户的访问量少时,你可以使用一台应用服务器,或将这三者部署在一起,形成一个独立的程序,当客户的访问量越来越大时,一个应用服务器已经无法承载了,这时你需要扩建一个服务器,那么客户的用户服务器要连接到哪个服务器呢?接入服务完成了这要的任务,更确切的说接入服务承担了负载均衡的任务。
当多个应用服务器提供应用时,需要将应用分类,一个应用服务器运行一类或两类引用,使用HTTP作为承载协议时不同的应用可以使用不同的URL表示,接入服务器更具不同的URL转发请求到不同的服务器。这是接入服务就是一个HTTP代理。
在大多数情况下,希望一个应用服务器对应一个数据服务器,这也就是对应用分类的一个原因。希望数据服务器的数据存储压力和访问查询压力减小。减少存储压力的有效方法就是分类,将不同的数据存在不同的数据库中,这些数据没有联系,同时数据的关联减少后,查询的关联将减少,将提高数据的查询能力。