极客时间架构师训练营 - week7 - 作业 1

简介: 极客时间架构师训练营 - week7 - 作业 1

  • 性能压测的时候,随着并发压力的增加,系统响应时间和吞吐量如何变化,为什么?

答:随着并发压力的增加,系统的响应时间在一定时间内呈现线性增加,当超过系统能承受的最大负载点之后,系统的响应时间会呈指数式增加,如下图所示,当并发压力进一步增加的时候,超出系统所能承受的最大量的时候,系统随时可能进入崩溃状态。

系统的整体吞吐量与并发数的关系如下图所示。在一定范围内,随着并发数的增加,系统的整体吞吐量线性增加(图中 0-1 的区间),当到达一定数值之后,系统的整体吞吐量到达瓶颈(图中 1-2 的区间),再增加并发之后,系统的整体吞吐量呈现下滑的趋势,系统有随时崩溃的风险。

  • 用你熟悉的编程语言写一个 web 性能压测工具,输入参数:URL,请求总次数,并发数。输出参数:平均响应时间,95% 响应时间。用这个测试工具以 10 并发、100 次请求压测 www.baidu.com。

答:采用 Java 语言实现,如下:

controller:

package com.example.performance.controller;
import com.example.performance.entity.PerformanceEntity;
import com.example.performance.entity.ResponseBean;
import com.example.performance.service.PerformanceService;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
/**
 * @author Jiang Jining
 * @date 2020/7/22 20:39
 */
@CrossOrigin
@RestController
public class PerformanceController {
    @Resource
    private PerformanceService performanceService;
    @PostMapping(value = "/api/v1/performance/test")
    public ResponseBean<String> testPerformance(@RequestBody PerformanceEntity performanceEntity) {
        String s = performanceService.calculatePerformance(performanceEntity);
        return ResponseBean.success(s);
    }
}


entity:

package com.example.performance.entity;
import lombok.Data;
/**
 * @author Jiang Jining
 * @date 2020/7/22 20:46
 */
@Data
public class PerformanceEntity {
    private String url;
    private Integer threadNum;
}



package com.example.performance.entity;
import com.alibaba.fastjson.JSON;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
/**
 * @author Administrator
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
public class ResponseBean<T> implements Serializable {
    private static final long serialVersionUID = -3699842403600131110L;
    /**
     * 状态码
     */
    private int code;
    /**
     * 消息
     */
    private String message;
    /**
     * 结果数据
     */
    private T data;
    @Override
    public String toString() {
        return JSON.toJSONString(this);
    }
    public static <T> ResponseBean<T> success() {
        return new ResponseBean(ErrorEnum.SUCCESS.getErrorCode(), ErrorEnum.SUCCESS.getErrorMsg(), null);
    }
    public static <T> ResponseBean<T> success(T data) {
        return new ResponseBean(ErrorEnum.SUCCESS.getErrorCode(), ErrorEnum.SUCCESS.getErrorMsg(), data);
    }
    public static <T> ResponseBean<T> success(T data, String message) {
        return new ResponseBean(ErrorEnum.SUCCESS.getErrorCode(), message, data);
    }
    public static <T> ResponseBean<T> error(int code, String message) {
        return new ResponseBean(code, message, null);
    }
    public static ResponseBean error(String message) {
        return new ResponseBean(ErrorEnum.FAIL.getErrorCode(), message, null);
    }
}



package com.example.performance.entity;
/**
 * @author
 * @date 2018/9/18
 */
public enum ErrorEnum {
    ERROR_10000(10000, "登录Token过期"),
    ERROR_10001(10001, "未登录"),
    ERROR_10002(10002, "账号在其他地方登陆"),
    SUCCESS(200, "成功"),
    FAIL(400, "失败"),
    UNAUTHORIZED(401, "认证失败"),
    PERMISSION_DENIED(402, "权限错误"),
    PARAMETER_ERROR(403, "参数错误"),
    NOT_FOUND(404, "接口不存在"),
    SERVER_ERROR(500, "服务器内部错误"),
    /**
     * 不推荐使用
     */
    E_400(400, "请求处理异常,请稍后再试"),
    ERROR_401(401, "账号权限不足"),
    ERROR_500(500, "系统内部错误");
    /**
     * 错误码
     */
    private int errorCode;
    /**
     * 错误信息
     */
    private String errorMsg;
    ErrorEnum(int errorCode, String errorMsg) {
        this.errorCode = errorCode;
        this.errorMsg = errorMsg;
    }
    public int getErrorCode() {
        return errorCode;
    }
    public void setErrorCode(int errorCode) {
        this.errorCode = errorCode;
    }
    public String getErrorMsg() {
        return errorMsg;
    }
    public void setErrorMsg(String errorMsg) {
        this.errorMsg = errorMsg;
    }
}


service:

package com.example.performance.service;
import com.example.performance.entity.PerformanceEntity;
/**
 * @author Jiang Jining
 * @date 2020/7/22 20:44
 */
public interface PerformanceService {
    String calculatePerformance(PerformanceEntity performanceEntity);
}



package com.example.performance.service.impl;
import cn.hutool.http.HttpUtil;
import lombok.AllArgsConstructor;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StopWatch;
import java.time.LocalDate;
import java.util.concurrent.Callable;
/**
 * @author Jiang Jining
 * @date 2020/7/22 21:17
 */
@Setter
@Slf4j
@AllArgsConstructor
public class PerformanceTask implements Callable<Long> {
    private Integer currentNum;
    private String url;
    @Override
    public Long call() throws Exception {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        LocalDate localDate = LocalDate.of(2020, 1, 1);
        localDate = localDate.plusDays(currentNum);
        url += "/s?wd=" + localDate.toString();
        String s = HttpUtil.get(url, 30_000);
        if (log.isDebugEnabled()) {
            log.debug(s);
        }
        stopWatch.stop();
        if (log.isInfoEnabled()) {
            log.info("currentNum:{}, date:{}, total:{}", currentNum, localDate.toString(), stopWatch.getTotalTimeSeconds());
        }
        return stopWatch.getTotalTimeMillis();
    }
}


package com.example.performance.service.impl;
import com.example.performance.entity.PerformanceEntity;
import com.example.performance.service.PerformanceService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.concurrent.BasicThreadFactory;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
/**
 * @author Jiang Jining
 * @date 2020/7/22 20:45
 */
@Slf4j
@Service
public class PerformanceServiceImpl implements PerformanceService {
    private ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1, 10, 1000L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(),
            new BasicThreadFactory.Builder().namingPattern("performance-pool-%d").daemon(true).build());
    @Override
    public String calculatePerformance(PerformanceEntity performanceEntity) {
        Objects.requireNonNull(performanceEntity);
        Integer threadNum = performanceEntity.getThreadNum();
        Objects.requireNonNull(threadNum);
        String url = performanceEntity.getUrl();
        Objects.requireNonNull(url);
        AtomicInteger atomicInteger = new AtomicInteger(0);
        List<Long> timeConsumeList = new ArrayList<>(threadNum);
        List<PerformanceTask> futureList = new ArrayList<>(threadNum);
        List<Future<Long>> tempList = new ArrayList<>(threadNum);
        for (int i = 0; i < threadNum; i++) {
            PerformanceTask performanceTask = new PerformanceTask(atomicInteger.addAndGet(1), performanceEntity.getUrl());
            Future<Long> timeConsumeFuture = threadPoolExecutor.submit(performanceTask);
            tempList.add(timeConsumeFuture);
            futureList.add(performanceTask);
        }
        try {
            threadPoolExecutor.invokeAll(futureList, 1, TimeUnit.MINUTES);
        } catch (InterruptedException e) {
            if (log.isErrorEnabled()) {
                log.error(e.getMessage());
            }
        }
        tempList.forEach(longFuture -> {
            try {
                Long aLong = longFuture.get();
                timeConsumeList.add(aLong);
            } catch (InterruptedException | ExecutionException exception) {
                if (log.isErrorEnabled()) {
                    log.error(exception.getMessage());
                }
            }
        });
        timeConsumeList.sort(Long::compare);
        long totalConsume = 0L;
        int size = timeConsumeList.size();
        for (Long aLong : timeConsumeList) {
            totalConsume += aLong;
        }
        int ninetyFifthIndex = (int) (size * 0.95);
        return "95%响应时间:" +
                timeConsumeList.get(ninetyFifthIndex - 1) +
                "ms, 平均响应时间:" +
                totalConsume * 1.0 / size +
                "ms";
    }
}


测试结果:

请求参数:

{"url":"http://www.baidu.com", "threadNum": 10}



计算结果:

{
    "code": 200,
    "message": "成功",
    "data": "95%响应时间:413ms, 平均响应时间:135.5ms"
}


请求参数:

{"url":"http://www.baidu.com", "threadNum": 100}


计算结果:

{
    "code": 200,
    "message": "成功",
    "data": "95%响应时间:818ms, 平均响应时间:600.38ms"
}

目录
相关文章
|
6月前
|
机器学习/深度学习 算法 安全
隐私计算训练营第三讲-详解隐私计算的架构和技术要点
SecretFlow 是一个隐私保护的统一框架,用于数据分析和机器学习,支持MPC、HE、TEE等隐私计算技术。它提供设备抽象、计算图表示和基于图的ML/DL能力,适应数据水平、垂直和混合分割场景。产品层包括SecretPad(快速体验核心能力)和SecretNote(开发工具)。算法层涉及PSI、PIR、数据分析和联邦学习(水平、垂直、混合)。此外,SecretFlow还有YACL密码库和Kusica任务调度框架,Kusica提供轻量化部署、跨域通信和统一API接口。
221 0
|
消息中间件 缓存 NoSQL
|
消息中间件 存储 关系型数据库
极客时间架构实战营作业八
极客时间架构实战营作业八
162 0
|
消息中间件 Java 中间件
极客时间架构实战营作业六
极客时间架构实战营作业六
121 0
|
资源调度 分布式计算 调度
Fink--3、Flink运行时架构(并行度、算子链、任务槽、作业提交流程)
Fink--3、Flink运行时架构(并行度、算子链、任务槽、作业提交流程)
|
容灾 网络协议
极客时间架构实战营模块 7 作业
极客时间架构实战营模块 7 作业
85 0
|
存储 缓存 负载均衡
极客时间架构实战营作业五
极客时间架构实战营作业五
129 0
|
存储 JSON NoSQL
极客时间架构实战营作业四
极客时间架构实战营作业四
114 0
|
10天前
|
缓存 负载均衡 JavaScript
探索微服务架构下的API网关模式
【10月更文挑战第37天】在微服务架构的海洋中,API网关犹如一座灯塔,指引着服务的航向。它不仅是客户端请求的集散地,更是后端微服务的守门人。本文将深入探讨API网关的设计哲学、核心功能以及它在微服务生态中扮演的角色,同时通过实际代码示例,揭示如何实现一个高效、可靠的API网关。
|
9天前
|
Cloud Native 安全 数据安全/隐私保护
云原生架构下的微服务治理与挑战####
随着云计算技术的飞速发展,云原生架构以其高效、灵活、可扩展的特性成为现代企业IT架构的首选。本文聚焦于云原生环境下的微服务治理问题,探讨其在促进业务敏捷性的同时所面临的挑战及应对策略。通过分析微服务拆分、服务间通信、故障隔离与恢复等关键环节,本文旨在为读者提供一个关于如何在云原生环境中有效实施微服务治理的全面视角,助力企业在数字化转型的道路上稳健前行。 ####