@ -0,0 +1 @@ | |||||
README CHANGE |
@ -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"] |
@ -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 |
@ -0,0 +1 @@ | |||||
ref: refs/heads/develop |
@ -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. |
@ -0,0 +1 @@ | |||||
c4729ee28f6cff91fd35196a61d75723434b9c5a |
@ -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 = "*" |
@ -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" | |||||
} | |||||
} | |||||
} |
@ -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 | |||||
 | |||||
集群部署有点问题被墙了。 | |||||
@ -0,0 +1,16 @@ | |||||
<?xml version="1.0" encoding="UTF-8"?> | |||||
<module type="PYTHON_MODULE" version="4"> | |||||
<component name="NewModuleRootManager"> | |||||
<content url="file:// |
|||||
<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=" |
|||||
</list> | |||||
</option> | |||||
</component> | |||||
</module> |
@ -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 |
@ -0,0 +1 @@ | |||||
Unnamed repository; edit this file 'description' to name the repository. |
@ -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' | |||||
@ -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/ |
@ -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; | |||||
} | |||||
} | |||||
@ -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 |
@ -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 |
@ -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 |
@ -0,0 +1,7 @@ | |||||
from albumy.__init__ import create_app | |||||
from flask import Flask | |||||
app = create_app() | |||||
if __name__ == "__main__": | |||||
app.run() |