diff --git a/COMMIT_EDITMSG b/COMMIT_EDITMSG new file mode 100644 index 0000000..a34af0e --- /dev/null +++ b/COMMIT_EDITMSG @@ -0,0 +1 @@ +README CHANGE diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..415dc17 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,19 @@ +FROM python:3.6 +RUN apt-get update +RUN apt install -y nginx + +WORKDIR /Project/demo + +COPY requirements.txt ./ +RUN pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple + +COPY . . + +RUN rm /etc/nginx/sites-enabled/default +COPY nginx_flask.conf /etc/nginx/sites-available/ +RUN ln -s /etc/nginx/sites-available/nginx_flask.conf /etc/nginx/sites-enabled/nginx_flask.conf +RUN echo "daemon off;" >> /etc/nginx/nginx.conf +CMD ["nginx","-c","/etc/nginx/nginx.conf"] +CMD ["nginx","-t"] +CMD ["nginx","-s","reload"] +CMD ["gunicorn", "run:app", "-c", "./gconfig.py"] diff --git a/FETCH_HEAD b/FETCH_HEAD new file mode 100644 index 0000000..62c1bea --- /dev/null +++ b/FETCH_HEAD @@ -0,0 +1,3 @@ +941b27bc0531c5401948df3564c5b5da371ee9e4 branch 'develop' of 106.75.225.141:guoteng/albumy +42295b43602cb2dd7896c365a821f6d6afba4672 not-for-merge branch 'feature' of 106.75.225.141:guoteng/albumy +549e8bab6eb6120bd84ff14324503868ec124b4e not-for-merge branch 'master' of 106.75.225.141:guoteng/albumy diff --git a/HEAD b/HEAD new file mode 100644 index 0000000..7ee7e4f --- /dev/null +++ b/HEAD @@ -0,0 +1 @@ +ref: refs/heads/develop diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..ef2a417 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2017 Grey Li + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/ORIG_HEAD b/ORIG_HEAD new file mode 100644 index 0000000..06dbb81 --- /dev/null +++ b/ORIG_HEAD @@ -0,0 +1 @@ +c4729ee28f6cff91fd35196a61d75723434b9c5a diff --git a/Pipfile b/Pipfile new file mode 100644 index 0000000..b80b0bc --- /dev/null +++ b/Pipfile @@ -0,0 +1,22 @@ +[[source]] +url = "https://pypi.python.org/simple" +verify_ssl = true +name = "pypi" + +[dev-packages] +faker = "*" +watchdog = "*" + +[packages] +flask-sqlalchemy = "*" +flask-login = "*" +flask-dropzone = "*" +flask-mail = "*" +flask-moment = "*" +flask-wtf = "*" +python-dotenv = "*" +pillow = "*" +bootstrap-flask = "*" +flask = "*" +flask-whooshee = "*" +flask-avatars = "*" diff --git a/Pipfile.lock b/Pipfile.lock new file mode 100644 index 0000000..52f5349 --- /dev/null +++ b/Pipfile.lock @@ -0,0 +1,269 @@ +{ + "_meta": { + "hash": { + "sha256": "8f77fa130f0a03afa0d2967bb6b7811e356ad34aef7a0aa88199fc29de15e1b5" + }, + "pipfile-spec": 6, + "requires": {}, + "sources": [ + { + "name": "pypi", + "url": "https://pypi.python.org/simple", + "verify_ssl": true + } + ] + }, + "default": { + "blinker": { + "hashes": [ + "sha256:471aee25f3992bd325afa3772f1063dbdbbca947a041b8b89466dc00d606f8b6" + ], + "version": "==1.4" + }, + "bootstrap-flask": { + "hashes": [ + "sha256:d03c738f5377dbe7ecce010e28afcc0fb8373c4c9d01f8590af7657b53342c1d", + "sha256:ed817e82acadac4c8b3fc2d1a310325b6ed395d13b0f6ca9d14e1742f880e685" + ], + "index": "pypi", + "version": "==1.2.0" + }, + "click": { + "hashes": [ + "sha256:8a18b4ea89d8820c5d0c7da8a64b2c324b4dabb695804dbfea19b9be9d88c0cc", + "sha256:e345d143d80bf5ee7534056164e5e112ea5e22716bbb1ce727941f4c8b471b9a" + ], + "version": "==7.1.1" + }, + "flask": { + "hashes": [ + "sha256:4efa1ae2d7c9865af48986de8aeb8504bf32c7f3d6fdc9353d34b21f4b127060", + "sha256:8a4fdd8936eba2512e9c85df320a37e694c93945b33ef33c89946a340a238557" + ], + "index": "pypi", + "version": "==1.1.2" + }, + "flask-avatars": { + "hashes": [ + "sha256:c83081641ee834063416d9437be7d947cdebac51125c5f561d75e7e60f14b21b", + "sha256:e49e9a333b76fb131f4b66c1221b505ab9b3dd0e47a27d6a23e5d24dd2fcb7b2" + ], + "index": "pypi", + "version": "==0.2.2" + }, + "flask-dropzone": { + "hashes": [ + "sha256:e5e3d4740d407807aa99d7b6438aad812a1ce01e1b07b0f409462ff078386709", + "sha256:fddeb963aef31da81e7bc39cad740e8778a8c59d96ef76c7d5ed362fc626a73a" + ], + "index": "pypi", + "version": "==1.5.4" + }, + "flask-login": { + "hashes": [ + "sha256:6d33aef15b5bcead780acc339464aae8a6e28f13c90d8b1cf9de8b549d1c0b4b", + "sha256:7451b5001e17837ba58945aead261ba425fdf7b4f0448777e597ddab39f4fba0" + ], + "index": "pypi", + "version": "==0.5.0" + }, + "flask-mail": { + "hashes": [ + "sha256:22e5eb9a940bf407bcf30410ecc3708f3c56cc44b29c34e1726fe85006935f41" + ], + "index": "pypi", + "version": "==0.9.1" + }, + "flask-moment": { + "hashes": [ + "sha256:3c509afa25fd77459c9d799f292dcea384b1cd588ed1fd68f97f6fda6131299e", + "sha256:3e8b88f99af7cf75f2f29ef9d8c158eb92ca6f3c1ba6456ad70f715efa6eb7f7" + ], + "index": "pypi", + "version": "==0.9.0" + }, + "flask-sqlalchemy": { + "hashes": [ + "sha256:0078d8663330dc05a74bc72b3b6ddc441b9a744e2f56fe60af1a5bfc81334327", + "sha256:6974785d913666587949f7c2946f7001e4fa2cb2d19f4e69ead02e4b8f50b33d" + ], + "index": "pypi", + "version": "==2.4.1" + }, + "flask-whooshee": { + "hashes": [ + "sha256:9ee837503eaead2a81554f0e01c2647f0240f247b0b5b01b431c8cb67617ff31" + ], + "index": "pypi", + "version": "==0.7.0" + }, + "flask-wtf": { + "hashes": [ + "sha256:57b3faf6fe5d6168bda0c36b0df1d05770f8e205e18332d0376ddb954d17aef2", + "sha256:d417e3a0008b5ba583da1763e4db0f55a1269d9dd91dcc3eb3c026d3c5dbd720" + ], + "index": "pypi", + "version": "==0.14.3" + }, + "itsdangerous": { + "hashes": [ + "sha256:321b033d07f2a4136d3ec762eac9f16a10ccd60f53c0c91af90217ace7ba1f19", + "sha256:b12271b2047cb23eeb98c8b5622e2e5c5e9abd9784a153e9d8ef9cb4dd09d749" + ], + "version": "==1.1.0" + }, + "jinja2": { + "hashes": [ + "sha256:93187ffbc7808079673ef52771baa950426fd664d3aad1d0fa3e95644360e250", + "sha256:b0eaf100007721b5c16c1fc1eecb87409464edc10469ddc9a22a27a99123be49" + ], + "version": "==2.11.1" + }, + "markupsafe": { + "hashes": [ + "sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473", + "sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161", + "sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235", + "sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5", + "sha256:13d3144e1e340870b25e7b10b98d779608c02016d5184cfb9927a9f10c689f42", + "sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff", + "sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b", + "sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1", + "sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e", + "sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183", + "sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66", + "sha256:596510de112c685489095da617b5bcbbac7dd6384aeebeda4df6025d0256a81b", + "sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1", + "sha256:6788b695d50a51edb699cb55e35487e430fa21f1ed838122d722e0ff0ac5ba15", + "sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1", + "sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e", + "sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b", + "sha256:7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905", + "sha256:88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735", + "sha256:8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d", + "sha256:98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e", + "sha256:9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d", + "sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c", + "sha256:ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21", + "sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2", + "sha256:b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5", + "sha256:b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b", + "sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6", + "sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f", + "sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f", + "sha256:cdb132fc825c38e1aeec2c8aa9338310d29d337bebbd7baa06889d09a60a1fa2", + "sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7", + "sha256:e8313f01ba26fbbe36c7be1966a7b7424942f670f38e666995b88d012765b9be" + ], + "version": "==1.1.1" + }, + "pillow": { + "hashes": [ + "sha256:04a10558320eba9137d6a78ca6fc8f4a5801f1b971152938851dc4629d903579", + "sha256:0f89ddc77cf421b8cd34ae852309501458942bf370831b4a9b406156b599a14e", + "sha256:251e5618125ec12ac800265d7048f5857a8f8f1979db9ea3e11382e159d17f68", + "sha256:291bad7097b06d648222b769bbfcd61e40d0abdfe10df686d20ede36eb8162b6", + "sha256:2f0b52a08d175f10c8ea36685115681a484c55d24d0933f9fd911e4111c04144", + "sha256:3713386d1e9e79cea1c5e6aaac042841d7eef838cc577a3ca153c8bedf570287", + "sha256:433bbc2469a2351bea53666d97bb1eb30f0d56461735be02ea6b27654569f80f", + "sha256:4510c6b33277970b1af83c987277f9a08ec2b02cc20ac0f9234e4026136bb137", + "sha256:50a10b048f4dd81c092adad99fa5f7ba941edaf2f9590510109ac2a15e706695", + "sha256:670e58d3643971f4afd79191abd21623761c2ebe61db1c2cb4797d817c4ba1a7", + "sha256:6c1924ed7dbc6ad0636907693bbbdd3fdae1d73072963e71f5644b864bb10b4d", + "sha256:721c04d3c77c38086f1f95d1cd8df87f2f9a505a780acf8575912b3206479da1", + "sha256:8d5799243050c2833c2662b824dfb16aa98e408d2092805edea4300a408490e7", + "sha256:90cd441a1638ae176eab4d8b6b94ab4ec24b212ed4c3fbee2a6e74672481d4f8", + "sha256:a5dc9f28c0239ec2742d4273bd85b2aa84655be2564db7ad1eb8f64b1efcdc4c", + "sha256:b2f3e8cc52ecd259b94ca880fea0d15f4ebc6da2cd3db515389bb878d800270f", + "sha256:b7453750cf911785009423789d2e4e5393aae9cbb8b3f471dab854b85a26cb89", + "sha256:b99b2607b6cd58396f363b448cbe71d3c35e28f03e442ab00806463439629c2c", + "sha256:cd47793f7bc9285a88c2b5551d3f16a2ddd005789614a34c5f4a598c2a162383", + "sha256:d6bf085f6f9ec6a1724c187083b37b58a8048f86036d42d21802ed5d1fae4853", + "sha256:da737ab273f4d60ae552f82ad83f7cbd0e173ca30ca20b160f708c92742ee212", + "sha256:eb84e7e5b07ff3725ab05977ac56d5eeb0c510795aeb48e8b691491be3c5745b" + ], + "index": "pypi", + "version": "==7.1.1" + }, + "python-dotenv": { + "hashes": [ + "sha256:81822227f771e0cab235a2939f0f265954ac4763cafd806d845801c863bf372f", + "sha256:92b3123fb2d58a284f76cc92bfe4ee6c502c32ded73e8b051c4f6afc8b6751ed" + ], + "index": "pypi", + "version": "==0.12.0" + }, + "sqlalchemy": { + "hashes": [ + "sha256:c4cca4aed606297afbe90d4306b49ad3a4cd36feb3f87e4bfd655c57fd9ef445" + ], + "version": "==1.3.15" + }, + "werkzeug": { + "hashes": [ + "sha256:2de2a5db0baeae7b2d2664949077c2ac63fbd16d98da0ff71837f7d1dea3fd43", + "sha256:6c80b1e5ad3665290ea39320b91e1be1e0d5f60652b964a3070216de83d2e47c" + ], + "version": "==1.0.1" + }, + "whoosh": { + "hashes": [ + "sha256:7ca5633dbfa9e0e0fa400d3151a8a0c4bec53bd2ecedc0a67705b17565c31a83", + "sha256:aa39c3c3426e3fd107dcb4bde64ca1e276a65a889d9085a6e4b54ba82420a852", + "sha256:e0857375f63e9041e03fedd5b7541f97cf78917ac1b6b06c1fcc9b45375dda69" + ], + "version": "==2.7.4" + }, + "wtforms": { + "hashes": [ + "sha256:0cdbac3e7f6878086c334aa25dc5a33869a3954e9d1e015130d65a69309b3b61", + "sha256:e3ee092c827582c50877cdbd49e9ce6d2c5c1f6561f849b3b068c1b8029626f1" + ], + "version": "==2.2.1" + } + }, + "develop": { + "faker": { + "hashes": [ + "sha256:2d3f866ef25e1a5af80e7b0ceeacc3c92dec5d0fdbad3e2cb6adf6e60b22188f", + "sha256:b89aa33837498498e15c709eb40c31386408a901a53c7a5e12a425737a767976" + ], + "index": "pypi", + "version": "==4.0.2" + }, + "pathtools": { + "hashes": [ + "sha256:7c35c5421a39bb82e58018febd90e3b6e5db34c5443aaaf742b3f33d4655f1c0" + ], + "version": "==0.1.2" + }, + "python-dateutil": { + "hashes": [ + "sha256:73ebfe9dbf22e832286dafa60473e4cd239f8592f699aa5adaf10050e6e1823c", + "sha256:75bb3f31ea686f1197762692a9ee6a7550b59fc6ca3a1f4b5d7e32fb98e2da2a" + ], + "version": "==2.8.1" + }, + "six": { + "hashes": [ + "sha256:236bdbdce46e6e6a3d61a337c0f8b763ca1e8717c03b369e87a7ec7ce1319c0a", + "sha256:8f3cd2e254d8f793e7f3d6d9df77b92252b52637291d0f0da013c76ea2724b6c" + ], + "version": "==1.14.0" + }, + "text-unidecode": { + "hashes": [ + "sha256:1311f10e8b895935241623731c2ba64f4c455287888b18189350b67134a822e8", + "sha256:bad6603bb14d279193107714b288be206cac565dfa49aa5b105294dd5c4aab93" + ], + "version": "==1.3" + }, + "watchdog": { + "hashes": [ + "sha256:c560efb643faed5ef28784b2245cf8874f939569717a4a12826a173ac644456b" + ], + "index": "pypi", + "version": "==0.10.2" + } + } +} diff --git a/README.md b/README.md index 60142cd..95e08f1 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,609 @@ -# cloud_computing_1 - + 本次实验源代码来自:https://github.com/greyli/albumy + demo网站:http://59.110.70.81:5000 + (主机的带宽最好大一点,我的1M小水管打开网站测试极慢) + tomcat需要8080端口,nginx需要5000,80端口。 + 不必要的端口不要开,提前提示,谨慎reboot,update,upgrade,高并发优化不是必要的,谨慎使用。 + 系统:Centos 8 + + 先创建一个有root权限的用户(这里用Rivenatte) + 切换到Rivenatte: + su Rivenatte + 更新: + sudo yum update + sudo yum upgrade + 检查有没有gcc: + gcc -v + 没有就: + sudo yum install gcc + 有时需安装git: + sudo yum install git + + 拉取项目(这里用原项目的): + git clone https://github.com/greyli/albumy.git + cd albumy + 配置虚拟环境: + python -m venv env(or python3 -m venv env) + source env/bin/activate + pip install -r requirements.txt + python -m pip install --upgrade pip + 生成测试数据并测试: + flask forge + flask run --host 0.0.0.0 --port 5000 + 用浏览器打开http://云主机ip:5000 + 测试的用户账号: + username:admin@helloflask.com + password:helloflask + + 下面的pip可以换成pip3,如果你在创建虚拟环境时用python3的话 + 然而flask自带的wsgi容器性能较差,我采用另一个服务器,gunicorn。 + 先将我git上的python文件放在albumy中, + 同时还需在项目目录下: + mkdir log + cd log + touch debug.log + touch gunicorn.pid + cd .. + 这里的albumy指项目目录,不是albumy模块。 + + gunicorn需要在虚拟环境下安装: + (没进虚拟环境的先: + source env/bin/activate) + pip install gunicorn + 同时还需安装gevent: + pip install gevent + 推荐参考这个格式,指定源: + pip install 包名 -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.com + 可以解决大多问题。 + + 然后: + cd albumy + 修改__init__.py的create_app中的 + app = Flask('albumy') + 改为 + app = Flask(__name__) + 输入 + gunicorn -c albumy项目的绝对路径/gconfig.py run:app + 像上面一样,打开浏览器测试 + + 继续用nginx来做反向代理。 + 先安装nginx: + sudo yum install nginx + 接下来的配置,不同的linux发行版修改的文件可能不同,但大体类似。 + 实在不行就用whereis nginx找。 + centos就先: + cd /etc/nginx + ls -a + 发现conf.d这个文件夹,这个是放配置文件的 + 先对nginx.conf修改。 + 一般第二个https的设置是被注释的,不用管。 + 看http的设置,在http部分的最下面加入: + include conf.d/*.conf;(;不能少了) + 这样我们就可以通过在conf.d文件夹里修改文件来进行配置 + 配置文件必须是.conf格式 + 比如 albumy.conf + server { + listen 80; + root albumy项目的绝对路径; + server_name 公网ip; + location / { + proxy_set_header x-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header Host $http_host; + proxy_pass http://localhost:5000/; # gunicorn绑定的端口号 + } + # 配置static的静态文件: + location ~ ^\/static\/.*$ { + root 项目的绝对路径; + } + } + 添加后 + sudo nginx -c /etc/nginx/nginx.conf + sudo nginx -t + sudo nginx -s reload + 用浏览器打开80,5000端口,看下有没有成功。 + 80端口的仅仅是静态页面,比较简陋。 + + 接着我们需要用nohup守护进程: + 进入项目文件夹的虚拟环境: + cd xxx/albumy/ + source env/bin/activate + nohup gunicorn -c gconfig.py run:app & + 然后看下有没有成功: + ps -e | grep gunicorn + + nohub不能让主机重启后自动运行进程,我们需要设置开机启动: + sudo vim /etc/rc.local + 在最下面添加命令行,这样就可以在重启后自动执行命令行了。 + 最后别忘了加: + chmod +x /etc/rc.d/rc.local + + 然后可以重启检查下。 + + 接下来进行高并发优化 + 我们需要安装ab压测工具 + 这个在任何服务器上部署都可以,只要在最后把ip改下就行。 + 这里申请一台centos8主机,部署ab。 + 同样不使用root用户。 + 先提醒下,deb系的安装与以下有点区别。 + + 先更新: + sudo yum update + sudo yum upgrade + + 安装依赖: + sudo yum install apr-util + sudo yum install yum-utils + sudo mkdir -p /appdata/apache/ab && cd /appdata/apache/ab + + 安装ab: + sudo yum install yum-utils.noarch + sudo yumdownloader httpd-tools* + 下一步需要root用户: + su root + rpm2cpio httpd-tools*.rpm | cpio -idmv + su Rivenatte + sudo cp /appdata/apache/ab/usr/bin/ab /usr/bin + + 执行ab: + ab -n 1000 -c 200 http://ip:5000/ + 如果不与项目在同一主机,写公网ip + 在就localhost + 1000指共访问了1000次,200指同时200并发 + 进行了5次 + 出现apr_pollset_poll: The timeout specified has expired (70007) + 就改为ab -n 1000 -c 200 -k http://ip:5000/ + 看主机配置,量力而行。 + + 先测试下,与优化后比较。 + + 回到部署nginx的主机。 + 先获取cpu核心数: + grep processor /proc/cpuinfo | wc -l + 一般在申请时就知道了 + 修改配置文件中的http模块: + sudo vim /etc/nginx/nginx.conf + 具体参数参考以下文章: + https://www.jianshu.com/p/0fa77899913a + 单核2g的主机可以参考以下配置: + worker_rlimit_nofile 10000; + events { + worker_connections 10000; + } + keepalive_timeout 0;(高并发的网站需要设置的参数) + + su root + (不用root用户无法进行下列命令) + 对系统配置: + ulimit -n 一个较大的数字 + echo 50000 > /proc/sys/net/core/somaxconn + more /proc/sys/net/core/somaxconn + 有50000则正常 + 下列同理: + echo 1 > /proc/sys/net/ipv4/tcp_tw_recycle(注意,现在的centos取消了这个参数,没有可以不管) + cat /proc/sys/net/ipv4/tcp_tw_recycle + echo 1 > /proc/sys/net/ipv4/tcp_tw_reuse + cat /proc/sys/net/ipv4/tcp_tw_reuse + echo 0 > /proc/sys/net/ipv4/tcp_syncookies + cat /proc/sys/net/ipv4/tcp_syncookies + dmesg|tail + (可能需vim /etc/sysctl.conf + 设置: + net.ipv4.tcp_syncookies = 0) + 对测试主机也需: + echo 50000 > /proc/sys/net/core/somaxconn + ulimit -n 一个较大的数字 + (可能需设置net.ipv4.tcp_syncookies = 0,同上) + +  + +不重启主机,对测试主机配置后开始测试: + sudo vim /etc/sysctl.conf + 加入: + net.nf_conntrack_max = 655360 + net.netfilter.nf_conntrack_tcp_timeout_established = 1200) + + + ab -c 100000 -n 100000 -r http://主机ip:5000/ + + (可以适当改下,但还是要看主机配置,我这台是2gRam 1核) + + 之后可以将以上系统设置加入自启动项(服务器重启可能会回到修改前设置) + + 下面添加邮箱: + 先去注册个邮箱,并以stmp服务器发送。(这个需要网上查下如何开放邮箱stmp,不同邮箱的可能不同) + + 像之前一样,修改启动项: + source env/bin/activate + export MAIL_SERVER='smtp.163.com' //示例 + export MAIL_USERNAME='XXXXXX@163.com' //填邮箱XXXXXX + export MAIL_PASSWORD='XXXXXX' //密码,注意是邮箱开启第三方smtp的认证码 + 别忘了chmod +x /etc/rc.d/rc.local + 最后reboot。 + (注:这里需要邮箱发送验证邮件,才可以输入验证码注册) +## 采用docker部署与k8s集群负载均衡 + +### 一、docker部署上传镜像 + +配置docker容器并push到远端,重新在别的服务器上部署时只需将镜像pull下来即可。 +写好Dockerfile,在本地build好镜像后,将容器push到远端。 + +在服务器上部署时只需将远端的容器pull到服务器上,再run即可 + +```python +我们首先要将上面的run.py中的 +app.run()改为app.run(host='0.0.0.0',port=3389) +``` + +部署时先下载docker + +```bash +curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun +``` + +若报错则先执行 + +```bash +yum install -y https://download.docker.com/linux/centos/7/x86_64/stable/Packages/containerd.io-1.2.6-3.3.el7.x86_64.rpm +``` + +接着启动docker服务 + +```bash +service docker start +``` + +写入我们的Dockerfile + +```bash +vim Dockerfile +``` + +``` +FROM python:3.6 +RUN apt-get update +RUN apt install -y nginx + +WORKDIR /Project/demo + +COPY requirements.txt ./ +RUN pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple + +COPY . . + +RUN rm /etc/nginx/sites-enabled/default +COPY nginx_flask.conf /etc/nginx/sites-available/ +RUN ln -s /etc/nginx/sites-available/nginx_flask.conf /etc/nginx/sites-enabled/nginx_flask.conf +RUN echo "daemon off;" >> /etc/nginx/nginx.conf +CMD ["nginx","-c","/etc/nginx/nginx.conf"] +CMD ["nginx","-t"] +CMD ["nginx","-s","reload"] +CMD ["gunicorn", "run:app", "-c", "./gconfig.py"] +``` + +其中需要我们之前部署时写的gconfig.py文件和我们的nginx配置文件 + +除此以外我们需要在根目录创建一个新文件**nginx_flask.conf** + +``` +server { + listen 80; + + location / { + proxy_pass http://localhost:5000/; + proxy_set_header Host $host; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + } + + location ^~ /static/ { + root /Project/demo; + } +} + +``` + +之后在本地建立镜像 + +```bash +docker build -t image1 . +``` + +建立成功后可以尝试启动docker容器 + +``` +docker run -d -p 3389:3389 --name test1 image1 +``` + +打开http://云主机ip:3389查看是否显示界面 + +之后将我们的镜像push到远端 + +没有注册docker账号的话先注册一个docker账号 + +https://registry.hub.docker.com/ + +接着登录docker账号 + +``` +docker login +输入账号 +输入密码 +``` + +显示login successful就成功了,之后push到远端 + +首先对镜像打标签 + +```bash +docker tag image1 lh123/albumy_nginx_mysql_image:v2 +``` + +之后将镜像推送到仓库 + +```bash +docker push lh123/albumy_nginx_mysql_image:v2 +``` + +以后需要创建应用时只需要从docker中拉取镜像运行即可。 + + + +新建云主机,安装docker之后将上述镜像pull到本地,之后执行 + +``` +docker run -d -p 3389:3389 --name test1 lh123/albumy_nginx_mysql_image:v2 +``` + +打开http:云主机ip:3389即可访问网页。 + + + +### 二、采用负载均衡 + +之后在ucloud中使用负载均衡ULB,创建负载均衡ULB。 + +接着在建立三台云主机,使用原来申请的有外网的云主机,分别通过内网连接三台新建的云主机。 + +在云主机上pull下来刚才上传的docker镜像 + +```bash +docker pull lh123/albumy_nginx_mysql_image:v2 +``` + +在云主机上启动镜像 + +```bash +docker run -d -p 3389:3389 --name test1 albumy_nginx_mysql_image:v2 +``` + +将我们启动好的三台云主机啊加到我们的负载均衡当中 + + + +使用负载均衡之后的压测效果更好 + + + +### 三、连接云数据库 + +为了保证负载均衡的服务器的数据一致性,我们将数据库挂在到云数据库mysql上 + +我们将项目的.flask.env文件中的设置改为 + +```bash +FLASK_APP=albumy +FLASK_ENV=development +``` + +再将setting.py中的设置改为 + +```bash +class ProductionConfig(BaseConfig): + SQLALCHEMY_DATABASE_URI = 'mysql://root:lianghui123@10.23.56.255:3306/flask_test' +``` + +再打包到docker并运行我们的项目 + +发现报错No module named MYSQLdb发现是因为 + +```bash +按照 Flask-SQLAlchemy 文档的说明,配置好 SQLALCHEMY_DATABASE_URI = 'mysql://username:password@server/db' 后操作 MySQL 报错 ImportError: No module named 'MySQLdb'。既然缺少 MySQLdb 这个模块,按照常规方法缺啥补啥吧,执行 pip install MySQL-python 却报错 ImportError: No module named 'ConfigParser'。查了一下,这是由于 MySQL-python 不支持 Python 3(MySQL-3.23 through 5.5 and Python-2.4 through 2.7 are currently supported)。 + +``` + +将MySQLdb换为pymsql,安装pymsql(记得先启动虚拟环境) + +```absh +pip install pymsql +``` + +并在__init__.py中加入 + +```python +import pymysql +pymysql.install_as_MySQLdb() +``` + +再将setting.py中的设置改为 + +```bash +class ProductionConfig(BaseConfig): + SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://root:lianghui123@10.23.56.255:3306/flask_test' +``` + +即可访问我们的云主机数据库。 + +最后将完成的项目打包好镜像push到远端仓库。 + + + +### 四、k8s集群部署(有点问题) + +建立好docker容器之后就可以使用k8s集群部署网页,采用k8s部署可以实现容器集群的自动化部署、自动扩缩容、维护等功能。 + +首先在ucloud中创建一个UK8S,之后申请一个云主机, + +登录云主机安装docker拉取镜像 + +``` +docker pull lh123/albumy_nginx_mysql_image:v2 +``` + +安装k8s + +```bash + +wget https://storage.googleapis.com/kubernetes-release/release/v1.19.0/bin/linux/amd64/kubectl +chmod +x kubectl +sudo mv kubectl /usr/local/bin/ (root用户:mv kubectl /usr/bin/) +kubectl version -o json +``` + +将K8S的集群凭证添加到kubectl配置文件中,从而能够操控集群。 + +打开K8S的外网集凭证复制,在云主机中创建~/.kube文件夹,并在其中创建config文件,将外网集凭证复制到config文件中。 + +为了能在k8s上部署我们的docker镜像,我们还需要在项目文件中添加两个文件**Deployment.yaml** 和 **service.yaml**, + +**deployment.yaml**中: + +```bash +apiVersion: extensions/v1beta1 + kind: Deployment + metadata: + name: albumy-node-deployment + spec: + replicas: 1 + selector: + matchLabels: + app: albumynode + template: + metadata: + labels: + app: albumynode + spec: + containers: + - name: albumynode + image: lh123/albumy_nginx_mysql_image:v2 + imagePullPolicy: Always + ports: + - containerPort: 3389 +``` + +**service.yaml**中: + +``` +apiVersion: v1 + kind: Service + metadata: + name: albumy-node-deployment + spec: + ports: + - port: 3389 + targetPort: 3389 + selector: + app: albumynode +``` + + + +之后运行一下命令部署项目 + +```bash +kubectl create -f deployment.yaml + +kubectl create -f service.yaml +``` + +查看pod是否处于ready状态,若pod不处于ready状态且一直是containercreating状态则 + + + +查看创建日志,发现是容器创建失败,谷歌不能访问,uhub-edu.service.ucloud.cn/google_containers/pause-amd64:3.0"镜像无法获取,这应该是ucloud端的问题。(我们采用平时实验作业第八次的部署方法部署实验2里的静态网页也还是报这个错误,真的是很无语)。 + +(即使用 + +```bash +kubectl create deployment webapp --image=lh123/albumy_nginx_mysql_image:v2 +``` + +我们发现这样子pod的状态还是一直处于containercreating的状态,而且也是报下图的错误,我觉得者应该是ucloud端的问题,被墙了。我怀疑是ucloud的教育云出问题了之前第八次实验的时候还可以用,现在就不可以用了。 + +) + + + +解决方法如下,从docker.io把pause-amd64镜像取下来,然后做个标签。这样就可以解决问题。 + +``` +docker pull googlecontainer/pause-amd64:3.0 +docker tag googlecontainer/pause-amd64:3.0 uhub-edu.service.ucloud.cn/google_containers/pause-amd64:3.0 +``` + +之后新建连接,登录云主机执行 + +```bash +echo -e "\n\e[92mStarting Proxy. After starting it will not output a response. Please click the first Terminal Tab\n"; kubectl proxy +``` + +之后访问我们的应用 + +``` +kubectl get pods#获取我们pod的名称 +export POD_NAME=$刚才得到的pod名称 +curl http://localhost:8001/api/v1/namespaces/default/pods/$POD_NAME/proxy/ +``` + +查看我们创建的POD的详细信息 + +``` +kubectl get pods -o wide +``` + +之后将副本scale到10个 + +```bash +kubectl scale deployments/albumy-node-deployment --replicas=10 +``` + +将我们的网页暴露给公网,并加上负载均衡 + +创建一个负载均衡 + +```bash +kubectl expose deployment albumy-node-deployment --type=LoadBalancer --port=80 +``` + +查看service,可以看到负载均衡服务的外网ip地址 + +```bash +kubectl get services +``` + +之后访问http:localhost:负载均衡ip就可以看到网页 + + + + + +本次作业镜像: + +账号:1491337293@qq.com + +密码:18830095812zxc + +docker账户 + +账号:lh123 + +密码:18830095812zxc + +docker镜像:lh123/albumy_nginx_mysql_image:v2 + + + +ucloud上docker部署镜像名:docker_nginx_mysql + + + +集群部署有点问题被墙了。 + diff --git a/albumy-master.iml b/albumy-master.iml new file mode 100644 index 0000000..91e2f1b --- /dev/null +++ b/albumy-master.iml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> +<module type="PYTHON_MODULE" version="4"> + <component name="NewModuleRootManager"> + <content url="file://$MODULE_DIR$" /> + <orderEntry type="inheritedJdk" /> + <orderEntry type="sourceFolder" forTests="false" /> + </component> + <component name="TemplatesService"> + <option name="TEMPLATE_CONFIGURATION" value="Jinja2" /> + <option name="TEMPLATE_FOLDERS"> + <list> + <option value="$MODULE_DIR$/albumy/templates" /> + </list> + </option> + </component> +</module> \ No newline at end of file diff --git a/config b/config new file mode 100644 index 0000000..12878cc --- /dev/null +++ b/config @@ -0,0 +1,21 @@ +[core] + repositoryformatversion = 0 + filemode = false + bare = false + logallrefupdates = true + symlinks = false + ignorecase = true +[remote "origin"] + url = git@106.75.225.141:guoteng/albumy.git + fetch = +refs/heads/*:refs/remotes/origin/* +[branch "master"] + remote = origin + merge = refs/heads/master + rebase = true +[branch "develop"] + remote = origin + merge = refs/heads/develop + rebase = true +[gui] + wmstate = normal + geometry = 1061x563+160+160 233 255 diff --git a/description b/description new file mode 100644 index 0000000..498b267 --- /dev/null +++ b/description @@ -0,0 +1 @@ +Unnamed repository; edit this file 'description' to name the repository. diff --git a/gconfig.py b/gconfig.py new file mode 100644 index 0000000..8a5845c --- /dev/null +++ b/gconfig.py @@ -0,0 +1,11 @@ +from gevent import monkey +monkey.patch_all() +import multiprocessing +debug = True +loglevel = 'debug' +bind = '0.0.0.0:3389' +pidfile = 'log/gunicorn.pid' +logfile = 'log/debug.log' +workers = multiprocessing.cpu_count() * 2 + 1 +worker_class = 'gevent' + diff --git a/index b/index new file mode 100644 index 0000000..5438156 Binary files /dev/null and b/index differ diff --git a/main.py b/main.py new file mode 100644 index 0000000..bf8b9e5 --- /dev/null +++ b/main.py @@ -0,0 +1,16 @@ +# This is a sample Python script. + +# Press Shift+F10 to execute it or replace it with your code. +# Press Double Shift to search everywhere for classes, files, tool windows, actions, and settings. + + +def print_hi(name): + # Use a breakpoint in the code line below to debug your script. + print(f'Hi, {name}') # Press Ctrl+F8 to toggle the breakpoint. + + +# Press the green button in the gutter to run the script. +if __name__ == '__main__': + print_hi('PyCharm') + +# See PyCharm help at https://www.jetbrains.com/help/pycharm/ diff --git a/nginx_flask.conf b/nginx_flask.conf new file mode 100644 index 0000000..95bfe6d --- /dev/null +++ b/nginx_flask.conf @@ -0,0 +1,15 @@ +server { + listen 80; + + location / { + proxy_set_header x-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header Host $http_host; + proxy_pass http://localhost:3389/; # gunicorn绑定的端口号 + } + # 配置static的静态文件: + location ~ ^\/static\/.*$ { + root /Project/demo; + } +} + diff --git a/nohup.out b/nohup.out new file mode 100644 index 0000000..4f0a4f1 --- /dev/null +++ b/nohup.out @@ -0,0 +1,198 @@ +[2021-01-14 08:37:45 +0800] [14269] [DEBUG] Current configuration: + config: gconfig.py + bind: ['0.0.0.0:3389'] + backlog: 2048 + workers: 5 + worker_class: gevent + threads: 1 + worker_connections: 1000 + max_requests: 0 + max_requests_jitter: 0 + timeout: 30 + graceful_timeout: 30 + keepalive: 2 + limit_request_line: 4094 + limit_request_fields: 100 + limit_request_field_size: 8190 + reload: False + reload_engine: auto + reload_extra_files: [] + spew: False + check_config: False + preload_app: False + sendfile: None + reuse_port: False + chdir: /root/albumy + daemon: False + raw_env: [] + pidfile: log/gunicorn.pid + worker_tmp_dir: None + user: 0 + group: 0 + umask: 0 + initgroups: False + tmp_upload_dir: None + secure_scheme_headers: {'X-FORWARDED-PROTOCOL': 'ssl', 'X-FORWARDED-PROTO': 'https', 'X-FORWARDED-SSL': 'on'} + forwarded_allow_ips: ['127.0.0.1'] + accesslog: None + disable_redirect_access_to_syslog: False + access_log_format: %(h)s %(l)s %(u)s %(t)s "%(r)s" %(s)s %(b)s "%(f)s" "%(a)s" + errorlog: - + loglevel: debug + capture_output: False + logger_class: gunicorn.glogging.Logger + logconfig: None + logconfig_dict: {} + syslog_addr: udp://localhost:514 + syslog: False + syslog_prefix: None + syslog_facility: user + enable_stdio_inheritance: False + statsd_host: None + dogstatsd_tags: + statsd_prefix: + proc_name: None + default_proc_name: run:app + pythonpath: None + paste: None + on_starting: <function OnStarting.on_starting at 0x7f4348074a60> + on_reload: <function OnReload.on_reload at 0x7f4348074b70> + when_ready: <function WhenReady.when_ready at 0x7f4348074c80> + pre_fork: <function Prefork.pre_fork at 0x7f4348074d90> + post_fork: <function Postfork.post_fork at 0x7f4348074ea0> + post_worker_init: <function PostWorkerInit.post_worker_init at 0x7f4348094048> + worker_int: <function WorkerInt.worker_int at 0x7f4348094158> + worker_abort: <function WorkerAbort.worker_abort at 0x7f4348094268> + pre_exec: <function PreExec.pre_exec at 0x7f4348094378> + pre_request: <function PreRequest.pre_request at 0x7f4348094488> + post_request: <function PostRequest.post_request at 0x7f4348094510> + child_exit: <function ChildExit.child_exit at 0x7f4348094620> + worker_exit: <function WorkerExit.worker_exit at 0x7f4348094730> + nworkers_changed: <function NumWorkersChanged.nworkers_changed at 0x7f4348094840> + on_exit: <function OnExit.on_exit at 0x7f4348094950> + proxy_protocol: False + proxy_allow_ips: ['127.0.0.1'] + keyfile: None + certfile: None + ssl_version: 2 + cert_reqs: 0 + ca_certs: None + suppress_ragged_eofs: True + do_handshake_on_connect: False + ciphers: None + raw_paste_global_conf: [] + strip_header_spaces: False +[2021-01-14 08:37:45 +0800] [14269] [INFO] Starting gunicorn 20.0.4 +[2021-01-14 08:37:45 +0800] [14269] [DEBUG] Arbiter booted +[2021-01-14 08:37:45 +0800] [14269] [INFO] Listening at: http://0.0.0.0:3389 (14269) +[2021-01-14 08:37:45 +0800] [14269] [INFO] Using worker: gevent +[2021-01-14 08:37:45 +0800] [14272] [INFO] Booting worker with pid: 14272 +[2021-01-14 08:37:45 +0800] [14273] [INFO] Booting worker with pid: 14273 +[2021-01-14 08:37:45 +0800] [14274] [INFO] Booting worker with pid: 14274 +[2021-01-14 08:37:45 +0800] [14276] [INFO] Booting worker with pid: 14276 +[2021-01-14 08:37:45 +0800] [14269] [DEBUG] 5 workers +[2021-01-14 08:37:45 +0800] [14277] [INFO] Booting worker with pid: 14277 +[2021-01-14 09:06:33 +0800] [17476] [INFO] Booting worker with pid: 17476 +[2021-01-14 09:06:33 +0800] [17481] [INFO] Booting worker with pid: 17481 +[2021-01-14 09:06:33 +0800] [14269] [DEBUG] 2 workers +[2021-01-14 09:06:33 +0800] [14269] [INFO] Handling signal: hup +[2021-01-14 09:06:33 +0800] [14269] [INFO] Hang up: Master +[2021-01-14 09:06:33 +0800] [14269] [DEBUG] Current configuration: + config: gconfig.py + bind: ['0.0.0.0:3389'] + backlog: 2048 + workers: 5 + worker_class: gevent + threads: 1 + worker_connections: 1000 + max_requests: 0 + max_requests_jitter: 0 + timeout: 30 + graceful_timeout: 30 + keepalive: 2 + limit_request_line: 4094 + limit_request_fields: 100 + limit_request_field_size: 8190 + reload: False + reload_engine: auto + reload_extra_files: [] + spew: False + check_config: False + preload_app: False + sendfile: None + reuse_port: False + chdir: /root/albumy + daemon: False + raw_env: [] + pidfile: log/gunicorn.pid + worker_tmp_dir: None + user: 0 + group: 0 + umask: 0 + initgroups: False + tmp_upload_dir: None + secure_scheme_headers: {'X-FORWARDED-PROTOCOL': 'ssl', 'X-FORWARDED-PROTO': 'https', 'X-FORWARDED-SSL': 'on'} + forwarded_allow_ips: ['127.0.0.1'] + accesslog: None + disable_redirect_access_to_syslog: False + access_log_format: %(h)s %(l)s %(u)s %(t)s "%(r)s" %(s)s %(b)s "%(f)s" "%(a)s" + errorlog: - + loglevel: debug + capture_output: False + logger_class: gunicorn.glogging.Logger + logconfig: None + logconfig_dict: {} + syslog_addr: udp://localhost:514 + syslog: False + syslog_prefix: None + syslog_facility: user + enable_stdio_inheritance: False + statsd_host: None + dogstatsd_tags: + statsd_prefix: + proc_name: None + default_proc_name: run:app + pythonpath: None + paste: None + on_starting: <function OnStarting.on_starting at 0x7f4348074a60> + on_reload: <function OnReload.on_reload at 0x7f4348074b70> + when_ready: <function WhenReady.when_ready at 0x7f4348074c80> + pre_fork: <function Prefork.pre_fork at 0x7f4348074d90> + post_fork: <function Postfork.post_fork at 0x7f4348074ea0> + post_worker_init: <function PostWorkerInit.post_worker_init at 0x7f4348094048> + worker_int: <function WorkerInt.worker_int at 0x7f4348094158> + worker_abort: <function WorkerAbort.worker_abort at 0x7f4348094268> + pre_exec: <function PreExec.pre_exec at 0x7f4348094378> + pre_request: <function PreRequest.pre_request at 0x7f4348094488> + post_request: <function PostRequest.post_request at 0x7f4348094510> + child_exit: <function ChildExit.child_exit at 0x7f4348094620> + worker_exit: <function WorkerExit.worker_exit at 0x7f4348094730> + nworkers_changed: <function NumWorkersChanged.nworkers_changed at 0x7f4348094840> + on_exit: <function OnExit.on_exit at 0x7f4348094950> + proxy_protocol: False + proxy_allow_ips: ['127.0.0.1'] + keyfile: None + certfile: None + ssl_version: 2 + cert_reqs: 0 + ca_certs: None + suppress_ragged_eofs: True + do_handshake_on_connect: False + ciphers: None + raw_paste_global_conf: [] + strip_header_spaces: False +[2021-01-14 09:06:33 +0800] [17510] [INFO] Booting worker with pid: 17510 +[2021-01-14 09:06:33 +0800] [17512] [INFO] Booting worker with pid: 17512 +[2021-01-14 09:06:33 +0800] [17509] [INFO] Booting worker with pid: 17509 +[2021-01-14 09:06:33 +0800] [17511] [INFO] Booting worker with pid: 17511 +[2021-01-14 09:06:33 +0800] [17518] [INFO] Booting worker with pid: 17518 +[2021-01-14 09:06:33 +0800] [14269] [DEBUG] 5 workers +[2021-01-14 09:06:33 +0800] [14269] [INFO] Handling signal: term +[2021-01-14 09:06:35 +0800] [17476] [INFO] Worker exiting (pid: 17476) +[2021-01-14 09:06:35 +0800] [17481] [INFO] Worker exiting (pid: 17481) +[2021-01-14 09:06:35 +0800] [17511] [INFO] Worker exiting (pid: 17511) +[2021-01-14 09:06:35 +0800] [17518] [INFO] Worker exiting (pid: 17518) +[2021-01-14 09:06:35 +0800] [17510] [INFO] Worker exiting (pid: 17510) +[2021-01-14 09:06:35 +0800] [17512] [INFO] Worker exiting (pid: 17512) +[2021-01-14 09:06:35 +0800] [17509] [INFO] Worker exiting (pid: 17509) +[2021-01-14 09:06:35 +0800] [14269] [INFO] Shutting down: Master diff --git a/packed-refs b/packed-refs new file mode 100644 index 0000000..b44eac8 --- /dev/null +++ b/packed-refs @@ -0,0 +1,4 @@ +# pack-refs with: peeled fully-peeled sorted +326f368eeaac6faa708e788440893c1d39acf864 refs/remotes/origin/develop +42295b43602cb2dd7896c365a821f6d6afba4672 refs/remotes/origin/feature +549e8bab6eb6120bd84ff14324503868ec124b4e refs/remotes/origin/master diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..e5bd62d --- /dev/null +++ b/requirements.txt @@ -0,0 +1,31 @@ +blinker==1.4 +bootstrap-flask==1.2.0 +click==7.1.1 +flask-avatars==0.2.2 +flask-dropzone==1.5.4 +flask-login==0.5.0 +flask-mail==0.9.1 +flask-moment==0.9.0 +flask-sqlalchemy==2.4.1 +flask-whooshee==0.7.0 +flask-wtf==0.14.3 +flask==1.1.2 +itsdangerous==1.1.0 +jinja2==2.11.1 +markupsafe==1.1.1 +pillow==7.1.1 +python-dotenv==0.12.0 +sqlalchemy==1.3.15 +werkzeug==1.0.1 +whoosh==2.7.4 +wtforms==2.2.1 +# dev +faker==4.0.2 +pathtools==0.1.2 +python-dateutil==2.8.1 +six==1.14.0 +text-unidecode==1.3 +watchdog==0.10.2 +gunicorn +gevent==1.4 +pymysql diff --git a/run.py b/run.py new file mode 100644 index 0000000..db9c03f --- /dev/null +++ b/run.py @@ -0,0 +1,7 @@ +from albumy.__init__ import create_app +from flask import Flask + +app = create_app() + +if __name__ == "__main__": + app.run() \ No newline at end of file