Flask服务部署与简单内网穿透
前言
最近学习部署的时候,想到深度学习里面通常用的部署方法是flask
做服务端,然后使用nginx
做负载均衡,貌似也能做内网穿透。不过我不太懂负载均衡,只想利用本地电脑搭建一个简单的服务器,实现外部调用 API 服务的功能。所以本文会介绍到的内容有:
-
flask
服务端与客户端的通信 -
ngrok
简单地做内网穿透,使得非同一个局域网的电脑能够通过公网 IP 访问服务
国际惯例,参考博客:
flask 官方文档[1]
ngrok 官方入口[2]
ngrok 的官方文档[3]
Flask
服务端和客户端
基于flask
写一个上传文件的功能,不管你传输的是图像还是文字,都可以用这个代码接收,然后处理完毕再返回一些信息,比如深度学习的预测结果或者状态信息之类的。
本博客不介绍flask
的使用方法,可以去 flask 官方快速入门章节看到非常详细的教程。
服务端
仿照flask 官方上传文件[4]的例子,直接写如下内容:
-
路由:指示通过什么接口(ip+端口+入口)能够访问提供的功能函数 -
功能:接收客户端信息,处理,返回结果信息
@app.route('/upload',methods=['POST'],strict_slashes=False)
def api_upload():
file_dir=os.path.join(basedir,app.config['UPLOAD_FOLDER'])
if not os.path.exists(file_dir):
os.makedirs(file_dir)
f=request.files["myfile"] # 从表单的myfile字段获取文件,myfile为该表单的name值
fname = request.form["name"]
if f and allowed_file(fname): # 判断是否是允许上传的文件类型
f.save(os.path.join(file_dir,fname)) #保存文件到upload目录
print(url_for('uploaded_file',filename=fname))
return jsonify({"succeed":'True',"msg":"upload succeed"})
else:
return jsonify({"succeed":'False',"msg":"upload failed"})
这里的操作是:
-
路由:通过本地 ip+端口+ /upload
访问此服务 -
功能:读取服务端发送的文件和文件名,然后保存在本地,返回状态
【注】
额外说一句,有时候我们要修改函数内容,就不得不重启服务,但是如果我们使用
app.run(debug=True,host='0.0.0.0',port=5555)
将debug
设置为True
,就可以不用重启服务,每次修改保存完毕后,服务会自动重启。
有时候会出现一句话:
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
改成:
serve(app, host="0.0.0.0", port=5555) #product
就没有这个warning
了
客户端
官方新建了一个html
作为服务端,我们也可以使用python
写一个客户端
实现的功能就是:
-
读取文件为二进制数据,并获取文件名 -
将文件和文件名发送到服务器
使用 html 作为客户端
这样就在服务端写一个html
的入口,用户访问这个端口的时候,显示一个上传界面,然后进行通信
@app.route('/test/upload')
def upload_test():
return render_template('upload.html')
但是需要注意,这个html
存在一个名为templates
文件夹中
<form id="form1" method="post" action="/upload" enctype="multipart/form-data">
<div>
<input id="File1" type="file" name="myfile"/>
<input id="name" type="text" name="name"/>
<input type="submit">提交</input>
</div>
</form>
打开服务端以后,直接在电脑上输入http://192.168.3.10:5555/test/upload
就可以进入传输界面
使用 python 写客户端
基本就是POST
通信方法
def upload_file(file_path):
file_bin = open(file_path,'rb').read()
upload_content = {"myfile":file_bin}
upload_name = {"name":os.path.basename(file_path)}
r = requests.post(REST_API_URL,data=upload_name,files=upload_content).json()
if(r['succeed']):
print("success")
else:
print("failed")
REST_API_URL = 'http://192.168.3.10:5555/upload'
ngrok
内网穿透
假设用户和你不在同一个局域网是无法通过上述 ip 访问到你的服务的,所以需要将内网提供服务的端口映射到外网,网上有很多内网穿透的工具和教程,我只是Google
了一下ngrok
,然后进入第一个网址,看着像官方的,然后引入眼帘的就是这样一张图
就是这么简单,直接去下载你电脑对应的可执行文件,然后直接输入
ngrok http 5555
pause
http://48a7fd5eedbb.ngrok.io/test/upload
后记
做算法的,能简单的快速验证提供 API 能力就行啦,至于什么服务分发,交给开发折腾就行。我问了一下身边的大佬,虽然网上说nginx
可以做服务穿透,但是它经常用于服务分发,比如有 100 个用户访问同时同一个服务,部署在一台电脑上可能会炸了,或者造成等待,那么我们可以通过nginx
把这些请求分发到不同服务器上去计算。后续有时间再研究。
参考资料
flask官方文档: http://docs.jinkan.org/docs/flask/
[2]ngrok官方入口: https://ngrok.com/
[3]ngrok的官方文档: https://dashboard.ngrok.com/get-started/setup
[4]flask官方上传文件: http://docs.jinkan.org/docs/flask/patterns/fileuploads.html