1.restful api 为何要有api?html
方便不一样系统之间的相互调用数据前端
2 restful规范python
使用httpsmysql
3.HTTP协议的理解web
基于socket使用TCP协议进行数据传输redis
短链接,一次请求和响应以后断开链接算法
无状态,短链接的特性形成的sql
数据格式数据库
4.公司的组织架构(公司部门的配比,人数)django
开发:前端,后端,产品经理 UI:1人 测试 、运维、运营、销售、人事、财务
5.认证方式和权限方式
四种认证方式:session、cookie、token、jwt(json web token)--将用户信息加密,加密后做为token,https://blog.csdn.net/qq_40081976/article/details/79046825 https://www.jianshu.com/p/af8360b83a9f https://www.cnblogs.com/zaixiuxing/p/6005968.html
单点登陆
什么是单点登陆?单点登陆全称Single Sign On(如下简称SSO),是指在多系统应用群中登陆一个系统,即可在其余全部系统中获得受权而无需再次登陆,包括单点登陆与单点注销两部分
单点登陆的原理:https://www.cnblogs.com/ywlaker/p/6113927.html
6.将去重规则放在redis中的意义?
意义:除了快,最主要的是能够实现相似于分布式的构造,将调度器和去重规则剖离出来,能够实现每个爬虫应用的调度。
7.在Python环境下用尽量多的方法反转字符串,例如将s = "abcdef"反转成 "fedcba"
第一种:使用字符串切片 result = s[::-1] 第二种:使用列表的reverse方法 l = list(s) result = "".join(l.reverse()) 固然下面也行 l = list(s) result = "".join(l[::-1]) 第三种:使用reduce result = reduce(lambda x,y:y+x,s) 第四种:使用递归函数 def func(s): if len(s) <1: return s return func(s[1:])+s[0] result = func(s) 第五种:使用栈 def func(s): l = list(s) #模拟所有入栈 result = "" while len(l)>0: result += l.pop() #模拟出栈 return result result = func(s) 第六种:for循环 def func(s): result = "" max_index = len(s)-1 for index,value in enumerate(s): result += s[max_index-index] return result result = func(s)
8.django和flask的区别
django 大而全 flask 小而精
若是应用很是简单,使用flask就会很是的快捷;若是应用比较复杂,就使用django,由于flask把全部的第三方组件拼起来就是个django。
9.python中的垃圾回收机制
python做为一门动态语言,一个简单的赋值语句也是很值得研究的,重要特色就是引用和对象分离。
python中使用引入计数为主,标记清除,和分代回收为辅。
每次建立对象都会分配内存,容器对象跟数字不同呢?这是由于Python的内存池机制。
Python内存池
若是频繁的调用 malloc 与 free 时,是会产生性能问题的.再加上频繁的分配与释放小块的内存会产生内存碎片.
Python 在这里主要干的工做有:
若是请求分配的内存在1~256字节之间就使用本身的内存管理系统,不然直接使用 malloc.
引用计数增长的状况:
1.对象被建立
2.对象被当成参数传入函数。
3.对象的引用被建立 好比:a=1 b=a
4.做为容器对象的一个元素
引用计数减小的状况:
1.对象被删除 好比:del a
2.对象从容器中删除 好比:li.remove(a)
3.对象被从新赋值
...
对于循环引用的对象,好比:a=[1,2],b = a.append(a),a.append(b),会采用标记清除。
引用计数是采用轮询的方式查看那些引用为0,这样就会出现一个问题,效率很是的低,为了解决效率低的问题,python引入了分代回收的机制。
分代回收是一种以空间换时间的操做方式,Python将内存根据对象的存活时间划分为不一样的集合,每一个集合称为一代,Python将内存分为了3“代”,分别为年轻代(第0代)、中年代(第1代)、老年代(第2代),他们对应的是3个链表,它们的垃圾收集频率与对象的存活时间的增大而减少。新建立的对象都会分配在年轻代,年轻代链表的总数达到上限时,Python垃圾收集机制就会被触发,把那些能够被回收的对象回收掉,而那些不会回收的对象就会被移到中年代去,依此类推,老年代中的对象是存活时间最久的对象,甚至是存活于整个系统的生命周期内。同时,分代回收是创建在标记清除技术基础之上。分代回收一样做为Python的辅助垃圾收集技术处理那些容器对象
建立对象和取消建立对象的差值700的时候
# gc.get_threshold()
# 链表 0代 1代 2代
# 每一代被触发垃圾回收的时候 剩下没有被回收的对象会被移到上一代里面
# 当0代被触发10次的时候 会触发1代的回收 也会回收0代的
# 当1代被触发10次的时候 会触发2代的回收 所有回收
10.flask-session的 做用:
将flask中的session由原来放置在加密cookie中,改成放置到其余数据源。
11.flask-session的原理
在flask中,请求进来后,会先执行open_session方法,该方法读取用户cookie中的session_id对应的随机字符串;若是获取到,根据随机字符串去redis中获取原来设置的值,并建立一个包含该值的字典。若是未获取到,就生成一个随机字符串并在内存中建立一个空字典。
在视图函数中,能够对该字典进行操做。
当请求结束时,会执行save_session方法,该方法去内存中读取这个特殊的字典,并将字典序列化为字符串,而后写到redis中,在将随机字符串写到用户的cookie中返回。
12.DBUtils的做用和原理
做用:建立数据库链接池。
原理: 启动时会在内存中维护一个链接池,当请求链接数据库时则去链接池中获取一个链接,若是有则获取,没有则等待或报错。使用完毕后,将链接归还到链接池中
13.写代码的过程当中有没有令你印象深入的事情。
好比:使用flask文件上传的时候,使用flask定制上传文件大小的错误信息时,使用mac是没有问题的,而使用Windows就会报错。系flask中的一个bug。
from gevent.pywsgi import WSGIServer if __name__ == '__main__': # app.run(host='127.0.0.1',port=5000) http_server = WSGIServer(('127.0.0.1', 5000), app) http_server.serve_forever()
14.上传一个excle文件并读取每一行的内容
# 上传一个Excel文件并读取其中每一行的内容 xlrd 模块 import xlrd f = xlrd.open_workbook(r'D:\新建文件夹\工做簿1.xlsx') ret = f.sheets()[0] # 获取第一个表格对象 print(type(ret)) # <class 'xlrd.sheet.Sheet'> n = ret.nrows #获取行数 m = ret.ncols # 获取列数 # 获取全部的数据 for i in range(n): for j in range(m): print(ret.row_values(i)[j],end=' ') # ret.row_values(i) 获取第几行的数据 # print(ret.col_values(j)) print()
15.请在Context类下完成实现
![]() |
执行 with-as 时,会先执行 __enter__方法,并将该方法的返回值,赋值给as 后的对象,而后执行with-as 中的代码块,无论代码块中的代码是否有异常,都会在离开执行__exit__方法,能够在__exit__方法中作一些收尾工做或者捕捉异常的处理操做。
因此,使用with - as 方法时,对象必须实现__enter__和__exit__方法。
class Context(object): def __enter__(self): return self def do_something(self): pass def __exit__(self, exc_type, exc_val, exc_tb): pass with Context() as ctx: ctx.do_something()
16.简述SQl注入的攻击原理以及如何在代码层面防止?
SQL的攻击原理:经过把SQL命令插入到Web表单递交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令
代码层面:引发的主要缘由在于后台写SQL语句的时候用了字符串拼接
解决方法:1 采用预编译语句集 2,对传过来的参数进行过滤 好比正则检查是否包含非法字符等
17.django内置的缓存机制。
django的缓存有六种
-- memchched缓存
-- 数据库缓存
-- 文件系统缓存
-- 本地内存缓存
-- 虚拟缓存
-- 自定义缓存
-- 应用
-- 全栈缓存 粒度大 中间件配置
-- 单独视图缓存 粒度适中 视图上方加装饰器或者在路由器配置
18.什么是xss攻击。
-- XSS攻击是向网页中注入恶意脚本,用在用户浏览网页时,在用户浏览器中执行恶意脚本的攻击。
-- XSS分类,反射型xss ,存储型xss
-- 反射型xss又称为非持久型xss,攻击者经过电子邮件等方式将包含注入脚本的连接发送给受害者,
受害者经过点击连接,执行注入脚本,达到攻击目的。
-- 持久型xss跟反射型的最大不一样是攻击脚本将被永久的存放在目标服务器的数据库和文件中,多见于论坛
攻击脚本连同正常信息一同注入到帖子内容当中,当浏览这个被注入恶意脚本的帖子的时候,恶意脚本会被执行
-- 防范措施 1 输入过滤 2 输出编码 3 cookie防盗
1,输入过滤 用户输入进行检测 不容许带有js代码
2,输出编码 就是把咱们的脚本代码变成字符串形式输出出来
3,cookie加密
19.偏函数的做用和好处
把一个函数的某些参数给固定住(也就是设置默认值),返回一个新的函数,调用这个新函数会更简单。
当函数的参数个数太多,须要简化时,使用functools.partial
能够建立一个新的函数,这个新函数能够固定住原函数的部分参数,从而在调用时更简单。
20.判断101-200之间有多少个质数(一个大于1的天然数,除了1和它自身外,不能被其余天然数整除的数叫质数),并输出全部的质数。
解题思路:首先这个数确定得大于1,并且能被其余天然数整除,就意味着整除它的数必然小于它自己,(若是大于其自己,获得是一个小数),因此能够写一个函数,将这个数被全部的数(大于1,小于自己)整除,(取余数,若是余数为0,表示能够整除,就返回一个true),根据这个函数的返回值,就能够过滤出全部的质数。
def func(x): if x >1: if x==2: return True for i in range(2,x): if x % i ==0: return True for i in range(101,201): ret = func(i) if not ret: print(i)
21.websocket是什么?
websocket是一套基于TCP链接的协议,这个协议规定:客户端向服务端建立链接后不断开。现象:客户端向服务端发送请求,服务端也能够主动向客户端推送消息。它实现了浏览器与服务器全双工(full-duplex)通讯。其本质是保持TCP链接,在浏览器和服务端经过Socket进行通讯。
22.websocket创建链接时,会先进行握手,认证的过程,
注:magic string为:258EAFA5-E914-47DA-95CA-C5AB0DC85B11
发起websocket请求时,会先进行一个认证握手的过程,这个过程为:
1.用户发起websocket请求后,会先在请求头中获取Sec-WebSocket-Key对应的值,再将这个值与majic_string(魔法字符串<这个字符串是固定的>)相加,将相加的结果先经过hashlib.sha1加密,在经过base64加密,而后在将加密后的结果返回给客户端。客户端收到后校验是否是采用的这张加密,经过后,创建起链接,不然就会拒绝链接。
握手成功后才能发送数据,并且收发数据是加密的。
客户端和服务端传输数据时,须要对数据进行【封包】和【解包】。
客户端的JavaScript类库已经封装【封包】和【解包】过程,但Socket服务端须要手动实现。
解包过程:
服务端接收到客户端发送的数据后,后先取出第二个字节的后七位,而后,对这后七位进行一个判断:(后七位转化为数字最大为127),若是后七位<=125,那么前两个字节就是报文;若是后七位=126,则继续日后读16个字节,也就是取前四个字节做为报文;若是后七位=127,则日后读64位,也就是取前10个字节做为报文。而后剩余的数据取前四个字节做为masking_key(掩码key),对剩下的数据在每一个字节的与masking_key作位运算,最终获得真实的数据。
websocket的使用场景
websocket主要用于页面数据的实时更新。
web实现数据的实时更新的方案:
1.长轮询 兼容性好
2.websocket 性能更优
23.给装饰器写log
def logwrap(wrap): def log_inner(func): print('装饰器执行以前') ret = wrap(func) return ret return log_inner @logwrap # wrapper = logwrap(wrapper) = log_inner def wrapper(func): def inner(*args,**kwargs): print('before') ret = func(*args,**kwargs) print('after') return ret return inner @wrapper # func = wrapper(func) = log_inner(func) def func(): print('哈哈哈') func()
24.
v = [lambda:x for x in range(10)]
print( v ) # 含有多个函数名的列表
print( v[0] ) # 第一个函数名
print( v[0]() ) # 9 等同于下面
for i in range(10):
def f():
return i
print(f())
25.mysql表的水平分表和垂直分表
水平分表用于表数据量很大时,垂直分表用于表中的字段不少
1,水平分割:
例:QQ的登陆表。假设QQ的用户有100亿,若是只有一张表,每一个用户登陆的时候数据库都要从这100亿中查找,会很慢很慢。若是将这一张表分红100份,每张表有1亿条,就小了不少,好比qq0,qq1,qq1...qq99表。
用户登陆的时候,能够将用户的id%100,那么会获得0-99的数,查询表的时候,将表名qq跟取模的数链接起来,就构建了表名。好比123456789用户,取模的89,那么就到qq89表查询,查询的时间将会大大缩短。
这就是水平分割。
2,垂直分割:
垂直分割指的是:表的记录并很少,可是字段却很长,表占用空间很大,检索表的时候须要执行大量的IO,严重下降了性能。这时须要把大的字段拆分到另外一个表,而且该表与原表是一对一的关系。
26.(HBase)列存储
2七、简述一致性哈希原理和它要解决的问题
详情参考:https://blog.csdn.net/lihao21/article/details/54193868
原理:一致性hash算法经过一个叫做一致性hash环的数据结构实现。这个环的起点是0,终点是2^32 - 1,而且起点与终点链接,环的中间的整数按逆时针分布,故这个环的整数分布范围是[0, 2^32-1]。将对象和机器均匀的放置在hash环上,在hash环上顺时针查找距离这个对象的hash值最近的机器,便是这个对象所属的机器。当增长或者减小机器,不会缓存命中的命中率
一致性hash算法解决了分布式环境下机器增长或者减小时,简单的取模运算没法获取较高命中率的问题。经过虚拟节点的使用,一致性hash算法能够均匀分担机器的负载,使得这一算法更具现实的意义。正因如此,一致性hash算法被普遍应用于分布式系统中。
2八、C10K问题和解决方案
C10K问题(即单机1万个并发链接问题) C10M问题(即单机1千万个并发链接问题)
解决方案:epoll和协程。
2九、classmethod和staticmethod的使用场景
应用场景:编写类时须要采用不少不一样的方式来建立实例,而咱们只有一个__init__函数,此时静态方法就派上用场了 复制代码 class Date: def __init__(self,year,month,day): self.year=year self.month=month self.day=day @staticmethod def now(): #用Date.now()的形式去产生实例,该实例用的是当前时间 t=time.localtime() #获取结构化的时间格式 return Date(t.tm_year,t.tm_mon,t.tm_mday) #新建实例而且返回 @staticmethod def tomorrow():#用Date.tomorrow()的形式去产生实例,该实例用的是明天的时间 t=time.localtime(time.time()+86400) return Date(t.tm_year,t.tm_mon,t.tm_mday) a=Date('1987',11,27) #本身定义时间 b=Date.now() #采用当前时间 c=Date.tomorrow() #采用明天的时间 print(a.year,a.month,a.day) print(b.year,b.month,b.day) print(c.year,c.month,c.day)
classmethod的使用场景:工厂模式
30.RabbitMQ的应用场景
1,异步的处理:好比注册后,将注册信息持久化后,须要发送注册邮件和注册短信,而后返回注册成功,而持久化数据后,发送邮件和短信不是必须的,就能够返回注册成功,只须要在持久化到数据库后,将发送邮件和短信放到消息队列中便可。而后返回注册成功。
2,应用的解耦:好比订单系统和仓库系统,当订单量很大时,将订单系统持久化后,就能够加入到消息队列中,仓库系统能够根据消息队列进行操做,而不会出现系统的宕机形成数据的丢失。
3,流量的削峰:好比秒杀活动,创建一个长度限制的消息队列,请求进来后,将请求加入到消息队列中,超过阈值后直接将后续的请求返回
详情请参考:https://baijiahao.baidu.com/s?id=1608348586147010884&wfr=spider&for=pc
RabbitMQ三种Exchange模式(fanout,direct,topic)的性能比较 RabbitMQ中,全部生产者提交的消息都由Exchange来接受,而后Exchange按照特定的策略转发到Queue进行存储 RabbitMQ提供了四种Exchange:fanout,direct,topic,header header模式在实际使用中较少,本文只对前三种模式进行比较。 性能排序:fanout > direct >> topic。比例大约为11:10:6 一.Direct Exchange 0ec0f465-49c6-361c-ae2b-dd951a6ed1a9 任何发送到Direct Exchange的消息都会被转发到RouteKey中指定的Queue。 1.通常状况可使用rabbitMQ自带的Exchange:”"(该Exchange的名字为空字符串,下文称其为default Exchange)。 2.这种模式下不须要将Exchange进行任何绑定(binding)操做 3.消息传递时须要一个“RouteKey”,能够简单的理解为要发送到的队列名字。 4.若是vhost中不存在RouteKey中指定的队列名,则该消息会被抛弃。 二.Fanout Exchange 0bbdcd3d-9fc6-3107-b7e0-db67c174d46a 任何发送到Fanout Exchange的消息都会被转发到与该Exchange绑定(Binding)的全部Queue上。 1.能够理解为路由表的模式 2.这种模式不须要RouteKey 3.这种模式须要提早将Exchange与Queue进行绑定,一个Exchange能够绑定多个Queue,一个Queue能够同多个Exchange进行绑定。 4.若是接受到消息的Exchange没有与任何Queue绑定,则消息会被抛弃。 三.Topic Exchange 11171ab4-af07-3ff6-bdf6-d1febda679c3 任何发送到Topic Exchange的消息都会被转发到全部关心RouteKey中指定话题的Queue上 1.这种模式较为复杂,简单来讲,就是每一个队列都有其关心的主题,全部的消息都带有一个“标题”(RouteKey),Exchange会将消息转发到全部关注主题能与RouteKey模糊匹配的队列。 2.这种模式须要RouteKey,也许要提早绑定Exchange与Queue。 3.在进行绑定时,要提供一个该队列关心的主题,如“#.log.#”表示该队列关心全部涉及log的消息(一个RouteKey为”MQ.log.error”的消息会被转发到该队列)。 4.“#”表示0个或若干个关键字,“*”表示一个关键字。如“log.*”能与“log.warn”匹配,没法与“log.warn.timeout”匹配;可是“log.#”能与上述二者匹配。 5.一样,若是Exchange没有发现可以与RouteKey匹配的Queue,则会抛弃此消息。
31.HTTP协议怎么区分长链接和短链接
HTTP的长链接和短链接本质上是TCP长链接和短链接。
在HTTP/1.0中默认使用短链接。而从HTTP/1.1起,默认使用长链接,用以保持链接特性。使用长链接的HTTP协议,会在响应头加入这行代码:Connection:keep-alive
在使用长链接的状况下,当一个网页打开完成后,客户端和服务器之间用于传输HTTP数据的TCP链接不会关闭,客户端再次访问这个服务器时,会继续使用这一条已经创建的链接。Keep-Alive不会永久保持链接,它有一个保持时间,能够在不一样的服务器软件(如Apache)中设定这个时间。实现长链接须要客户端和服务端都支持长链接。
3二、redis中持久化的两种方式,区别,如何开启
redis中持久化的功能默认是不开启的。
redis的持久化分为两种:
RDB (point in time snapshot) 基于时间点的快照技术,优势:持久化速度快,须要的磁盘较少。缺点:只能将数据定格在一个时间 点,不能记录数据的变化过程。应用场景:经常使用于备份,主从复制就是基于RDB功能的。
AOF:Append Only Logfile 只追加的日志文件,保存全部键值对修改的变化过程 。优势:记录数据的变化过程,更加安全。缺点:持久 化速度相对慢,须要更多的磁盘空间。用处:须要数据安全性和一致性要求更高业务场景,Redis分布式架构基于AOF来实现高可用。
3三、什么是响应式布局?
经过页面窗口的大小作出响应不一样的展现效果,经过@media属性 @media (max-size:123) {...}
3四、MySQL数据库中开启锁的方式:begin;操做语句加for update;释放锁:commit;
django中开启锁的方式:from api import models
from django.db import transaction
with transaction.atomic():
res = models.Comment.objects.all().for_update()
35.为何要有消息队列
为了应用之间的通讯(rpc),解决供求关系(生产者消费者模型)
36. 程序之间如何实现通讯
1. 使用restful api(json数据格式) 2.webservice(xml数据格式) 3. rpc(基于消息队列实现应用程序之间进行通讯)
37.令你印象最深入的官方文档:rabbitmq 写得通俗易懂,对于没有接触过的人来讲,很是容易上手。
38.tcp是如何保证不丢包的
39, 多进程的部署
40,使用列表推导式实现快排