永利集团3044官网欢迎您

test

发布时间:2021-07-20 0:00:00浏览次数:7

内容提要

近几年随着网络的发展,对于服务器的性能需求也逐渐提高。尤其是近十年,WEB服务器大放光彩,对于高并发服务器需求也更高。一个Web系统,在很短时间内收到很多请求时,系统的优化和稳定至关重要,大型网站,比如门户网站,在面对大量用户访问、高并发请求方面,基本的解决方案集中在这样几个环节:使用高性能的服务器、高性能的数据库、高效率的编程语言、还有高性能的Web容器。这几个解决思路在一定程度上意味着更大的投入。

本文首先介绍服务器,说明什么是高并发服务器。其次提升高并发量服务器性能解决思路。最后使用C++实现高并发服务器项目,当掌握服务器高并发的原理和思路后服务器的百万、千万、亿万都是有基础实现的。

关键词:服务器 高并发 原理 优化 思路 实现

 目录

 C++实现高并发服务器5

 1. 高并发服务器5

 1.1. 什么是高并发5

 1.2. 服务器的高并发5

 1.3. 对于高并发带来的后果6

 2. 性能提升和优化6

 2.1. 硬件性能提升6

 2.2. 服务基本提升7

 2.2.1. 服务器代理Nginx7

 2.2.2. 部署集群7

 2.2.3. 数据缓存,Cache7

 2.2.4. 高并发能力语言7

 2.2.5. CDN部署7

 2.2.6. DBA数据库的优化8

 2.2.7. 消息存储机制8

 2.2.8. 脚本合理控制请求8

 3. 高并发服务器的实现8

 3.1. 服务器连接过程8

 3.1.1. 面向连接流服务端8

 3.1.2. 面向连接流客户端8

 3.1.3. 面向无连接流服务端8

 3.1.4. 面向无连接流客户端9

 3.2. 需要使用的函数9

 3.3. 使用C++实现9

 参考文献10


 C++实现高并发服务器

现代信息时代的发展,对于服务器,尤其是Web服务器来说服务器的高并发是极其重要的。高并发(High Concurrency)是互联网分布式系统架构设计中必须考虑的因素之一,它通常是指,通过设计保证系统能够同时并行处理很多请求。当用户不再满足文字的交互后,多媒体富文本交互已是主流。

  1.  高并发服务器

    1.  什么是高并发

      高并发(High Concurrency)是互联网分布式系统架构设计中必须考虑的因素之一,它通常是指,通过设计保证系统能够同时并行处理很多请求。通俗来说高并发是指在同一个时间点,有很多用户同时的访问URL地址。高并发服务器有如下指标:

      相应时间(Response Time):客户端在访问服务器时,系统对请求做出响应时间。例如当用户打开浏览器时,系统则会处理HTTP的请求。如果请求时间用了100MS,则150MS就是系统的响应时间。

      吞吐量(Throughput):单位时间内处理请求数量。

      每秒查询率QPS(Query Per Second):每秒响应请求数。

      并发用户数:同时承载正常使用系统功能的用户数量。比如一个TCP局域网通信访问中有四个用户加入,则并发用户数为四。

        1.  服务器的高并发

          对于服务器的高并发通常是可以在有多用户访问的高吞吐量下仍然可以保障快速相应,也就是通常所说的不卡。对于一个服务器的关键指标QPS——一个高并发服务器美妙百万或者千万的场景。

            1.  对于高并发带来的后果

              如果服务器对于高并发的处理不得到完善,那么非常容易产生诸多的缺陷和使用的影响。具体如下:

              Server:服务器资源被占满导致崩溃;计算机的内存缓存被占满导致系统使用swap交换内存但极大损耗了CPU的效率,如果SWAP被占用完全则会直接占用大量CPU资源从而导致服务器崩溃(宕机、死机),这样会导致数据没有保存就丢失;高并发的占用还可能导致数据重复,同一用户反复添加,或数据始终无法被添加上。

              Client:对于用户而言最主要也最直接的体现便是卡,服务器连接缓慢或者连接不上。如果是网页那么会直接无法打开网页或者所点击的表单无法提交,可能后端服务器已经接收不到。更有甚者在浏览视频时视频卡顿,视频看完却显示只有99%进度等。

              1.  性能提升和优化

                1.  硬件性能提升

                  服务器在运行时,硬件的配置也会决定一个服务器的上限。互联网分布式架构设计,提高系统并发能力的方式,使用的方法主要有垂直扩展和水平扩展。

                  水平扩展(Scale out):只要增加服务器数量,就能线性扩充系统性能。水平扩展对系统架构设计是有要求的,如何在架构各层进行可水平扩展的设计,以及互联网公司架构各层常见的水平扩展实践。通俗来说就是增加更多的服务器后服务器的所有性能都可以直线上升,可以用来解决大多数问题。

                  垂直扩展(Scale up):提升单机处理能力。将单独的机器进行一系列的配置和升级已解决问题。垂直扩展又有两种:

                  增强单机硬件性能,根据服务器的类型选择需要升级的配置,比如在web服务器中提高SSD硬盘大小,增加网络带宽,提高CDN加速。在需要大量计算的服务器如转码网站则可以提高内存以及CPU核心数量和直接提高CPU。

                  提升单机架构性能,例如:使用Cache来减少IO次数,使用异步来增加单服务吞吐量,使用无锁数据结构来减少响应时间;

                  不管是提升单机硬件性能,还是提升单机架构性能,都有一个致命的不足:单机性能总是有极限的。所以互联网分布式架构设计高并发终极解决方案还是水平扩展。

                    1.  服务基本提升

                      1.  服务器代理Nginx

                        做服务器的均衡负载,把压力均衡到多台服务器

                            1.  部署集群  

                               MySQL数据库, Redis服务器,或者mongodb服务器,把一些常用的查询数据,并且不会经常的变化的数据保存到其他NoSQL DB服务器中,来减少数据库服务器的压力,加快数据的响应速度。

                                  1.  数据缓存,Cache

                                     比较常见的模式有分为两大类: Cache-aside 以及 Cache-as-SoR。其中 Cache-as-SoR(System of Record, 即直接存储数据的DB) 又包括 Read-through、Write-through、Write-behind。

                                        1.  高并发能力语言

                                           在高并发接口的设计中可以使用具有高并发能力的编程语言去开发:nodejs做web接口

                                              1.  CDN部署

                                                 CDN (Content Delivery Network or Content Ddistribute Network)内容分发网络。其目的是使用户可就近取得所需内容,解决 Internet网络拥挤的状况,提高用户访问网站的响应速度。CDN网络可以将源站的内容缓存到分布全球的CDN节点,根据用户的访问IP,就近连接CDN,提高网站响应速度。

                                                    1.  DBA数据库的优化

                                                       查询条件,索引优化

                                                          1.  消息存储机制

                                                             将数据添加到信息队列中(redis list),然后再写工具去入库

                                                                1.  脚本合理控制请求

                                                                   防止用户重复点击导致的ajax多余的请求,等等。

                                                                  1.  高并发服务器的实现

                                                                    1.  服务器连接过程

                                                                      Server与Client的连接主要有两种方式:面向连接流与面向无连接流。

                                                                          1.  面向连接流服务端

                                                                          2. WSAStartUp初始化

                                                                          3. 创建SOCKET

                                                                          4. 用bind指定对象

                                                                          5. Listen函数设置监听

                                                                          6. Accept接收请求

                                                                          7. Send发送请求

                                                                          8. CloseSocket 关闭 socket

                                                                              1.  面向连接流客户端

                                                                              2. WSAStartUp初始化

                                                                              3. 创建SOCKET

                                                                              4. Connect请求连接

                                                                              5. Send发送会话

                                                                                      1. (可添加RECV进行消息相互传输)

                                                                                        1. Closesocket 关闭 socket

                                                                                              1.  面向无连接流服务端

                                                                                                1. WSAStartUp初始化

                                                                                                2. 创建SOCKET

                                                                                                3. 调用recvFrom和sendTo进行通信

                                                                                                4. 调用CloseSocket关闭socket

                                                                                                      1.  面向无连接流客户端

                                                                                                        1. WSAStartUp初始化

                                                                                                        2. 创建SOCKET

                                                                                                        3. 调用recvFrom和Sendto进行通信

                                                                                                        4. 调用CloseSocket关闭socket

                                                                                                            1.  需要使用的函数

                                                                                                              WSAStartU初始化ws2-32.dll动态连接库

                                                                                                               int WSAStartup (WORD,wVersionRequested,LPWSDATA);

                                                                                                              socket创建套接字

                                                                                                               SOCKET socket(int af,int type,int protocol);

                                                                                                              bind 将套接字绑定到指定端口和地址

                                                                                                               int bind(SOCKET s,const struct sockaddr FAR * name,int namelen);

                                                                                                              listen 将套接字设定为监听模式

                                                                                                               int listen (SOCKET S,int backlog);

                                                                                                              accept 接收连接请求

                                                                                                               SOCKET accept(SOCKET s,struct sockaddr FAR * addr,int FAR * addrlen);

                                                                                                              closesocket 关闭套接字

                                                                                                               int closesocket(SOCKET s);

                                                                                                              connect 发送连接请求

                                                                                                               int connect(SOCKET s,const struct sockaddr FAR * name, int namelen);

                                                                                                              htons 将16位无符号短整型数据转换成网络并排方式

                                                                                                               v-short htons(v-short hostshort);

                                                                                                              htonl 将无符号长整型转换为网络排列方式

                                                                                                               v-long htonl(v-long hostlog);

                                                                                                              inet-addr 将字符串表示的地址转换为32位的无符号长整数据

                                                                                                               unsigned-long inet_addr(const char FAR* cp);

                                                                                                              recv 接受数据

                                                                                                               int recv(SOCKET s,char FAR * buf ,int len,int flags);

                                                                                                              send 发送数据

                                                                                                               int send(SOCKET s,const char FAR * buf,int len,int flags);

                                                                                                              select 检查套接字是否处于可读,可写或错误状态)

                                                                                                               int select(int nfds,fd_set FAR * writefds, fd-set FAR * execptfds, const struct timeval FAR * timeout);

                                                                                                              WSACleanUp 释放ws2-32.dll 的分配资源

                                                                                                               int WSACleanUp(void);

                                                                                                              WSAAsyncSelect 将网络中的某关联到窗口的某个消息中

                                                                                                               int WSAAsyncSelect(SOCKET s,HWND hwnd,unsigned int wMsg ,long iEvent);

                                                                                                              ioctlsocket 设置套接字的i/o模式

                                                                                                               int ioctlscoket(SOCKET s,long cmd,v-long FAR * argp);

                                                                                                                1.  使用C++实现

                                                                                                                  示意图 1

                                                                                                                  对于多进程服务器实现需考虑:

                                                                                                                  1. 父进程最大文件描述个数

                                                                                                                  2. 系统内创建进程个数

                                                                                                                  3. 进程创建过多是否降低服务性能

                                                                                                                  4. 对于每个线程的内存申请和释放

                                                                                                                  5. 服务器的性能和计划使用的性能

                                                                                                                     对于socket服务器使用框架的话,windows可以了解:IOCP,Linux则可以了解一下epoll。

                                                                                                                     了解完上述内容后,我们仅需将函数组装起来即可,这里使用端口完成大并发服务器的搭建,需要的模块:完成创建端口、根据CPU核心数量创建一定量线程、在线程中不断检查端口状态,分别给予处理、创建一个socket套接字,绑定ip端口、将套接字绑定到创建完成的端口上。

                                                                                                                     创建IO完成端口句柄

                                                                                                                     获取当前服务器的CPU核心数量

                                                                                                                     根据服务器CPU核心数量创建一定数量的工作线程

                                                                                                                     创建线程

                                                                                                                     创建的线程不断检查完成端口的状态,有则处理


                                                                                                                    提供一个入口,供其它socket绑定完成端口

                                                                                                                     参考文献

                                                                                                                    duzhongli 高并发(水平扩展,垂直扩展) (2017-09-20) [2020-03-19]

                                                                                                                     https://www.jianshu.com/p/be66a52d2b9b

                                                                                                                    八英里 什么是高并发 ,详细讲解 (2019-02-06) [2020-03-19]

                                                                                                                     https://www.cnblogs.com/deepalley/p/10353508.html

                                                                                                                    猿来是U_U 高并发详解(一)(2018-05-08) [2020-03-19]

                                                                                                                     https://blog.csdn.net/qq_39949109/article/details/80234071

                                                                                                                    joeyos C++网络通信实现 [2018-08-03 ] [2020-03-20]

                                                                                                                     https://blog.csdn.net/zhangquan2015/article/details/81347392

                                                                                                                     pointerC++ Linux C编程之十八 高并发服务器 (2015-05-14)[2020-04-17]

                                                                                                                     https://www.cnblogs.com/xuejiale/p/10849095.html

                                                                                                                     海涛高软 c++使用完成端口实现服务器的高性能并发 (2018-05-07) [2020-04-17]

                                                                                                                     https://blog.csdn.net/qq_15267341/article/details/80223760


版权所有©3044am永利(中国)集团官方网站-欢迎您   Copyright © 2007-2020. All Rights Reserved