业务架构 - 功能模块 - 思维导图 - 核心业务流程
技术架构 - 前端 / 移动端 / 后端 / 持久化
物理架构 - 上线部署
- 输入URL ---DNS(本地/服务器)--> 域名解析成IP地址
DNS - Domain Name Service
HttpRequest - 封装HTTP请求 - 可以获得请求行、请求头、消息体
HttpResponse - 封装HTTP响应 - 可以操作响应行、响应头、消息体
TCP/IP模型 - 四层模型 - Internet的基础
应用层 - 定义应用级协议 - HTTP(s) / SMTP / POP3 / SSH / QQ
1. HTTP请求
2. HTTP响应
传输层 - 端到端(可靠)传输 - TCP / UDP
1. 可靠传输 - 不传错(校验) 不传丢(握手)
2. 流量控制 - 收发数据双方速率匹配(滑动窗口协议)
3. 拥塞控制 - 不给网络添堵(RRT+滑动窗口)
网络层 - IP地址 - 寻址和路由 - IP / ICMP
物理链路层(网络接口层)- 电气特性、分帧、校验
MIME类型 - 告诉浏览器服务器给的内容是什么类型的数据
Multi-purpose Internet Mail Extension
text/html
application/json
application/pdf
video/mp4
audio/mpeg
image/png, image/jpeg, image/gif
application/msword
导出Excel - xlwt
导出PDF - pyreport
参考链接: https://mp.weixin.qq.com/s?__biz=MzA5MzY4NTQwMA==&mid=2651004938&idx=2&sn=6bd9bb476bb9353e56a94b2102776e54&chksm=8bad93fdbcda1aeb750c340956ef8776bc0bcb3c7e29b9712f84b467fcad029ee72d390f5076&mpshare=1&scene=23&srcid=1127NptlJX0SiWiGbFIzYAKu#rd
def download(request):
with open('/Users/Hao/Desktop/Docker.pdf', 'rb') as fs:
# 一般情况下如果文件较大就不要一次性读入而要通过迭代器进行流式处理
resp = HttpResponse(fs.read())
# 通过设置响应头来设置MIME类型
resp['content-type'] = 'application/pdf'
# 将中文处理成百分号编码(quote / unquote)
filename = parse.quote('Docker从入门到住院.pdf')
print(filename)
# 设置是下载(attachment)还是内联打开(inline)
resp['content-disposition'] = f'attachment; filename="{filename}"'
return resp
def download_file(request):
file_stream = open('...', 'rb')
# 如果文件的二进制数据较大则最好用迭代器进行处理避免过多的占用服务器内存
file_iter = iter(lambda: file_stream.read(4096), b'')
resp = StreamingHttpResponse(file_iter)
# 中文文件名要处理成百分号编码
filename = quote('...', 'utf-8')
resp['Content-Type'] = '...'
resp['Content-Disposition'] = f'attachment; filename="{filename}"'
return resp
PING to death - DoS攻击 - Deny of Service
DDoS - Distributed Deny of Service - 肉机
TCP Flood - 洪泛攻击
移动端
Android - Java / Kotlin - AndroidStudio - apk
iOS - Objective-C / Swift - Xcode - ipa
跨平台 - ReactNative - JSX
后端渲染 - 前端渲染(前后端分离)
服务器Python程序 JavaScript
DTL/Jinja2 Vue.js/AngularJS
RESTful API 前端MV*框架
作用: 解耦和(model和view)
djangorestframework
django-redis
django-celery
django-crontab
dfr-extensions
dfr-jwt
xlrd / xlwt
上手 - crash course
最佳实践 - best practice
字符序列
str - 不变字符串
StringIO - 可变字符串
字节序列
bytes - 不可变字节序列
BytesIO - 可变字节序列
JavaScript - 打包工具 - 解决兼容性 / 压缩和优化代码
gulp webpack rollup parcle
CDN - Content Delivery Network - 加速静态资源的访问
如果想了解Django程序执行状况:
- 配置日志 - DEBUG
- Django-Debug-Toolbar
1+N查询问题
N+1查询问题
项目的架构(业务架构、技术架构、物理架构)
单机架构 ---> 多机架构 ---> 读写分离 ---> 集群架构
垂直扩展和水平扩展
Django工作流 / M(数据持久化)-V(页面/报表/图表)-C(接纳请求/操作模型/生成视图)
Django模型操作 - ORM - 正向反向工程
Model - save() / delete()
Model.objects - get() / filter() / all()
ForeignKey - related_name='+'
Dept.objects.get(no=20).emp_set.all() - 不推荐
Emp.objects.filter(dept__no=20) - 推荐
only() / defer() - 指定查询哪些属性(SQL投影)
解决1+N查询问题(多个select变成一个select)
select_related() - 多对一关系 / 一对一关系
prefetch_related() - 多对多关系
params = []
params.append(Q(price__gte=2000))
params.append(Q(price__lte=3000))
params.append(Q(type=3))
House.objects.filter(*params)
什么时候需要事务环境 - 一个用户请求涉及到多个持久化操作
而且这些操作不可分割 这时候就需要事务环境的支持
当有并发事务访问数据库的数据时就有可能产生5类问题:
- 第1类丢失更新
- 第2类丢失更新
- 脏读(读脏数据) - read committed 可以避免脏读 - Oracle
- 可不重复读 - repeatable read 可以避免不可重复读 - MySQL
- 幻读 - serializable
事务隔离级别越高数据越安全但是并发性也越低(性能越差)
数据库底层可以通过锁来保护数据避免并发访问数据的问题
但是如果在写SQL时直接使用锁操作会非常麻烦(行级锁、表级锁、共享锁、排他锁),所以可以根据业务的需求设置适当的事务隔离级别让数据库自动选择加锁的方式
MySQL查看事务隔离级别:
select @@tx_isolation;
MySQL修改当前会话的事务隔离级别:
set session transaction isolation level read committed;
MySQL修改全局的事务隔离级别:
set global transaction isolation level read committed;
read uncommitted - 读未提交
read committed - 读提交
repeatable read - 可重复读
serializable - 串行化
日志 - 系统内日志 / 运行日志(Nginx,uWSGI)
给视图函数添加事务环境的两种方式:
@transaction.atomic()
with transaction.atomic():
pass
自己处理不了的业务 - 外包出去 / 通过其他平台完成 - 业务下沉
- 调用数据接口(http/https) - urllib / requests / responses
- 集成SDK - pip install 三方库 - 对象方法、函数
短信平台 - SendCloud / luosimao / 又拍云 / 云片 / 互亿无线 / 阿里云(?)/
中间件的写法 - 3种
静态资源存储 - 云存储(视频编解码/图片水印/缩略图/CDN) - 七牛 / LeanCloud / Bmob / OSS
缓存配置 - Redis - django-redis
CACHES = {
'default': {
'BACKEND': 'django_redis.cache.RedisCache',
'LOCATION': [],
'KEY_PREFIX': '...',
'OPTIONS': {},
}
}
在settings文件中配置
# 配置基于Redis的缓存系统
# 配置基于Redis的缓存系统
CACHES = {
'default': {
'BACKEND': 'django_redis.cache.RedisCache',
'LOCATION': [
'redis://39.108.113.203:6379/0',
],
'KEY_PREFIX': 'association',
'OPTIONS': {
'CLIENT_CLASS': 'django_redis.client.DefaultClient',
'CONNECTION_POOL_KWARGS': {
'max_connections': 500,
},
'PASSWORD': '123456',
}
},
'page': {
'BACKEND': 'django_redis.cache.RedisCache',
'LOCATION': [
'redis://39.108.113.203:6379/1',
],
'KEY_PREFIX': 'association:page',
'OPTIONS': {
'CLIENT_CLASS': 'django_redis.client.DefaultClient',
'CONNECTION_POOL_KWARGS': {
'max_connections': 1000,
},
'PASSWORD': '123456',
}
},
'session': {
'BACKEND': 'django_redis.cache.RedisCache',
'LOCATION': [
'redis://39.108.113.203:6379/2',
],
'KEY_PREFIX': 'association:session',
'TIMEOUT': 1209600,
'OPTIONS': {
'CLIENT_CLASS': 'django_redis.client.DefaultClient',
'CONNECTION_POOL_KWARGS': {
'max_connections': 1000,
},
'PASSWORD': '123456',
}
},
'code': {
'BACKEND': 'django_redis.cache.RedisCache',
'LOCATION': [
'redis://39.108.113.203:6379/3',
],
'KEY_PREFIX': 'association:code',
'OPTIONS': {
'CLIENT_CLASS': 'django_redis.client.DefaultClient',
'CONNECTION_POOL_KWARGS': {
'max_connections': 500,
},
'PASSWORD': '123456',
}
},
}
# 配置将Session放置在缓存中
SESSION_ENGINE = 'django.contrib.sessions.backends.cache'
SESSION_CACHE_ALIAS = 'session'
在Django项目中使用缓存
- 存储用户会话 - session
- 缓存页面
- 缓存热点数据
- 缓存手机验证码
- 缓存查询结果
- 点赞 / 排行榜 / 秒杀
cache.set() / cache.get()
caches['code'].set() / get()
django-redis:
get_redis_connection() --> StrictRedis(Redis客户端对象)
client = get_redis_connection()
client.hvals('...')