场景一

客户要求服务满足2000人同时并发的情况,也就是2000同时刻的并发,根据业务接口相应情况qps大致为5000-7000左右 场景几乎为请求不会高频率,处理时间短,假设大用户用户群体平均请求间隔为5秒

用户数=2000 x 1/0.4 x 5 = 25000 (人),就是要满足两万的活跃用户。

前置考虑:

服务器 8核16G

tomcat 最大线程数可在400-800 等待队列可在 100-500 此时表明同一时刻最少可存在500个线程 最大为1300个线程

基于服务器配置以及处理业务所需场景考虑应为io密集型任务居多,则服务器处理一个线程在200ms-500ms(正常来说考虑异步处理io任务为200ms),因为考试系统并发情况为考试是拉取试卷资源以及提交试卷为高频调用接口,业务处理不算复杂。那么根据一般情况单核在同一时间的处理能力一般在50-200个线程。

则根据预定服务器配置:

并发数=CPU核心数*单核处理能力/单次请求耗时=8x100/0.3=2666

方案一

将服务器提升至16核心 tomcat最大线程配置为2000 可以直接解决问题,此处需考虑内存,一个线程大概占用1MB左右内存并发2000线程内存会占用2G

方案二

将服务集群化部署

最终归结于服务器配置,从数值上来说16核32G服务器可以直接满足业务需求,8核16G勉强满足

实施方案:

方案一:

单体部署,将tomcat最大线程数提升至2000,同时为了避免极端情况应将服务器配置给到16核32G。

方案二:

集群部署单个服务处理线程同一时刻并发在1000左右,同时nginx作均衡负载以轮询的方式放压力平均分配到两个服务上面。

#user  nobody;
worker_processes 1;

error_log /var/log/nginx/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid        logs/nginx.pid;

events {
    worker_connections 40960;
}

http {
    include mime.types;
    default_type application/octet-stream;

    log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for" $request_time $upstream_response_time';

    access_log /var/log/nginx/access.log main;

    sendfile on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout 65;
    client_max_body_size 200m;
    #gzip  on;

    # 配置负载均衡池
    upstream backend {
        # 定义后端服务器池,采用轮询方式(默认)
        server 127.0.0.1:8001;
        server 127.0.0.1:8002;
    }

    server {
        listen 6556;
        server_name localhost;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        location / {
            root /var/www/html;
            index index.html index.htm;
        }

        location /helperapi/ {
            proxy_pass http://127.0.0.1:18001/;
        }

        location /ewei/web/ {
            root /var/www/html/;
            try_files $uri $uri/ /ewei/web/index.html;
        }

        location /ewei/zyy/ {
            root /var/www/html/;
            try_files $uri $uri/ /ewei/zyy/index.html;
        }

        # 配置 /ewei/myapi/ 路径的负载均衡
        location /ewei/myapi/ {
            #rewrite ^/ewei(/.*)$ $1 break; 
            proxy_pass http://backend/myapi/;  # 使用负载均衡池
            #proxy_pass http://127.0.0.1:8002/myapi/;
            proxy_cookie_path /myapi/ /ewei/myapi/;
            client_body_buffer_size 2048k;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "Upgrade";
            proxy_set_header X-real-ip $remote_addr;
            proxy_set_header X-Forwarded-For $remote_addr;
            proxy_read_timeout 3600s;
        }
    }
}

场景二

知识库热搜记录,记录业务中知识库的热搜情况,业务需要满足高并发,进行了分布式部署,当记录热搜关键词记录管理时容易出现漏记,两次只记录一次的情况

解决方案:在此处使用redis实现分布式锁。

redis锁使用方式

使用redissen和原生redis两种方式

场景三

在进行导入操作时系统设计是先将文件上传到服务器,然后采用异步读取文件进行导入,在分布式部署的使用了轮询策略到各个集群服务上且服务采用docker容器化部署,出现了文件上传到第一个服务器,然后点击导入使用异步导入时轮询到了另一个服务,就找不到本地需要导入的文件出现导入失败的问题。

解决方案: 使用共享存储(OSS)

将原本存在本地的文件上传至oss