關於部署流程,主要包含如下兩個方面:部署方案、部署環境:css
1. 分析項目的產品需求文檔,定好部署方案的方向 2. 分析項目開發文檔,按照功能邊界,設計部署的結點 3. 分析項目功能軟件,合理的取捨,選符合當前業務場景的 4. 梳理項目部署涉及到的部署軟件實現方案,根據上面第2點肯定的結點,肯定第一版部署方案 5. 根據項目實際狀況,調整優化並肯定項目部署方案
工做人員:本身
工做平臺:我的筆記本、公司配的電腦
平臺特色:環境是本身配的,團隊中不一樣的我的開發環境能夠不同
工做內容:項目的子模塊,子功能
完成標準:完成領導安排的內容[項目的功能子模塊開發]
工做人員:開發團隊
工做平臺:公司內部服務器
平臺特色:服務器環境和線上的服務器環境徹底一致
工做內容:項目子模塊間的功能聯調
完成標準:項目階段開發、調試完成
工做人員:測試團隊 工做平臺:公司內部服務器 平臺特色:服務器環境和線上的服務器環境徹底一致 工做內容:項目功能/非功能/探索等測試 完成標準:項目階段功能正常運行
工做人員:運維團隊
工做平臺:公司線上服務器組中的一臺
平臺特色:服務器環境和線上的服務器環境徹底一致
工做內容:特殊功能測試(好比支付)、數據壓力測試、其餘安全測試等
完成標準:項目階段功能正常運行,最後一道防線
工做人員:運維團隊
工做平臺:公司線上服務器組
平臺特色:標準線上的服務器環境
工做內容:代碼部署和維護、記錄內部架構文檔
完成標準:項目正常運行
服務器數量: 1000QPS 每秒請求數html
服務器類型:物理服務器,雲服務器前端
併發瓶頸:vue
1. 帶寬:200M/10K 2. 處理併發的能力 3. 數據庫查詢能力:mysql 1000次/S
可使用apache ab工具進行壓測python
將先後端項目上傳碼雲mysql
自動化程序會將打包的文件自動生成到項目的dist文件夾中。linux
npm run build
nginx
由於根據咱們上面的部署方案,咱們須要安裝nginx來運行這個項目。git
sudo apt-get install nginx
upstream luffy { # 反向代理池 server 106.52.122.145:8000; }
# nginx 反向代理uwsgi server { listen 80; server_name 106.52.122.145 api.additwujiahua.com; # location / {
# 經過uwsgi_pass 設置服務器地址和協議,將動態請求轉發給uwsgi處理 include uwsgi_params; uwsgi_pass luffy; } location ~ .*\.(css|js)$ { root /home/luffy/; } } server { listen 80; server_name additwujiahua.com www.additwujiahua.com; location / { #root /opt/luffyweb/dist/; root /home/luffy-cli/dist; index index.html; try_files $uri $uri /index.html;
# nginx 處理靜態葉頁面資源
# 當用戶請求的是additwujiahua.com/static這個頁面時,會進入這個location匹配
# alias 參數進行路徑別名 讓nginx去/opt/staic底下去找靜態資源
# location / static {
# alias /opt/static;
# }
} }
重啓nginxgithub
service nginx restart
nignx -s reload
啓動nginx服務器
service nginx start
中止nginx服務器
service nginx stop
將mysql和redis部署到 docker容易裏面
更新ubuntu的apt源索引
sudo apt-get update
安裝包容許apt經過HTTPS使用倉庫
sudo dpkg --configure -a sudo apt-get install apt-transport-https ca-certificates curl software-properties-common
添加Docker官方GPG key
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
設置Docker穩定版倉庫
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
添加倉庫後,更新apt源索引
sudo apt-get update
安裝最新版Docker CE(社區版)
sudo apt-get install docker-ce
檢查Docker CE是否安裝正確
sudo docker run hello-world
安裝完成Docker後,默認已經啓動了docker服務,如需手動控制docker服務的啓停,可執行以下命令
# 啓動docker sudo service docker start # 中止docker sudo service docker stop # 重啓docker sudo service docker restart # 列出鏡像 docker image ls # 拉取鏡像 docker image pull library/hello-world # 刪除鏡像 docker image rm 鏡像id/鏡像ID # 建立容器 docker run [選項參數] 鏡像名 [命令] # 中止一個已經在運行的容器 docker container stop 容器名或容器id # 啓動一個已經中止的容器 docker container start 容器名或容器id # kill掉一個已經在運行的容器 docker container kill 容器名或容器id # 刪除容器 docker container rm 容器名或容器id
# 在docker中下載nginx鏡像 docker image pull nginx # 使用git把碼雲上面的編譯過的vue項目克隆到服務器/home # 阿里雲服務器中,咱們從碼雲克隆下來的前端項目: /home/luffyproject_pc/dist git clone 項目git地址 # 建立nginx容器,並以80端口對外提供服務 docker run -itd -p 80:80 -v /home/luffyproject_pc/dist:/usr/share/nginx/html nginx # 啓動nginx容器中的nginx【容器ID經過docker container ls --all能夠查看到】 docker container exec -itd [容器ID] nginx """ /etc/nginx # nginx容器中nginx的配置目錄 /usr/share/nginx/html # nginx容器中www目錄 """
3.4.1
在項目中複製開發配置文件dev.py 到生產配置prod.py
修改配置中的地址相關便可。藍色部分爲修改部分
import os # Build paths inside the project like this: os.path.join(BASE_DIR, ...) BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) import sys sys.path.insert(0, os.path.join(BASE_DIR, "apps")) # Quick-start development settings - unsuitable for production # See https://docs.djangoproject.com/en/2.2/howto/deployment/checklist/ # SECURITY WARNING: keep the secret key used in production secret! SECRET_KEY = '!!t0^(#x0l@!pp6@^!0u5lyq+4ctyui)sxmsc4*r7644@(4uh@' # SECURITY WARNING: don't run with debug turned on in production! DEBUG = False ALLOWED_HOSTS = [ # "api.luffycity.cn", # "additwujiahua.com", 'api.additwujiahua.com', ] # CORS組的配置信息 CORS_ORIGIN_WHITELIST = ( 'www.additwujiahua.com' 'additwujiahua.com:80' ) CORS_ALLOW_CREDENTIALS = True # 容許ajax跨域請求時攜帶cookie # Application definition INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', # 跨域 'corsheaders', # drf 'rest_framework', # xadmin 'xadmin', 'crispy_forms', 'reversion', # 富文本編輯器 'ckeditor', # 富文本編輯器 'ckeditor_uploader', # 富文本編輯器上傳圖片模塊 # 子應用 'home', "users", "courses", "cart", 'orders', "coupon", "payments" ] MIDDLEWARE = [ 'corsheaders.middleware.CorsMiddleware', 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', ] ROOT_URLCONF = 'luffy.urls' TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [], 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], }, }, ] WSGI_APPLICATION = 'luffy.wsgi.application' # Database # https://docs.djangoproject.com/en/2.2/ref/settings/#databases DATABASES = { "default": { "ENGINE": "django.db.backends.mysql", "HOST": "127.0.0.1", "PORT": 3306, "USER": "luffy_user", "PASSWORD": "luffy", "NAME": "luffycity", } } # Password validation # https://docs.djangoproject.com/en/2.2/ref/settings/#auth-password-validators AUTH_PASSWORD_VALIDATORS = [ { 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', }, { 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', }, { 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', }, { 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', }, ] # Internationalization # https://docs.djangoproject.com/en/2.2/topics/i18n/ LANGUAGE_CODE = 'zh-hans' TIME_ZONE = 'Asia/Shanghai' USE_I18N = True USE_L10N = True USE_TZ = False # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/2.2/howto/static-files/ # 訪問靜態文件的url地址前綴 STATIC_URL = '/static/' # 設置django的靜態文件目錄 STATICFILES_DIRS = [ os.path.join(BASE_DIR, "luffy/statics") ] # 項目中存儲上傳文件的根目錄[暫時配置],注意,static目錄須要手動建立不然上傳文件時報錯 MEDIA_ROOT = os.path.join(BASE_DIR, "luffy/statics") # 訪問上傳文件的url地址前綴 MEDIA_URL = "/media/" # 緩存配置 CACHES = { "default": { "BACKEND": "django_redis.cache.RedisCache", # 項目上線時,須要調整這裏的路徑 "LOCATION": "redis://127.0.0.1:6379/0", "OPTIONS": { "CLIENT_CLASS": "django_redis.client.DefaultClient", } }, "session": { "BACKEND": "django_redis.cache.RedisCache", # 項目上線時,須要調整這裏的路徑 "LOCATION": "redis://127.0.0.1:6379/1", "OPTIONS": { "CLIENT_CLASS": "django_redis.client.DefaultClient", } }, # 提供存儲短信驗證碼 "sms_code": { "BACKEND": "django_redis.cache.RedisCache", "LOCATION": "redis://127.0.0.1:6379/2", "OPTIONS": { "CLIENT_CLASS": "django_redis.client.DefaultClient", } }, # 儲存購物車信息 "cart": { "BACKEND": "django_redis.cache.RedisCache", "LOCATION": "redis://127.0.0.1:6379/3", "OPTIONS": { "CLIENT_CLASS": "django_redis.client.DefaultClient", } }, } # 設置xadmin用戶登陸時,登陸信息session保存到redis SESSION_ENGINE = "django.contrib.sessions.backends.cache" SESSION_CACHE_ALIAS = "session" # 日誌配置 LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'formatters': { 'verbose': { 'format': '%(levelname)s %(asctime)s %(module)s %(lineno)d %(message)s' }, 'simple': { 'format': '%(levelname)s %(module)s %(lineno)d %(message)s' }, }, 'filters': { 'require_debug_true': { '()': 'django.utils.log.RequireDebugTrue', }, }, 'handlers': { 'console': { 'level': 'DEBUG', 'filters': ['require_debug_true'], 'class': 'logging.StreamHandler', 'formatter': 'simple' }, 'file': { 'level': 'DEBUG', 'class': 'logging.handlers.RotatingFileHandler', # 日誌位置,日誌文件名,日誌保存目錄必須手動建立 'filename': os.path.join(os.path.dirname(BASE_DIR), "logs/luffy.log"), # 日誌文件的最大值,這裏咱們設置300M 'maxBytes': 300 * 1024 * 1024, # 日誌文件的數量,設置最大日誌數量爲10 'backupCount': 10, # 日誌格式:詳細格式 'formatter': 'verbose' }, }, # 日誌對象 'loggers': { 'django': { 'handlers': ['console', 'file'], 'propagate': True, # 是否讓日誌信息繼續冒泡給其餘的日誌處理系統 }, } } REST_FRAMEWORK = { # 異常處理 'EXCEPTION_HANDLER': 'luffy,utils.exceptions.custom_exception_handler', # 登陸認證 'DEFAULT_AUTHENTICATION_CLASSES': ( 'rest_framework_jwt.authentication.JSONWebTokenAuthentication', 'rest_framework.authentication.SessionAuthentication', 'rest_framework.authentication.BasicAuthentication', ), } # 保存時間1天 import datetime JWT_AUTH = { 'JWT_EXPIRATION_DELTA': datetime.timedelta(days=1), # 設置jwt登陸視圖的返回值 'JWT_RESPONSE_PAYLOAD_HANDLER': 'users.utils.jwt_response_payload_handler', } # 告訴django咱們使用本身的用戶認證組件 AUTH_USER_MODEL = 'users.User' # 配置django的認證類功能,增長手機號登陸 AUTHENTICATION_BACKENDS = [ 'users.utils.UsernameMobileAuthBackend', ] PC_GEETEST_ID = '81c4fd5a59bfd9da92796db7a45cce3e' PC_GEETEST_KEY = '1e4a137ed379d88ef171c0ac8d7b927f' # 短信配置 # 主帳號 SMS_ACCOUNTSID = "8aaf07086ab0c082016ab3eda41a00bd" # 主帳號Token SMS_ACCOUNTTOKEN = "29c414dd7446457d8f4a0678c6a2de86" # 建立應用的APPID SMS_APPID = "8aaf07086ab0c082016ab3eda47100c3" # 說明:請求地址,生產環境配置成app.cloopen.com SMS_SERVERIP = "sandboxapp.cloopen.com" # 富文本編輯器ckeditor配置 CKEDITOR_CONFIGS = { 'default': { 'toolbar': 'full', # 工具條功能 'height': 300, # 編輯器高度 # 'width': 300, # 編輯器寬 }, } CKEDITOR_UPLOAD_PATH = '' # 上傳圖片保存路徑,留空則調用django的文件上傳功能 # 保利威視頻加密服務 POLYV_CONFIG = { "userId": "00573fd073", "secretkey": "m2Xc6C6Fb0", "servicesUrl": "https://hls.videocc.net/service/v1/token", } # 支付寶 ALIPAY_APPID = "2016093000628031" # 應用ID APP_NOTIFY_URL = None # 應用回調地址[支付成功之後,支付寶返回結果到哪個地址下面] ALIPAY_DEBUG = True # APIPAY_GATEWAY="https://openapi.alipay.com/gateway.do" APIPAY_GATEWAY = "https://openapi.alipaydev.com/gateway.do" ALIPAY_RETURN_URL = "http://www.additwujiahua.com/success" # 支付寶會根據API中商戶傳入的notify_url,經過POST請求的形式將支付結果做爲參數通知到商戶系統 ALIPAY_NOTIFY_URL = "http://api.additwujiahua.com:8000/payments/success"
咱們先收集全部靜態文件。項目中的靜態文件除了咱們使用的上傳文件以外,django自己還有本身的靜態文件,如rest_framework、xadmin、admin、ckeditor等。咱們須要收集這些靜態文件,集中一塊兒放到靜態文件服務器中。
咱們要將收集的靜態文件放到項目的static目錄中,因此先建立目錄static。
Django提供了收集靜態文件的方法。先在配置文件中配置收集以後存放的目錄
settings/prop.py,代碼:
STATIC_ROOT = os.path.join(os.path.dirname(BASE_DIR), 'static')
而後執行收集命令
python manage.py collectstatic
將 static文件 上傳到碼雲
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'luffy.settings.prop')
咱們能夠在本地環境中先安裝uwsgi模塊進行使用,而後成功了再上傳到服務器中。
pip install uwsgi uwsgi --version # 查看 uwsgi 版本
在項目根目錄下建立uwsgi配置文件uwsgi.ini
[uwsgi] #使用nginx鏈接時使用,Django程序所在服務器地址 ;socket=127.0.0.1:8000 #直接作web服務器使用,Django程序所在服務器地址 http=127.0.0.1:8000 #項目目錄 chdir=/home/moluo/Desktop/luffy #項目中wsgi.py文件的目錄,相對於項目目錄 wsgi-file=luffy/wsgi.py # 進程數 processes=2 # 線程數 threads=2 # uwsgi服務器的角色 master=True # 存放進程編號的文件 pidfile=uwsgi.pid # 日誌文件,由於uwsgi能夠脫離終端在後臺運行,日誌看不見。咱們之前的runserver是依賴終端的 daemonize=uwsgi.log # 指定依賴的虛擬環境 virtualenv=/home/moluo/.virtualenvs/luffy
啓動uwsgi服務器,必須在uwsgi配置文件中運行下面的命令
注意,在本地環境中必須先把runserver關閉
uwsgi --ini uwsgi.ini
中止uwsgi服務器,還能夠經過使用kill命令中止
uwsgi --stop uwsgi.pid
uwsgi -9 進程號
pip freeze > requirements.txt
cd /home/luffyproject
git pull
# 安裝python3的pip工具 apt install python3-pip # 使用pip安裝虛擬環境 pip3 install virtualenv pip3 install virtualenvwrapper # 配置虛擬環境的環境變量 # 執行命令 mkdir $HOME/.virtualenvs # 執行命令,打開並編輯 ~/.bashrc vim ~/.bashrc # 文件末尾添加如下幾行代碼,:wq 保存退出。 export WORKON_HOME=$HOME/.virtualenvs export VIRTUALENVWRAPPER_PYTHON=/usr/bin/python3 source /usr/local/bin/virtualenvwrapper.sh # 刷新配置文件 source ~/.bashrc # 建立虛擬環境 mkvirtualenv luffyproject -p python3 # 在虛擬環境中同步以前的我的開發環境中安裝包列表 requirements.txt cd /home/luffy/docs pip install -r requirements.txt -i https://pypi.douban.com/simple # 項目中 pip install https://codeload.github.com/sshwsfc/xadmin/zip/django2 # 安裝完成這些手動安裝的包之後,咱們再次執行上面的命令 pip install -r requirements.txt -i https://pypi.douban.com/simple # 通過上面的步驟,咱們直接切到uwsgi.ini所在目錄下,運行項目 uwsgi --ini uwsgi.ini # 咱們會發現上面命令運行不起來,緣由是咱們的本地模塊包是重新安裝的,以前有修改過,因此須要調整。同時由於咱們以前已經在項目中使用到了redis和mysql # 所以咱們須要在docker中下載redis和mysql的容器 docker pull redis docker pull mysql # 建立redis容器並運行redis docker container run -itd -p6379:6379 redis # 建立mysql容器並啓動mysql docker container run -itd -p3306:3306 -e MYSQL_ROOT_PASSWORD=luffy mysql:5.7 # 接下來遠程在本地環境中導出當前項目的數據庫,並導入到服務器中的數據庫中 # 1. 本地導出數據 cd ~/Desktop/luffy/docs/ mysqldump -uroot -p123 luffycity>./luffycity.sql # 本地數據庫帳號 # 2. 在服務器中建立數據和數據庫用戶 mysql -uroot -pluffy -h47.112.204.45 # 本地登錄線上的mysql數據庫 > create database luffycity charset=utf8mb4; > create user luffy_user identified by 'luffy'; > grant all privileges on luffycity.* to 'luffy_user'@'%'; > flush privileges; > exit # 3. 退出服務器數據庫終端,使用如下命令導入數據庫 cd ~/Desktop/luffy/docs/ mysql -uroot -pluffy -h47.112.204.45 luffycity < ./luffycity.sql # 4. 繼續使用manage.py運行django項目,修改數據庫的decode錯誤之後,就正常運行。
第一個錯誤:註釋掉對應的錯誤
第二個錯誤:加上decode() # 5. 使用uwsgi來運行django項目 uwsgi --ini uwsgi.ini # 新的配置信息 uwsgi.ini [uwsgi] #使用nginx鏈接時使用,Django程序所在服務器地址 socket=0.0.0.0:8000 #直接作web服務器使用,Django程序所在服務器地址 #http=127.0.0.1:8000 #http=0.0.0.0:8000 #項目目錄 chdir=/home/luffy #項目中wsgi.py文件的目錄,相對於項目目錄 wsgi-file=luffy/wsgi.py # 進程數 processes=1 # 線程數 threads=1 # uwsgi服務器的角色 master=True # 存放進程編號的文件 pidfile=uwsgi.pid # 日誌文件,由於uwsgi能夠脫離終端在後臺運行,日誌看不見。咱們之前的runserver是依賴終端的 daemonize=uwsgi.log # 指定依賴的虛擬環境 virtualenv=/root/.virtualenvs/luffyproject
配置好重啓uwsgi便可