高并发设计的基本方法:
1.横向扩展:买更多的服务器,更多的CPU(32C)
2.异步处理:把同步等待的时间转为并发执行
3.使用缓存:本质上会缓解磁盘和CPU之间的速差,提高效率
4.高并发系统的演进应该是循序渐进,以解决系统中存在的问题为目的和驱动力
分层设计:
MVC框架:
M是模型 V是用户界面 C:业务逻辑
与表现层,逻辑层和数据访问层相对应
分层的好处:
简化系统设计:不同人的关注某一层
分层可以有更高的复用性
更容易做横向扩展‘
不足:
增加了代码的复杂度
每个层次独立部署,层次间通过网络来交互
每个网络之间的交互带来损耗
三大目标:
高性能
性能评价度量:
响应时间是性能评价指标&吞吐量
平均值
最大值
分位值:第90位相应相应
理论最优:99分位为200ms
提高性能:
性能优化-问题导向
遵循“八二”原则20%时间解决80%并发问题
要有数据支撑
指导思想:
1.增加核心数
2.减少单次的响应时间
高可用
平均故障的时间间隔
故障的平均恢复时间:
N个9
6个9:年故障32s,天故障86ms
高可用的设计标准:
Designed for failure
1.failover(故障转移)
2.超时控制:确定超时时间
3.限流:对并发请求限速
4.降级:牺牲非核心服务
系统运维:
1.灰度分布:
2.故障演练
可扩展(应对大流量):
数据库,缓存,依赖的第三方,负载均衡,交换机带宽
可扩展的设计思路:
拆分:将复杂问题简单化
存储层的扩展:业务维度,事务不跨库
业务层的扩展:业务维度,重要性维度。请求来源的维度
//epoll实现的简单高并发服务器
#ifndef _HEAD_H
#define _HEAD_H
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <dirent.h>
#include <errno.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <pthread.h>
#include <sys/sem.h>
#include <sys/msg.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/epoll.h>
#include "common.h"
#include "my_popen.h"
#include "thread_pool.h"
#include "reactor.h"
#include "add_to_subreactor.h"
#include "head.h"
#include "color.h"
#endif
#ifndef _COMMON_H
#define _COMMON_H
int make_nonblock(int fd);
int make_block(int fd);
int socket_create(int port);
int socket_connect(const char *ip, int port);
#ifdef _D
#define DBG(fmt, args...); printf(fmt, ##args);
#else
#define DBG(fmt, args...)
#endif
#endif
#define MAXUSER 1024
#define MAXEVENT 10
struct NUser{
char name[50];
int fd;
};
int main(int argc,char**argv){
if(argc!=2){
fprintf(stderr,"Usage:%s port!\n".argv[0]);
exit(1);
}
int epollfd,server_listen,sockfd;
struct epoll_event ev,events[MAXEVENT];
if(epollfd=epoll_create(1)<0){
perror("epoll_create");
exit(1);
}
if((server_listen=socket_create(atoi(argv[1])))<0){
perror("server_listen");
exit(1);
}
ev.events=EPOLLIN;
ev.data.fd=server_listen;
if(epoll_ctl(epollfd,EPOLL_CTL_ADD,server_listen,&ev)<0){
perror("epoll_ctl");
exit(1);
}
while(1){
int nfds;
if((nfds=epoll_wait(epollfd,events,MAXEVENT,-1))<0){
perror("epoll_ctl");
exit(1);
}
for(int i=0;i<nfds;i++){
struct User*user=events[i].data.ptr;
if(user->fd==server_listen){
DBG(GREEN"<New coming>...\n"NONE);
if((sockfd=accept(server_listen,NULL,NULL))<0){
perror("accept");
exit(1);
}
if(sockfd>MAXUSER){
fprintf(stderr,RED"Too Many clients!\n"NONE);
continue;
}
users[sockfd].fd=sockfd;
ev.data.ptr=&users[sockfd];
ev.events=EPOLLIN|EPOLLET;
if(epoll_ctl(epollfd,EPOLL_CTL_ADD,sockfd,&ev)<0){
perror("epoll_ctl");
exit(1);
}
}else{
char buff[1024]={0};
if(events[i].events&&(EPOLLIN|EPOLLERR|EPOLLHUP)){
if(!strlen(user->name)){
if(recv(user->fd,user->name,sizeof(user->name),0)<=0){
close(user->fd);
user->fd=-1;
epoll_ctl(epollfd,EPOLL_CTL_DEL,user->fd,NULL);
}
user->name[strlen(user->name)-2]='\0';
DBG(GREEN"<Login>"NONE" : %s!\n",user->name);
continue;
}
int ret =recv(user->fd,buff,sizeof(buff),0);
if(ret<=0){
close(user->fd);
memset(user->name,0,sizeof(user->name));
epoll_ctl(epollfd,EPOLL_CTL_DEL,user->fd,NULL);
continue;
}
printf(BLUE"%s"NONE":%s",user->name,buff);
}
}
}
}
}
}