chaoz的杂货铺

生命有息、学无止境、折腾不止

0%

python-Django框架-微信小助手实践

小程序基础

全局入口 —— app.js
全局配置 —— app.json
全局样式 —— app.wxss

全局配置(页面导航)

pages 列表配置

页面

window 属性配置

导航条背景/文字/等颜色

tabbar 配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
 "tabBar": {
"list": [
{
"pagePath": "pages/index/index",
"text": "首页"
},
{
"pagePath": "pages/logs/logs",
"text": "日志"
},
{
"pagePath": "pages/demogrid/demogrid",
"text": "九宫格"
}
]
}

小程序的页面设置

json

开启下拉刷新

1
2
3
{
"enablePullDownRefresh": true
}

小程序的注册逻辑层

app.js

小程序的注册逻辑

App函数
注册全局唯一的小程序
只能调用一次
接收一个对象作为函数参数

页面注册逻辑

Page函数
注册一个页面
接受一个对象作为函数参数

页面数据

data属性

使用全局数据
获取全局唯一的 App 实例
通过唯一实例获取全局数据

页面生命周期

页面生命周期

页面生命周期

小程序的视图层

数据绑定

1
2
3
语法 {{}}
<view>{{ message }}</view>
message: "Hello World, Hello Django",

列表渲染

语法:wx:for

1
2
3
4
5
6
7
8
9
10
11
<view wx:for="{{array}}">
No.{{index}} item, message: {{item.message}}
</view>
array: [
{
message: "Hello World",
},
{
message: "Hello Django",
}
]

条件渲染

语法:wx:if wx:else wx:elif

绑定事件

绑定事件的写法以key、value的形式
key以bind或者catch开头,然后跟上事件的类型

1
2
3
4
5
<view bindtap='tapName'>TapTap</view>

tapName: function(event){
console.log(' in tabName function')
},

小程序框架

小程序提供的能力和常用的API

微信API

网络请求
HTTP请求


Http请求异步特性:
不管是什么情况,先返回过程后返回结果。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<button bindtap='testNetwork'>Test Network</button>
testNetwork: function(event){
var data = 'undefined'
wx.request({
url: 'http://www.imooc.com',
method: 'GET',
header: {},
success: function(res){
console.log('in success')
data = res.data
},
fail: function(res){
console.log('request failed.')
}
})
console.log('data: ', data)
},
文件上传、下载

*Task(网络任务对象)

中断任务
触发回调函数
关闭连接

本地存储

将数据存储在本地缓存中指定的key中,数据存储生命周期跟小程序本身一致。
◆wx.setStorage
◆wx.getStorage
◆wx.removeStorage
◆wx.clearStorage(前三个操作指定的缓存,最后一个删除所有缓存)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
  <button bindtap='testStorage'>Test Storage</button>
testStorage: function(){
wx.setStorage({
key: 'test',
data: 'data',
})
wx.getStorage({//异步
key: 'test',
success: function(res) {
var data = res.data
console.log('data from storage 1: ', data)
},
})
var data = wx.getStorageSync('test')//同步

console.log('data from storage 2: ', data)

},

文件系统

提供一个全局的问价管理系统,来实现对文件的增删改查

var fs=wx. getFileSystemManager()

◆fs.saveFile
◆fs.removeSavedFile
◆fs.writeFile
◆fs.appendFile
◆fs.readFile

文件夹操作

◆fs.mkdir
◆fs.rmdir
◆fs.isDirectory
◆fs.isFile

开放能力

◆用户数据
◆推送消息
◆运营数据

用户数据

◆头像、昵称等公开信息—wx.getUserlnfo)
◆openid等敏感数据

基础组件

开源

Django视图层

Django Response对象
◆状态码——Response对象的status属性
◆应答内容——Response对象的content属性
◆延伸的Response子类——(JsonResponse、FileResponse)

会话管理

有状态服务

什么是状态

无状态服务:就是没有特殊状态的服务,各个请求对于服务器来说统一无差别处理,请求自身携带了所有服务端所需要的所有参数(服务端自身不存储跟请求相关的任何数据,不包括数据库存储信息)

有状态服务:与之相反,有状态服务在服务端保留之前请求的信息,用以处理当前请求,比如session等

小程序状态:小程序与后台通信需要通过微信后台来进行转发。

小程序的状态管理

在 utils 包中添加 Cookie.js 工具包,然后在里面有三个函数,取出、存储、取出。

const key = ‘cookie’

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function getSessionIDFromResponse(res){
var cookie = res.header['Set-Cookie']
console.log('get cookie from response: ' + cookie)
return cookie
}

function setCookieToStorage(cookie) {
try{
wx.setStorageSync(key, cookie)
}catch(e){
console.log(e)
}
}

function getCookieFromStorage() {
var value = wx.getStorageSync(key)
return value
}

Django 的 Session 中间件

启用 Session 中间件:setting中的 MIDDLEWARE。

使用 Session 的方法:

1
2
3
4
5
6
7
8
9
10
def test_session(request):
request.session['message'] = 'Test Django Session OK!'
response = wrap_json_response(code=ReturnCode.SUCCESS)
return JsonResponse(data=response, safe=False)


def test_session2(request):
print('session content: ', request.session.items())
response = wrap_json_response(code=ReturnCode.SUCCESS)
return JsonResponse(data=response, safe=False)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
onReadCookies: function (){
wx.request({
url: app.globalData.serverUrl + app.globalData.apiVersion + '/auth/test',
success: function(res){
var cookie = cookieUtil.getSessionIDFromResponse(res)
console.log(cookie)
cookieUtil.setCookieToStorage(cookie)

var newCookie = cookieUtil.getCookieFromStorage()

var header = {}
header.Cookie = newCookie

wx.request({
url: app.globalData.serverUrl + app.globalData.apiVersion + '/auth/test2',
header: header,
success: function(res){

}
})
}
})
},

小程序中的状态管理

小程序登录功能

使用哪种用户体系呢

自建用户体系:
邮箱、电话等标记用户;填写、去重等复杂的交互逻辑。

沿用微信用户体系:
openid——微信用户的唯一识别标志。

用户模型与用户视图:
用户的唯一标识;
用户的基本信息。
获取用户的 OpenID

1
2
3
4
5
class User(models.Model):
# openid
open_id = models.CharField(max_length=32, unique=True)
# 昵称
nickname = models.CharField(max_length=256)
1
2
3
4
5
class UserView(View,CommonResponseMixin):
def get(self, request):
pass
def post(self, request):
pass
1
2
3
4
# 路径:
path('user', views.UserView.as_view())

# 为什么是 as.view()

步骤

调用微信的 wx.login 获取临时的 code,不需要任何的参数,直接定义成功的回调函数,然后就是赋值,定义请求函数,包含请求链接、请求方式、请求内容,以及确定 GET POST 请求方式是否需要请求头,可以定义一个回调函数番薯输出登录成功。
定义cookies:获取、存储、获取

问题:
code 是啥?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
authorize: function () {
wx.login({
success: function(res){
var code = res.code
var appId = app.globalData.appId
var nickname = app.globalData.userInfo.nickName
wx.request({
url: app.globalData.serverUrl + app.globalData.apiVersion + '/auth/authorize',
method: 'POST',
data: { //数据内容
code: code,
appId: appId,
nickname: nickname
},
header: { //请求头
'content-type': 'application/json'
},
success: function(res){ //回调函数
wx.showToast({
title: '授权成功'
})
var cookie = cookieUtil.getSessionIDFromResponse(res)
cookieUtil.setCookieToStorage(cookie)
console.log(cookie)
}
})
}
})
},

出现的错误:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
ModuleNotFoundError: No module named 'Crypto'
解决方法:

pip install pycryptodome
当然有可能会出现这种情况:看到报错后是这么安装的:pip install crypto

但是运行还是报错:ModuleNotFoundError: No module named 'Crypto';
此时需要去环境中将安装的包crypto的名字改成Crypto,首字母大写;
然后再次运行,出现这个错误:ModuleNotFoundError: No module named 'Crypto.Cipher'
此时进入到安装的文件夹下,发现没有此文件:
需要卸载刚才安装的包:pip uninstall crypto
然后重新安装:pip install pycryptodome,即可!

"errcode":40029:
解决方法:

微信开发者工具里开发项目需要填写appID,后台请求openid也需要appID,
确认appID是否一致,确认appsecret是否一致,临时登录凭证code ,appID和appsecret必须相互对应。

errcode":40125:
解决方法:

1.代码中设置的微信APPsecret和微信开放平台不一致,需要您自己对照微信开放平台和代码中的appsecret, 检查修正。
2.由于秘钥无效导致的,秘钥如果长时间不登录,会自动重置。

完善用户的个人信息

用户模型的变更

修改个人信息的功能开发

复杂多变的用户状态管理

有状态的应用服务

Index 首页的实现

深入 Django 模型层

跨DB迁移——模型层使用至数据库迁移

迁移的必要性

sqlite3在项目开发初期便利

sqlite3是文件数据库,性能跟不上

mysql是工业界非常常用的数据库

迁移的过程

数据备份

python manage.py dumpdate authorization > authorization_data.json

表结构同步配置

创建Mysql数据库并更新配置

创建slave数据库

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
},
'slave': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'backend',
'USER': 'root',
'PASSWORD': '',
'HOST': '127.0.0.1',
'PORT': '3306'
}
}

# 可以同时支持多个数据库,但是仅仅只有default默认数据库挂掉以后启动第二个
'''
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'backend',
'USER': 'root',
'PASSWORD': '',
'HOST': '127.0.0.1',
'PORT': '3306'
}
}

表结构的同步

1
python manager.py migrate --run-syncdb --database slave
数据迁移

python manager.py loaddata authorization_data.json

数据库索引——模型层使用之索引

索引的概述

索引是对数据库表中一列或多列的值进行排序的一种结构,使用索引可快速访问数据库表中的特定信息。如果想按特定职员的姓来查找他或她,则与在表中搜索所有的行相比,索引有助于更快地获取信息。
索引的一个主要目的就是加快检索表中数据,亦即能协助信息搜索者尽快的找到符合限制条件的记录ID的辅助数据结构。

优点:
加快检索数据的速度
降低插入、删除、更新的速度

应该被索引的字段

需要排序操作的字段(order_by)

需要比较操作的字段(> <>)

需要过滤操作的字段(fluter)

添加索引的两种方法

属性中定义

nickname = models.CharField(max_length=256,db_index=True)

模型的Meta添加索引
1
2
3
4
5
class Meta: 
indexes = [
models.Index(fields=['nickname']),
models.Index(fields=['open_id', 'nickname'])
]
1
2
3
4
5
6
7
8
9
10
11
12
13
组合索引是什么?组合索引建立的原则。b树和b+树的区别。

一次查询只能用到一个索引,所以 首先枪毙 a,b各建索引方案

a还是b? 谁的区分度更高(同值的最少),建谁!

当然,联合索引也是个不错的方案,ab,还是ba,则同上,区分度高者,在前

索引用于快速找出在某个列中有一特定值的行。不使用索引,MySQL必须从第1条记录开始然后读完整个表直到找出相关的行,还需要考虑每次读入数据页的IO开销。而如果采取索引,则可以根据索引指向的页以及记录在页中的位置,迅速地读取目标页进而获取目标记录。

大多数情况下都(默认)采用B树来构建索引。只是空间列类型的索引使用R-树,并且MEMORY表还支持hash索引。B树是平衡多叉树,每个节点存放多少个值取决于值所占的空间,这与每一张数据页存放多少条记录与记录信息量有关同理。节点中的值是以非降序进行排列的,节点中的值总是小于等于指向它的结点中的值。

MySQL使用B树构造索引的情况下,是由叶子指向具体的页和记录的。并且一个叶子有一个指针指向下一个叶子。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
Django模型类的Meta是一个内部类,它用于定义一些Django模型类的行为特性。而可用的选项大致包含以下几类

abstract
这个属性是定义当前的模型是不是一个抽象类。所谓抽象类是不会对应数据库表的。一般我们用它来归纳一些公共属性字段,然后继承它的子类可以继承这些字段。

Options.abstract
如果abstract = True 这个model就是一个抽象类

app_label
这个选型只在一种情况下使用,就是你的模型不在默认的应用程序包下的models.py文件中,这时候需要指定你这个模型是哪个应用程序的。

Options.app_label
如果一个model定义在默认的models.py,例如如果你的app的models在myapp.models子模块下,你必须定义app_label让Django知道它属于哪一个app
app_label = 'myapp'

db_table
db_table是指定自定义数据库表明的。Django有一套默认的按照一定规则生成数据模型对应的数据库表明。
Options.db_table
定义该model在数据库中的表名称
  db_table = 'Students'
如果你想使用自定义的表名,可以通过以下该属性
  table_name = 'my_owner_table'

db_teblespace
Options.db_teblespace
定义这个model所使用的数据库表空间。如果在项目的settin中定义那么它会使用这个值

get_latest_by
Options.get_latest_by
在model中指定一个DateField或者DateTimeField。这个设置让你在使用model的Manager上的lastest方法时,默认使用指定字段来排序

managed
Options.managed
默认值为True,这意味着Django可以使用syncdb和reset命令来创建或移除对应的数据库。默认值为True,如果你不希望这么做,可以把manage的值设置为False

order_with_respect_to
这个选项一般用于多对多的关系中,它指向一个关联对象,就是说关联对象找到这个对象后它是经过排序的。指定这个属性后你会得到一个get_xxx_order()和set_xxx_order()的方法,通过它们你可以设置或者回去排序的对象

ordering
这个字段是告诉Django模型对象返回的记录结果集是按照哪个字段排序的。这是一个字符串的元组或列表,没有一个字符串都是一个字段和用一个可选的表明降序的'-'构成。当字段名前面没有'-'时,将默认使用升序排列。使用'?'将会随机排列

ordering=['order_date'] # 按订单升序排列
ordering=['-order_date'] # 按订单降序排列,-表示降序
ordering=['?order_date'] # 随机排序,?表示随机
ordering=['-pub_date','author'] # 以pub_date为降序,在以author升序排列
permissions
permissions主要是为了在Django Admin管理模块下使用的,如果你设置了这个属性可以让指定的方法权限描述更清晰可读。Django自动为每个设置了admin的对象创建添加,删除和修改的权限。
permissions = (('can_deliver_pizzas','Can deliver pizzas'))

proxy
这是为了实现代理模型使用的,如果proxy = True,表示model是其父的代理 model

unique_together
unique_together这个选项用于:当你需要通过两个字段保持唯一性时使用。比如假设你希望,一个Person的FirstName和LastName两者的组合必须是唯一的,那么需要这样设置:
unique_together = (("first_name", "last_name"),)
一个ManyToManyField不能包含在unique_together中。如果你需要验证关联到ManyToManyField字段的唯一验证,尝试使用signal(信号)或者明确指定through属性。

verbose_name
verbose_name的意思很简单,就是给你的模型类起一个更可读的名字一般定义为中文,我们:
verbose_name = "学校"

verbose_name_plural
这个选项是指定,模型的复数形式是什么,比如:
verbose_name_plural = "学校"
如果不指定Django会自动在模型名称后加一个’s’

关系映射实战

有没有用到关系映射实战
用到哪种关系映射
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
from django.db import models

class Wife(models.Model):
pass

class Husband(models.Model):
wife = models.OneToOneField(Wife,on_delete=models.CASCADE)
pass

class Mother(models.Model):
pass

class Father(models.Model):
Wife = models.OneToOneField(Mother, on_delete=models.DO_NOTHING)
pass

class YoungerBrother(models.Model):
pass

class ElderBrother(models.Model):
father_id = models.ForeignKey(Father,on_delete=models.DO_NOTHING)
younger_brother = models.ManyToManyField(YoungerBrother)
pass

增删改查——模型层使用之数据库操作

模型层关系映射——模型层使用之关系映射

三种关系映射

一对一的关系:OneToOneField

一对多的关系:ForeignKey

多对多的关系:ManyToManyfield

Django MTV 中的M: Model

Django ORM 框架

ORM
优点:屏蔽数据库差异;提供迁移工具;简化开发流程.

Django 后台

Django 日志模块

产生日志->渲染日志->匹配过滤->持久化

Request 信息
Setting 配置
Trabook 信息

日志模块配置

格式器 formattar

格式器

eg
eg

配置日志格式(位置、时间)

沿用python 语言里卖弄的格式属性

过滤器 filter

日志有用打印,无用抛弃。

处理器 handler

对日志进行处理,比如:写进文件、打印屏幕等
常用处理器(文件处理器、终端处理器)

日志实例 logger

在python代码里面打印日志的入口点
日志级别(DEBUG、INFO、WARNING、ERROR、CRITICAL)

Django admin 模块

为什么Django提供admin模块

管理界面是基础设施非常重要的一部分
添加、编辑和删除网站内容
功能类似但开发繁琐

认证用户->权限验证->页面展示->数据管理

admin模块是什么

Django的自动管理界面
管理Django用户权限、模型数据、信息发布
拓展性强,基于此定制很多功能

admin模块怎么使用

创建超级管理员用户
python manage.py createsuperuser

确认添加admin模块和路由说明
创建超级管理员
注册模型到admin模块

内容列表字段:重写str函数
不显示不可编辑字段:fields列表或exclude列表
重写save model函数实现保存逻辑

Django 缓存模块

缓存概述

缓存是(高速)缓存的简称,英语:Cache
根本目的是为了加快数据访问速度,提高性能
协调两者数据传输速度的差异

缓存的置换策略
LFU、FIFO、LRU等算法
settings.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
CACHES = {
'default': {
# 1. MemCache
# 'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
# 'LOCATION': '127.0.0.1:11211',

# 2. DB Cache
# 'BACKEND': 'django.core.cache.backends.db.DatabaseCache',
# 'LOCATION': 'my_cache_table',

# 3. Filesystem Cache
# 'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
# 'LOCATION': '/var/tmp/django_cache',

# 4. Local Mem Cache
'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
'LOCATION': 'backend-cache'
}
}

伪代码

1
2
3
4
5
6
if data is in the cache:
return data
else:
generate the data
save the data in the cache(set timeout)
return the generated data

Django缓存模块

Django 后台服务部署

Django crontab 定时服务

Linux下的crontab命令

用于提交和管理用户的周期性任务
crond进程每分钟定时检查
时间间隔

1
2
3
4
5
eg:
minutes hours day month week command
*/5 * * * * echo 'Hi' >/dev/nul:每隔五分钟执行一次
0 12 * * * do something:每天12点整执行一次
0 12 * * 1-5 do something:周一到周五每天12点整执行一次

django-crontab插件的使用

pip 安装

seetings.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',

# 新应用
'apis.apps.ApisConfig',
'authorization.apps.AuthorizationConfig',

# 第三方应用
'django_crontab'
]

CRONJOBS = [
('*/1 * * * *', 'cron.jobs.demo')
]

1
2
3
4
python manage.py crontab add
python manage.py crontab show/remove/run
crontab -l
tail -f service.log

说明:配置->crontab add(提交)-> Django crontab插件 -定时任务-> Linux crond服务 -负责执行->

Django 中间件

什么是Django中间件

Django中间件是一个类
请求前后在合适的时机执行相应方法
配置MIDDLEWARE CLASSES属性

SecurityMiddleware:安全中间件
GzipMiddleware:Gzip压缩中间件
SessionMiddleware:状态服务Session中间件
CsrfViewMiddleware:防止跨站伪造请求的中间件
AuthorizationMiddleware:Django自带的认证体系中间件
MessageMiddleware:消息中间件

Django 中间件的执行逻辑

每个请求都会两次经过配置的中间件
多个中间件之间存在执行顺序

中间件执行逻辑

1
2
3
4
5
6
7
8
9
10
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
# 'django.middleware.csrf.CsrfViewMiddleware',
'ops.middlewaredemo.TestMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

实现自定义中间件

在每个请求前后打印log

1
2
3
4
5
6
7
8
9
10
11
import logging
logger = logging.getLogger('django')
class TestMiddleware:
def __init__(self, get_response):
self.get_response = get_response
logger.info("Build TestMiddleware")
def __call__(self, request):
logger.info("TestMiddleware before request.")
response = self.get_response(request)
logger.info("TestMiddleware after request.")
return response

邮件模块

QQ邮箱SMTP服务与授权码

简单邮件传输协议(Simple Mail Transfer Protocol)
SMTP服务使用TCP端口25
使用QQ邮箱SMTP服务需要授权码

配置并使用标准库发送邮件

seetings.py

1
2
3
4
5
6
7
8
9
10
11
12
13
# Email config
# QQ邮箱 SMTP 服务器地址
EMAIL_HOST = 'smtp.qq.com'
# 端口
EMAIL_PORT = 465
# 发送邮件的邮箱
EMAIL_HOST_USER = '******@qq.com'
# 在邮箱中设置的客户端授权密码
EMAIL_HOST_PASSWORD = 'anzthepddgaldafi'
# 开启TLS
EMAIL_USE_TLS = True
# 收件人看到的发件人
EMAIL_FROM = '******@qq.com'

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
def send_mail():
msg = MIMEText("邮件通道测试", "plain", "utf-8")
msg['FROM'] = "Mail Test"
msg['Subject'] = "【Mail Test】"
receivers = ['************@qq.com']
server = smtplib.SMTP_SSL(settings.EMAIL_HOST, settings.EMAIL_PORT)
server.set_debuglevel(1)
server.login(settings.EMAIL_HOST_USER, settings.EMAIL_HOST_PASSWORD)
server.sendmail(settings.EMAIL_FROM, receivers, msg.as_string())
server.close()
```

### 基于邮件通知的服务监控和告警系统

配置专用日志格式器记录耗时
编写请求耗时统计功能的中间件
配置定时任务统计指标并通过邮件发送

![邮件告警](http://tuchuang.xchcloud.cn/%E9%82%AE%E4%BB%B6%E5%91%8A%E8%AD%A6.png)

## 运维提升专题之部署篇

![高可用](http://tuchuang.xchcloud.cn/%E9%AB%98%E5%8F%AF%E7%94%A8.png)

### Django依赖服务的高可用

#### 依赖服务高可用的问题

#### 解决依赖服务单点故障的方法

### Nginx必知必会

#### Nginx概述

网站服务器、反向代理器、负载均衡器

#### Nginx 安装与基本命令

默认配置目录:/etc/nginx

sudo nginx -s stop
sudo nginx -s quit
sudo nginx -s reload(重新加载配置文件)
sudo nginx -s reopen(重新打开日志文件)


#### Nginx 关键配置模块

events 配置域:网络连接相关配置(I/O模型等)
server 配置域:相关服务节点配置
location 配置域:资源路由配置

http 配置域:Nginx作为网页服务器时的配置(#mail)
upstream 配置域:反向代理配置域

异步事件处理模型VS多线程客户机处理模型
模块化设计、丰富模块库
俄罗斯开发者开发的服务器
异步事件处理模型:更高并发
模块化设计、丰富的模块库

### uWSGl必知必会

全称:Web Server Gateway Interface
Web Server 和Web Application 通信的规范

![WSGI](http://tuchuang.xchcloud.cn/WSGI.png)

实现了WSGl协议
Web服务器
接收客户端请求通过协议传达给Django应用

pip install uwsgi

chdir:WSGI应用目录
module:WSGI应用的模块名字
processes:uWSGl 进程数
(http-)socket:套接字路径、地址
max-requests:最大并发请求数
vacuum:清理环境配置(Boolean)

启动方法:

uwsgi --chdir xxxx --socket:80 --max-requests 5000 --processes 4 --module xxx.wsgi

配置文件启动

停止:

uwsgi --stop pid/uwsgi-8000.pid

### Django uWSGI部署

Django runserver 可以直接对外服务,但只是用于测试
uWSGI可以很好的进行多线程调度、进程监控
uWSGl 提供完善的请求日志处理

uwsgi --http :8000 --module django_deployment.wsgi

uwsgi --ini django-uwsgi.ini

django-uwsgi.ini:

[uwsgi]

chdir = /home/ubuntu/jarvis/deployment/django_deployment
module = django_deployment.wsgi
http-socket = :8000
master = True
processes = 4
threads = 1
vacuum = true

backend run uwsgi

daemonize = %(chdir)/log/uwsgi-8000.log
log-maxsize = 1024000000
pidfile = %(chdir)/pid/uwsgi-8000.pid

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

### Django Nginx+uWSGl部署

知名服务器,Nginx提供更加安全的服务保障
提供反向代理、负载均衡等丰富功能
对于静态文件的处理能力更强

uWSGl 启动Django应用服务
修改Nginx配置文件,完成反向代理配置
收集静态文件,完成静态文件寻址配置

Nginx:软连接
ln -s sites-available/nginx-uwsgi.conf nginx.conf

ll nginx.conf

静态文件处理:

python manage.py collectstatic

nginx.conf location 指定地址

### Django HTTPS部署

HTTPS协议使用443端口
HTTPS协议加密报文传输内容
HTTPS协议耗费CPU计算资源和时间

部署方案:

![](http://tuchuang.xchcloud.cn/Https%20%E9%83%A8%E7%BD%B2.png)

server {
        listen 80;
        server_name .dongcia.com;
        return     301 https://dongcia.com$request_uri;
}

server {
        listen 443 ssl;
        server_name .dongcia.com;
        charset utf-8;
        ssl_certificate     /etc/nginx/ssl/dongcia.com.crt;
        ssl_certificate_key /etc/nginx/ssl/dongcia.com.key;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE

        access_log /var/log/nginx/nginx-uwsgi.log;

        location / {
               proxy_pass http://uwsgi;
        }

        location /static {
               alias /home/ubuntu/jarvis/deployment/django_deployment/static;
        }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

### 使用Nginx进行高可用服务部署

#### 为什么需要部署高可用服务?

![](http://tuchuang.xchcloud.cn/%E9%AB%98%E5%8F%AF%E7%94%A8%E5%8E%9F%E5%9B%A0.png)

#### 反向代理

![](http://tuchuang.xchcloud.cn/%E5%8F%8D%E5%90%91%E4%BB%A3%E7%90%86.png)

![](http://tuchuang.xchcloud.cn/%E5%8F%8D%E5%90%91%E4%BB%A3%E7%90%862.png)

#### 负载均衡

![](http://tuchuang.xchcloud.cn/%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1.png)
权重:

upstream uwsgi {

        # server 127.0.0.1:8000;
        server 127.0.0.1:8001 weight=3;
        server 127.0.0.1:8002 weight=1;
}
1
2
3
4
5
6

#### 注意

不要使用root权限启动uWSGI服务

关闭uWSGl外网访问

[uwsgi]

chdir = /home/ubuntu/jarvis/deployment/django_deployment
module = django_deployment.wsgi
http-socket = 127.0.0.1:8001
master = True
processes = 1
threads = 1
vacuum = true

backend run uwsgi

daemonize = %(chdir)/log/uwsgi-8001.log
log-maxsize = 1024000000
pidfile = %(chdir)/pid/uwsgi-8001.pid
`

喜欢这篇文章?打赏一下作者吧!

欢迎关注我的其它发布渠道