前言:
最近在面试找工作,整理一下遇到的面试题.大公司更倾向于基础,小公司更偏向于业务处理,但整体上遇到的面试问题大部分都会围绕于你简历中写了哪些技术.
写下这些面试题,权且当做对用到的技术做概念上的梳理.当然其中一些答案有的是我摘自别人的,可能存在不严谨的情况,建议自行验证
Django
讲一下Django的生命周期
浏览器发起请求>>WSGI创建socket服务端,接收请求(Httprequest)>>中间件处理请求>>url路由,根据当前请求的URL找到视图函数>>view视图,进行业务处理>>中间件处理响应>>WSGI返回响应(HttpResponse)>>浏览器渲染
说一下用过哪些中间件
缓存中间件: django.middleware.cache.UpdateCacheMiddleware django.middleware.cache.FetchFromCacheMiddleware 开启全站范围的缓存。 如果开启了这些缓存,任何一个由Django提供的页面将会被缓存,缓存时长在CACHE_MIDDLEWARE_SECONDS中配置定义。
会话中间件 django.contrib.sessions.middleware.SessionMiddleware 开启会话支持,session支持中间件,加入这个中间件,会在数据库中生成一个django_session的表。
通用中间件: django.middleware.common.CommonMiddleware 通用中间件,会处理一些URL,比如baidu.com会自动的处理成www.baidu.com。比如/blog/111会处理成/blog/111/自动加上反斜杠。
CSRF保护中间件 django.middleware.csrf.CsrfViewMiddleware 跨域请求伪造中间件。加入这个中间件,在提交表单的时候会必须加入csrf_token,cookie中也会生成一个名叫csrftoken的值,也会在header中加入一个HTTP_X_CSRFTOKEN的值来放置CSRF攻击。
用户授权中间件: django.contrib.auth.middleware.AuthenticationMiddleware 他会在每个HttpRequest对象到达view之前添加当前登录用户的user属性,也就是你可以在view中通过request访问user。
消息中间件 django.contrib.messages.middleware.MessageMiddleware 展示一些后台信息给前端页面。如果需要用到消息,还需要在INSTALLED_APPS中添加django.contrib.message才能有效。如果不需要,可以把这两个都删除。
XFrameOptionsMiddleware中间件 django.middleware.clickjacking.XFrameOptionsMiddleware 防止通过浏览器页面跨Frame出现clickjacking(欺骗点击)攻击出现。
Python
python中俩个列表如何取交集
获取两个list 的交集
- 方法一:
a=[2,3,4,5]
b=[2,5,8]
tmp = [j for j in a if j in b] #列表推导式求的两个列表的交集
print(tmp)
- 方法二:
print(list(set(a).intersection(set(b)))) # #列用集合的取交集方法
- 方法三:
lst = []
for i in a:
if i in b :
lst.append(i)
print(lst)
拓展:
获取两个 list 的差集
方法一:
ret = list(set(a)-set(b))
print(ret)
方法二:
print(list(set(b).difference(set(a)))) # b中有而a中没有的
获取两个 list 的并集
方法一:
ret = list(set(a)-set(b))
print(ret)
方法二:
print(list(set(b).difference(set(a)))) # b中有而a中没有的
python全局变量应用场景
Python 允许在所有函数的外部定义变量,这样的变量称为全局变量(Global Variable)
全局变量的默认作用域是整个程序,即全局变量既可以在各个函数的外部使用,也可以在各函数内部使用
globals() 函数为 Python 的内置函数,它可以返回一个包含全局范围内所有变量的字典,该字典中的每个键值对,键为变量名,值为该变量的值
locals() 函数也是 Python 内置函数之一,通过调用该函数,我们可以得到一个包含当前作用域内所有变量的字典。这里所谓的“当前作用域”指的是,在函数内部调用 locals() 函数,会获得包含所有局部变量的字典;而在全局范文内调用 locals() 函数,其功能和 globals() 函数相同
python可变数据类型有哪些
可变数据类型:list(列表)、dict(字典)、set(集合,不常用)
不可变数据类型:数值类型(int、float、bool)、string(字符串)、tuple(元组)
可变数据类型:当该数据类型对应的变量的值发生了变化时,如果它对应的内存地址不发生改变,那么这个数据类型就是 可变数据类型。
不可变数据类型:当该数据类型对应的变量的值发生了变化时,如果它对应的内存地址发生了改变,那么这个数据类型就是 不可变数据类型。
总结:可变数据类型更改值后,内存地址不发生改变。不可变数据类型更改值后,内存地址发生改变。
装饰器用过吗,写一个简单的装饰器
用自己的话总结一下
装饰器可完成对原函数的扩展,可传递函数做为参数
# 一个简单的装饰器
def wsm(f):
def wzj(*args,**kwargs):
s = time.time()
res = f(*args,**kwargs)
e = time.time()
h = (e -s)
print(f'当前耗时{h}秒')
return res
return wzj
@wsm
def func():
time.sleep(2)
list1 = [1,2,2,3]
list2 = list(set(list1))
print(list2)
func()
Docker
Dockerfile中ENTRYPOINT和CMD的区别:
- CMD命令设置容器启动后默认执行的命令及其参数,但CMD设置的命令能够被
docker run
命令后面的命令行参数替换 - ENTRYPOINT配置容器启动时的执行命令(不会被忽略,一定会被执行,即使运行
docker run
时指定了其他命令)
总结:CMD和ENTRYPOINT可指定容器启动运行的参数,但是真实启动时如果RUN后面修改了启动参数,那以RUN修改的参数优先,而ENTRYPOINT比较倔,就不改
ADD和COPY的区别:
- ADD支持从远程URL获取资源
- COPY只能从本地获取
docker的几种网络模型
- host模式:net=host 容器和宿主机共享network namespace
- container模式:net=container:NAME_or_ID 容器之间共享Network namespace,k8s中的pod就是多个容器共享一个Network namespace
- none模式:net=none 容器有独立的Network namespace,但并没有对其进行热河网络设置,如分配veth pair和网桥连接配置ip等
- bridge模式:net=bridge 默认为该模式
K8S
k8s的工作原理
用户创建pod请求信息>>存到etcd中>>scheduler查询分配未使用的node创建pod>>kubelet接收创建指令,实时汇报pod信息>>contrller-manager通过apiserver监控集群状态,确保集群处于预期工作中
用户通过kubectl或者APIserver的rest api接口提交需要运行的docker容器(创建pod请求)
api server将创建pod相关请求数据存储至etcd中
scheduler监听API server,查询还未分配的Node的pod,然后根据调度策略为这些pod分配节点
kubelet负责在所在的node节点上接收主节点发来的指令,管理pod及pod中的容器,并定时向master主节点汇报节点资源的使用情况及容器的情况
controller-manager则通过api-server监控整个集群的状态,并确保集群处于预期的工作
k8s中的常用组件
- etcd:提供数据库服务保存了整个集群的状态
- kube-apiserver:提供了资源操作的唯一入口,并提供认证、授权、访问控制、API注册和发现等机制
- kube-controller-manager:负责维护集群的状态,比如故障检测、自动扩展、滚动更新等
- cloud-controller-manager:是与底层云计算服务商交互的控制器
- kub-scheduler:负责资源的调度,按照预定的调度策略将Pod调度到相应的机器上
- kubelet:负责维护容器的生命周期,同时也负责Volume和网络的管理
- kube-proxy:负责为Service提供内部的服务发现和负载均衡,并维护网络规则
- container-runtime:是负责管理运行容器的软件,比如docker
k8s的网络模式
k8s 网络模型要符合四个基础原则、三个网络要求原则、一个架构原则、一个 IP 原则。
每个 Pod 都拥有一个独立的 IP 地址,而且假定所有 Pod 都在一个可以直接连通的、扁平的网络空间中,不管是否运行在同一 Node 上都可以通过 Pod 的 IP 来访问。
k8s 中的 Pod 的 IP 是最小粒度 IP。同一个 Pod 内所有的容器共享一个网络堆栈,该模型称为 IP-per-Pod 模型。
- Pod 由 docker0 实际分配的 IP。
- Pod 内部看到的 IP 地址和端口与外部保持一致。
- 同一个 Pod 内的不同容器共享网络,可以通过localhost来访问对方的端口,类似同一个虚拟机内不同的进程。
IP-per-Pod 模型从端口分配、域名解析、服务发现、负载均衡、应用配置等角度看,Pod 可以看做是一台独立的虚拟机或物理机。 - 所有容器都可以不用 NAT 的方式同别的容器通信。
- 所有节点都可以在不同 NAT 方式下同所有容器通信,反之亦然。
- 容器的地址和别人看到的地址是同一个地址。
pod有几种状态
- Pending:Pod创建已经提交给k8s,但是因为某种原因不能顺利创建,例如下载镜像慢,调度不成功等
- Running:Pod已经绑定到一个节点上了,并且已经创建了所有容器。只是有一个容器正在运行,或者在启动中。
- Secceeded:Pod中的所有容器都已经成功终止,不能重新启动。
- Failed: Pod中所有的容器均已经终止,且至少有一个容器已经在故障中终止。
- Unkown:由于某中原因apiserver无法获取到Pod的状态。通常是由于Master与pod所在的主机失去连接了
pod服务启动失败有哪些原因及排查:
# 获取信息
kubectl describe pod 资源id
# 查看日志
kubectl logs 资源id
# 进入资源中
kubectl exec -it 资源id bash
常见故障
-
Pod状态 一直处于Pending
Pending状态意味着Pod的YAML文件已经提交给Kubernetes,API对象已经被创建并保存在Etcd当中。但是,这个Pod里有些容器因为某种原因而不能被顺利创建。比如,调度不成功(可以通过kubectl describe pod 命令查看到当前Pod的事件,进而判断为什么没有调度)。可能原因:资源不足(集群内所有的Node都不满足该Pod请求的CPU、内存、GPU等资源);HostPort已被占用(通常推荐使用Service对外开放服务端口
-
Pod状态 一直处于Waiting
首先还是通过kubectl describe pod 命令查看当前Pod的事件。可能的原因有:
1、镜像拉取失败,比如镜像地址配置错误、拉取不了国外镜像源(gcr.io)、私有镜像密钥配置错误、镜像太大导致拉取超时(可以适当调整kubelet的-image-pull-progress-deadline和-runtime-request-timeout选项)等。
2、CNI网络错误,一般需要检查CNI网络插件的配置,比如:无法配置Pod网络、无法分配IP地址。
3、容器无法启动,需要检查是否打包了正确的镜像或者是否配置了正确的容器参数
4、Failed create pod sandbox,查看kubelet日志,原因可能是磁盘坏道(input/output error)
-
Pod状态 一直处于ContainerCreating
处理方法同Waiting
-
Pod状态 处于ImagePullBackOff
通常是镜像名称配置错误或者私有镜像的密钥配置错误导致。这种情况可以使用docker pull来验证镜像是否可以正常拉取
-
Pod状态 处于CrashLoopBackOff
此状态说明容器曾经启动了,但又异常退出。这时可以先查看一下容器的日志
-
Pod状态 处于Error
通常处于Error状态说明Pod启动过程中发生了错误。常见的原因:依赖的ConfigMap、Secret或PV等不存在;请求的资源超过了管理员设置的限制,比如超过了LimitRange等;违反集群的安全策略,比如违反了PodSecurityPolicy等;容器无法操作集群内的资源,比如开启RDAC后,需要为ServiceAccount配置角色绑定
-
Pod状态 一直处于Terminating
从v1.5开始,Kubernetes不会因为Node失联而删除其上正在运行的Pod,而是将其标记为Terminating 或 Unknown 状态。想要删除这些状态的Pod有三种方法:
1、从集群中删除Node。使用公有云时,kube-controller-manager会在VM删除后自动删除对应的Node。而在物理机部署的集群中,需要管理员手动删除Node(kubectl delete node)。
2、Node恢复正常。kubelet会重新跟kube-apiserver通信确认这些Pod的期待状态,进而再决定删除或者继续运行这些Pod。用户强制删除,用户可以执行(kubectl delete pods pod-name --grace-period=0 --force)强制删除Pod。除非明确知道Pod的确处于停止状态(比如Node所在VM或物理机已经关机),否则不建议使用该方法。特别是StatefulSet 管理的Pod,强制删除容易导致脑裂或数据丢失等问题。
3、Pod行为异常,这里所说的行为异常是指Pod没有按预期的行为执行,比如没有运行podSpec 里面设置的命令行参数。这一般是podSpec yaml文件内容有误,可以尝试使用 --validate 参数重建容器,比如(kubectl delete pod mypod 和 kubectl create --validate -f mypod.yaml);也可以查看创建后的podSpec是否是对的,比如(kubectl get pod mypod -o yaml);修改静态Pod的Manifest后未自动重建,kubelet 使用inotify 机制检测 /etc/kubernetes/manifests 目录(可通过 kubelet 的 -pod-manifest-path 选项指定)中静态Pod的变化,并在文件发生变化后重新创建相应的 Pod。但有时也会发现修改静态Pod的 Manifest后未自动创建新 Pod的情景,此时已过简单的修复方法是重启 Kubelet
-
Pod状态 处于Unknown
这个异常状态意味着Pod的状态不能持续地被 kubelet汇报给 kube-apiserver,这很有可能是主从节点(Master 和 Kubelet)间的通信出现了问题
VUE
vue中组件间怎么传递数据:
父组件向子组件传递数据,使用props属性;子组件向父组件中传递数据,在子组件中使用$emit派发事件,父组件中使用v-on
监听事件;缺点:组件嵌套层次多的话,传递数据比较麻烦。祖先组件通过依赖注入(inject / provide)的方式,向其所有子孙后代传递数据;缺点:无法监听数据修改的来源,不支持响应式。
通过属性parent / $children /
ref,访问根组件、父级组件、子组件中的数据;缺点:要求组件之间要有传递性。通过事件总线(event
bus)的方式,可以实现任意两个组件间进行数据传递;缺点:不支持响应式,这个概念是vue1.0版本中的,现在已经废弃。通过 VueJs 的状态管理模式 Vuex,实现多个组件进行数据共享,推荐使用这种方式进行项目中各组件间的数据传递。
下面详细介绍数据传递的几种方式
vue中data内要return为什么:
- 组件是一个可复用的实例,当你引用一个组件的时候,组件里的data是一个对象,所有用到这个组件的都引用的同一个对象,就会造成数据污染
- 将data封装成函数后,在引用组件的时候,我们只是调用了data函数生成的数据副本,是一个新对象,避免了数据污染
vue组件的生命周期:
组件的生命周期就是一个组件创建、数据初始化、挂载、更新、销毁的整个过程,其中具体方法:
beforeCreate
// 在实例初始化之后,数据观测和event/watcher时间配置之前被调用
created
// 实例已经创建完成之后被调用。在这一步,实例已经完成以下的配置:数据观测,属性和方法的运算,watch/event事件回调。然而,挂载阶段还没开始,$el属性目前不可见
beforeMount
// 在挂载开始之前被调用:相关的render函数首次被调用。
// 该钩子在服务器端渲染期间不被调用
mounted (
// el被新创建的vm.$el替换,并挂在到实例上去之后调用该钩子函数。如果root实例挂载了一个文档内元素,当mounted被调用时vm.$el也在文档内。
// 该钩子在服务端渲染期间不被调用。
beforeUpdate
// 数据更新时调用,发生在虚拟DOM重新渲染和打补丁之前。
// 你可以在这个钩子中进一步第更改状态,这不会触发附加的重渲染过程。
// 该钩子在服务端渲染期间不被调用。
updated
// 由于数据更改导致的虚拟DOM重新渲染和打补丁,在这之后会调用该钩子。
// 当这个钩子被调用时,组件DOM已经更新,所以你现在可以执行依赖于DOM的操作。然而在大多数情况下,你应该避免在此期间更改状态,因为这可能会导致更新无限循环。
//该钩子在服务端渲染期间不被调用
)
beforeDestroy
// 实例销毁之间调用。在这一步,实例仍然完全可用。
// 该钩子在服务端渲染期间不被调用。
destroyed
// Vue实例销毁后调用。调用后,Vue实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。
// 该钩子在服务端渲染不会被调用
DevOps
jenkins的流程,怎么构建的
- 开发者开发代码
- 提交至git仓库
- jenkins从仓库拉取代码
- jenkins通过maven(ant,gradle等)构建项目推到docker仓库
- 生成一个在tomcat运行的项目的docker容器
- 测试人员测试
jenkins的webhook怎么配置
shell
使用脚本取公网ip和内网ip
-
使用
curl
获取本机公网ipcurl cip.cc curl v4.ident.me curl myip.ipip.net
-
使用正则匹配
ip a|grep 'inet'|grep -v 'inet6'|awk '{print $2}'|cut -d '/' -f 1
-
使用路由获取
ip route show
-
使用
hostname
获取题目有限制要求取所有内网ip,可以在取出所有ip后,使用grep过滤出内网IP
hostname -I
还有很多其他方法....
strace命令可以获取一个程序调用哪些函数的整个过程,貌似是这个命令
使用脚本写出多块4T盘,格式化后分区挂载并添加自启动
for V in $(ls /dev/sd[b-z])
do
echo -e "n\np\n\n\n\nw\n" |parted $V
mkfs.xfs -i size=512 ${V}1 &>/dev/null
sleep 1
M=$(echo "$V" |awk -F "/" '{print $3}')
mkdir -p /data/${M}1 &>/dev/null
echo -e "${V}1 /data/${M}1 xfs defaults 0 0\n" >>/etc/fstab
mount -a &>/dev/null
done
使用脚本监测一个程序每15秒的状态,如果15秒中未监测到进程,则视为程序退出了(还有其他需求,大致记得这么多)
一个简单思路,未做验证,还有语法可能不通
c = 1
while true
do
# 获取此程序pid
A = ps -ef|grep '程序'
if '$A' == '';then
sleep 3
c += 1
if [ $c -eq 5 ];then
break
fi
else
continue
fi
done
其他
Linux开机启动顺序
我觉得不准确,再查一查
1、加载BIOS(包含了CPU的相关信息、设备启动顺序信息、硬盘信息、内存信息、时钟信息、PnP特性等)
2、读取MBR(硬盘上第0磁道第一个扇区)
3、Boot Loader(初始化硬件设备、建立内存空间的映射图)
4、加载内核
5、设定运行等级(init0-init6)
6、执行rc.sysinit
7、启动内核模块
8、执行不同运行级别的脚本
9、执行rc.local
10、执行/bin/login 进入登陆状态
Redis持久化
- 默认为RDB(redis database),定时快照至硬盘,对应产生的数据文件为dump.rdb
- AOF 持久化(即Append Only File持久化),则是将Redis执行的每次写命令记录到单独的日志文件中,当重启Redis会重新将持久化的日志中文件恢复数据
Zabbix自动发现及分布式
自动发现(server端轮询网段扫描发现agent)
自动发现:server-->轮询扫描-->ip地址段
-
自动发现:ip、ftp、ssh、web、pop3、imap、tcp
- ip范文自动发现(两个阶段:发现-->动作)
- zabbix-web自动发现定义自动监控的网段中的zabixx-agent(配置文件中server已经定义zabbix-server地址)
- ip范文自动发现(两个阶段:发现-->动作)
-
自动发现所执行的动作
- 发送消息
- 添加/删除主机
- 启用/禁用主机
- 添加主机到组
- 从组中删除主机
- 将主机链接到模板/从模板中取消链接
- 执行远程脚本命令
主动注册(agent端主动告诉server端请求加入)
zabbix-server必须开启自动注册-->操作-->(通知|加入监控|套用模板)
软连接与硬链接的区别:
- 软连接原文件与连接文件拥有不同的inode号,是俩个不同的文件,而硬链接是和链接文件共一个inode,是同一个文件
- 软链接支持跨文件系统建立,硬链接不支持
- 软链接的链接数目不会增加,文件大小是不一样的,硬链接显示的大小是和源文件一样的
僵尸进程和孤儿进程的区别:
- 孤儿进程:一个父进程退出,而它的一个或多个子进程还在运行,那么那些子进程将成为孤儿进程。孤儿进程将被init进程(进程号为1)所收养,并由init进程对它们完成状态收集工作。
- 僵尸进程:一个进程使用fork创建子进程,如果子进程退出,而父进程并没有调用wait或waitpid获取子进程的状态信息,那么子进程的进程描述符仍然保存在系统中。这种进程称之为僵死进程。
- 僵尸进程危害场景:
例如有个进程,它定期的产 生一个子进程,这个子进程需要做的事情很少,做完它该做的事情之后就退出了,因此这个子进程的生命周期很短,但是,父进程只管生成新的子进程,至于子进程 退出之后的事情,则一概不闻不问,这样,系统运行上一段时间之后,系统中就会存在很多的僵死进程,倘若用ps命令查看的话,就会看到很多状态为Z的进程。 严格地来说,僵死进程并不是问题的根源,罪魁祸首是产生出大量僵死进程的那个父进程。因此,当我们寻求如何消灭系统中大量的僵死进程时,答案就是把产生大 量僵死进程的那个元凶枪毙掉(也就是通过kill发送SIGTERM或者SIGKILL信号啦)。枪毙了元凶进程之后,它产生的僵死进程就变成了孤儿进 程,这些孤儿进程会被init进程接管,init进程会wait()这些孤儿进程,释放它们占用的系统进程表中的资源,这样,这些已经僵死的孤儿进程 就能瞑目而去了
怎么查看僵尸进程:
- 使用Top命令查找,当zombie前的数量不为0时,即系统内存在相应数量的僵尸进程
- 使用命令
ps -A -ostat,ppid,pid,cmd |grep -e '^[Zz]'
定位僵尸进程以及该僵尸进程的父进程 - 使用
Kill -HUP
僵尸进程ID来杀死僵尸进程,往往此种情况无法杀死僵尸进程,此时就需要杀死僵尸进程的父进程
kill -HUP 僵尸进程父ID
Nginx中location的匹配规则:
「=」 修饰符:要求路径完全匹配
「~」修饰符:区分大小写的正则匹配
「~*」不区分大小写的正则匹配
「^~」修饰符:前缀匹配 如果该 location 是最佳的匹配,那么对于匹配这个 location 的字符串, 该修饰符不再进行正则表达式检测。注意,这不是一个正则表达式匹配,它的目的是优先于正则表达式的匹配
- 精确匹配
=
- 前缀匹配
^~
(立刻停止后续的正则搜索) - 按文件中顺序的正则匹配
~
或~*
- 匹配不带任何修饰的前缀匹配。
Nginx日志中出现499报错是怎么回事
后端处理请求时间过长,客户端等的不耐烦了,提前关闭了http连接.常见于后台接口处理时间比较长,而前端请求又自带有超时时间
排查方法:
- 1、cpu(top)与内存(free -h)的使用
- 2、后台程序
- 3、 MySQL慢查询
Apche与Nginx的区别
简单来说apache是同步多进程处理业务,更稳定,nginx异步处理业务,面对高并发更快性能更好.
nginx适合静态服务
- apache 的 rewrite 比 nginx 强大,在 rewrite 频繁的情况下,用 apache
- apache 发展到现在,模块超多,基本想到的都可以找到
- apache 更为成熟,少 bug ,nginx 的 bug 相对较多
- apache 超稳定
- apache 对 PHP 支持比较简单,nginx 需要配合其他后端用
- apache 在处理动态请求有优势,nginx 在这方面是鸡肋,一般动态请求要 apache 去做,nginx 适合静态和反向。
- apache 仍然是目前的主流,拥有丰富的特性,成熟的技术和开发社区
TCP连接的几种状态:
LISTEN:侦听来自远方的TCP端口的连接请求
SYN-SENT:再发送连接请求后等待匹配的连接请求(客户端)
SYN-RECEIVED:再收到和发送一个连接请求后等待对方对连接请求的确认(服务器)
ESTABLISHED:代表一个打开的连接
FIN-WAIT-1:等待远程TCP连接中断请求,或先前的连接中断请求的确认
FIN-WAIT-2:从远程TCP等待连接中断请求
CLOSE-WAIT:等待从本地用户发来的连接中断请求
CLOSING:等待远程TCP对连接中断的确认
LAST-ACK:等待原来的发向远程TCP的连接中断请求的确认
TIME-WAIT:等待足够的时间以确保远程TCP接收到连接中断请求的确认
CLOSED:没有任何连接状态
常见状态码:
- 400 客户端请求的语法错误,服务器无法理解
- 401 请求要求用户的身份认证
- 403 服务器理解请求客户端的请求,但是拒绝执行此请求
- 404 服务器无法根据客户端的请求找到资源(网页)。通过此代码,网站设计人员可设置"您所请求的资源无法找到"的个性页面
- 405 客户端请求中的方法被禁止
- 500 服务器内部错误,无法完成请求
- 501 服务器不支持请求的功能,无法完成请求
- 502是报错类型代码 bad gate way 错误的网关。产生错误的原因是连接超时,我们向服务器发送请求,由于服务器当前 链接 太多,导致服务器方面无法给于正常的响应,产生此类报错
- 504错误代表网关超时 (Gateway timeout),是指 服务器 作为网关或代理,但是没有及时从上游服务器收到请求。. 服务器(不一定是 Web 服务器)正在作为一个网关或代理来完成客户(如您的 浏览器 或我们的 CheckUpDown 机器人)访问所需网址的请求。. 为了完成您的 HTTP 请求, 该服务器访问一个上游服务器, 但没得到及时的响应。. 这通常意味着上游服务器已关闭(不响应 网关 / 代理),而不是上游服务器和网关/代理在交换数据的协议上不一致。. 正常情况下,是由于被请求服务器发送超时引起。
Ansible的使用:
ansible testservers -m copy -a 'src=/root/install.log dest=/tmp/install.log owner=testuser group=testgroup'
# 先进入somedir/ ,再在somedir/目录下让所有节点运行somescript.sh并把log输出到somelog.txt
ansible -i hosts all -m shell -a "somescript.sh >> somelog.txt" chdir=somedir/
LVS模式的几种及使用场景:
LVS工作模式分为NAT模式、TUN模式、以及DR模式
- 常用DR模式:
直接路由模式,数据环形传输,用户请求>>LVS>>分配请求给节点>>节点返回报文给用户
DR模式修改目标MAC地址来完成负载分发实现
场景:支持大并发,但不能修改端口,要求调度器与后端服务器必须在同一个局域网内,节点要绑定VIP,抑制ARP - TUN模式:
与DR相似,也是环形传输数据,但是是以添加数据包头的实现完成数据传输分发到节点,对请求报文重新封装
场景:请求报文不能太大 - NAT模式:
数据为往返式传输,LVS在中间完成网络地址转换的工作
用户请求>>LVS>>节点>>LVS>>用户
灾备是如何做的(其实就是数据库备份)
列出服务器备份恢复策略
- 全网备份服务器
- 数据库完全备份
- 数据库增量备份
- 差异备份
- 冷数据归档
- 定时任务备份站点目录,配置文件等。 恢复策略
- 数据库增量恢复,全量恢复
- 站点目录,配置文件等故障后随时调取备份来备份
mysql 主从备份,每日做一次增量备份
每周一次完整备份异地备份 - 增量备份
rsync是Linux系统下的数据镜像备份工具,使用快速增量备份工具Remote Sync可以远程同步,支持本地复制,或者与其他SSH、rsync主机同步
Rsync 三种模式
- 本地模式,类似于cp
- 隧道模式:类似scp
- 守护进程模式:以守护进程socket 的方式传输数据
在使用rsync
首次全量同步后,结合inotify
对源目录进行实时监控,只要有文件变动或新文件产生,就会立刻同步到目标目录下,非常高效实用。
linux系统做过内核优化吗?
没有,但是知道是修改sysctl.conf
文件其中存在比较多的参数可供优化,但是做过nginx等中间件的优化....
最大并发连接数
允许系统打开的端口范围
发送缓存区的最大值
发送缓存区的默认值
socket保持FN-WAIT-2状态的最大时间
.......
并发翻倍,系统正在扩容中,但是扩容需要7分钟才可以完成,怎么用现有服务器抗住7分钟内的翻倍并发
我不知道
面试官答:是在代码中做了埋点,当并发大于某一阈值,会触发开关,此时业务上存在的部分功能不可用,比如微博上传视频此时不做转码等等,以牺牲部分功能延缓到扩容完成后(简单的讲就是业务降级)
系统出现504需要怎么排查
客户访问时,代理不能及时地从远程服务器获得应答给客户,此时要检查后端数据服务是否出现问题,为什么未及时返还数据
写一下你们现有的架构
自己写