了解mysql基准测试工具sysbench

1、什么是基准测试

数据库的基准测试是对数据库的性能指标进行定量的、可复现的、可对比的测试。

基准测试与压力测试

基准测试可以理解为针对系统的一种压力测试。但基准测试不关心业务逻辑,更加简单、直接、易于测试,数据可以由工具生成,不要求真实;而压力测试一般考虑业务逻辑(如购物车业务),要求真实的数据。

2、基准测试的作用

对于多数Web应用,整个系统的瓶颈在于数据库;原因很简单:Web应用中的其他因素,例如网络带宽、负载均衡节点、应用服务器(包括CPU、内存、硬盘灯、连接数等)、缓存,都很容易通过水平的扩展(俗称加机器)来实现性能的提高。而对于MySQL,由于数据一致性的要求,无法通过增加机器来分散向数据库写数据带来的压力;虽然可以通过前置缓存(Redis等)、读写分离、分库分表来减轻压力,但是与系统其它组件的水平扩展相比,受到了太多的限制。

而对数据库的基准测试的作用,就是分析在当前的配置下(包括硬件配置、OS、数据库设置等),数据库的性能表现,从而找出MySQL的性能阈值,并根据实际系统的要求调整配置。

使用 WebSocket 和 SSE 实现 HTTP 服务器推送

HTTP 服务器推送也称为 HTTP 流,是一种客户端-服务器通信模式,它将信息从 HTTP 服务器异步发送到客户端,而无需客户端请求。在高度交互的 Web 或移动应用程序中,一个或多个客户端需要连续不断地从服务器接收信息,服务器推送架构对这类应用程序特别有效。在本文中,您将了解 WebSocket 和 SSE(服务器发送的事件),它们是实现 HTTP 服务器推送的两种技术。

我首先将概述两种解决方案之间的技术差异,以及如何在 Web 架构中实现每种解决方案。我将通过一个示例应用程序,向您展示如何设置一个 SSE 实现,然后介绍一个类似的 WebSocket 实现。最后,我将比较两种技术,并提出我关于在不同类型 Web 或移动应用程序中使用它们的结论。

请注意,本文要求熟悉 HTTP 服务器推送的语言和概念。两个应用程序都是在 Python 中使用 CherryPy 编写的。

基于 Swagger 的前后端分离开发实践

前后端分离开发已经是很流行的一个开发模式。前端开发不需要部署后端语言的环境,后端开发也不需要前端写好的任何程序。后端只管暴露各种 API 接口供给前端进行数据的增、删、改、查,不负责生成 HTML 页面,这种方式能够减轻后端任务让后端开发更加专注。尤其是在微服务的开发框架下, 前后端分离开发的模式应用更加广泛。本篇亦是在微服务的开发框架下的实践总结。

在微服务开发框架下,前端通常被设计成一个独立的微服务。前后端仅仅通过接口来协作,前端服务最终生成一个独立的 Docker 镜像来部署。在产品的核心微服务定义完成后,我们希望前后端 Service 同时开始开发,所以这里我们利用 Swagger 创建了一个基于 Node.js 的 Mock Server 作为前后端分离开发的工具。在后端服务没有完全实现的情况下, 使用 Mock Server 作为前端开发的支持工具, 来实现前后端同时开发的目的。

Java源码ImageVerifyUtils验证码工具类

应用于验证码校验与生成,一个简单的验证码生成类。

功能结合了,生成验证码,及验证码校验,需要传入http session。

直接上源码:

package com.mymvc.system.utils;

import com.mymvc.system.exception.IllegalValidateException;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.logging.Logger;

/**
 * image verify class.
 * <p>
 * ImageVerifyUtils verify = new ImageVerifyUtils();
 * verify.make(response, request.getSession());
 * <p>
 * verify.check(request.getSession(),code); => true or throw new Exception.
 */
public class ImageVerifyUtils {

    private static final Logger log = Logger.getLogger(ImageVerifyUtils.class.getName());

    private String KEY_SESSION_VERIFY = "key_session_image_verify";
    private String KEY_SESSION_DATETIME = "key_session_time_verify";

    private Long expireIn = 300000L;
    private String hash = "hash";

    //    private String raw = "qwertyupkijhgfdsazxcvbnmABCDEFGHJKLMNPQRSTUVWXYZ1234567890";
    private String raw = "1234567890";

    public ImageVerifyUtils() {

    }

    public void make(HttpServletResponse response, HttpSession session) throws Exception {
        this.make(response, session, 120, 40);
    }

    public void make(HttpServletResponse response, HttpSession session, int width, int height) throws Exception {
        this.make(response, session, width, height, 4);
    }

    /**
     * make a image verify
     * @param response output to browser.
     * @param session http session,use it to save verify code.
     * @param width default is 120px
     * @param height default is 40px
     * @param num the verify code.
     * @throws Exception
     */
    public void make(HttpServletResponse response, HttpSession session, int width, int height, int num) throws Exception {
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);

        int r = this.getRandom(200, 255);
        int g = this.getRandom(200, 255);
        int b = this.getRandom(200, 255);

        Graphics2D g2d = (Graphics2D) image.getGraphics();
        g2d.setColor(new Color(r, g, b));
        g2d.fillRect(0, 0, width, height);

        g2d.setStroke(new BasicStroke(1.5f));
        for (int i = 0; i < 5; i++) {
            r = this.getRandom(50, 200);
            g = this.getRandom(50, 200);
            b = this.getRandom(50, 200);
            g2d.setColor(new Color(r, g, b));

            g2d.drawLine(getRandom(0, width), getRandom(0, height), getRandom(0, width), getRandom(0, height));
        }

        int fontSize = (width - 26) / num;

        r = this.getRandom(0, 180);
        g = this.getRandom(0, 180);
        b = this.getRandom(0, 180);
        g2d.setColor(new Color(r, g, b));
        g2d.setFont(new Font(null, Font.PLAIN, fontSize));
        List<String> codes = this.getVerifyString(num);
        String code = "";

        int __x = (width - fontSize * num) / 2;
        for (int i = 0; i < codes.size(); i++) {
            code += codes.get(i);
            if (i == 0) {
                g2d.drawString(codes.get(i), __x, getRandom(20, height));
            } else {
                g2d.drawString(codes.get(i), fontSize * i + __x, getRandom(20, height));
            }
        }

        log.info(">>code:" + code);
        //绘制干扰点
        g2d.setStroke(new BasicStroke(2.6f));
        for (int i = 0; i < 10; i++) {
            r = this.getRandom(100, 255);
            g = this.getRandom(100, 255);
            b = this.getRandom(100, 255);
            g2d.setColor(new Color(r, g, b));

            int x = getRandom(0, width);
            int y = getRandom(0, height);
            g2d.drawLine(x, y, x + 2, y + 2);
        }

        session.setAttribute(KEY_SESSION_VERIFY, Md5Utils.md5(code.toLowerCase() + hash).toUpperCase());
        session.setAttribute(KEY_SESSION_DATETIME, System.currentTimeMillis() + expireIn);

        response.setContentType("image/jpeg");
        OutputStream ops = response.getOutputStream();
        ImageIO.write(image, "jpeg", ops);
        ops.close();
    }

    /**
     * check the code valid or invalid.
     * @param session Http session
     * @param verifyCode code string
     * @return true or throws.
     * @throws IllegalValidateException
     */
    public boolean check(HttpSession session, String verifyCode) throws IllegalValidateException {

        if (verifyCode == null) {
            throw new IllegalValidateException("请输入验证码");
        }

        Long makeTime = (Long) session.getAttribute(KEY_SESSION_DATETIME);
        if (makeTime == null) {
            throw new IllegalValidateException("验证码不存在");
        }

        if (makeTime.longValue() < System.currentTimeMillis()) {
            throw new IllegalValidateException("验证码已过期");
        }

        String source = (String) session.getAttribute(KEY_SESSION_VERIFY);
        if (source == null) {
            throw new IllegalValidateException("验证码不存在");
        }

        String now = Md5Utils.md5(verifyCode.toLowerCase() + hash).toUpperCase();
        if (now.equals(source)) {
            session.removeAttribute(KEY_SESSION_DATETIME);
            session.removeAttribute(KEY_SESSION_VERIFY);
            return true;
        }

        throw new IllegalValidateException("验证码错误");

    }

    /**
     * get verify code.
     * @param num the code length,default is 4.
     * @return
     */
    private List<String> getVerifyString(int num) {
        if (num <= 0) {
            num = 4;
        }
        List<String> res = new ArrayList<>();
        Random r = new Random();
        for (int i = 0; i < num; i++) {
            res.add(String.valueOf(raw.charAt(r.nextInt(raw.length()))));
        }
        return res;
    }

    /**
     * get number by random.
     * @param min min number
     * @param max max number
     * @return between min to max.
     */
    private int getRandom(int min, int max) {
        Random random = new Random();
        return random.nextInt(max) % (max - min + 1) + min;
    }

}

 

使用方法(生成):

ImageVerifyUtils verify = new ImageVerifyUtils();
try {
    verify.make(response, request.getSession());
} catch (Exception e) {
    e.printStackTrace();
}

校验:

ImageVerifyUtils verify = new ImageVerifyUtils();
try {

    String code = request.getParameter("code");
    verify.check(request.getSession(),code);
} catch (IllegalValidateException e) {
    e.printStackTrace();
}

 

 

AngularJS实现slide指令

前端的HTML代码如下:

<div test-slide="{{imgs}}" data-time="3"></div>

指令testSlide代码:

.directive("testSlide", function ($interval) {
    return {
        restrict: 'A',
        replace: false,
        link: function (scope, ele, attr) {
            scope.imgs = JSON.parse(attr.testSlide);
            var time = parseFloat(attr.time);
            if (scope.imgs.length > 0 && time > 0) {
                if (typeof window.__slide === "object" && window.__slide != null) {
                    $interval.cancel(window.__slide);
                }
                window.__slide = $interval(function () {
                    var n = $(".slide>.active");
                    var c = $(".slide").children();

                    var index = -1;
                    $.each(c, function (i, n) {
                        if (i + 1 === c.length && index === -1) {
                            index = 0;
                        }
                        if ($(n).hasClass('active') === true && index === -1) {
                            index = i+1;
                        }
                    })

                    n.removeClass('active slideInRight');
                    $(c[index]).addClass('active slideInRight');

                    if(typeof c[index] === "undefined"){
                        $interval.cancel(window.__slide);
                    }
                }, time * 1000)
            }
        },
        template: '<div><style>\n' +
        '        .slide{width: 100%;}\n' +
        '        .slide .slide-img{width: 100%;display: none;}\n' +
        '        .slide .active{display: block;}\n' +
        '    </style><div class="slide">' +
        '   <div class="slide-img {{$first?\'active\':\'\'}}" ng-repeat="v in imgs">' +
        '       <img ng-src="{{v}}"/>' +
        '   </div>' +
        '</div></div>'
    }
})

 

功能实现了,但是可能需要增加一些动画效果,这里就懒得整了。

123480