多副本web服务
- 单个flask服务封装的模型推理,在单机上支持的并发连接请求数量无法满足要求,压测为300左右的数量级别,压测代码如下:
- 通过客户端传输base64字节流到服务端处理,返回抠图结果
import base64
import cv2,os
import numpy as np
import requests
import json
import threading
import time
img_path = 'E:/mission/img'
out_path = 'E:/mission/out/'
class postrequests():
def __init__(self,img_path):
self.url = 'http://127.0.0.1:9110/api/matting_base64'
self.img_path = img_path
self.bg_color = [33, 150, 242]
self.headers = {'content-type': 'application/json'}
def post(self):
try:
with open(self.img_path, 'rb') as f:
img_base64 = base64.b64encode(f.read())
request_data = json.dumps(
{
'image': img_base64.decode('utf-8'),
'bg': json.dumps(self.bg_color)
}
)
headers = {
"Content-Type": "application/json;charset=utf8"
}
start_time = time.time()
r = requests.post(self.url, data=request_data, headers=headers)
response_data = r.json()
end_time = time.time()
print(f'time:{end_time - start_time:.2f}s')
result_base64 = base64.b64decode(response_data['result'])
result_numpy = cv2.imdecode(np.fromstring(result_base64, np.uint8), cv2.IMREAD_COLOR)
name = self.img_path.split("/")[-1]
name = name.replace('.jpg', '.png')
cv2.imwrite(out_path + name, result_numpy)
except Exception as e:
print(e)
def kquan_bf(image_path):
login = postrequests(image_path)
return login.post()
try:
i = 0
# 开启线程数目
tasks_number =450
img_names = os.listdir(img_path)
print('测试启动')
time1 = time.clock()
while i < tasks_number:
image_path = img_path+"/"+img_names[i%len(img_names)]
print(image_path)
t = threading.Thread(target=kquan_bf,args=(image_path,))
t.start()
i += 1
time2 = time.clock()
times = time2 - time1
print(times / tasks_number)
except Exception as e:
print(e)
- 单个副本启动时,响应的请求数量维持在300左右,但超过300会有部分请求url超过重试次数,即无响应。
Nginx负载均衡多副本任务
- 为了解决并发连接数的问题,采用nginx作为代理服务器分发http请求。
- Nginx配置文件如下:
- 如果端口服务出现错误可以查看nginx的errors日志文件debug,这次因为开启多端口最少连接分发中发现有不少连接到达服务器时,携带的body信息不完整,查看log发现是clientbodymaxsize设置问题。
worker_processes 1;
#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
#pid logs/nginx.pid;
events {
worker_connections 1024;
}
http {
client_max_body_size 50m;
client_header_timeout 1m;
client_body_timeout 1m;# 文件超时
proxy_connect_timeout 600;
proxy_read_timeout 600;
proxy_send_timeout 600;
upstream matting_base64 {
least_conn;
server localhost:9111;
server localhost:9112;
server localhost:9113;
server localhost:9114;
}
server {
listen 9110;
proxy_connect_timeout 600;
proxy_read_timeout 600;
proxy_send_timeout 600;
client_max_body_size 50m;
server_name localhost;
location /api/matting_base64 {
proxy_set_header Connection "";
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://matting_base64;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
本次改动一共涉及到分发策略、更改限制上传附件大小(默认为1M,如果不更改会导致高并发的情况下到达分发服务的请求,不携带有效的body),连接设置超时时间和文件上传超时时间。
最后修改nginx监听端口,依靠其自动转发即可。
nginx启动停止命令
-
查看nginx的版本号:nginx -v
-
启动nginx:start nginx
-
快速停止或关闭nginx:nginx -s stop
-
正常停止或关闭nginx:nginx -s quit
-
配置文件nginx.conf修改重装载命令:nginx -s reload
Nginx实现负载均衡
- 轮询
轮询方式是Nginx负载默认的方式,顾名思义,所有请求都按照时间顺序分配到不同的服务上,如果服务Down掉,可以自动剔除,如下配置后轮训10001服务和10002服务。 - 权重weight=$
指定每个服务的权重比例,weight和访问比率成正比,通常用于后端服务机器性能不统一,将性能好的分配权重高来发挥服务器最大性能,如下配置后10002服务的访问比率会是10001服务的二倍。 - ip_hash
每个请求都根据访问ip的hash结果分配,经过这样的处理,每个访客固定访问一个后端服务,如下配置(ip_hash可以和weight配合使用)。 - 最少连接least_conn
将请求分配到连接数最少的服务上。 - fair
按后端服务器的响应时间来分配请求,响应时间短的优先分配。