1、谈谈对http协议的认识
流程:
1.域名解析
域名解析检查顺序为:浏览器自身DNS缓存---》OS自身的DNS缓存--》读取host文件--》本地域名服务器--》权限域名服务器--》根域名服务器。如果有且没有过期,则结束本次域名解析。域名解析成功之后,进行后续操作
2.tcp3次握手建立连接
3.建立连接后,发起http请求
4.服务器端响应http请求,浏览器得到到http请求的内容
5.浏览器解析html代码,并请求html代码中的资源
6.浏览器对页面进行渲染,展现在用户面前
2、谈谈对websocket协议的认识
WebSocket是HTML5开始提供的一种浏览器与服务器间进行全双工通讯的网络技术。依靠这种技术可以实现客户端和服务器端的长连接,双向实时通信。
特点:
事件驱动
异步
使用ws或者wss协议的客户端socket
能够实现真正意义上的推送功能
缺点:
少部分浏览器不支持,浏览器支持的程度与方式有区别。
http://www.cnblogs.com/best/p/5695570.html#_label1
3、什么是magic string
4、如何创建响应式布局
@media (min-width: 768px){
.pg-header{
background-color: green;
}
}
@media (min-width: 992px){
.pg-header{
background-color: pink;
}
}
5、什么是ajax请求,并使用jquery和XMLHttpRequest对象实现一个ajax请求
http://www.cnblogs.com/wupeiqi/articles/5703697.html
6、如何在前端实现轮询
轮询:客户端定时向服务器发送Ajax请求,服务器接到请求后马上返回响应信息并关闭连接。
优点:后端程序编写比较容易。 缺点:请求中有大半是无用,浪费带宽和服务器资源。 实例:适于小型应用。
https://www.cnblogs.com/zhaowinter/p/5332681.html
7、如何在前端实现长轮询
客户端向服务器发送Ajax请求,服务器接到请求后hold住连接,直到有新消息才返回响应信息并关闭连接,客户端处理完响应信息后再向服务器发送新的请求。
优点:在无消息的情况下不会频繁的请求,耗费资小。
缺点:服务器hold连接会消耗资源,返回数据顺序无保证,难于管理维护。 Comet异步的ashx,
实例:WebQQ、Hi网页版、Facebook IM。
8、vuex的作用
在使用库或框架时,需要注意一个「适用性」的问题。
Vuex 或者说实现了 Flux 思想的库,解决了几个问题:
组件之间的数据通信
使用单向数据流的方式进行数据的中心化管理
为什么要解决这样的问题呢?其实是因为当程序逻辑过于复杂的时候,非中心化的数据管理会让整个 app 的逻辑非常混乱。
举一个不使用中心化的数据管理机制的具体例子:
一个 app ,有四个 tab,每个 tab 都需要读取用户的资料。如果数据在每个 tab 的控制器里(或者说组件里)都存了一份,那么在用户手动更新了用户资料之后,就需要在每一个 tab 里都更新一遍用户资料,才能保证用户看到的永远是最新的资料。
如你问题里所说,我每进一个 tab 的时候重新请求一下不就好了吗?
这样的解决方案不是不可以,但弊端也非常明显:
- 对于服务器端来说,频繁的请求是非常占用资源的,如果你的 app 用户足够多,那么每多出一个请求,对公司来说,都是一大笔钱。如果数据存在了 store 中,并且所有的 tab 都读取同一份数据,在用户更新资料时,在前端更新了 store 中的数据,是不是在切换 tab 时就减少了四个请求呢?
- 对于前端开发者来说,如果你的项目足够复杂,团队的规模也不仅是一个人,那么前端代码就会因为数据分散管理而产生非常严重的性能和稳定性的隐患(比如你的同事觉得进入模块就刷新用户资料太慢了,手贱把刷新的代码删了,你又没发现)。
https://segmentfault.com/q/1010000011402824
9、Vue中路由的拦截器作用
vue-resource的interceptors拦截器的作用正是解决此需求的妙方。在每次http的请求响应之后,如果设置了拦截器如下,会优先执行拦截器函数,获取响应体,然后才会决定是否把response返回给then进行接收
10、axios的作用
https://blog.csdn.net/qq_27626333/article/details/76254888
11、列举vue中常见的指令
1、v-if指令:判断指令,根据表达式值得真假来插入或删除相应的值。
2、v-show指令:条件渲染指令,无论返回的布尔值是true还是false,元素都会存在在html中,只是false的元素会隐藏在html中,并不会删除.
3、v-else指令:配合v-if或v-else使用。
4、v-for指令:循环指令,相当于遍历。
5、v-bind:给DOM绑定元素属性。
6、v-on指令:监听DOM事件。
12、简述jsonp及实现原理
JSONP是json用来跨域的一个东西。原理是通过script标签的跨域特性来绕过同源策略。(创建一个回调函数,然后在远程服务上调用这个函数并且将json数据形式作为参数传递,完成回调)。
http://www.cnblogs.com/huchong/p/8469053.html
13、什么是cors
跨域资源共享(CORS,Cross-Origin Resource Sharing),其本质是设置响应头,使得浏览器允许跨域请求。
http://www.cnblogs.com/huchong/p/8469063.html
14、列举http请求中常见的请求方式
请求方法有8种,分别为:
GET:请求获取由 Request-URI 所标识的资源。
POST:在 Request-URI 所标识的资源后附加新的数据。
HEAD:请求获取由 Request-URI 所标识的资源的响应消息报头。
OPTIONS:请求查询服务器的性能,或查询与资源相关的选项和需求。
PUT:请求服务器存储一个资源,并用 Request-URI作为其标识。
DELETE:请求服务器删除由 Request-URI所标识的资源。
TRACE:请求服务器回送收到的请求信息,主要用语测试或诊断。
CONNECT:HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器。
15、列举http请求中的状态码
常见的响应状态码有以下几种,在各种下面分别列几个常见的状态码:
1开头(信息)
2开头(成功)
200(OK):请求成功
202(Accepted):已接受请求,尚未处理
204(No Content):请求成功,且不需返回内容
3开头(重定向)
301(Moved Permanently):被请求的资源已永久移动到新位置
301(Moved Temporarily):被请求的资源已临时移动到新位置
4开头(客户端错误)
400(Bad Request):请求的语义或是参数有错
403(Forbidden):服务器拒绝了请求
404(Not Found):未找到请求的资源
5开头(服务器错误)
500(Internal Server Error):服务器遇到错误,无法完成请求
502(Bad Getway):网关错误,一般是服务器压力过大导致连接超时
503(Service Unavailable):服务器宕机
16、列举http请求中常见的请求头
Accept:
浏览器端可以接受的媒体类型,通配符 * 代表任意类型
Accept-Encoding:
浏览器申明自己接收的编码方法,例如: Accept-Encoding: zh-CN,zh;q=0.8
Accept-Language:
浏览器申明自己接收的语言,
Connection:
如Connection: keep-alive 当一个网页打开完成后,客户端和服务器之间用于传输HTTP数据的TCP连接不会关闭,
如果客户端再次访问这个服务器上的网页,会继续使用这一条已经建立的连接。
Referer:
当浏览器向web服务器发送请求的时候,一般会带上Referer,告诉服务器我是从哪个页面链接过来的,服务器籍此可以获得一些信息用于处理。
User-Agent:
告诉HTTP服务器, 客户端使用的操作系统和浏览器的名称和版本.
Cookie:
Cookie是用来存储一些用户信息以便让服务器辨别用户身份的(大多数需要登录的网站上面会比较常见),比如cookie会存储一些用户的用户名和密码,
当用户登录后就会在客户端产生一个cookie来存储相关信息,这样浏览器通过读取cookie的信息去服务器上验证并通过后会判定你是合法用户,从而允许查看相应网页。
17、django、flask、tornado框架对比
d:大而全
f:微型灵活
t:异步非阻塞
18、什么是wsgi
Python Web服务器网关接口(Python Web Server Gateway Interface,缩写为WSGI)是Python应用程序或框架和Web服务器之间的一种接口,已经被广泛接受, 它已基本达成它的可移植性方面的目标。
http://python.jobbole.com/88653/
19、django的请求生命周期
a. wsgi, 创建socket服务端,用于接收用户请求并对请求进行初次封装。
b. 中间件,对所有请求到来之前,响应之前定制一些操作。
c. 路由匹配,在url和视图函数对应关系中,根据当前请求url找到相应的函数。
d. 执行视图函数,业务处理【通过ORM去数据库中获取数据,再去拿到模板,然后将数据和模板进行渲染】
e. 再经过所有中间件。
f. 通过wsgi将响应返回给用户。
20、列举django中内置的组件
form/modelform/admin
21、列举django中间件的5个方法,以及中间件的应用场景
中间件中方法?5个方法,分别是:
process_request(self,request)
process_view(self, request, callback, callback_args, callback_kwargs)
process_template_response(self,request,response)
process_exception(self, request, exception)
process_response(self, request, response)
1 请求先执行所有中间件的process_request,然后做路由匹配,找到函数不执行。
2 再执行所有的process_view,在执行视图函数。
3 再执行process_response
4 如果程序报错执行process_exception
5 如果程序有render方法则执行process_template_response
22、简述什么是FBV和CBV
1 FBV方式请求的过程
用户发送url请求,Django会依次遍历路由映射表中的所有记录,一旦路由映射表其中的一条匹配成功了,
就执行视图函数中对应的函数名,这是fbv的执行流程
2 CBV方式请求的过程
当服务端使用CBV模式的时候,用户发给服务端的请求包含url和method,这两个信息都是字符串类型
服务端通过路由映射表匹配成功后会自动去找dispatch方法,然后Django会通过dispatch反射的方式找到类中对应的方法并执行
类中的方法执行完毕之后,会把客户端想要的数据返回给dispatch方法,由dispatch方法把数据返回经客户端
把上面的例子中的视图函数修改成如下:
from django.views import View
class CBV(View):
def dispatch(self, request, args, kwargs):
print("dispatch......")
res=super(CBV,self).dispatch(request,args,kwargs)
return res
def get(self,request):
return render(request, "cbv.html")
def post(self,request):
return HttpResponse("cbv.get")
3 FBV和CBV的区别?
- 没什么区别,因为他们的本质都是函数。CBV的.as_view()返回的view函数,view函数中调用类的dispatch方法,在dispatch方法中通过反射执行get/post/delete/put等方法。
- CBV比较简洁,GET/POST等业务功能分别放在不同get/post函数中。FBV自己做判断进行区分。
http://www.cnblogs.com/renpingsheng/p/7534897.html
23、django的request对象什么时候创建
当请求一个页面时, Django会建立一个包含请求元数据的 HttpRequest 对象. 当Django 加载对应的视图时, HttpRequest对象将作为视图函数的第一个参数. 每个视图会返回一个HttpResponse对象.
https://blog.csdn.net/mbl114/article/details/78090773
24、如何给CBV添加装饰器
-
装饰器
from django.views import View
from django.utils.decorators import method_decoratordef auth(func):
def inner(args,kwargs):
return func(args,**kwargs)
return innerclass UserView(View):
@method_decorator(auth)
def get(self,request,args,*kwargs):
return HttpResponse('...')- csrf的装饰器要加到dispath
from django.views import View
from django.utils.decorators import method_decorator
from django.views.decorators.csrf import csrf_exempt,csrf_protect
- csrf的装饰器要加到dispath
class UserView(View):
@method_decorator(csrf_exempt)
def dispatch(self, request, *args, **kwargs):
return HttpResponse('...')
或
from django.views import View
from django.utils.decorators import method_decorator
from django.views.decorators.csrf import csrf_exempt,csrf_protect
@method_decorator(csrf_exempt,name='dispatch')
class UserView(View):
def dispatch(self, request, *args, **kwargs):
return HttpResponse('...')
24、列举django orm中所有方法(QuerySet对象的所有方法)
返回QuerySet对象的方法有:
all()
filter()
exclude()
order_by()
reverse()
distinct()
特殊的QuerySet:
values() 返回一个可迭代的字典序列
values_list() 返回一个可迭代的元组序列
返回具体对象的:
get()
first()
last()
返回布尔值的方法有:
exists()
返回数字的方法有:
count()
25、only和defer的区别
def defer(self, *fields):
models.UserInfo.objects.defer('username','id')
或
models.UserInfo.objects.filter(...).defer('username','id')
#映射中排除某列数据
def only(self, *fields):
#仅取某个表中的数据
models.UserInfo.objects.only('username','id')
或
models.UserInfo.objects.filter(...).only('username','id')
26、select_related和prefetch_related的区别
title = models.CharField(max_length=32)
class UserInfo(models.Model):
name = models.CharField(max_length=32)
email = models.CharField(max_length=32)
ut = models.ForeignKey(to='UserType')
ut = models.ForeignKey(to='UserType')
ut = models.ForeignKey(to='UserType')
ut = models.ForeignKey(to='UserType')
1次SQL
select * from userinfo
objs = UserInfo.obejcts.all()
for item in objs:
print(item.name)
n+1次SQL
select * from userinfo
objs = UserInfo.obejcts.all()
for item in objs:
# select * from usertype where id = item.id
print(item.name,item.ut.title)
示例1:
.select_related()
# 1次SQL
# select * from userinfo inner join usertype on userinfo.ut_id = usertype.id
objs = UserInfo.obejcts.all().select_related('ut')
for item in objs:
print(item.name,item.ut.title)
示例2:
.prefetch_related()
# select * from userinfo where id <= 8
# 计算:[1,2]
# select * from usertype where id in [1,2]
objs = UserInfo.obejcts.filter(id__lte=8).prefetch_related('ut')
for obj in objs:
print(obj.name,obj.ut.title)
两个函数的作用都是减少查询次数
27、filter和exclude的区别
def filter(self, *args, **kwargs)
# 条件查询(符合条件)
# 条件可以是:参数,字典,Q
def exclude(self, *args, **kwargs)
# 条件查询(排除条件)
# 条件可以是:参数,字典,Q
28、列举django orm中三种能写sql的方法
1.使用execute执行自定义SQL
from django.db import connection, connections
cursor = connection.cursor() # cursor = connections['default'].cursor()
cursor.execute("""SELECT * from auth_user where id = %s""", [1])
row = cursor.fetchone()
2.使用extra方法
extra(self, select=None, where=None, params=None, tables=None, order_by=None, select_params=None)
Entry.objects.extra(select={'new_id': "select col from sometable where othercol > %s"}, select_params=(1,))
Entry.objects.extra(where=['headline=%s'], params=['Lennon'])
Entry.objects.extra(where=["foo='a' OR bar = 'a'", "baz = 'a'"])
Entry.objects.extra(select={'new_id': "select id from tb where id > %s"}, select_params=(1,), order_by=['-nid'])
3.使用raw方法
解释:执行原始sql并返回模型
说明:依赖model多用于查询
用法:
book = Book.objects.raw("select * from hello_book")
for item in book:
print(item.title)
https://www.cnblogs.com/413xiaol/p/6504856.html
29、django orm如何设置读写分离
class Router1:
def allow_migrate(self, db, app_label, model_name=None, **hints):
"""
All non-auth models end up in this pool.
"""
if db=='db1' and app_label == 'app02':
return True
elif db == 'default' and app_label == 'app01':
return True
else:
return False
# 如果返回None,那么表示交给后续的router,如果后续没有router,则相当于返回True
def db_for_read(self, model, **hints):
"""
Attempts to read auth models go to auth_db.
"""
if model._meta.app_label == 'app01':
return 'default'
else:
return 'db1'
def db_for_write(self, model, **hints):
"""
Attempts to write auth models go to auth_db.
"""
if model._meta.app_label == 'app01':
return 'default'
else:
return 'db1'
30、F和Q的作用
F:Django 支持 F() 对象之间以及 F() 对象和常数之间的加减乘除和取模的操作。
修改操作也可以使用F函数,比如将每一本书的价格提高30元
例:把所有书名后面加上(第一版)
from django.db.models.functions import Concat
from django.db.models import Value
models.Book.objects.all().update(title=Concat(F("title"), Value("("), Value("第一版"), Value(")")))
Q:
Q(条件1) | Q(条件2) 或
Q(条件1) & Q(条件2) 且
Q(条件1) & ~Q(条件2) 非
31、values和values_list的区别
values() 返回一个可迭代的字典序列
values_list() 返回一个可迭代的元组序列
32、如何使用django orm批量创建数据
def bulk_create(self, objs, batch_size=None):
# 批量插入
# batch_size表示一次插入的个数
objs = [
models.DDD(name='r11'),
models.DDD(name='r22')
]
models.DDD.objects.bulk_create(objs, 10)
33、django中Form和ModelForm的作用
- 作用:
- 对用户请求数据格式进行校验
- 自动生成HTML标签- 区别:
- Form,字段需要自己手写。
class Form(Form):
xx = fields.CharField(.)
xx = fields.CharField(.)
xx = fields.CharField(.)
xx = fields.CharField(.) - ModelForm,可以通过Meta进行定义
class MForm(ModelForm):
class Meta:
fields = "all"
model = UserInfo
- Form,字段需要自己手写。
- 应用:只要是客户端向服务端发送表单数据时,都可以进行使用,如:用户登录注册
- 区别:
34、django的Form组件中,如果字段包含choices参数,请使用两种方式实现数据源实
方式一:重写构造方法,在构造方法中重新去数据库获取值
class UserForm(Form):
name = fields.CharField(label='用户名',max_length=32)
email = fields.EmailField(label='邮箱')
ut_id = fields.ChoiceField(
# choices=[(1,'二B用户'),(2,'山炮用户')]
choices=[]
)
def __init__(self,*args,**kwargs):
super(UserForm,self).__init__(*args,**kwargs)
self.fields['ut_id'].choices = models.UserType.objects.all().values_list('id','title')
方式二: ModelChoiceField字段
from django.forms import Form
from django.forms import fields
from django.forms.models import ModelChoiceField
class UserForm(Form):
name = fields.CharField(label='用户名',max_length=32)
email = fields.EmailField(label='邮箱')
ut_id = ModelChoiceField(queryset=models.UserType.objects.all())
依赖:
class UserType(models.Model):
title = models.CharField(max_length=32)
def __str__(self):
return self.title
35、django的Model中的ForeignKey字段中的on_delete参数的作用
on_delete有CASCADE、PROTECT、SET_NULL、SET_DEFAULT、SET()五个可选择的值
CASCADE:此值设置,是级联删除。
PROTECT:此值设置,是会报完整性错误。
SET_NULL:此值设置,会把外键设置为null,前提是允许为null。
SET_DEFAULT:此值设置,会把设置为外键的默认值。
SET():此值设置,会调用外面的值,可以是一个函数。
36、django中csrf的实现机制
Django预防CSRF攻击的方法是在用户提交的表单中加入一个csrftoken的隐含值,这个值和服务器中保存的csrftoken的值相同,这样做的原理如下:
1、在用户访问django的可信站点时,django反馈给用户的表单中有一个隐含字段csrftoken,这个值是在服务器端随机生成的,每一次提交表单都会生成不同的值
2、当用户提交django的表单时,服务器校验这个表单的csrftoken是否和自己保存的一致,来判断用户的合法性
3、当用户被csrf攻击从其他站点发送精心编制的攻击请求时,由于其他站点不可能知道隐藏的csrftoken字段的信息这样在服务器端就会校验失败,攻击被成功防御
具体配置如下:
template中添加{%csrf_token%}标签
https://blog.csdn.net/u012556900/article/details/57412707
37、django中如何实现websocket
https://www.cnblogs.com/huguodong/p/6611602.html
38、基于django使用ajax发送post请求时,都可以使用哪种方法携带csrf_token
三种方式:https://www.cnblogs.com/wxp5257/p/7834090.html
39、django如何实现orm表中添加数据时创建一条日志记录
LOGGING配置查看翻译的SQL:
在Django的日志设置中,配置上一个名为django.db.backends的logger实例即可查看翻译后的SQL语句。
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'console':{
'level':'DEBUG',
'class':'logging.StreamHandler',
},
},
'loggers': {
'django.db.backends': {
'handlers': ['console'],
'propagate': True,
'level':'DEBUG',
},
}
}
http://www.cnblogs.com/owasp/p/5981355.html
40、如何设置django缓存
三种粒度缓存
1 中间件级别
'django.middleware.cache.UpdateCacheMiddleware',
'django.middleware.cache.FetchFromCacheMiddleware',
CACHE_MIDDLEWARE_SECONDS=10
2 视图级别
from django.views.decorators.cache import cache_page
@cache_page(15)
def index(request):
import time
t=time.time()
return render(request,"index.html",locals())
3 局部缓存
{% load cache %}
...
...
{% cache 15 "time_cache" %}
缓存时间:{{ t }}
{% endcache %}
41、django中的缓存能使用redis吗,能的话如何配置
pip install django-redis
apt-get install redis-server
然后在settings.py 里面添加CACHES = {
'default': {
'BACKEND': 'redis_cache.cache.RedisCache',
'LOCATION': '127.0.0.1:6379',
"OPTIONS": {
"CLIENT_CLASS": "redis_cache.client.DefaultClient",
},
}
42、django中路由系统的name的作用
简单说,name 可以用于在 templates, models, views ……中得到对应的网址,相当于“给网址取了个名字”,只要这个名字不变,网址变了也能通过名字获取到。
https://blog.csdn.net/liweiblog/article/details/77599604
43、django模板中filter和simple_tag的区别
simple_tag
-参数任意,但是不能作为if条件判断的条件
filter
-参数最多只能有两个,但是可以作为if条件判断的条件。
http://www.cnblogs.com/cerofang/p/8367588.html
44、djang-debug-toolbar的作用
django_debug_toolbar 是django的第三方工具包,给django扩展了调试功能。
包括查看执行的sql语句,db查询次数,request,headers,调试概览等。
https://blog.csdn.net/weixin_39198406/article/details/78821677
45、django如何实现单元测试
https://www.jianshu.com/p/34267dd79ad6
46、简述orm中的db first和code first的含义
datebase first就是代表数据库优先,那么前提就是先创建数据库。
model first就是代表model优先,那么前提也就是先创建model,然后根据model自动建立数据库。
47、django中如何根据数据库表生成model中的类
https://jingyan.baidu.com/article/4ae03de3e513d23eff9e6bb7.html
48、使用orm和原生sql的优缺点
ORM框架:对象关系映射,通过创建一个类,这个类与数据库的表相对应!类的对象代指数据库中的一行数据。
简述ORM原理:让用户不再写SQL语句,而是通过类以及对象的方式,和其内部提供的方法,进行数据库操作!把用户输入的类或对象转换成SQL语句,转换之后通过pymysql执行完成数据库的操作。
ORM的优缺点:
优点:
提高开发效率,降低开发成本
使开发更加对象化
可移植
可以很方便地引入数据缓存之类的附加功能
缺点:
在处理多表联查、where条件复杂之类的查询时,ORM的语法会变得复杂。就需要写入原生SQL。
49、简述MVC和MTV
MTV和MVC?
MVC: model view controller
MTV: model tempalte view
50、django中contenttype组件的作用
contenttype是django的一个组件(app),为我们找到django程序中所有app中的所有表并添加到记录中。
可以使用他再加上表中的两个字段实现:一张表和N张表创建FK关系。
- 字段:表名称
- 字段:数据行ID
应用:路飞表结构优惠券和专题课和学位课关联。
http://www.cnblogs.com/iyouyue/p/8810464.html
51、谈谈对restful规范的认识
- restful其实就是一套编写接口的协议,协议规定如何编写以及如何设置返回值、状态码等信息。
- 最显著的特点:
restful: 给用户一个url,根据method不同在后端做不同的处理,比如:post 创建数据、get获取数据、put和patch修改数据、delete删除数据。
no rest: 给调用者很多url,每个url代表一个功能,比如:add_user/delte_user/edit_user/ - 当然,还有协议其他的,比如:
- 版本,来控制让程序有多个版本共存的情况,版本可以放在 url、请求头(accept/自定义)、GET参数
- 状态码,200/300/400/500
- url中尽量使用名词,restful也可以称为“面向资源编程”
- api标示:
api.YueNet.com
www.YueNet.com/api/
- 最显著的特点:
- https
- 域名
- api.oldboy.com
- www.oldboy.com/api
- 版本:
- www.oldboy.com/api/v1
- URL资源,名词
- www.oldboy.com/api/v1/student
- 请求方式:
- GET/POST/PUT/DELETE/PATCH/OPTIONS/HEADERS/TRACE
- 返回值:
- www.oldboy.com/api/v1/student/ -> 结果集
- www.oldboy.com/api/v1/student/1/ -> 单个对象
- URL添加条件
- www.oldboy.com/api/v1/student?page=11&size=9
- 状态码:
- 200
- 300
- 301
- 302
- 400
- 403
- 404
- 500
- 错误信息
{
code:1000,
meg:'xxxx'
}
- hyperlink
{
id:1
name: ‘xiangl’,
type: http://www.xxx.com/api/v1/type/1/
}
52、接口幂等性是什么
一个接口通过首先进行1次访问,然后对该接口进行N次相同访问的时候,对访问对象不造成影响,那么就认为接口具有幂等性。
比如:
GET, 第一次获取数据、第二次也是获取结果,幂等。
POST, 第一次新增数据,第二次也会再次新增,非幂等。
PUT, 第一次更新数据,第二次不会再次更新,幂等。
PATCH,第一次更新数据,第二次可能再次更新,非幂等。
DELTE,第一次删除数据,第二次不会再次删除,幂等。
53、什么是RPCRPC(Remote Procedure Call)—远程过程调用,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。RPC协议假定某些传输协议的存在,如TCP或UDP,为通信程序之间携带信息数据。在OSI网络通信模型中,RPC跨越了传输层和应用层。RPC使得开发包括网络分布式多程序在内的应用程序更加容易。
54、http和https的区别
超文本传输协议HTTP协议被用于在Web浏览器和网站服务器之间传递信息,HTTP协议以明文方式发送内容,不提供任何方式的数据加密,如果攻击者截取了Web浏览器和网站服务器之间的传输报文,就可以直接读懂其中的信息,因此,HTTP协议不适合传输一些敏感信息,比如:信用卡号、密码等支付信息。
为了解决HTTP协议的这一缺陷,需要使用另一种协议:安全套接字层超文本传输协议HTTPS,为了数据传输的安全,HTTPS在HTTP的基础上加入了SSL协议,SSL依靠证书来验证服务器的身份,并为浏览器和服务器之间的通信加密。
https://www.cnblogs.com/wqhwe/p/5407468.html
55、为什么要使用django rest framework框架
1.客户端-服务端分离
优点:提高用户界面的便携性,通过简化服务器提高可伸缩性....
2.无状态(Stateless):从客户端的每个请求要包含服务器所需要的所有信息
优点:提高可见性(可以单独考虑每个请求),提高了可靠性(更容易从局部故障中修复),提高可扩展性(降低了服务器资源使用)
3.缓存(Cachable):服务器返回信息必须被标记是否可以缓存,如果缓存,客户端可能会重用之前的信息发送请求
优点:减少交互次数,减少交互的平均延迟
4.统一接口
优点:提高交互的可见性,鼓励单独改善组件
5.支持按需代码(Code-On-Demand 可选)
优点:提高可扩展性
https://www.cnblogs.com/vipchenwei/p/7867028.html
56、django rest framework框架中有哪些组件
-
路由,自动帮助开发者快速为一个视图创建4个url
www.oldboyedu.com/api/v1/student/www.oldboyedu.com/api/v1/student/(?P
\d+)/$ www.oldboyedu.com/api/v1/student/(?P \d+)(?P \w+)$ -
版本处理
- 问题:版本都可以放在那里?
- url
- GET
- 请求头
- 问题:版本都可以放在那里?
-
认证
- 问题:认证流程?
-
权限
- 权限是否可以放在中间件中?以及为什么?
-
访问频率的控制
匿名用户可以真正的防止?无法做到真正的访问频率控制,只能把小白拒之门外。
如果要封IP,使用防火墙来做。登录用户可以通过用户名作为唯一标示进行控制,如果有人注册很多账号,也无法防止。
视图
解析器 ,根据Content-Type请求头对请求体中的数据格式进行处理。request.data
分页
-
序列化
- 序列化
- source
- 定义方法
- 请求数据格式校验
- 序列化
渲染器
-
57、django rest framework框架中的视图都可以继承那些类
a. 继承 APIView
这个类属于rest framework中顶层类,内部帮助我们实现了只是基本功能:认证、权限、频率控制,但凡是数据库、分页等操作都需要手动去完成,比较原始。
class GenericAPIView(APIView)
def post(...):
pass
b. 继承 GenericViewSet(ViewSetMixin, generics.GenericAPIView)
如果继承它之后,路由中的as_view需要填写对应关系 .as_view({'get':'list','post':'create'})
在内部也帮助我们提供了一些方便的方法:
- get_queryset
- get_object
- get_serializer
注意:要设置queryset字段,否则会跑出断言的异常。
# 只提供增加功能
class TestView(GenericViewSet):
serializer_class = XXXXXXX
def create(self,*args,**kwargs):
pass # 获取数据并对数据进行操作
c. 继承
- ModelViewSet
- mixins.CreateModelMixin,GenericViewSet
- mixins.CreateModelMixin,DestroyModelMixin,GenericViewSet
对数据库和分页等操作不用我们在编写,只需要继承相关类即可。
示例:只提供增加功能
class TestView(mixins.CreateModelMixin,GenericViewSet):
serializer_class = XXXXXXX
http://www.cnblogs.com/iyouyue/p/8798572.html#_label3
58、简述django rest framework框架的认证流程
- 如何编写?写类并实现authticate
- 方法中可以定义三种返回值:
- (user,auth),认证成功
- None , 匿名用户
- 异常 ,认证失败
- 流程:
- dispatch
- 再去request中进行认证处理
https://www.cnblogs.com/haiyan123/p/8419872.html
- 方法中可以定义三种返回值:
59、django rest framework如何实现用户访问频率限制
a. 基于用户IP限制访问频率
b. 基于用户IP显示访问频率(利于Django缓存)
c. view中限制请求频率
d. 匿名时用IP限制+登录时用Token限制
e. 全局使用
REST_FRAMEWORK = {
'DEFAULT_THROTTLE_CLASSES': [
'api.utils.throttles.throttles.LuffyAnonRateThrottle',
'api.utils.throttles.throttles.LuffyUserRateThrottle',
],
'DEFAULT_THROTTLE_RATES': {
'anon': '10/day',
'user': '10/day',
'luffy_anon': '10/m',
'luffy_user': '20/m',
},
}
https://www.cnblogs.com/vipchenwei/p/7867028.html
60、Flask框架的优势
一、整体设计方面
首先,两者都是非常优秀的框架。整体来讲,两者设计的哲学是区别最大的地方。Django提供一站式的解决方案,从模板、ORM、Session、Authentication等等都分配好了,连app划分都做好了,总之,为你做尽量多的事情,而且还有一个killer级的特性,就是它的admin,配合django-suit,后台就出来了,其实最初Django就是由在新闻发布公司工作的人设计的。Flask只提供了一些核心功能,非常简洁优雅。它是一个微框架,其他的由扩展提供,但它的blueprint使它也能够很方便的进行水平扩展。
二、路由设计
Django的路由设计是采用集中处理的方法,利用正则匹配。Flask也能这么做,但更多的是使用装饰器的形式,这个有优点也有缺点,优点是读源码时看到函数就知道怎么用的,缺点是一旦源码比较长,你要查路由就不太方便了,但这也促使你去思考如何更合理的安排代码。
三、应用模块化设计
Django的模块化是集成在命令里的,也就是说一开始Django的目标就是为以后玩大了做准备的。每个都是一个独立的模块,为以后的复用提供了便利。Flask通过Blueprint来提供模块化,自己对项目结构划分成不同的模块进行组织。
四、配置
Django的配置主要还是靠settings.py来做,当然为了Development和Production环境分离,还有一些方法来处理配置。Flask的配置很灵活,有多种方法配置,不同环境的配置也非常方便。
五、文档
两者都提供了详尽的文档,Flask的文档风格很受我个人喜好,Django的文档也非常优秀,当时用学Django时,就是只看了Django的文档。
六、社区
Django社区很大,各种插件很齐全,大部分情况下你都能找到你想要的。Flask起步晚,但社区也不小,之前有一次看在github上的star数,两个相差并不远,说明越来越多的人关注它,虽然插件没那么全,但常用的还都是有的,而且质量都比较高。
61、Flask框架依赖组件
Flask依赖两个外部库:
Jinja2模板引擎
Werkzeng WSGI工具集。
62、Flask中的蓝图有什么用途
将不同的功能 模块化;
构建大型的应用;
优化项目结构;
增强可读性,易于维护;
63、列举使用过的Flask第三方组件
内置:
- 配置
- 路由
- 视图
- 模板
- session
- 闪现
- 蓝图
- 中间件
- 特殊装饰器
第三方:
- Flask组件:
- flask-session
- flask-SQLAlchemy
- flask-migrate
- flask-script
- blinker
- 公共组件:
- wtforms
- dbutile
- sqlalchemy
- 自定义Flask组件
- auth ,参考flask-login组件
64、简述Flask上下文管理流程
每次有请求过来的时候,flask 会先创建当前线程或者进程需要处理的两个重要上下文对象,把它们保存到隔离的栈里面,这样视图函数进行处理的时候就能直接从栈上获取这些信息。
参考链接:http://python.jobbole.com/87398/
65、Flask中的g的作用
g 相当于一次请求的全局变量,当请求进来时将g和current_app封装为一个APPContext类,在通过LocalStack将Appcontext放入Local中,取值时通过偏函数,LocalStack、loca l中取值,响应时将local中的g数据删除
66、Flask中上下文管理涉及到哪些相关的类,并描述其主要作用
flask
requestcontext
request
securecookiesessioninterface
securecookiesession
67、为什么要Flask把Local对象中的值stack维护成一个列表
当是web应用时:不管是单线程还是多线程,栈中只有一个数据
- 服务端单线程:
{
111:{stack: [ctx, ]}
}
- 服务端多线程:
{
111:{stack: [ctx, ]}
112:{stack: [ctx, ]}
}
68、Flask中多app应用是怎么完成的
目的是想要将local中的值维护成一个栈,例如:在多app应用中编写离线脚本时,可以实用上。
from m_app import app01,app02
from flask import current_app
"""
{
1231: {
stack: [app01,app02,]
}
}
"""
with app01.app_context():
print(current_app)
with app02.app_context():
print(current_app)
print(current_app)
69、在Flask中实现websocket需要什么组件
Flask-SocketIO
Flask-Sockets是Flask框架的一个扩展,通过它,Flask应用程序可以使用WebSocket。
https://blog.csdn.net/u013793383/article/details/72848252
https://github.com/miguelgrinberg/Flask-SocketIO
70、wtforms组件的作用
WTForms是一个支持多个web框架的form组件,主要用于对用户请求数据进行验证。
https://www.cnblogs.com/big-handsome-guy/p/8552079.html
https://www.cnblogs.com/liuwei0824/p/8330985.html
71、Flask框架默认session处理机制
Flask的默认session利用了Werkzeug的SecureCookie,把信息做序列化(pickle)后编码(base64),放到cookie里了。
过期时间是通过cookie的过期时间实现的。
为了防止cookie内容被篡改,session会自动打上一个叫session的hash串,这个串是经过session内容、SECRET_KEY计算出来的,看得出,这种设计虽然不能保证session里的内容不泄露,但至少防止了不被篡改。
https://blog.csdn.net/qq_33733970/article/details/79008831
72、解释Flask中Local对象和threading.local对象的区别
a. threading.local
作用:为每个线程开辟一块空间进行数据存储。
问题:自己通过字典创建一个类似于threading.local的东西。
storage={
4740:{val:0},
4732:{val:1},
4731:{val:3},
...
}
b. 自定义Local对象
作用:为每个线程(协程)开辟一块空间进行数据存储。
try:
from greenlet import getcurrent as get_ident
except Exception as e:
from threading import get_ident
from threading import Thread
import time
class Local(object):
def __init__(self):
object.__setattr__(self,'storage',{})
def __setattr__(self, k, v):
ident = get_ident()
if ident in self.storage:
self.storage[ident][k] = v
else:
self.storage[ident] = {k: v}
def __getattr__(self, k):
ident = get_ident()
return self.storage[ident][k]
obj = Local()
def task(arg):
obj.val = arg
obj.xxx = arg
print(obj.val)
for i in range(10):
t = Thread(target=task,args=(i,))
t.start()
73、Flask中blinker是什么
Flask框架中的信号基于blinker,可以让开发者在flask请求过程中 定制一些用户行为执行。
在请求前后,模板渲染前后,上下文前后,异常 的时候
http://www.cnblogs.com/big-handsome-guy/p/8551973.html
74、SQLAlchemy中的session和scoped_session的区别
使用scoped_session的目的主要是为了线程安全。
scoped_session类似单例模式,当我们调用使用的时候,会先在Registry里找找之前是否已经创建session了。
要是有,就把这个session返回。
要是没有,就创建新的session,注册到Registry中以便下次返回给调用者。
这样就实现了这样一个目的:在同一个线程中,call scoped_session 的时候,返回的是同一个对象
https://www.cnblogs.com/geeklove01/p/8179220.html
https://www.cnblogs.com/lianxuebin/p/8664401.html
75、SQLAlchemy如何执行原生sql
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
engine = create_engine('mysql://root:*****@127.0.0.1/database?charset=utf8')
DB_Session = sessionmaker(bind=engine)
session = DB_Session()
session.execute('alter table mytablename drop column mycolumn ;')
https://www.cnblogs.com/franknihao/p/7268752.html
76、ORM的实现原理
概念: 对象关系映射(Object Relational Mapping,简称ORM,或O/RM,或O/R mapping),是一种程序技术,用于实现面向对象编程语言里不同类型系统的数据之间的转换。
详细介绍: 让我们从O/R开始。字母O起源于"对象"(Object),而R则来自于"关系"(Relational)。几乎所有的程序里面,都存在对象和关系数据库。在业务逻辑层和用户界面层中,我们是面向对象的。当对象信息发生变化的时候,我们需要把对象的信息保存在关系数据库中。
当你开发一个应用程序的时候(不使用O/R Mapping),你可能会写不少数据访问层的代码,用来从数据库保存,删除,读取对象信息,等等。你在DAL中写了很多的方法来读取对象数据,改变状态对象等等任务。而这些代码写起来总是重复的。
ORM解决的主要问题是对象关系的映射。域模型和关系模型分别是建立在概念模型的基础上的。域模型是面向对象的,而关系模型是面向关系的。一般情况下,一个持久化类和一个表对应,类的每个实例对应表中的一条记录,类的每个属性对应表的每个字段。
ORM技术特点:
1.提高了开发效率。由于ORM可以自动对Entity对象与数据库中的Table进行字段与属性的映射,所以我们实际可能已经不需要一个专用的、庞大的数据访问层。
2.ORM提供了对数据库的映射,不用sql直接编码,能够像操作对象一样从数据库获取数据。
77、DBUtils模块的作用
使用DBUtils模块
两种使用模式:
1 为每个线程创建一个连接,连接不可控,需要控制线程数
2 创建指定数量的连接在连接池,当线程访问的时候去取,如果不够了线程排队,直到有人释放。平时建议使用这种!
https://www.cnblogs.com/ArmoredTitan/p/Flask.html
78、一下SQLAlchemy的字段是否正确,如果不正确请改正
from datetime import datetime
from sqlalchemy.ext.declarative
import declarative_base
from sqlalchemy import Column, Integer, String, DateTime
Base = declarative_base()
class UserInfo(Base):
tablename = 'userinfo'
id = Column(Integer, primary_key=True, autoincrement=True)
name = Column(String(64), unique=True)
ctime = Column(DateTime, default=datetime.now())
ctime字段中的参数应该为default=datetime.now, now后面不应该加括号.如果加了,字段不会随时更新
79、SQLAlchemy中如何为表设置引擎和字符编码
sqlalchemy设置编码字符集一定要在数据库访问的URL上增加charset=utf8,否则数据库的连接就不是utf8的编码格式
eng = create_engine('mysql://root:root@localhost:3306/test2?charset=utf8',echo=True)
80、SQLAlchemy如何设置联合唯一索引
UniqueConstraint 设置联合唯一索引
https://www.cnblogs.com/jasonwang-2016/p/5980237.html
81、简述Tornado框架的特点
Tornado的独特之处在于其所有开发工具能够使用在应用开发的任意阶段以及任何档次的硬件资源上。而且,完整集的Tornado工具可以使开发人员完全不用考虑与目标连接的策略或目标存储区大小。Tornado 结构的专门设计为开发人员和第三方工具厂商提供了一个开放环境。已有部分应用程序接口可以利用并附带参考书目,内容从开发环境接口到连接实现。Tornado包括强大的开发和调试工具,尤其适用于面对大量问题的嵌入式开发人员。这些工具包括C和C++源码级别的调试器,目标和工具管理,系统目标跟踪,内存使用分析和自动配置. 另外,所有工具能很方便地同时运行,很容易增加和交互式开发。
82、简述Tornado框架中Futrue对象的作用
http://python.jobbole.com/87310/
83、Tornado如何编写websocket程序
https://www.cnblogs.com/aguncn/p/5665916.html
84、Tornado中静态文件是如何处理的
如:
处理方法:
static_path = os.path.join(os.paht.dirname(file), "static") #这里增加设置了静态路径
另外一个修改就是在实例化 tornado.web.Application() 的时候,在参数中,出了有静态路径参数 static_path ,还有一个参数设置 debug=True
https://blog.csdn.net/hqzxsc2006/article/details/72833012
85、Tornado操作MySQL使用的模块
torndb是一个轻量级的基于MySQLdb封装的一个模块,从tornado3.0版本以后,其已经作为一个独立模块发行了。torndb依赖于MySQLdb模块,因此,在使用torndb模块时,要保证系统中已经有MySQLdb模块。
86、Tornado操作Redis使用的模块
tornado-redis
https://blog.csdn.net/guoqianqian5812/article/details/68587921
87、简述Tornado框架适用的场景Tornado是使用Python编写的一个强大的、可扩展的Web服务器。它在处理严峻的网络流量时表现得足够强健,但却在创建和编写时有着足够的轻量级,并能够被用在大量的应用和工具中。
我们现在所知道的Tornado是基于Bret Taylor和其他人员为FriendFeed所开发的网络服务框架,当FriendFeed被Facebook收购后得以开源。不同于那些最多只能达到10,000个并发连接的传统网络服务器,Tornado在设计之初就考虑到了性能因素,旨在解决C10K问题,这样的设计使得其成为一个拥有非常高性能的框架。此外,它还拥有处理安全性、用户验证、社交网络以及与外部服务(如数据库和网站API)进行异步交互的工具。
https://www.cnblogs.com/luotianshuai/p/5482612.html
88、git常见命令作用
某个文件夹中的内容进行版本管理:
进入文件夹,右键git bash
git init 初始化,当前所在的文件夹可以被管理且以后版本相关的数据都会存储到.git文件中
git status 查看当前文件夹以及子目录中文件是否发生变化:内容修改/新增文件/删除,已经变化的文件会变成红色,已经add的文件会变成绿色
git add . 给发生变化的文件(贴上一个标签)或 将发生变化的文件放到某个地方,只写一个句点符就代表把git status中红色的文件全部打上标签
git commit -m '新增用户登录认证功能以及xxx功能' 将“绿色”文件添加到版本中
git log 查看所有版本提交记录,可以获取版本号
git reset --hard 版本号 将最新的版本回退到更早的版本
git reflog 回退到之前版本后悔了,再更新到最新或者最新之前的版本
git reset --hard 版本 回退
89、简述一下git中stash命令作用以及其他相关命令
stash用于将工作区发生变化的所有文件获取临时存储在“某个地方”,将工作区还原当前版本未操作前的状态;stash还可以将临时存储在“某个地方”的文件再次拿回到工作区。
git stash 将当前工作区所有修改过的内容存储到“某个地方”,将工作区还原到当前版本未修改过的状态
git stash list 查看“某个地方”存储的所有记录
git stash clear 清空“某个地方”
git stash pop 将第一个记录从“某个地方”重新拿到工作区(可能有冲突)
git stash apply 编号, 将指定编号记录从“某个地方”重新拿到工作区(可能有冲突)
git stash drop 编号,删除指定编号的记录
90、git中rebase和merge命令的区别
https://www.cnblogs.com/xueweihan/p/5743327.html
91、公司如何用git进行协同开发
https://www.cnblogs.com/abelsu/p/5138136.html
92、如何基于git进行代码review
https://blog.csdn.net/maray/article/details/50206927
93、git如何实现v1.0、v2.0等版本的管理
https://blog.csdn.net/zhazhaji/article/details/75258426
94、什么是gitlabGitLab 是一个用于仓库管理系统的开源项目,使用Git作为代码管理工具,并在此基础上搭建起来的web服务。安装方法是参考GitLab在GitHub上的Wiki页面。
95、GitHub和gitlab的区别
先说一下相同点,二者都是基于web的Git仓库,在很大程度上GitLab是仿照GitHub来做的,它们都提供了分享开源项目的平台,为开发团队提供了存储、分享、发布和合作开发项目的中心化云存储的场所。
GitHub作为开源代码库及版本控制系统,拥有超过900万的开发者用户,目前仍然是最火的开源项目托管系统。GitHub同时提供公共仓库和私有仓库,但如果要使用私有仓库,是需要付费的。
而GitLab解决了这个问题,你可以在上面创建私人的免费仓库。
GitLab让开发团队对他们的代码仓库拥有更多的控制,相比于GitHub,它有不少的特色:
允许免费设置仓库权限;允许用户选择分享一个project的部分代码;允许用户设置project的获取权限,进一步的提升安全性;可以设置获取到团队整体的改进进度;通过innersourcing让不在权限范围内的人访问不到该资源。
从代码私有性方面来看,有时公司并不希望员工获取到全部的代码,这个时候GitLab无疑是更好的选择。但对于开源项目而言,GitHub依然是代码托管的首选。
96、如何为GitHub上的开源项目贡献代码
对一个开源项目有足够了解的情况下,如果你发现问题或者更好的解决方案的话,可以开个issue先。
一般情况下维护这个项目的人或者其他使用这个项目的人会参与讨论的,然后基于这些讨论你可以发一些pull requests。
如果你的方案得到很多人赞同的话,项目维护人员会把他们merge,你也就成了这个项目的contributor了。
当然很多情况下,你开的这个issue已经有人提过了,或者说是你自己误解了,但是相信在和其他开发人员交流的过程中,你也能学到许多。
97、git中.gitignore文件的作用
一般来说每个Git项目中都需要一个“.gitignore”文件,这个文件的作用就是告诉Git哪些文件不需要添加到版本管理中。
实际项目中,很多文件都是不需要版本管理的,比如Python的.pyc文件和一些包含密码的配置文件等等。
98、什么是敏捷开发
敏捷开发以用户的需求进化为核心,采用迭代、循序渐进的方法进行软件开发。在敏捷开发中,软件项目在构建初期被切分成多个子项目,各个子项目的成果都经过测试,具备可视、可集成和可运行使用的特征。换言之,就是把一个大项目分为多个相互联系,但也可独立运行的小项目,并分别完成,在此过程中软件一直处于可使用状态。
99、简述jenkins工具的作用
Jenkins是一个开源软件项目,是基于Java开发的一种持续集成工具,用于监控持续重复的工作,旨在提供一个开放易用的软件平台,使软件的持续集成变成可能。
100、公司如何实现代码发布
1、开发人员提交代码更新,主要提交的字段包括“更新理由”,“svn代码路径”;
2、后端收到请求后,把此数据插入到数据库,标记此更新单为“等待预发布环境更新”的状态;
3、后台进程定时查询是否有等待预发布环境更新的更新单,如果有,读取svn路径,执行svn up更新代码操作,并标记此更新单为“预发布环境已更新,等待完成测试”;
4、开发人员或者测试人员通过预发布环境的域名来测试功能是否正常,如果不正常,作代码修改后提交svn,再到web发布后台点击“返回修改”,对svn路径或者不做任何修改再点击“重新提交”,然后更新单又一次回到”等待预发布环境更新“状态。循环3、4步骤,直至预发布环境测试通过为止;
5、在确认测试通过后,开发人员点击”测试通过“,这时更新单进入”等待审核状态“;
6、负责人确认可以发布后,点击”审批“按钮,这时更新单进入”审核通过,等待执行发布操作“的状态。这时,开发人员得到发布代码的授权;
7、开发人员点击”发布代码“按钮,更新单进入”已执行发布,等待系统完成发布“状态;
8、后台进程查询状态为”已执行发布,等待系统完成发布“的更新单,执行git发布命令。git命令大概为,进入预发布代码目录,执行git add .;git commit -m “更新原因”;git tag 上一次版本号+1,再进入已发布代码的目录,执行git pull同步预发布代码目录的更改。最后调用rsync命令同步代码到生产环境。
http://blog.jobbole.com/110304/
101、简述RabbitMQ、Kafka和ZeroMQ的区别
RabbitMQ
RabbitMQ是使用Erlang编写的一个开源的消息队列,本身支持很多的协议:AMQP,XMPP, SMTP, STOMP,也正因如此,它非常重量级,更适合于企业级的开发。同时实现了Broker构架,这意味着消息在发送给客户端时先在中心队列排队。对路由,负载均衡或者数据持久化都有很好的支持。
Redis
Redis是一个基于Key-Value对的NoSQL数据库,开发维护很活跃。虽然它是一个Key-Value数据库存储系统,但它本身支持MQ功能,所以完全可以当做一个轻量级的队列服务来使用。对于RabbitMQ和Redis的入队和出队操作,各执行100万次,每10万次记录一次执行时间。测试数据分为128Bytes、512Bytes、1K和10K四个不同大小的数据。实验表明:入队时,当数据比较小时Redis的性能要高于RabbitMQ,而如果数据大小超过了10K,Redis则慢的无法忍受;出队时,无论数据大小,Redis都表现出非常好的性能,而RabbitMQ的出队性能则远低于Redis。
ZeroMQ
ZeroMQ号称最快的消息队列系统,尤其针对大吞吐量的需求场景。ZeroMQ能够实现RabbitMQ不擅长的高级/复杂的队列,但是开发人员需要自己组合多种技术框架,技术上的复杂度是对这MQ能够应用成功的挑战。ZeroMQ具有一个独特的非中间件的模式,你不需要安装和运行一个消息服务器或中间件,因为你的应用程序将扮演这个服务器角色。你只需要简单的引用ZeroMQ程序库,可以使用NuGet安装,然后你就可以愉快的在应用程序之间发送消息了。但是ZeroMQ仅提供非持久性的队列,也就是说如果宕机,数据将会丢失。其中,Twitter的Storm 0.9.0以前的版本中默认使用ZeroMQ作为数据流的传输(Storm从0.9版本开始同时支持ZeroMQ和Netty作为传输模块)。
ActiveMQ
ActiveMQ是Apache下的一个子项目。 类似于ZeroMQ,它能够以代理人和点对点的技术实现队列。同时类似于RabbitMQ,它少量代码就可以高效地实现高级应用场景。
Kafka/Jafka
Kafka是Apache下的一个子项目,是一个高性能跨语言分布式发布/订阅消息队列系统,而Jafka是在Kafka之上孵化而来的,即Kafka的一个升级版。具有以下特性:快速持久化,可以在O(1)的系统开销下进行消息持久化;高吞吐,在一台普通的服务器上既可以达到10W/s的吞吐速率;完全的分布式系统,Broker、Producer、Consumer都原生自动支持分布式,自动实现负载均衡;支持Hadoop数据并行加载,对于像Hadoop的一样的日志数据和离线分析系统,但又要求实时处理的限制,这是一个可行的解决方案。Kafka通过Hadoop的并行加载机制统一了在线和离线的消息处理。Apache Kafka相对于ActiveMQ是一个非常轻量级的消息系统,除了性能非常好之外,还是一个工作良好的分布式系统。
102、RabbitMQ如何在消费者获取任务后未处理完前就挂掉时,保持数据不丢失
103、RabbitMQ如何对消息做持久化
https://www.cnblogs.com/xiangjun555/articles/7874006.html
104、RabbitMQ如何控制消息被消费的顺序
https://blog.csdn.net/varyall/article/details/79111745
105、以下RabbitMQ的exchange type分别代表什么意思,如:fanout、direct、topic
https://www.cnblogs.com/shenyixin/p/9084249.html
106、简述一下celery是什么以及应用场景
Celery是由Python开发的一个简单、灵活、可靠的处理大量任务的分发系统,它不仅支持实时处理也支持任务调度。
http://www.cnblogs.com/wupeiqi/articles/8796552.html
107、简述celery的运行机制
108、celery如何实现定时任务
109、简述celery多任务结构目录
110、celery中装饰器@app.task和@shared_task的区别
111、简述requests模块的作用及基本使用
模拟浏览器发送请求
http://www.cnblogs.com/linhaifeng/articles/7785043.html
112、简述Beautifulsoup模块的作用及基本使用
Beautiful Soup 是一个可以从HTML或XML文件中提取数据的Python库
http://www.cnblogs.com/linhaifeng/articles/7783586.html
113、简述selenium模块的作用及基本使用
selenium最初是一个自动化测试工具,而爬虫中使用它主要是为了解决requests无法直接执行JavaScript代码的问题
selenium本质是通过驱动浏览器,完全模拟浏览器的操作,比如跳转、输入、点击、下拉等,来拿到网页渲染之后的结果,可支持多种浏览器
http://www.cnblogs.com/linhaifeng/articles/7783599.html
114、scrapy框架中各组件的工作流程
1、生成初始的Requests来爬取第一个URLS,并且标识一个回调函数
第一个请求定义在start_requests()方法内默认从start_urls列表中获得url地址来生成Request请求,默认的回调函数是parse方法。回调函数在下载完成返回response时自动触发
2、在回调函数中,解析response并且返回值
返回值可以4种:
包含解析数据的字典
Item对象
新的Request对象(新的Requests也需要指定一个回调函数)
或者是可迭代对象(包含Items或Request)
3、在回调函数中解析页面内容
通常使用Scrapy自带的Selectors,但很明显你也可以使用Beutifulsoup,lxml或其他你爱用啥用啥。
4、最后,针对返回的Items对象将会被持久化到数据库
通过Item Pipeline组件存到数据库:https://docs.scrapy.org/en/latest/topics/item-pipeline.html#topics-item-pipeline)
或者导出到不同的文件(通过Feed exports:https://docs.scrapy.org/en/latest/topics/feed-exports.html#topics-feed-exports)
http://www.cnblogs.com/linhaifeng/articles/7811861.html
115、scrapy中如何设置代理(两种方式)
scrapy自带的代理组件:
from scrapy.downloadermiddlewares.httpproxy import HttpProxyMiddleware
from urllib.request import getproxies
116、scrapy框架中如何实现大文件的下载
持久化时:
from twisted.web.client import Agent, getPage, ResponseDone, PotentialDataLoss
from twisted.internet import defer, reactor, protocol
from twisted.web._newclient import Response
from io import BytesIO
class _ResponseReader(protocol.Protocol):
def __init__(self, finished, txresponse, file_name):
self._finished = finished
self._txresponse = txresponse
self._bytes_received = 0
self.f = open(file_name, mode='wb')
def dataReceived(self, bodyBytes):
self._bytes_received += len(bodyBytes)
# 一点一点的下载
self.f.write(bodyBytes)
self.f.flush()
def connectionLost(self, reason):
if self._finished.called:
return
if reason.check(ResponseDone):
# 下载完成
self._finished.callback((self._txresponse, 'success'))
elif reason.check(PotentialDataLoss):
# 下载部分
self._finished.callback((self._txresponse, 'partial'))
else:
# 下载异常
self._finished.errback(reason)
self.f.close()
117、scrapy中如何实现限速
http://scrapy-chs.readthedocs.io/zh_CN/1.0/topics/autothrottle.html
118、scrapy中如何实现暂定爬虫
有些情况下,例如爬取大的站点,我们希望能暂停爬取,之后再恢复运行。
Scrapy通过如下工具支持这个功能:
一个把调度请求保存在磁盘的调度器
一个把访问请求保存在磁盘的副本过滤器[duplicates filter]
一个能持续保持爬虫状态(键/值对)的扩展
Job 路径
要启用持久化支持,你只需要通过 JOBDIR 设置 job directory 选项。这个路径将会存储 所有的请求数据来保持一个单独任务的状态(例如:一次spider爬取(a spider run))。必须要注意的是,这个目录不允许被不同的spider 共享,甚至是同一个spider的不同jobs/runs也不行。也就是说,这个目录就是存储一个 单独 job的状态信息。
https://scrapy-chs.readthedocs.io/zh_CN/1.0/topics/jobs.html?highlight=item
119、scrapy中如何进行自定制命令
在spiders同级创建任意目录,如:commands
在其中创建 crawlall.py 文件 (此处文件名就是自定义的命令)
from scrapy.commands import ScrapyCommand
from scrapy.utils.project import get_project_settings
class Command(ScrapyCommand):
requires_project = True
def syntax(self):
return '[options]'
def short_desc(self):
return 'Runs all of the spiders'
def run(self, args, opts):
spider_list = self.crawler_process.spiders.list()
for name in spider_list:
self.crawler_process.crawl(name, **opts.__dict__)
self.crawler_process.start()
在settings.py 中添加配置 COMMANDS_MODULE = '项目名称.目录名称'
在项目目录执行命令:scrapy crawlall
http://www.cnblogs.com/wupeiqi/articles/6229292.html
120、scrapy中如何实现记录爬虫深度
class scrapy.contrib.spidermiddleware.depth.DepthMiddleware
DepthMiddleware是一个用于追踪每个Request在被爬取的网站的深度的中间件。 其可以用来限制爬取深度的最大深度或类似的事情。
DepthMiddleware 可以通过下列设置进行配置(更多内容请参考设置文档):
DEPTH_LIMIT - 爬取所允许的最大深度,如果为0,则没有限制。
DEPTH_STATS - 是否收集爬取状态。
DEPTH_PRIORITY - 是否根据其深度对requet安排优先级
121、scrapy中pipelines工作原理
Scrapy 提供了 pipeline 模块来执行保存数据的操作。在创建的 Scrapy 项目中自动创建了一个 pipeline.py 文件,同时创建了一个默认的 Pipeline 类。我们可以根据需要自定义 Pipeline 类,然后在 settings.py 文件中进行配置即可
https://blog.csdn.net/Ahri_J/article/details/72472170
122、scrapy中pipelines中如何丢弃一个item对象
123、scarpy中爬虫中间件和下载中间件的作用
http://www.cnblogs.com/wupeiqi/articles/6229292.html
124、scrapy-redis组件的作用
scheduler - 调度器
dupefilter - URL去重规则(被调度器使用)
pipeline - 数据持久化
125、scrapy-redis组件中如何实现任务去重
定义去重规则(被调度器调用并应用)
a. 内部会使用以下配置进行连接Redis
# REDIS_HOST = 'localhost' # 主机名
# REDIS_PORT = 6379 # 端口
# REDIS_URL = 'redis://user:pass@hostname:9001' # 连接URL(优先于以上配置)
# REDIS_PARAMS = {} # Redis连接参数 默认:REDIS_PARAMS = {'socket_timeout': 30,'socket_connect_timeout': 30,'retry_on_timeout': True,'encoding': REDIS_ENCODING,})
# REDIS_PARAMS['redis_cls'] = 'myproject.RedisClient' # 指定连接Redis的Python模块 默认:redis.StrictRedis
# REDIS_ENCODING = "utf-8" # redis编码类型 默认:'utf-8'
b. 去重规则通过redis的集合完成,集合的Key为:
key = defaults.DUPEFILTER_KEY % {'timestamp': int(time.time())}
默认配置:
DUPEFILTER_KEY = 'dupefilter:%(timestamp)s'
c. 去重规则中将url转换成唯一标示,然后在redis中检查是否已经在集合中存在
from scrapy.utils import request
from scrapy.http import Request
req = Request(url='http://www.cnblogs.com/wupeiqi.html')
result = request.request_fingerprint(req)
print(result) # 8ea4fd67887449313ccc12e5b6b92510cc53675c
PS:
- URL参数位置不同时,计算结果一致;
- 默认请求头不在计算范围,include_headers可以设置指定请求头
示例:
from scrapy.utils import request
from scrapy.http import Request
req = Request(url='http://www.baidu.com?name=8&id=1',callback=lambda x:print(x),cookies={'k1':'vvvvv'})
result = request.request_fingerprint(req,include_headers=['cookies',])
print(result)
req = Request(url='http://www.baidu.com?id=1&name=8',callback=lambda x:print(x),cookies={'k1':666})
result = request.request_fingerprint(req,include_headers=['cookies',])
print(result)
"""
Ensure all spiders share same duplicates filter through redis.
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
126、scrapy-redis中的调度器如何实现任务的深度优先和广度优先
http://www.cnblogs.com/wupeiqi/articles/6912807.html
127、简述virtualenv的作用
virtualenv就是用来为一个应用创建一套“隔离”的Python运行环境。
https://www.cnblogs.com/technologylife/p/6635631.html
128、简述pipreqs及应用场景
查找python项目依赖并生成requirements.txt
https://www.cnblogs.com/bonelee/p/8183038.html
129、在python中使用过什么代码检查工具
1)PyFlakes:静态检查Python代码逻辑错误的工具。
2)Pep8: 静态检查PEP8编码风格的工具。
3)NedBatchelder’s McCabe script:静态分析Python代码复杂度的工具。
Python代码分析工具:PyChecker、Pylint
130、简述saltstack、ansible、fabric、puppet工具的作用
131、B Tree和B+ Tree的区别
https://www.jianshu.com/p/0371c9569736
132、请列举常见的排序并通过代码实现任意三种
冒泡/选择/插入/快排
https://www.cnblogs.com/Liqiongyu/p/5911613.html
http://www.cnblogs.com/feixuelove1009/p/6143539.html
133、请列举常见的查照并通过代码实现任意三种
无序查找/二分查找/插值查找
http://www.cnblogs.com/feixuelove1009/p/6148357.html
134、请列举你熟悉的设计模式
工厂模式/单例模式等
https://www.cnblogs.com/Liqiongyu/p/5916710.html
135、有没有刷过LeetCode
https://leetcode-cn.com/problemset/all/
136、列举熟悉的Linux命令
- mkdir –p 创建多级目录
- ls -l 显示详细信息
- cd change directory 进入到目录中
- pwd print working directory 显示当前所在位置
- touch 创建文件 修改文件的时间戳
- vi 编辑文件
- cat 显示文件内容
- cp copy 复制
- mv move 移动
- rm 删除文件或目录 -f 强制删除不提示 -r 递归删除目录 慎用
- find 查找 -type f(file) d(dir) -name 名字
- grep 过滤 -v 排除
- head 显示文件的前几行 默认显示文件的前10行 -n2 === -2 显示文件的前2行
- tail 显示文件的最后几行 默认显示文件的后10行
-n1 === -1 显示文件的最后1行
-f 实时显示文件的更新 - sed 取行
-n 取消默认输出
-i 修改文件的内容 - tar 创建解压查看压缩包
- yum install yum install -y
- ping baidu.com
137、解释PV、UV的含义
PV访问量(Page View),即页面访问量,每打开一次页面PV计数+1,刷新页面也是。
IP访问数指独立IP访问数,计算是以一个独立的IP在一个计算时段内访问网站计算为1次IP访问数。在同一个计算时段内不管这个IP访问多少次均计算为1次。计算时段有以1天为一个计算时段,也有以1个小时为一个计算时段。
UV访问数(Unique Visitor)指独立访客访问数,一台电脑终端为一个访客。
在同一个局域网中对互联网访问时对外通常是同一个IP,如果该局域网中有10台终端在同一个计算时段内访问同一个网站,对该网站的独立IP访问数贡献为1,而不是10。而此时UV访问数则为10。
138、解释QPS的含义
Query Per Second
每秒查询率QPS是对一个特定的查询服务器在规定时间内所处理流量多少的衡量标准。
139、uwsgi和wsgi的区别
WSGI:全称是Web Server Gateway Interface,WSGI不是服务器,python模块,框架,API或者任何软件,只是一种规范,描述web server如何与web application通信的规范。server和application的规范在PEP 3333中有具体描述。要实现WSGI协议,必须同时实现web server和web application,当前运行在WSGI协议之上的web框架有Bottle, Flask, Django。
uwsgi:与WSGI一样是一种通信协议,是uWSGI服务器的独占协议,用于定义传输信息的类型(type of information),每一个uwsgi packet前4byte为传输信息类型的描述,与WSGI协议是两种东西,据说该协议是fcgi协议的10倍快。
uWSGI:是一个web服务器,实现了WSGI协议、uwsgi协议、http协议等。
https://www.jianshu.com/p/679dee0a4193
140、supervisor的作用
supervisor管理进程,是通过fork/exec的方式将这些被管理的进程当作supervisor的子进程来启动,所以我们只需要将要管理进程的可执行文件的路径添加到supervisor的配置文件中就好了。此时被管理进程被视为supervisor的子进程,若该子进程异常终端,则父进程可以准确的获取子进程异常终端的信息,通过在配置文件中设置autostart=ture,可以实现对异常中断的子进程的自动重启。
141、什么是反向代理
反向代理(Reverse Proxy)方式是指以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给internet上请求连接的客户端,此时代理服务器对外就表现为一个反向代理服务器。
142、简述SSH的整个过程
SSH 为 Secure Shell 的缩写,由 IETF 的网络小组(Network Working Group)所制定;SSH 为建立在应用层基础上的安全协议。SSH 是目前较可靠,专为远程登录会话和其他网络服务提供安全性的协议。利用 SSH 协议可以有效防止远程管理过程中的信息泄露问题。
https://www.jianshu.com/p/33461b619d53
143、最近研究什么新技术
emmmm........ NP完全问题、霍奇猜想、庞加莱猜想、黎曼假设、杨-米尔斯存在性和质量缺口、纳卫尔-斯托可方程、BSD猜想
144、是否了解过领域驱动模型
Domain-Driven Design
https://www.cnblogs.com/netfocus/archive/2011/10/10/2204949.html