geventhttpclient
是一款使用gevent的高性能python并发HTTP客户端库` >>>Github
目前在官方说明里没有提到如何用本地环境配套生成的CA证书来发起HTTPS请求, 遂自己翻它的源码来分析
本地环境:
- macOS 10.14.5
- Python 3.7
目录
一. 先贴一下源码截图
进入client.py
跳到connectionpool.py
从上面几个源码文件可以看出: 默认会用这个default_options作为默认的SSL配置去请求,但我们要用自定义的.
- 简单汇总一下本次要做哪些工作:
- 先给服务端(可以是虚拟机)生成CA证书,关注
server
和client
2份,它们是配对使用的- 使用Flask编写Web服务,提供一个待测接口
- 将
server
证书配置在Web服务里,启动- CA证书拷贝到客户端
- 客户端带上CA证书发起HTTPS请求
二. 在CentOS 7.4 中生成CA证书
1. 命令和操作步骤如下
mkdir ~/https_certificate
cd ~/https_certificate
mkdir ./ca
openssl genrsa -out ca/ca-key.pem 1024
openssl req -new -out ca/ca-req.csr -key ca/ca-key.pem
openssl x509 -req -in ca/ca-req.csr -out ca/ca-cert.pem -signkey ca/ca-key.pem -days 3650
mkdir ./server
openssl genrsa -out server/server-key.pem 1024
openssl req -new -out server/server-req.csr -key server/server-key.pem
openssl x509 -req -in server/server-req.csr -out server/server-cert.pem -signkey server/server-key.pem -CA ca/ca-cert.pem -CAkey ca/ca-key.pem -CAcreateserial -days 3650
openssl x509 -req -in server/server-req.csr -out server/server-cert.pem -signkey server/server-key.pem -CA ca/ca-cert.pem -CAkey ca/ca-key.pem -CAcreateserial -days 3650
mkdir ./client
openssl genrsa -out client/client-key.pem 1024
openssl req -new -out client/client-req.csr -key client/client-key.pem
openssl x509 -req -in client/client-req.csr -out client/client-cert.pem -signkey client/client-key.pem -CA ca/ca-cert.pem -CAkey ca/ca-key.pem -CAcreateserial -days 3650
以上操作正常完成后, 服务器得到了这3个目录:
~/https_certificate/ca
~/https_certificate/server
~/https_certificate/client
- 把
~/https_certificate/server
目录下server-cert.pem和server-key.pem 拷贝到Web项目根目录 - 把
~/https_certificate/car
目录下ca-cert.pem 拷贝到你的机器上
三. 使用Flask编写一个简单的HTTPS待压测接口
#!/usr/bin/env python3
#coding=utf-8
import sys
import os
import datetime
from flask import Flask, request, jsonify, render_template, make_response
# 默认查找server运行目录下的文件: ~/mock_sony_api_data/
DEFAULT_READ_XML_PATH = os.getcwd()
CERTIFICATE_FILE_PATH = '/'.join([DEFAULT_READ_XML_PATH,'https_certificate/server'])
app = Flask(__name__)
@app.route('/info', methods=['GET'])
def get_info():
get_CST_time_in_ISO_format = lambda: datetime.datetime.now().isoformat()
return jsonify({'msg': 'SUCCESS', 'code': '200', 'ts': get_CST_time_in_ISO_format()})
if __name__ == "__main__":
app.run(host='0.0.0.0', port='443', debug=True,
ssl_context=('/'.join([CERTIFICATE_FILE_PATH, 'server-cert.pem']), '/'.join([CERTIFICATE_FILE_PATH, 'server-key.pem'])))
四. 将ca-cert.pem
文件放到压测代码的同级目录, 然后给http对象的ssl_options
传入它
import logging
import traceback
# import ssl
from time import time
from locust import User, task, between, events
from geventhttpclient import HTTPClient, URL
TEST_URL = "https://192.168.1.55/info"
EXPECTED_RESULTS = 200
class PerformanceModel(User):
host_url = URL(TEST_URL)
ca_option = {'ca_certs': './ca-cert.pem'}
http_client = HTTPClient.from_url(host_url, concurrency=10, ssl_options=ca_option)
host = str(http_client.get_base_url())
min_wait = 1.0
max_wait = 2.0
wait_time = between(min_wait, max_wait)
# def on_stop(self):
# self.http_client.close()
@task
def tp_info(self):
_res, end_time, response_length = None, None, None
try:
start_time = time()
_res = self.http_client.get(self.host_url.request_uri)
end_time = (time() - start_time) * 1000
response_length = len(_res.status_message)
assert _res.status_code == EXPECTED_RESULTS
except AssertionError:
events.request_failure.fire(request_type="GET", name="test_failure", response_time=end_time,
response_length=response_length,
exception="report failed:{}".format(_res.status_code))
logging.info(_res)
except Exception as e:
events.request_failure.fire(request_type="GET", name="test_failure", response_time=0,
response_length=0, exception=e)
traceback.print_exc()
else:
events.request_success.fire(request_type="GET", name="test_success", response_time=end_time,
response_length=response_length)
五. 启动压测
#TODO 压测报告和说明待更新~