Python 知识点

                                      Python 知识点

1.对不定长参数的理解

不定长参数有两种:*args和**kwargs;

*args:是不定长参数,用来将参数打包成tuple给函数体调用;

**kwargs:是关键字参数,打包关键字参数成dict给函数体调用在定义函数的时候不确定要传入的参数个数会有多少个的时候就可以使用不定长参数作为形参。

2.对缺省参数的理解?

缺省参数指在调用函数的时候没有传入参数的情况下,调用默认的参数,在调用函数的同时赋值时,所传入的参数会替代默认参数。

3.什么是lambda函数?它有什么好处?写一个匿名函数求两个数的和。

lambda函数是匿名函数;使用lambda函数能创建小型匿名函数。这种函数得名于省略了用def声明函数的标准步骤;

f = lambda x,y:x+y
print(f(2017,2018))

4.深拷贝和浅拷贝的区别?

(1)python中的拷贝分为浅拷贝和深拷贝,若不特殊说明拷贝一般是浅拷贝

(2)浅拷贝是将对象顶层拷贝,拷贝了引用,并没有拷贝内容,原对象改变新对象也跟着改变

(3)深拷贝是对一个对象的所有层次的拷贝(递归),但是修改原来的值,新对象不受影响

(4)浅拷贝对于可变类型和不可变类型是不同的,对于可变类型只拷贝顶层,不可变类型依然是原来的对象

5.什么是可变、不可变?元组里添加字典,会改变id吗?

(1)可变不可变指的是内存中的值是否可以被改变,不可变类型指的是对象所在内存块里面的值不可以改变,有数值、字符串、元组;可变类型则是可以改变,主要有列表、字典

(2)元组的顶层元素中包含可变类型,在可变类型中修改或添加字典id不会改变

6.生成器、迭代器的区别?

(1)在Python中,一边循环一边计算的机制,称为生成器:generator,生成器是可以迭代对象,但是生成器可以通过send传值返回到前面;

(2)迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。

  1. 迭代器是一个可以记住遍历的位置的对象。

7.range()和xrange()函数的用法?

(1)range(start,stop,step)函数按照从start到stop每个step生成一个数值,生成的是列表对象,一次性将所有数据都返回;

(2)xrange(start,stop,step)函数按照从start到stop每个step生成一个数值,返回的是可迭代对象,每次调用返回其中的一个值

8.对装饰器的理解,写出一个装饰器用来打印函数的执行时间。

装饰器本质上是一个Python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能,装饰器的返回值也是一个函数对象

import time

def timeit(func):

  def wrapper():

    start = time.clock()

    func()

end =time.clock()

result = end - start

    print(end)

    return wrapper

@timeit

def foo():

Print(‘函数执行时间’)

foo()
  1. 什么单例模式,其应用场景都有哪些?

      

class Single(object):

           def __new__(cls, *args, **kwargs):

              if not hasattr(cls, '_instance'):(hasattr判断里面有没有某个属性或者方法)

              cls._instance = super(DanLi, cls).__new__(cls)

           return cls._instance

      

single1 = Single()

single2 = Single()

Print(id(single1))

Print(id(single2))

 

      (1)__new__()在__init__()之前被调用,用于生成实例对象,利用这个方法和类的属性的特点可以实现设计模式的单例模           式。单例模式是指创建唯一对象,单利模式设计的类只能实例化一个对象。

(2)确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,这个类称为单例类,单例模式是一种对象创建型模式。

Windows的Task Manager(任务管理器)、Recycle Bin(回收站)、网站计数器

(3)单例模式应用的场景一般发现在以下条件下:

资源共享的情况下,避免由于资源操作时导致的性能或损耗等。如上述中的日志文件,应用配置。

控制资源的情况下,方便资源之间的互相通信。如线程池等

10.并行(parallel)和并发(concurrency)?线程是并发还是并行,进程是并发还是并行?

(1)线程是并发,进程是并行;进程之间相互独立,是系统分配资源的最小单位,同一个线程中的所有线程共享资源

(2)并行:同一时刻多个任务同时在运行

(3)并发:在同一时间间隔内多个任务都在运行,但是并不会在同一时刻同时运行,存在交替执行的情况

(4)实现并行的库有:multiprocessing

(5)实现并发的库有:threading

(6)程序需要执行较多的读写、请求和回复任务的需要大量的IO操作,IO密集型操作使用并发更好

CPU运算量大的程序程序,使用并行会更好

11.什么是线程安全,什么是互斥锁?

(1)每个对象都对应于一个可称为" 互斥锁" 的标记,这个标记用来保证在任一时刻,只能有一个线程访问该对象。

(2)同一个进程中的多线程之间是共享系统资源的,多个线程同时对一个对象进行操作,一个线程操作尚未结束,另一个线程已经对其进行操作,导致最终结果出现错误,此时需要对被操作对象添加互斥锁,保证每个线程对该对象的操作都得到正确的结果

12.python的内存管理机制及调优手段?

内存管理机制:引用计数、垃圾回收、内存池

(1)引用计数

引用计数是一种非常高效的内存管理手段, 当一个Python对象被引 用时其引用计数增加1, 当其不再被一个变量引用时则计数减1. 当引用计数等于0时对象被删除.

2)垃圾回收

  1. 引用计数

引用计数也是一种垃圾收集机制,而且也是一种最直观,最简单的垃圾收集技术。当Python的某个对象的引用计数降为0时,说明没有任何引用指向该对象,该对象就成为要被回收的垃圾了。比如某个新建对象,它被分配给某个引用,对象的引用计数变为1。如果引用被删除,对象的引用计数为0,那么该对象就可以被垃圾回收。 
不过如果出现循环引用的话,引用计数机制就不再起有效的作用了

  1. 标记清除

如果两个对象的引用计数都为1,但是仅仅存在他们之间的循环引用,那么这两个对象都是需要被回收的,也就是说,它们的引用计数虽然表现为非0,但实际上有效的引用计数为0。所以先将循环引用摘掉,就会得出这两个对象的有效计数。

  1. 分代回收

从前面“标记-清除”这样的垃圾收集机制来看,这种垃圾收集机制所带来的额外操作实际上与系统中总的内存块的数量是相关的,当需要回收的内存块越多时,垃圾检测带来的额外操作就越多,而垃圾回收带来的额外操作就越少;反之,当需回收的内存块越少时,垃圾检测就将比垃圾回收带来更少的额外操作。 

(3)内存池

1.Python的内存机制呈现金字塔形状,-1,-2层主要有操作系统进行操作;

2.第0层是C中的malloc,free等内存分配和释放函数进行操作;

3.第1层和第2层是内存池,有Python的接口函数PyMem_Malloc函数实现,当对象小于256K时有该层直接分配内存;

4.第3层是最上层,也就是我们对Python对象的直接操作;

Python在运行期间会大量地执行malloc和free的操作,频繁地在用户态和核心态之间进行切换,这将严重影响Python的执行效率。为了加速Python的执行效率,Python引入了一个内存池机制,用于管理对小块内存的申请和释放。 
    Python内部默认的小块内存与大块内存的分界点定在256个字节,当申请的内存小于256字节时,PyObject_Malloc会在内存池中申请内存;当申请的内存大于256字节时,PyObject_Malloc的行为将蜕化为malloc的行为。当然,通过修改Python源代码,我们可以改变这个默认值,从而改变Python的默认内存管理行为。

4)调优手段(了解)  

1.手动垃圾回收

2.调高垃圾回收阈值

3.避免循环引用(手动解循环引用和使用弱引用)

13.read、readline和readlines的区别

read:读取整个文件

readline:读取下一行,使用生成器方法

readlines:读取整个文件到一个迭代器以供我们遍历

14.什么是死锁以及怎么解决?

死锁:在线程间共享多个资源的时候,如果两个线程分别占有一部分资源并且同时等待对方的资源,就会造成死锁

给互斥锁添加超时时间

程序设计时要尽量避免(银行家算法)

15.解释一下什么是闭包

在函数内部再定义一个函数,并且这个函数用到了外边函数的变量,那么将这个函数以及用到的一些变量称之为闭包

16.描述Python GIL的概念,以及它对Python多线程的影响?

GIL:全局解释器锁。每个线程在执行的过程都需要先获取GIL,保证同一时刻只有一个线程可以执行字节码。

线程释放GIL锁的情况:

在IO操作等可能会引起阻塞的system call之前,可以暂时释放GIL,但在执行完毕后,必须重新获取GIL

Python 3.x使用计时器(执行时间达到阈值后,当前线程释放GIL)或Python 2.x,tickets计数达到100

Python使用多进程是可以利用多核的CPU资源的。

多线程爬取比单线程性能有提升,因为遇到IO阻塞会自动释放GIL锁

17.Python中有日志吗?怎么使用?

有日志;

python自带logging模块,调用logging.basicConfig()方法,配置需要的日志等级和相应的参数,python解释器会按照配置的参数生成相应的日志。

18.与、或、亦或的优先级(and、or、xor)

答:xor的优先级高,因为是单运算符,and和or的优先级比较低,and比   or有限级高。

19.说说进程、线程、协程

进程是系统进行资源分配的最小单位,每个进程都有自己的独立内存空间,不用进程通过进程间通信来通信。但是进程占据独立空间,比较重量级,所以上下文进程间的切换开销比较大,但是比较稳定安全。

   线程是进程的一个实体,是CPU进行调度的最小单位,他是比进程更小能独立运行的基本单位。线程基本不拥有系统资源,只占用一点运行中的资源(如程序计数器,一组寄存器和栈),但是它可以与同属于一个进程的其他线程共享全部的资源。提高程序的运行速率,上下文切换快,开销比较少,但是不够稳定,容易丢失数据,形成死锁。

    协程:是更小的执行单位,是一种轻量级的线程,协程的切换只是单纯的操作CPU的上下文,所以切换速度特别快,且耗能小。线程切换从系统层面远不止保存和恢复CPU上下文这么简单,操作系统为了程序运行的高效性,每个线程会有缓存的数据,操作系统还会做回复数据的操作,实际上是消耗性能的。

     对于IO密集型的程序,由于IO操作远远慢于CPU的操作,所以往往需要CPU去等IO操作,这样在同步IO下就需要切换线程,让操作系统去执行其他的代码,但是这样带来大量的性能浪费。如果把一个IO操作写成一个协程。当触发IO操作时候自动让出CPU给其他协程,协程的切换轻的,协程通过这种异步IO的封装,即保留了性能也保证了代码的可读性,在高IO密集型的程序下很好,但是高CPU密集型的程序就不好了。

20.面向对象有哪些方法

(实例方法、静态方法、类方法)

静态方法需要@staticmethod进行修饰,不需要定义参数。类方法是类对象所拥有的方法,需要用装饰器@classmethod来标示,以cls为第一个参数,能够通过实例对象和类对象去访问。实例方法以self为第一个参数,可以通过self访问实力属性

21.生产者消费者模型优点

生产者消费者模型:解耦,通过队列降低耦合,支持并发,生产者和消费者是两个独立的并发体,他们之间使用缓冲区作为桥梁连接,生产者只往里丢数据,就可以生产下一个数据了,消费者从中拿数据,这样就不会阻塞,影响速度。可以很好的支持任务的忙闲不均匀的问题。

22.在当前目录以及子目录下查找文件名包含指定字符串的文件,并打印出完整路径

import os

MySelectPath = 'D:\\tmp'


def Findtxt(MyPath):
    for i in os.listdir(MyPath):
        FilePath = os.path.abspath(os.path.join(MyPath, i))

            #	输出找到的.txt格式的文件
        if os.path.splitext(i)[1] == '.txt':
            print('找到txt文件 :', i)
            print('文件路径是 :', FilePath)
        elif os.path.isdir(FilePath):
            #   print FilePath
            #   print '进入文件夹 :', i
            Findtxt(FilePath)


Findtxt(MySelectPath)
  1. python如何获取一个文件夹内包括子文件夹所有文件的名字和路径
import os
dir="./"
f=open("dir.txt","a")
for root,dirs,files in os.walk(dir):
    for file in files:
        f.writelines(os.path.join(root,file)+"\n")
  1. 写一个列表生成式 例如产生一个公差为的等差数列
a = [i for i in range(10)]      #公差为1
a = [i*2 for i in range(10)]    #公差为2

25.新式类与经典类区别

从继承上说,新式类默认从object继承,经典类需要指定(python3中没有)

经典类继承深度优先(先深入继承左侧,再返回,在开始找右侧)

新式类继承广度优先(优先水平搜索)

26.谈谈你对查询集的理解

查询集表示从数据库中获取的对象集合,在管理器上调用过滤器方法返回查询集,查询集可以包括一个、两个或者多个过滤器。过滤器基于所给的参数限制查询的结果。

查询集的特性之一是:惰性--创建查询机不会访问数据库,直到调用数据时,才会访问数据库。

查询集的另一个特性是:缓存:使用同一个查询集,第一次使用时会发生数据库的查询,再次使用这个查询集时会使用缓存的数据。

如果是两个相同的查询集,无法重用缓存,每次查询都会和数据库进行一次交互,增加了数据库的负载。缓存可以加快获取数据的速率,减轻数据库的压力。

过滤器种类:all()  返回所有数据。filter()返回满足条件的数据,过滤。

exclude()返回满足条件之外的数据  order_by()对结果排序。

get()返回单个满足条件的对象。  count()返回当前查询结果的总条数  aggregrate()聚合,返回一个字典   exist()判断查询机是否有数据。

 

27.谈谈你对Django查询中FQ对象的理解

1.之前的查询都是属性与常量值的比较,F对象实现了属性与属性之间的比较

BookInfo.objects.filter(bread__gt=F('bcomment'))属性名一定要有单引号。

BookInfo.objects.filter(bread__gt=F('bcomment')*2) 2倍的记录。

2.可以直接使用条件表达式来描述逻辑与and,逻辑非not的关系,但是逻辑或or的关系不行。Q对象:描述逻辑关系。

Q对象可以使用&,|连接,&表示逻辑与,|表示逻辑或  Q对象前可以使用~操作符,表示非(not)

28.如何用函数的形式将两个有序集合合并成一个有序集合?

1.函数

def fun(list1,list2):
    result = []
    while list1 and list2:

        if list1[0] < list2[0]:

            result.append(list1[0])

            del list1[0]
        else:

            result.append(list2[0])

            del list2[0]
    if list1:
        result.extend(list1)
    if list2:
        result.extend(list2)
    return result


ret = fun([1,2,3,4],[4,5,6])

print(ret)
  1. 内置函数
list1 = [1,2,3,4]
list2 = [5,6,7,8]
for i in list2:

    list1.append(i)

    list1.sort()

print(list1)

 

29.反向解析:

使用场景:模板中的超链接,视图中的重定向

使用:在定义url时为include定义namespace属性,为url定义name属性

在模板中使用url标签:{% url 'namespace_value:name_value'%}

在视图中使用reverse函数:redirect(reverse('namespce_value:name_value’))

根据正则表达式动态生成地址,减轻后期维护成本。

注意反向解析传参数,主要是在我们的反向解析的规则后面天界了两个参数,两个参数之间使用空格隔开:<a href="{% url 'booktest:fan2' 2 3 %}">位置参数</a>

30.monkey patch(猴子补丁)

用来在运行时动态修改已有的代码,而不需要修改原始代码。在gevent中,会在开头的地方gevent.monkey.patch_all(),把标准库中的thread/socket等给替换掉,这样我们后面使用socket的时候能够跟寻常一样使用,无序改动代码,可以使他变成非堵塞的。

 

31.git简介及相关命令的使用

总结git的两大特点:

  • 版本控制:可以解决多人同时开发的代码问题,也可以解决找回历史代码的问题
  • 分布式:Git是分布式版本控制系统,同一个Git仓库,可以分布到不同的机器上。首先找一台电脑充当服务器的角色,每天24小时开机,其他每个人都从这个“服务器”仓库克隆一份到自己的电脑上,并且各自把各自的提交推送到服务器仓库里,也从服务器仓库中拉取别人的提交。可以自己搭建这台服务器,也可以使用GitHub网站

   步骤及相关命令:

  • 组员在ubuntu中生成ssh密钥,然后交给项目经理添加到github中,等项目经理在github上添加后,会将项目地址下发,然后就可以参与到项目开发中进行后续操作
  1. ssh-keygen -t rsa -C "Github账号,可以是用户名,也可以是邮箱地址"。
  2. 将项目克隆到本地(git clone 项目地址),在克隆下来的目录下隐藏目录.git存储了服务器、分支、文件变更等信息
  3. 以自己的姓名创建分支,要保证分支名字唯一(git checkout -b name)
  4. 将本地分支推送到服务器(git push origin name)
  5. 将本地分支跟踪服务器分支(git branch --set-upstream=origin/分支 分支)
  6. 将GitHub上的dev分支同步到本地,因为开发过程中所有组员都向这个分支上提交阶段性代码,并从这个分支获取阶段性代码。(git checkout -b dev origin/dev)
  7. 查看当前状态:git status 保存现场:git stash
  8. 工作区向暂存区提交代码git add 文件或目录。恢复代码git checkout --文件,删除文件 git rm 文件
  9. 暂存区与仓库区:提交git commit -m ‘备注’,恢复git reset HEA或版本号

10本地与服务器推送指将特定分支在本地仓库区的记录发送到服务器上

git push origin分支

将服务器特定分支向本地工作区同步

git checkout dev

git pull

git checkout zhujiao

33.restful风格:

1.每一种请求都代表一种资源,它主要强调http应该以资源为中心,并且规范了URI的风格,URI:统一资源标志符,某一规则下能把一个资源独一无二地标识出来,好比每个人都有身份证号码

2.它有四种对资源操作的请求,分别是POST新增资源,GET获取资源,PUT更新资源,DELETE删除资源,客户端通过这四个请求对资源进行操作,实现表现层状态转换。

 

第二章 网络编程

1.Tcp协议和udp协议有什么区别

(1)TCP面向连接(如打电话要先拨号建立连接);UDP是无连接的,即发送数据之前不需要建立连接
    (2)TCP提供可靠的服务。也就是说,通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达;UDP尽最大努力交付,即不保   证可靠交付
    (3)TCP面向字节流,实际上是TCP把数据看成一连串无结构的字节流;UDP是面向报文的,UDP没有拥塞控制,因此网络出现拥塞不会使源主机的发送速率降低(对实时应用很有用,如IP电话,实时视频会议等)

(4)每一条TCP连接只能是点到点的;UDP支持一对一,一对多,多对一和多对多的交互通信
    (5)TCP首部开销20字节;UDP的首部开销小,只有8个字节
    (6)TCP的逻辑通信信道是全双工的可靠信道,UDP则是不可靠信道

2.Post和get区别?

(1)GET请求,请求的数据会附加在URL之后,以?分割URL和传输数据,多个参数用&连接。URL的编码格式采用的是ASCII编码,而不是uniclde,即是说所有的非ASCII字符都要编码之后再传输。

POST请求:POST请求会把请求的数据放置在HTTP请求包的包体中。上面的item=bandsaw就是实际的传输数据。

因此,GET请求的数据会暴露在地址栏中,而POST请求则不会。

(2)传输数据的大小

在HTTP规范中,没有对URL的长度和传输的数据大小进行限制。但是在实际开发过程中,对于GET,特定的浏览器和服务器对URL的长度有限制。因此,在使用GET请求时,传输数据会受到URL长度的限制。

对于POST,由于不是URL传值,理论上是不会受限制的,但是实际上各个服务器会规定对POST提交数据大小进行限制,Apache、IIS都有各自的配置。

(3)安全性

POST的安全性比GET的高。这里的安全是指真正的安全,而不同于上面GET提到的安全方法中的安全,上面提到的安全仅仅是不修改服务器的数据。比如,在进行登录操作,通过GET请求,用户名和密码都会暴露再URL上,因为登录页面有可能被浏览器缓存以及其他人查看浏览器的历史记录的原因,此时的用户名和密码就很容易被他人拿到了。除此之外,GET请求提交的数据还可能会造成Cross-site request frogery攻击。

3.cookie 和session 的区别?

1cookie数据存放在客户的浏览器上,session数据放在服务器上。

2cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗考虑到安全应当使用session

3session会在一定时间内保存在服务器上。当访问增多,会比较占用服务器的性能考虑到减轻服务器性能方面,应当使用COOKIE

4)单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20cookie

5)建议:
   将登陆信息等重要信息存放为SESSION
  
其他信息如果需要保留,可以放在COOKIE

4.请简单说一下三次握手和四次挥手?什么是2msl?为什么要这样做?

(1)2MSL即两倍的MSL,TCP的TIME_WAIT状态也称为2MSL等待状态,

(2)当TCP的一端发起主动关闭,在发出最后一个ACK包后,即第3次握手完成后发送了第四次握手的ACK包后就进入了TIME_WAIT状态,

必须在此状态上停留两倍的MSL时间,等待2MSL时间主要目的是怕最后一个 ACK包对方没收到,那么对方在超时后将重发第三次握手的FIN包,主动关闭端接到重发的FIN包后可以再发一个ACK应答包。

(3)在TIME_WAIT状态 时两端的端口不能使用,要等到2MSL时间结束才可继续使用。

(4)当连接处于2MSL等待阶段时任何迟到的报文段都将被丢弃。

不过在实际应用中可以通过设置 SO_REUSEADDR选项达到不必等待2MSL时间结束再使用此端口。

5.什么是僵尸进程和孤儿进程,怎么避免僵尸进程?

(1)孤儿进程:父进程退出,子进程还在运行的这些子进程都是孤儿进程,孤儿进程将被init进程(进 程号为1)所收养,并由init进程对它们完成状态收集工作。

(2)僵尸进程:进程使用fork创建子进程,如果子进程退出,而父进程并没有调用wait或waitpid获取子进程的状态信息,那么子进程的进程描述符仍然保存在系统中的这些进程是僵尸进程。

(3)避免僵尸进程的方法:

1.fork两次用孙子进程去完成子进程的任务。

2.用wait()函数使父进程阻塞。

3.使用信号量,在signal handler中调用 waitpid,这样父进程不用阻塞。

6.长链接与短链接的区别?

(1)短连接

连接->传输数据->关闭连接

HTTP是无状态的,浏览器和服务器每进行一次HTTP操作,就建立一次连接,但任务结束后就中断连接。短连接是指SOCKET连接后发送后接收完数据后马上断开连接。

(2)长连接

连接->传输数据->保持连接->传输数据->....->关闭连接

长连接指建立SOCKET连接后不管是否使用都保持连接,但安全性较差。

7.HTTP协议状态码有什么用,都表示什么意思

作用:告诉用户当前操作所处的状态

200 OK 服务器成功处理了请求(这个是我们见到最多的)

301/302 Moved Permanently(重定向)请求的URL已移走。Response中应该包含一个Location URL, 说明资源现在所处的位置

304 Not Modified(未修改)客户的缓存资源是最新的, 要客户端使用缓存

404 Not Found 未找到资源

501 Internal Server Error服务器遇到一个错误,使其无法对请求提供服

8、死锁

(1)原因: 1.竞争资源2.程序推进顺序不当

(2)必要条件:1.互斥条件2.请求和保持条件3.不剥夺条件4.环路等待条件

(3)处理死锁基本方法:

1、预防死锁(摒弃除1以外的条件)

2、避免死锁(银行家算法)

3、检测死锁(资源分配图)

    (4)解除死锁:1.剥夺死锁 2.撤销进程

9.从输入http://www.baidu.com/到页面返回,中间都是发生了什么?

(浏览器发送一个请求到返回一个页面的具体过程)

第一步,解析域名,找到ip

浏览器会缓存DNS一段时间,一般2-30分钟不等,如果有缓存,直接返回ip,否则下一步。

缓存中无法找到ip,浏览器会进行一个系统调用,查询hosts文件。如果找到,直接返回ip,否则下一步。

进行1 和2 本地查询无果,只能借助于网络,路由器一般都会有自己的DNS缓存,ISP服务商DNS缓存,这时一般都能够得到相应的ip,如果还是无果,只能借助于DNS递归解析了。

这时ISP的DNS服务器就会开始从根域名服务器开始递归搜索,从.com 顶级域名服务器,到baidu的域名服务器。 
到这里,浏览器就获得网络ip,在DNS解析过程中,常常解析出不同的IP。

第二步,浏览器于网站建立TCP连接

浏览器利用ip直接网站主机通信,浏览器发出TCP连接请求,主机返回TCP应答报文,浏览器收到应答报文发现ACK标志位为1,表示连接请求确认,浏览器返回TCP()确认报文,主机收到确认报文,三次握手,TCP连接建立完成。

第三步, 浏览器发起默认的GET请求

浏览器向主机发起一个HTTP-GET方法报文请求,请求中包含访问的URL,也就是http://www.baidu.com/还有User-Agent用户浏览器操作系统信息,编码等,值得一提的是Accep-Encoding和Cookies项。Accept-Encoding一般采用gzip,压缩之后传输html文件,Cookies如果是首次访问,会提示服务器简历用户缓存信息,如果不是,可以利用Cookies对应键值,找到相应缓存,缓存里面存放着用户名,密码和一些用户设置项

第四步,显示页面或返回其他

返回状态码200 OK,表示服务器可以响应请求,返回报文,由于在报头中Content-type为“text/html”,浏览器以HTML形式呈现,而不是下载文件。 
但是对于大型网站存在多个主机站点,往往不会直接返回请求页面,而是重定向。返回的状态码就不是 200 OK, 而是301,302以3开头的重定向吗。浏览器在获取了重定向响应后,在响应报文中Location项找到重定向地址,浏览器重新第一步访问即可。

10.使用Socket套接字需要传入哪些参数:

1.通讯方式可以选择AF_INET(用于 Internet 进程间通信) 或者 AF_UNIX(用于同一台机器进程间通信),实际工作中常用AF_INET

2.套接字类型套接字类型,可以是 SOCK_STREAM(流式套接字,主要用于 TCP 协议)或者 SOCK_DGRAM(数据报套接字,主要用于 UDP 协议)

 

 

                                              第三章 数据库

1.说一下mysql数据库存储的原理?

储存过程是一个可编程的函数,它在数据库中创建并保存。它可以有SQL语句和一些特殊的控制结构组成。当希望在不同的应用程序或平台上执行相同的函数,或者封装特定功能时,存储过程是非常有用的。数据库中的存储过程可以看做是对编程中面向对象方法的模拟。它允许控制数据的访问方式。存储过程通常有以下优点:

a、存储过程能实现较快的执行速度。

b、存储过程允许标准组件是编程。

c、存储过程可以用流程控制语句编写,有很强的灵活性,可以完成复杂的判断和较复杂的运算。

d、存储过程可被作为一种安全机制来充分利用。

e、存储过程能够减少网络流量。

2.事务的特性?

(1)原子性(Atomicity):事务中的全部操作在数据库中是不可分割的,要么全部完成,要么均不执行。

(2)一致性(Consistency):几个并行执行的事务,其执行结果必须与按某一顺序串行执行的结果相一致。

(3)隔离性(Isolation):事务的执行不受其他事务的干扰,事务执行的中间结果对其他事务必须是透明的。

(4)持久性(Durability):对于任意已提交事务,系统必须保证该事务对数据库的改变不被丢失,即使数据库出现故障

3.使用Mysql数据库中的事务的方法?

MYSQL 事务处理主要有两种方法:

1、用 BEGIN, ROLLBACK, COMMIT来实现

BEGIN 开始一个事务

ROLLBACK 事务回滚

COMMIT 事务确认

2、直接用 SET 来改变 MySQL 的自动提交模式:

SET AUTOCOMMIT=0 禁止自动提交

SET AUTOCOMMIT=1 开启自动提交

4.数据库索引

数据库索引,是数据库管理系统中一个排序的数据结构,以协助快速查询、更新数据库表中数据。索引的实现通常使用B_TREE。B_TREE索引加速了数据访问,因为存储引擎不会再去扫描整张表得到需要的数据;相反,它从根节点开始,根节点保存了子节点的指针,存储引擎会根据指针快速寻找数据。

5.索引怎么建立?原理是什么?

在表格上面创建某个一个唯一的索引。唯一的索引意味着两个行不能拥有相同的索引值。

CREATE UNIQUE INDEX 索引名称

ON 表名称 (列名称)

“列名称”规定你需要索引的列

原理:索引问题就是一个查找问题。

数据库索引,是数据库管理系统中一个排序的数据结构,以协助快速查询、更新数据库表中数据。索引的实现通常使用B树及其变种B+树。
在数据之外,数据库系统还维护着满足特定查找算法的数据结构,这些数据结构以某种方式引用(指向)数据,这样就可以在这些数据结构上实现高级查找算法。这种数据结构,就是索引。

6.在关系型数据库中,索引(index)存在的意义是什么?

(1)通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。

(2)可以大大加快数据的检索速度,这也是创建索引的最主要的原因。

(3)可以加速表和表之间的连接,特别是在实现数据的参考完整性方面特别有意义。

(4)在使用分组和排序子句进行数据检索时,同样可以显著减少查询中分组和排序的时间。

(5)通过使用索引,可以在查询的过程中,使用优化隐藏器,提高系统的性能。

7.BTree索引和Hash索引的优缺点各是什么?

(1)BTree(多路搜索树,并不是二叉的)是一种常见的数据结构。使用BTree结构可以显著减少定位记录时所经历的中间过程,从而加快存取速度。这个数据结构一般用于数据库的索引,综合效率较高。

不适合:单列索引的列不能包含null的记录,复合索引的各个列不能包含同时为null的记录,否则会全表扫描;

不适合键值较少的列(重复数据较多的列);前导模糊查询不能利用索引(like '%XX'或者like '%XX%')

(2)Hash散列索引

Hash散列索引是根据HASH算法来构建的索引。虽然 Hash 索引效率高,但是 Hash 索引本身由于其特殊性也带来了很多限制和弊端,主要有以下这些。

适合:精确查找非常快(包括= <> 和in),其检索效率非常高,索引的检索可以一次定位,不像BTree 索引需要从根节点到枝节点,所以 Hash 索引的查询效率要远高于 B-Tree 索引。

不适合:

1、不适合模糊查询和范围查询(包括like,>,<,between……and等),由于 Hash 索引比较的是进行 Hash 运算之后的 Hash 值,所以它只能用于等值的过滤,不能用于基于范围的过滤,因为经过相应的 Hash 算法处理之后的 Hash 值的大小关系,并不能保证和Hash运算前完全一样;

2、不适合排序,数据库无法利用索引的数据来提升排序性能,同样是因为Hash值的大小不确定;

复合索引不能利用部分索引字段查询,Hash 索引在计算 Hash 值的时候是组合索引键合并后再一起计算 Hash 值,而不是单独计算 Hash 值,所以通过组合索引的前面一个或几个索引键进行查询的时候,Hash 索引也无法被利用。

同样不适合键值较少的列(重复值较多的列);

8.redis 和 mysql 的区别

readis 是内存数据库, 数据保存在内存中, 速度快。

mysql 是关系型数据库,持久化存储,存放在磁盘里面,功能强大。检索的话, 会涉及到一定的 IO, 数据访问也就慢。

9.你用的mysql是哪个引擎,各引擎之间有什么区别?

主要 MyISAM 与 InnoDB 两个引擎,其主要区别如下:

InnoDB 支持事务,MyISAM 不支持,这一点是非常之重要。事务是一种高级的处理方式,如在一些列增删改中只要哪个出错还可以回滚还原,而 MyISAM就不可以了;

MyISAM 适合查询以及插入为主的应用,InnoDB 适合频繁修改以及涉及到安全性较高的应用;

InnoDB 支持外键,MyISAM 不支持;

MyISAM 是默认引擎,InnoDB 需要指定;

InnoDB 不支持 FULLTEXT 类型的索引;

InnoDB 中不保存表的行数,如 select count(*) from table 时,InnoDB;需要扫描一遍整个表来计算有多少行,但是 MyISAM 只要简单的读出保存好的行数即可。注意的是,当 count(*)语句包含 where 条件时 MyISAM 也需要扫描整个表;

对于自增长的字段,InnoDB 中必须包含只有该字段的索引,但是在 MyISAM表中可以和其他字段一起建立联合索引;清空整个表时,InnoDB 是一行一行的删除,效率非常慢。MyISAM 则会重建表;

InnoDB 支持行锁(某些情况下还是锁整表,如 update table set a=1 where user like '%lee%'

10.Redis和MongoDB的优缺点

MongoDB 和 Redis 都是 NoSQL, 采用结构型数据存储。 二者在使用场景中, 存在一定的区别, 这也主要由于二者在内存映射的处理过程, 持久化的处理方法不同。 MongoDB 建议集群部署, 更多的考虑到集群方案,Redis 更偏重于进程顺序写入, 虽然支持集群, 也仅限于主-从模式.

Redis 优点:

读写性能优异

支持数据持久化, 支持 AOF 和 RDB 两种持久化方式

支持主从复制, 主机会自动将数据同步到从机, 可以进行读写分离。

数据结构丰富: 除了支持 string 类型的 value 外还支持string、 hash、 set、 sortedset、 list 等数据结构。

Redis缺点:

Redis 不具备自动容错和恢复功能, 主机从机的宕机都会导致前端部分读写请求失败, 需要等待机器重启或者手动切换前端的 IP才能恢复。

主机宕机, 宕机前有部分数据未能及时同步到从机, 切换 IP后还会引入数据不一致的问题, 降低了系统的可用性。

Redis 的主从复制采用全量复制, 复制过程中主机会 fork 出一个子进程对内存做一份快照, 并将子进程的内存快照保存为文件发送给从机, 这一过程需要确保主机有足够多的空余内存。 若快照文件较大, 对集群的服务能力会产生较大的影响, 而且复制过程是在从机新加入集群或者从机和主机网络断开重连时都会进行, 也就是网络波动都会造成主机和从机间的一次全量的数据复制, 这对实际的系统运营造成了不小的麻烦。

Redis 较难支持在线扩容, 在集群容量达到上限时在线扩容会变得很复杂。 为避免这一问题, 运维人员在系统上线时必须确保有足够的空间, 这对资源造成了很大的浪费。

MongoDB优点:

弱一致性(最终一致) , 更能保证用户的访问速度文档结构的存储方式, 能够更便捷的获取数内置 GridFS, 高效存储二进制大对象 (比如照片和视频)

支持复制集、 主备、 互为主备、 自动分片等特性

动态查询

全索引支持,扩展到内部对象和内嵌数组

MongoDB缺点:

不支持事务

MongoDB 占用空间过大

维护工具不够成熟

10.数据库优化方案

优化索引、SQL 语句、分析慢查询

设计表的时候严格根据数据库的设计范式来设计数据库

使用缓存,把经常访问到的数据而且不需要经常变化的数据放在缓存中,能节约磁盘IO

优化硬件;采用SSD,使用磁盘队列技术(RAID0,RAID1,RDID5)等;

采用MySQL 内部自带的表分区技术,把数据分层不同的文件,能够提高磁盘的读取效率

垂直分表;把一些不经常读的数据放在一张表里,节约磁盘I/O

主从分离读写;采用主从复制把数据库的读操作和写入操作分离开来

分库分表分机器(数据量特别大),主要的的原理就是数据路由

选择合适的表引擎,参数上的优化

进行架构级别的缓存,静态化和分布式

不采用全文索引

采用更快的存储方式,例如NoSql存储经常访问的数据

 

11.怎样解决海量数据的存储和访问造成系统设计瓶颈的问题?

- 水平切分数据库: 可以降低单台机器的负载, 同时最大限度的降低了宕机造成的损失; 分库降低了单点机器的负载; 分表, 提高了数据操作的效率,

- 负载均衡策略: 可以降低单台机器的访问负载, 降低宕机的可能性;

- 集群方案:解决了数据库宕机带来的单点数据库不能访问的问题;

- 读写分离策略:最大限度了提高了应用中读取数据的速度和并发量;

12.怎样解决数据库高并发的问题?

解决数据库高并发:

分表分库

数据库索引

redis缓存数据库

读写分离

负载均衡集群:将大量的并发请求分担到多个处理节点。由于单个处理节点的故障不影响整个服务,负载均衡集群同时也实现了高可用性。

12.数据库负载均衡

负载均衡集群是由一组相互独立的计算机系统构成,通过常规网络或专用网络进行连接, 由路由器衔接在一起, 各节点相互协作、 共同负载、 均衡压力, 对客户端来说, 整个群集可以视为一台具有超高性能的独立服务器。

1、 实现原理

实现数据库的负载均衡技术,首先要有一个可以控制连接数据库的控制端。 在这里, 它截断了数据库和程序的直接连接, 由所有的程序来访问这个中间层, 然后再由中间层来访问数据库。 这样, 我们就可以具体控制访问某个数据库了,然后还可以根据数据库的当前负载采取有效的均衡策略, 来调整每次连接到哪个数据库。

2、 实现多据库数据同步

对于负载均衡,最重要的就是所有服务器的数据都是实时同步的。这是一个集群所必需的, 因为, 如果数不据实时、 不同步, 那么用户从一台服务器读出的数据, 就有别于从另一台服务器读出的数据, 这是不能允许的。 所以必须实现数据库的数据同步。 这样, 在查询的时候就可以有多个资源, 实现均衡。比较常用的方法是 Moebius for SQL Server 集群, Moebius for SQL Server 集群采用将核心程序驻留在每个机器的数据库中的办法, 这个核心程序称为 Moebius for SQL Server 中间件, 主要作用是监测数据库内数据的变化并将变化的数据同步到其他数据库中。 数据同步完成后客户端才会得到响应, 同步过程是并发完成的,所以同步到多个数据库和同步到一个数据库的时间基本相等; 另外同步的过程是在事务的环境下完成的, 保证了多份数据在任何时刻数据的一致性。 正因为 Moebius 中间件宿主在数据库中的创新, 让中间件不但能知道数据的变化, 而且知道引起数据变化的 SQL 语句,根据 SQL 语句的类型智能的采取不同的数据同步的策略以保证数据同步成本的最小化。数据条数很少, 数据内容也不大, 则直接同步数据数据条数很少, 但是里面包含大数据类型, 比如文本, 二进制数

据等, 则先对数据进行压缩然后再同步, 从而减少网络带宽的占用和传输所用的时间。数据条数很多,此时中间件会拿到造成数据变化的 SQL 语句, 然后对 SQL 语句进行解析, 分析其执行计划和执行成本, 并选择是同步数据还是同步 SQL 语句到其他的数据库中。此种情况应用在对表结构进行调整或者批量更改数据的时候非常有用。

3、 优缺点优点:

**优点:**

- (1) 扩展性强: 当系统要更高数据库处理速度时, 只要简单地增加数据库服务器就 可以得到扩展。

- (2) 可维护性: 当某节点发生故障时, 系统会自动检测故障并转移故障节点的应用, 保证数据库的持续工作。

- (3) 安全性: 因为数据会同步的多台服务器上, 可以实现数据集的冗余, 通过多份数据来保证安全性。 另外它成功地将数据库放到了内网之中, 更好地保护了数据库的安全性。

- (4) 易用性: 对应用来说完全透明, 集群暴露出来的就是一个IP

**缺点:**

- (1) 不能够按照 Web 服务器的处理能力分配负载。

- (2) 负载均衡器(控制端)故障, 会导致整个数据库系统瘫痪。

13.数据库备份怎么做,服务器挂了怎么办?

备份数据库

shell> mysqldump -h host -u root -p dbname >dbname_backup.sql

恢复数据库

shell> mysqladmin -h myhost -u root -p create dbname

shell> mysqldump -h host -u root -p dbname < dbname_backup.sql

14.如何把整个数据库导出来,再导入指定数据库中

导出:

mysqldump  [-h主机]  -u用户名 -p 数据库名 > 导出的数据库名.sql

导入指定的数据库中:

第一种方法:

mysqldump  [-h主机]   -u用户名 -p 数据库名 < 导出的数据库名.sql

第二种方法:

先创建好数据库,因为导出的文件里没有创建数据库的语句,如果数据库已经建好,则不用再创建。

create database example charset=utf8;(数据库名可以不一样) 

切换数据库:

use example; 

导入指定sql文件:

mysql>source /path/example.sql; 

15.数据库怎么优化查询效率?

1、储存引擎选择:如果数据表需要事务处理,应该考虑使用InnoDB,因为它完全符合ACID特性。如果不需要事务处理,使用默认存储引擎MyISAM是比较明智的

2、分表分库,主从。

3、对查询进行优化,要尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引

4、应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描

5、应尽量避免在 where 子句中使用 != 或 <> 操作符,否则将引擎放弃使用索引而进行全表扫描

6、应尽量避免在 where 子句中使用 or 来连接条件,如果一个字段有索引,一个字段没有索引,将导致引擎放弃使用索引而进行全表扫描

7、Update 语句,如果只更改1、2个字段,不要Update全部字段,否则频繁调用会引起明显的性能消耗,同时带来大量日志

8、对于多张大数据量(这里几百条就算大了)的表JOIN,要先分页再JOIN,否则逻辑读会很高,性能很差。

16.如果每天有5T的用户数据量需要存入mysql中,怎么优化数据库?

1、尽量使数据库一次性写入Data File 
    2、减少数据库的checkpoint 操作 
    3、程序上尽量缓冲数据,进行批量式插入与提交 
    4、减少系统的IO冲突

17.如何查找MySQL中查询慢的SQL语句

1,slow_query_log

这个参数设置为ON,可以捕获执行时间超过一定数值的SQL语句。

2,long_query_time

当SQL语句执行时间超过此数值时,就会被记录到日志中,建议设置为1或者更短。

 

                                                 第四章 前端

1.什么是css初始化?有什么好处?

 

- CSS初始化是指重设浏览器的样式。不同的浏览器默认的样式可能不尽相同,如果没对CSS初始化往往会出现浏览器之间的页面差异。

- 好处:能够统一标签在各大主流浏览器中的默认样式,使得我们开发网页内容时更加方便简洁,同时减少CSS代码量,节约网页下载时间。

 

2.简述浮动的特征和清除浮动的方法?

- **浮动的特征:**

- 浮动元素有左浮动(float:left)和右浮动(float:right)两种

- 浮动的元素会向左或向右浮动,碰到父元素边界、其他元素才停下来

- 相邻浮动的块元素可以并在一行,超出父级宽度就换行

- 浮动让行内元素或块元素转化为有浮动特性的行内块元素(此时不会有行内块元素间隙问题)

- 父元素如果没有设置尺寸(一般是高度不设置),父元素内整体浮动的子元素无法撑开父元素,父元素需要清除浮动

- **清除浮动的方法:**

- 父级上增加属性overflow:hidden

- 在最后一个子元素的后面加一个空的div,给它样式属性 clear:both

- 使用成熟的清浮动样式类,clearfix

```css

.clearfix:after,.clearfix:before{ content: "";display: table;}

.clearfix:after{ clear:both;}

.clearfix{zoom:1;}

```

3.对react和vue的了解?

      React是一个用于构建用户界面的js React主要用于构建UI MVC 中的 V(视图)拥有较高的性能,代码逻辑非常简单

   Vue 是一套用于构建用户界面的渐进式框架Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。

 

 

                                                  第五章 web框架

1.MVC解读

M:Model,模型,和数据库进行交互

V:View,视图,负责产生Html页面

C:Controller,控制器,接收请求,进行处理,与M和V进行交互,返回应答。

 

1、 用户点击注按钮,将要注册的信息发送给网站服务器。

2、 Controller控制器接收到用户的注册信息,Controller会告诉Model层将用户的注册信息保存到数据库

3、 Model层将用户的注册信息保存到数据库

4、 数据保存之后将保存的结果返回给Model模型,

5、 Model层将保存的结果返回给Controller控制器。

6、 Controller控制器收到保存的结果之后,或告诉View视图,view视图产生一个html页面。

7、 View将产生的Html页面的内容给了Controller控制器。

8、 Controller将Html页面的内容返回给浏览器。

9、 浏览器接受到服务器Controller返回的Html页面进行解析展示。

 

2.Django创建项目后,项目文件夹下的组成部分(对mvt的理解)

项目文件夹下的组成部分:

manage.py是项目运行的入口,指定配置文件路径。

与项目同名的目录,包含项目的配置文件

___init.py是一个空文件,作用是这个目录可以被当作包使用。

settings.py是项目的整体配置文件。

urls.py是项目的URL配置文件。

wsgi.py是项目与WSGI兼容的Web服务器入口

 

3.MVT解读

M:Model,模型,和MVC中的M功能相同,和数据库进行交互。

V:view,视图,和MVC中的C功能相同,接收请求,进行处理,与M和T进行交互,返回应答。

T:Template,模板,和MVC中的V功能相同,产生Html页面

1、 用户点击注册按钮,将要注册的内容发送给网站的服务器。

2、 View视图,接收到用户发来的注册数据,View告诉Model将用户的注册信息保存进数据库。

3、 Model层将用户的注册信息保存到数据库中。

4、 数据库将保存的结果返回给Model

5、 Model将保存的结果给View视图。

6、 View视图告诉Template模板去产生一个Html页面。

7、 Template生成html内容返回给View视图。

8、 View将html页面内容返回给浏览器。

9、 浏览器拿到view返回的html页面内容进行解析,展示。

(新增)说一下Django,MIDDLEWARES中间件的作用?

中间件是介于request与response处理之间的一道处理过程,相对比较轻量级,并且在全局上改变django的输入与输出。

 

(新增)django中那里用到了线程,那里用到了协程,那里用到了进程?

```

1.django利用多线程增加异步任务.celery消息队列.

2.django中使用多线程发送邮件.send_mail().

3.django原生为单线程序,当第一个请求没有完成时,第二个请求阻塞,直到第一个请求完成,第二个请 求才会执行.

使用uwsgi编程多并发,使用nginx+uwsgi提供高并发,nginx的并发能力超高,单台并发能力过万 (不绝对).

4.django自带的development server为多线程模式,但是他还有一个小问题就是它不是线程安全的。 可能在请求很多时会出现数据不同步,当然,这一般不是问题,因为我们通常只在自己机器上调试时才用Development Server。

```

 

 

4.django关闭浏览器,怎么清除cookies和session?

cookie是有过期时间的,如果不指定,默认关闭浏览器之后cookie就会过期。

如果 SESSION_EXPIRE_AT_BROWSER_CLOSE 设置为 False ,cookie可以在用户浏览器中保持有效达 SESSION_COOKIE_AGE 秒(存活时间)。

如果不想用户每次打开浏览器都必须重新登陆的话,可以用这个参数。

如果 SESSION_EXPIRE_AT_BROWSER_CLOSE 设置为 True ,当浏览器关闭时,Django会使cookie失效

Django中操作session:

session也是有过期时间,如果不指定,默认两周就会过期。

request.session.set_expiry(0);那么当浏览器关闭时,session失效

删除session:del request[key]

5.Django里QuerySet的get和filter方法的区别

1、输入参数

- get 的参数只能是model中定义的那些字段,只支持严格匹配

- filter 的参数可以是字段,也可以是扩展的where查询关键字,如in,like等

2、返回值

- get 返回值是一个定义的model对象

- filter 返回值是一个新的QuerySet对象,然后可以对QuerySet在进行查询返回新的QuerySet对象,支持链式操作QuerySet一个集合对象,可使用迭代或者遍历,切片等,但是不等于list类型(使用一定要注意)

3、异常

- get 只有一条记录返回的时候才正常,也就说明get的查询字段必须是主键或者唯一约束的字段。当返回多条记录或者是没有找到记录的时候都会抛出异常

- filter 有没有匹配的记录都可以。

 

6.简述Django对http请求的执行流程

> 在接受一个Http请求之前的准备

> 启动一个支持WSGI网关协议的服务器监听端口等待外界的Http请求,比如Django自带的开发者服务器或者uWSGI服务器。

> 服务器根据WSGI协议指定相应的Handler来处理Http请求,并且初始化该Handler,在Django框架中由框架自身负责实现这一个Handler。

> 此时服务器已处于监听状态,可以接受外界的Http请求

> 当一个http请求到达服务器的时候

> 服务器根据WSGI协议从Http请求中提取出必要的参数组成一个字典(environ)并传入Handler中进行处理。

> 在Handler中对已经符合WSGI协议标准规定的http请求进行分析,比如加载Django提供的中间件,路由分配,调用路由匹配的视图等。

> 返回一个可以被浏览器解析的符合Http协议的HttpResponse。

 

7.简述Django下的(内建)缓存机制

> Django根据设置的缓存方式,浏览器第一次请求时,cache会缓存单个变量或整个网页等内容到硬盘或者内存中,同时设置response头部,当浏览器再次发起请求时,附带f-Modified-Since请求时间到Django,Django 发现f-Modified-Since会先去参数之后,会与缓存中的过期时间相比较,如果缓存时间比较新,则会重新请求数据,并缓存起来然后返回response给客户端,如果缓存没有过期,则直接从缓存中提取数据,返回给response给客户端。

8.Django中model的SlugField类型字段有什么用途?

> SlugField字段是将输入的内容中的空格都替换成‘-’之后保存,Slug 是一个新闻术语,通常是某些东西的短标签。一个slug只能包含字母、数字、下划线或者是连字符,通常用来作为短标签。通常它们是用来放在URL里的。

> SlugField字段的Field.db_index自动设置为True。

> 通常根据另一个值自动生成slug来填充到SlugField的值

9.第三方支付是如何实现的?

聚合支付:ping++,付钱拉,Paymax...

直接对接:支付宝,微信,qq钱包,银联,百度钱包...

建议:去该类官网了解接口相关知识

1、简单加密

目的是为了保证上传的参数信息没有被篡改,主要分成三部分

接口参数 : 需要和第三方对接的参数

加密类型 : 使用什么类型加密,一般为MD5

加密密文 : 使用接口参数和第三方生成的Code值(固定salt),进行MD5加密成密文

Md5作为数字签名 H(A)=P 已知A P,在特殊情况下可以伪造A1 满足H(A1)=p

2、生成加密的密钥Key

随机生成16位的加密密钥Key,用于对上一步的内容进行对称加密

3、使用证书加密密钥Key

对随机生成的密钥key进行加密。防止在传输过程中被截获破解。

使用了三种加密算法:

摘要算法:验证原文是否被篡改

对称加密算法:使用密钥对原文进行加密(AES)

非对称加密算法:对密钥进行分发

发送方:

入参 + H(入参+分配的code)= P 得到键值对 ParamMap

AES ( ParamMap + 随机生成的Key ) 进行对称加密得到 DecodeString

随机生成的Key + 私钥证书加密, 得到 EnCodeKey

Http发送请求, 将 DecodeString 和 EnCodeKey发送给第三方支付公司

接收方:

证书加密的随机数,使用私钥解密得到 Akey

AES(AKey) = sourceCode("入参","P")

验证:H(sourceCode + code) = P

 

(新增)Form表单的提交和ajax的提交

1、提交方式

form表单通常是通过在HTML中定义的action,method及submit来进行表单提交,另外也可以通过在js中调用submit函数来进行表单提交。

具体的提交方式有很多种,比如可以通过封装成XMLHttpRequest对象进行提交。Ajax是基于XMLHttpRequest进行的。

2、页面刷新

Form提交,更新数据完成后,需要转到一个空白页面再对原页面进行提交后处理。哪怕是提交给自己本身的页面,也是需要刷新的,因此局限性很大。

Ajax可以实现页面的局部刷新,整个页面不会刷新。

3、请求由谁来提交

Form提交是浏览器完成的,无论浏览器是否开启JS,都可以提交表单。

Ajax是通过js来提交请求,请求与响应均由js引擎来处理,因此不启用JS的浏览器,无法完成该操作。

4、是否可以上传文件

最初,ajax出于安全性考虑,不能对文件进行操作,所以就不能通过ajax来实现文件上传,但是通过隐藏form提交则可以实现这个功能,所以这也是用隐藏form提交的主要用途。

后来XMLHttpRequest引入了FormData类型,使得通过Ajax也可以实现文件上传。

(新增)类似qq在线人数,用ajax怎么实现?

可以使用ajax的异步处理,(单使一个一个进程或线程)每隔一段时间请求数据库人数数据。

Ajax主要功能是实现异步,事件触发,Ajax 会创建一个xmlhttprequest,对象,把http方法和目标url,以及回调函数函数设置到xmlhttprequest对象,通过xmlhttprequest对象向浏览器发送请求,请求发送后继续响应用户,并交互,只有等到请求真正从服务器返回的时候才调用callback()函数,对响应数据进行处理.

关键的技术: xhtml css ,用来格式化输出页面,dom (动态修改文档的内容和结构,),xml进行数据交换和处理, javascript 进行上述技术的捆绑,使其协同工作.

**总结:**

```

Ajax 利用javascript创建xmlhttpscript对象,再由javascript调用xmljtmlscript对象完成随异步通讯最后通过javascript 调用dom的属性和方法进行页面不完全刷新

(新增)项目中使用什么调试?

- 1、在Eclipse+Pydev中调试Django

适用于测试环境。

可进行单步调试,查看变量值,当出现except时,可以用Python标准模块traceback的print_exc()函数查看函数调用链,

是最强大的调试利器。

- 2、使用Django的error page

适用于测试环境。

Django的error page功能很强大,能提供详细的traceback,包括局部变量的值,以及一个纯文本的异常信息。拥有同phpinfo()

一样的作用,可以展示当前应用的相关设置,包括请求中的 GET, POST and COOKIE 数据以及HTTP环境中的所有重要META fields。

- 3、django-debug-toolbar

不确定是否用于生产环境。听说功能非常强大。

- 4、输出log到开发服务器终端中

适用于生产环境。

借助python的logging模块

10.项目怎么优化?提过哪些建议?

对于开发人员来说,网站性能优化一般包括Web前端性能优化、应用服务器性能优化、存储服务器性能优化三类。

**Web前端性能优化:**

- 1、减少http请求 http协议是无状态的应用层协议,意味着每次http请求都需要建立通信链路、进行数据传输,而在服务器端,每个http请求都需要启动独立的线程去处理。减少http请求的数目可有效提高访问性能。**减少http的主要手段是合并CSS、合并javascript、合并图片。**

- 2、使用浏览器缓存 对一个网站而言,CSS、javascript、logo、图标,这些静态资源文件更新的频率都比较低,而这些文件又几乎是每次http请求都需要的。如果将这些文件缓存在浏览器中,可以极好的改善性能。通过设置http头中的cache-control和expires的属性,可设定浏览器缓存,缓存时间可以自定义。

- 3、启用压缩 在服务器端对文件进行压缩,在浏览器端对文件解压缩,可有效减少通信传输的数据量。如果可以的话,尽可能的将外部的脚本、样式进行合并,多个合为一个。文本文件的压缩效率可达到80%以上,因此HTML、CSS、javascript文件启用GZip压缩可达到较好的效果。但是压缩对服务器和浏览器产生一定的压力,在网络带宽良好,而服务器资源不足的情况下要综合考虑。

- 4、CSS放在页面最上部,javascript放在页面最下面 浏览器会在下载完成全部CSS之后才对整个页面进行渲染,因此最好的做法是将CSS放在页面最上面,让浏览器尽快下载CSS。 Javascript则相反,浏览器在加载javascript后立即执行,有可能会阻塞整个页面,造成页面显示缓慢,因此javascript最好放在页面最下面。

**应用服务器优化**

应用服务器也就是处理网站业务的服务器,网站的业务代码都部署在这里,主要优化方案有缓存、异步、集群等。

**1、合理使用缓存**

当网站遇到性能瓶颈时,第一个解决方案一般是缓存。在整个网站应用中,缓存几乎无处不在,无论是客户端,还是应用服务器,或是数据库服务器。在客户端和服务器的交互中,无论是数据、文件都可以缓存,合理使用缓存对网站性能优化非常重要。

缓存一般用来存放那些读写次数比较高,变化较少的数据,比如网站首页的信息、商品的信息等。应用程序读取数据时,一般是先从缓存中读取,如果读取不到或数据已失效,再访问磁盘数据库,并将数据再次写入缓存。

缓存的基本原理是将数据存储在相对有较高访问速度的存储介质中,比如内存。一方面缓存访问速度快,另一方面,如果缓存的数据是需要经过计算处理得到的,那使用缓存还可以减少服务器处理数据的计算时间。

使用缓存并不是没有缺陷:内存资源是比较宝贵的,不可能将所有数据都缓存,一般频繁修改的数据不建议使用缓存,这会导致数据不一致。

网站数据缓存一般遵循二八定律,即80%的访问都在20%的数据上。所以,一般将这20%的数据缓存,可以起到改善系统性能,提高服务器读取效率。

**2、异步操作**

使用消息队列将调用异步化,可以改善网站系统的性能。

在不使用消息队列的情况下,用户的请求直接写入数据库,在高并发的情况下,会对数据库造成非常大的压力,也会延迟响应时间。

在使用消息队列后,用户请求的数据会发送给消息队列服务器,消息队列服务器会开启进程,将数据异步写入数据库。消息队列服务器的处理速度远超过数据库,因此用户的响应延迟可得到改善。

消息队列可以将短时间内的高并发产生的事务消息,存储在消息队列中,从而提高网站的并发处理能力。在电商网站的促销活动中,合理使用消息队列,可以抵御短时间内用户高并发的冲击。

**3、使用集群**

在网站高并发访问的情况下,使用负载均衡技术,可以为一个应用构建由多台服务器组成的服务器集群,将并发访问请求,分发到多台服务器上处理,避免单一服务器因负载过大,而导致响应延迟。

**4、代码优化**

网站的业务逻辑代码主要部署在应用服务器上,需要处理复杂的并发事务。合理优化业务代码,也可以改善网站性能。

任何web网站都会遇到多用户的并发访问,大型网站的并发用户会达到数万。每个用户请求都会创建一个独立的系统进程去处理。由于线程比进程更轻量,占用资源更少,所以,目前主流的web应用服务器都采用多线程的方式,处理并发用户的请求,因此,网站开发多数都是多线程编程。

使用多线程的另一个原因是服务器有多个CPU,现在手机都到了8核CPU的时代,一般的服务器至少是16核CPU,要想最大限度的使用这些CPU,必须启动多线程。

那么,启动多少线程合适呢?

启动线程数和CPU内核数量成正比,和IO等待时间成正比。如果都是计算型的任务,那么线程数最多不要超过CPU内核数,因为启动再多,CPU也来不及调用。如果任务是等待读写磁盘、网络响应,那么多启动线程会提高任务并发度,提高服务器性能。

或者用个简化的公式来描述:

启动线程数 = (任务执行时间/(任务执行事件 - IO等待时间)) * CPU内核数

**5、存储优化**

数据的读写是网站处理并发访问的另一瓶颈。使用缓存虽然可以解决一部分数据读写压力,但很多时候,磁盘仍然是系统最严重的瓶颈。而且磁盘是网站最重要的资产,磁盘的可用性和容错性也至关重要。

机械硬盘和固态硬盘 机械硬盘是目前最常用的硬盘,通过马达带动磁头到指定磁盘的位置访问数据,每次访问数据都需要移动磁头,在读取连续数据和随机访问上,磁头移动的次数相差巨大,因此机械硬盘的性能表现差别巨大,读写效率较低。而在网站应用中,大多数数据的访问都是随机的,在这种情况下,固态硬盘具有更高的性能。但目前固态硬盘在工艺上、数据可靠性上还有待提升,因此固态硬盘的使用尚未普及,从发展趋势看,取代机械硬盘应该是迟早的事情。

总结:

网站性能优化是在用户高并发访问,网站遇到问题时的解决方案。所以网站性能优化的主要内容是改善高并发用户访问情况下的网站响应速度。

网站性能优化的最终目的是改善用户的体验。但性能优化本身也是需要综合考虑的。比如说,性能提高一倍,服务器数量也要增加一倍,这样的优化是否可以考虑?

技术是由业务驱动的,离开业务的支撑,任何性能优化都是空中楼阁。

 

11.Flask和Django路由映射的区别?

在django中,路由是浏览器访问服务器时,先访问的项目中的url,再由项目中的url找到应用中url,这些url是放在一个列表里,遵从从前往后匹配的规则。在flask中,路由是通过装饰器给每个视图函数提供的,而且根据请求方式的不同可以一个url用于不同的作用。

12.Flask中正则URL的实现?

@app.route('<URL>')中URL显式支持string、int、float、path 4种类型,隐式支持正则

第一步:写正则类,继承BaseConverter,将匹配到的值设置为regex的值

class RegexUrl(BaseConverter):

    def __init__(self, url_map, *args):

        super(RegexUrl, self).__init__(url_map)

        self.regex = args[0]

第二步:把正则类赋值给我们定义的正则规则

app.url_map.converters['re'] = RegexUrl

第三步:在URL中使用正则

@app.route('/regex/<re("[a-z]{3}"):id>')

def regex111(id):

return 'id:%s'%id

 

13.Flask中请求上下文和应用上下文的区别和作用?

current_app、g就是应用上下文
requests、session就是请求上下文

手动创建上下文的两种方法:

with app.app_context()

app = current_app._get_current_object()

 

14.一个变量后写多个过滤器是如何执行?

{{ expression | filter1 | filter2 | ... }}  即 表达式(expression)使用filter1过滤后再使用filter2过滤..

 

 

15.Flask中数据库app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN']设置的作用?

作用:可以配置请求执行完逻辑之后自动提交,而不用我们每次都手动调用session.commit()

补充:

监听数据库中的数据,当发生改变,就会显示一些内容

app.config['SQLALCHEMY_TRACK_MODIFICATIONS']=True

显示打印的数据以及sql语句,建议不设置,默认为False

app.config['SQLALCHEMY_ECHO'] = True

16.模糊查询和精确查询的区别?

filter()模糊查询:把过滤器添加到原查询上,返回一个新查询

filter_by()精确查询:把等值过滤器添加到原查询上,返回一个新查询

17.对flask蓝图(Blueprint)的理解?

1.蓝图定义:

蓝图 /Blueprint 是Flask应用程序 组件化 的方法,可以在一个应用内或跨越 多个项目共用蓝图。使用蓝图可以极大地简化大型应用的开发难度,也为Flask扩展 提供了一种在应用中注册服务的集中式机制。

2.蓝图的应用场景

1,把一个应用分解为一个蓝图的集合。这对大型应用是理想的。一个项目可以实例化一个应用对象,初始化几个扩展,并注册一集合的蓝图。

2,以 URL 前缀和/或子域名,在应用上注册一个蓝图。 URL 前缀/子域名中的参数即成为这个蓝图下的所有视图函数的共同的视图参数(默认情况下)。

3,在一个应用中用不同的 URL 规则多次注册一个蓝图。

4,通过蓝图提供模板过滤器、静态文件、模板和其它功能。一个蓝图不一定要实现应用或者视图函数。

5,初始化一个 Flask 扩展时,在这些情况中注册一个蓝图。

3.蓝图的缺点

不能在应用创建后撤销注册一个蓝图而不销毁整个应用对象。

4.使用蓝图的三个步骤

1.创建 一个蓝图对象

blue = Blueprint("blue",__name__)

2.在这个蓝图对象上进行 操作 ,例如注册路由、指定静态文件夹、注册模板过滤器...

@blue.route('/')

def blue_index():

    return 'Welcome to my blueprint'

3.在应用对象上 注册 这个蓝图对象

app.register_blueprint(blue,url_prefix='/blue')

 

 

18.跨站请求伪造和跨站请求保护的实现?

图中Browse是浏览器,WebServerA是受信任网站/被攻击网站A,WebServerB是恶意网站/攻击网站B。
(1)一开始用户打开浏览器,访问受信任网站A,输入用户名和密码登陆请求登陆网站A。
(2)网站A验证用户信息,用户信息通过验证后,网站A产生Cookie信息并返回给浏览器。
(3)用户登陆网站A成功后,可以正常请求网站A。
(4)用户未退出网站A之前,在同一浏览器中,打开一个TAB访问网站B。
(5)网站B看到有人方式后,他会返回一些攻击性代码。
(6)浏览器在接受到这些攻击性代码后,促使用户不知情的情况下浏览器携带Cookie(包括sessionId)信息,请求网站A。这种请求有可能更新密码,添加用户什么的操作。

从上面CSRF攻击原理可以看出,要完成一次CSRF攻击,需要被攻击者完成两个步骤:
   1.登陆受信任网站A,并在本地生成COOKIE。
   2.在不登出A的情况下,访问危险网站 B。
如果不满足以上两个条件中的一个,就不会受到CSRF的攻击,以下情况可能会导致CSRF:
    1.登录了一个网站后,打开一个tab页面并访问另外的网站。
    2.关闭浏览器了后,本地的Cookie尚未过期,你上次的会话还没有已经结束。(事实上,关闭浏览器不能结束一个会话,但大多数人都会错误的认为关闭浏览器就等于退出登录/结束会话了……)

解决办法:就是在表单中添加from.csrf_token

19.Flask项目中如何实现session信息的写入?

flask中有三个session:

第一个:数据库中的session,例如:db.session.add()

第二个:在flask_session扩展中的session,使用:from flask_session import Session,使用第三方扩展的session可以把信息存储在服务器中,客户端浏览器中只存储sessionid

第三个:flask自带的session,是一个请求上下文, 使用:from flask import session。自带的session把信息加密后都存储在客户端的浏览器cookie中

20.Flask(__name__)中的__name__可以传入哪些值?

可以传入的参数:

1,字符串:‘hello’,

但是‘abc’,不行,因为abc是python内置的模块

2,__name__,约定俗成

不可以插入的参数

1,python内置的模块,re,urllib,abc等

2,数字

21.Flask中请求钩子的理解和应用

请求钩子是通过装饰器的形式实现的,支持以下四种:

1,before_first_request在处理第一个请求前运行

2,before_request:在每次请求前运行

3,after_request:如果没有未处理的异常抛出,在每次请求后运行

4,teardown_request:即使有未处理的异常抛出,在每次请求后运行

应用:

# 请求钩子

@api.after_request

def after_request(response):

    """设置默认的响应报文格式为application/json"""

    # 如果响应报文response的Content-Type是以text开头,则将其改为默认的json类型

    if response.headers.get("Content-Type").startswith("text"):

        response.headers["Content-Type"] = "application/json"

return response

22.自定义过滤器的步骤?

第一步:先定义自定义过滤器函数

def count_substring(string, substring):

    return string.count(substring)

第二步:注册自己定义的过滤器

app.jinja_env.filters['count_substring'] = count_substring

第三步:最后在模板文件html中直接使用注册时的键名

{#前面的作为原字符串string,传入的作为子字符串substring#}

{{ 'A long long long long long  long longabc string ' | count_substring('long') }}<br/>

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值