我又来了,又来大言不惭的说自己全栈了

观众:XXX 退钱!

其实读到最后,重点就不再是不是全栈上了。

咱就是说,突出一个字。

需求

之前玩了玩UOJ,苦于它出题的时候数据的输入太麻烦,于是就想写个什么东西来帮着造数据。

具体怎么个麻烦法呢?首先得造数据,造出一堆数据然后还得写个配置文件,写完配置文件后然后把这一坨坨东西打包才能够上传。其中,造数据的话就得写标程,写对拍,然后配置文件就得按照格式填。

其实现在看看也没特别麻烦,只是一般的麻烦。但是我就是懒得读配置文件,懒得写对拍,懒得打包,懒癌晚期患者了

于是就有了上面的需求:写一个啥东西来处理一些比较简单的数据生成工作

实现

一通乱搞后,最后还是使用Bootstrap+Flask+Python来实现了项目,然后部署方面一部分用了Gunicorn+docker(docker打包项目),另一部分用了Gunicorn+项目。至于为什么要这样……主要是太懒了

PartOne

这一部分实现的是主要的功能,也就包含数据生成,数据打包,前后端交互等功能。(其实我这种流派都用不着考虑什么前后端的。主要是太菜,也只能前后端不分离这种流派能够写写玩了)

数据生成

输入数据

数据生成的话,瞎分析了一下,觉得这样安排一般能够满足大部分的需求:

  • 生成长度为n的数列
  • 生成m个长度为n的数列

  • 生成一个有向带权图
  • 生成一个无向带权图
  • 生成一个有向无权图
  • 生成一个无向无权图
  • 生成多个不连通的子图

  • 生成一棵随机树
  • 生成一条链
  • 生成一个n叉树

字符串

  • 生成一个长度为n的字符串
  • 生成m个长度为n的字符串

然后,思来想去,还是不能完全自己写数据生成器还是因为懒,于是想起洛谷有个项目可以用一用,就去白嫖了一波Luogu的cYaRon,然后封装了下,就可以生成数据了。

输出数据

输入有了,输出咋办?先假设前端能够拿到用户输入的代码,然后呢?然后得运行代码吧。咋运行呢?不同的语言有不同的运行方法。不过如果只允许用python的话,那就直接命令行python run就行了,看来只限定Python会简单很多。

不过有没有自动运行代码的API捏?有,但是懒得研究,不想写了

其实吧,只能输入python然后跑Python确实很low, 但是就是懒得写了

好吧那就,但是输出数据放哪儿呢?放本地呗,放一个文件夹里面,然后爱咋咋地。

不过还有个问题,如果代码TLE了咋办?这得计时跑的来着。一开始思考的是,能不能多线程同时跑数据,但是发现实现不了(又懒又菜),于是那就一个一个跑吧。于是研究了一下Python的多线程,使用daemon属性很不清真的实现了一个计时跑代码的功能。

数据打包

现在有了输入数据和输出数据,那么再假设现在有了配置文件,那么现在需要干啥捏?打包呗。调库,zipfile,完事

前端代码和前后端交互

这一部分之前也弄过,但是不是很熟练,甚至连jinja2是啥都不知道就套着用了。(小知识:jingja2是模版引擎,渲染html模版用的)

那既然这样,就先得有html模版。于是就开抄Bootstrap,改改改改出几份页面出来,然后flask设计路由,设置模版渲染等等。

值得一提的是这次不仅用了jinja2渲染,还用了js来实现动态效果。这次也新学到了用flask-wtf来处理表单以及send_from_directory这种有意思的小东西。

反正无论不管怎么样如何,最后这坨东西是跑起来了。

PartTwo

这一部分主要就是上线的问题了。

清真的上线

咋才能把这坨东西部署到服务器上面?之前用的是uwsgi。不过啥是uwsgi?当时是不知道的。现在知道了:

首先有个东西叫做wsgi,也就是Web服务器网关接口(Python Web Server Gateway Interface,缩写为WSGI)。啥意思?就是一个连接Web服务器和Python应用的一个玩意儿。像我这用Flask写的一个东西就是一个Python应用。而关于Web服务器,我也暂时说不出个所以然来,之前看到一篇文章写的挺有启发的:

web服务器(http服务器):负责处理和响应用户请求,一般也称为http服务器,如 Apache、IIS、Nginx
应用服务器:存放和运行系统程序的服务器,负责处理程序中的业务逻辑,如 Tomcat、Weblogic、Jboss(现在大多数应用服务器也包含了web服务器的功能)

然后,uwsgi就是上述的Web服务器一种,面向wsgi的web服务器。还有另外一种同类型的叫做gunicorn,这次就用它来部署了一波

理论上讲,gunicorn外面再套一个nginx代理一下会好很多(nginx也是web服务器),但是咱这小项目,着实没必要(主要还是懒

然后,为了方便,配好服务器后用docker封装一下,拉到服务器上面跑

然后……然后就跑起来了捏~~

不清真的上线

不过问题很快就出来了。如果两个人同时访问docker,那不就寄了(原因很简单,同一个文件会被不同的线程写入,最后出来的数据是啥完全无法预测)

其实这个时候,写一个异步IO也不是不行。但是还是那个问题,懒得写

那么怎么办呢?

那么怎么办呢?

那么怎么办呢?

哦……

每次访问我的url,我就给这个人开一个新的docker,然后把他重定向到新的docker的url。这个时候,如果多个人访问url,那就访问的是不同的docker,这个时候就不会有这个问题了呢

因此,还需要写个东西来进行docker的生成(控制端口和docker的生命周期)和路由的转发

然后写写写,写写写,写完了同样用flask装一下,用gunicorn上个线,这个就不用docker装了,因为装了就跑不了了

最后的最后,它成功的跑起来了

复盘

其实还是学到了很多东西:

  • 复习了html,css,js,Bootstrap,Flask
  • 学明白了jinja2的概念,以及基本的调用方式
  • 学到了Flask的一些有意思的操作,包括文件传输,路由重定向,模版渲染,Flask-wtf表单生成等
  • 学会了用Python的多线程
  • 搞明白了wsgi是个啥
  • 学会了gunicorn和nginx的基本配置(虽然最后没用nginx,但是还是学过了的)

一些很好的文章的链接

连前端都看得懂的《Nginx 入门指南》

一文详解gunicorn的功能及使用方法

菜鸟教程 Nginx 配置详解

Flask + Docker 无脑部署新手教程

Python线程

然后,很显然的,这玩意儿到处是bug,因此还得改,改,改。

这俩在github上的住址:EasyDataMaker-For-UOJ,EasyDataMaker_Docker_allocator