Golang面经整理(二)(k8s,docker二次开发方向,云原生方向)

         第一篇博客主要介绍了面试的各个大厂里面的相关算法,其实算法在大厂中的作用还是挺大的,还很多方面几乎起到了决定性的作用,默认的就是算法挂了那么这场面试基本就挂了。除了算法之外,golang的一些基础知识也是蛮重要,下面对面试中问到的golang的相关知识进行汇总整理,并给出相关参考。

一、golang基础

1. golang的GMP模型是什么?

         这个问的概率也是蛮高,基本上大厂必问,GMP是三个单词的缩写,也叫PMG模型(有的面试官这么叫,阿里面试官这么叫),G-gorountine,M-machine,P-processor 。

        GPM 模型,有一个全局队列(Global Queue):存放等待运行的 G,还有一个 P 的本地队列:也是存放等待运行的 G,但数量有限,不超过 256 个。GPM 的调度流程从 go func()开始创建一个 goroutine,新建的 goroutine 优先保存在 P 的本地队列中,如果 P 的本地队列已经满了,则会保存到全局队列中。M 会从 P 的队列中取一个可执行状态的 G 来执行,如果 P 的本地队列为空,就会从其他的 MP 组合偷取一个可执行的 G 来执行,当 M 执行某一个 G 时候发生系统调用或者阻塞,M 阻塞,如果这个时候 G 在执行,runtime 会把这个线程 M 从 P 中摘除,然后创建一个新的操作系统线程来服务于这个 P,当 M 系统调用结束时,这个 G 会尝试获取一个空闲的 P 来执行,并放入到这个 P 的本地队列,如果这个线程 M 变成休眠状态,加入到空闲线程中,然后整个 G 就会被放入到全局队列中。

       关于 G,P,M 的个数问题,G 的个数理论上是无限制的,但是受内存限制,P 的数量一般建议是逻辑 CPU 数量的 2 倍,M 的数据默认启动的时候是 10000,内核很难支持这么多线程数,所以整个限制客户忽略,M 一般不做设置,设置好 P,M 一般都是要大于 P。

        这个直接背下来就行。

2. golang的内存管理是怎么样的?

 度小满,腾讯,字节都问了,具体可以参考之前整理的沃享荟文章。Go语言内存管理

        golang的内存管理蛮有意思的,把对象放在一个个的span中,不同大小的对象放在不同的span中,有64种。Go语言内存划分的三个区域分别为:arena区,bitmap区,spans区。对象分配在arena区,基本存储单元为span。bitmap区记录了GC和对象是否包含指针的标志位,spans记录了span索引指针,便于查找。

3.golang的测试方法,怎么用的,在哪个包下,有几种类型?

        致景科技问了这个题目,考察的还挺细致,go的测试方法包含:单元测试、性能测试,都是在testing这个包下面。单元测试是testing.T 和性能测试 testing.B。

  有几个约定需要遵守:

1.一般测试func TestXxx(*testing.T)

测试行必须Test开头,Xxx为字符串,第一个X必须大写的[A-Z]的字幕,一般Xxx为被测试方法的函数名。

2.性能测试func BenchmarkXxx(*testing.B)

性能测试用Benchmark标记,Xxx同上。

3. 测试文件名约定

go语言测试文件名约定规则是必须以_test.go结尾,放在相同包下。

举个栗子:这是一个主函数,定义了加法Add运算

package main
import “fmt”
func add(x, y int) int {
return x + y
}
func main() {
fmt.Println(add(1,2))
}

一般测试怎么弄呢?

package main
import “testing”
func TestAdd(t *testing.T) {
if add(1,2) != 3 {
t.Error(“test foo:Addr failed”)
} else {
t.Log(“test foo:Addr pass”)
}
}

 运行的话go test就行了。

 性能测试怎么弄呢?

package main
import “testing”
func BenchmarkAdd(b *testing.B) {
for i := 0; i < b.N; i++ {
add(1, 2)
}
}

运行  go test -v -test.bench=”.*” -count=5

4.golang的make和new的区别?(必问)

       几乎每个厂都会问一下这个,大概说出几条就行,现在面试官也不会太深问这个玩意,但是要知道。

1. new 和 make 都是在堆上分配内存,内存逃逸不讲,当然也可以了解一下。

2. new 对指针类型分配内存,返回值是分配类型的指针,new也可以对 slice 、map、channel 分配内存;

3. make 仅用于 slice、map和 channel 的初始化,返回值为类型本身,而不是指针;

 5.golang中channel怎么用的,底层的结构,向已关闭的channel中读和向channel中写有何区别?

         阿里一面就问了这个问题,当时正好背下来了,

概括:底层结构需要描述出来,这个简单,buf,发送队列,接收队列,lock。

答:channel 的数据结构包含 qccount 当前队列中剩余元素个数,dataqsiz 环形队列长度,即可以存放的元素个数,buf 环形队列指针,elemsize 每个元素的大小,closed 标识关闭状态,elemtype 元素类型,sendx 队列下表,指示元素写入时存放到队列中的位置,recv 队列下表,指示元素从队列的该位置读出。recvq 等待读消息的 goroutine 队列,sendq 等待写消息的 goroutine 队列,lock 互斥锁,chan 不允许并发读写。

channel 的几个特点 1)、读写值 nil 管道会永久阻塞 2)、关闭的管道读数据仍然可以读数据 3)、往关闭的管道写数据会 panic 4)、关闭为 nil 的管道 panic 5)、关闭已经关闭的管道 panic

 6.golang的select怎么用的?(竟然是HR面问的,有点牛)

         这个是阿里HR面问的一道题目,可能是当时HR为了筛选人员问了一道基础题吧。

       golang 中的 select 就是用来监听和 channel 有关的 IO 操作,当 IO 操作发生时,触发相应的动作。有点像系统IO中的select、poll、epoll中的select ,select 只能应用于 channel 的操作,既可以用于 channel 的数据接收,也可以用于 channel 的数据发送。如果 select 的多个分支都满足条件,则会随机的选取其中一个满足条件的分支执行。

select {
	case <- chan1:
		// 如果 chan1 成功读到数据,则进行该 case 处理语句
	case chan2 <- 1:
		// 如果成功向 chan2 写入数据,则进行该 case 处理语句
	default:
		// 如果上面都没有成功,则进入default处理流程
}

7. golang在什么情况下会发生内存泄漏?

       这个当时百度问了这个问题,我说发生内存泄漏的时候,就是对象不能被GC回收掉。面试官明显不是很满意。

        1.实际开发中更多的还是Goroutine引起的内存泄漏,因为Goroutine的创建非常简单,通过关键字go即可创建,由于开发的进度大部分程序猿只会关心代码的功能是否实现,很少会关心Goroutine何时退出。如果Goroutine在执行时被阻塞而无法退出,就会导致Goroutine的内存泄漏,一个Goroutine的最低栈大小为2KB,在高并发的场景下,对内存的消耗也是非常恐怖的。

        2. 互斥锁未释放会造成内存泄漏。

        3. time.Ticker 是每隔指定的时间就会向通道内写数据。作为循环触发器,必须调用 stop 方法才会停止,从而被 GC 掉,否则会一直占用内存空间。

       4. 字符串的截取引发临时性的内存泄漏

func main() {
	var str0 = "12345678901234567890"
	str1 := str0[:10]
}

以上代码,会有10字节的内存泄漏,我们知道,str0和str1底层共享内存,只要str1一直活跃,str0 就不会被回收,10字节的内存被使用,剩下的10字节内存就造成了临时性的内存泄漏,直到str1不再活跃如果str0足够大,str1截取足够小,或者在高并发场景中频繁使用,那么可想而知,会造成临时性内存泄漏,对性能产生极大影响。

        5. 切片截取引起子切片内存泄漏

func main() {
	var s0 = []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
	s1 := s0[:3]
}

在Go中发现内存泄露有2种方法,一个是通用的监控工具,另一个是go pprof。

8.golang的性能调优工具?pprof?怎么用?

      首先咱们来了解一个概念。

profile

       profile 就是对应用的画像,这里画像就是应用使用 CPU 和内存等情况,也就是说应用使用了多少 CPU 资源、都是哪些部分在使用、每个函数使用的比例是多少、有哪些函数在等待 CPU 资源等等。知道了这些,我们就能对应用进行规划,也能快速定位性能瓶颈。Golang 是一个对性能特别看重的语言,因此语言中自带了 profile 的库。

        golang在语言层面集成了profile采样工具,在程序运行过程中可以获取cpu、heap、block、traces等执行信息,这些会涉及到runtime/pprofnet/http/pprofruntime/trace等package。

        一般情况下,获取profile数据最有两种形式:web形式与profile文件生成形式。

        具体用法就是引入包 net/http/pprof,然后在代码中

package main

import (
	"log"
	"net/http"
	_ "net/http/pprof"
)

func main() {
	// 性能分析
	go func() {
		log.Println(http.ListenAndServe(":8080", nil))
	}()

	// 实际业务代码
	for {
		Add("test")
	}
}

func Add(str string) string {
	data := []byte(str)
	sData := string(data)
	var sum = 0
	for i := 0; i < 10000; i++ {
		sum += i
	}
	return sData
}

       其中,net/http/pprof包的init函数中注册了以下路由到http服务中,用浏览器打开http://localhost:8080/debug/pprof/,即可使用pprof提供的功能。

 9.golang中map线程安全吗?sync.Map?怎么用?

       致景科技问了这个问题,现在的面试官都很精明了,为了防止大家背八股文,还会讲怎么用,哪里用了,真的是太难了。划重点!!!!map不是线程安全的。所以搞了一个sync.Map。

        原生的 go Map 在并发读写场景下经常会遇到 panic 的情况。造成的原因是 map 是非线性安全的,并发读写过程中 map 的数据会被写乱。

        而一般情况下,解决并发读写 map 的思路是加锁,或者把一个 map 切分成若干个小 map,对 key 进行哈希。在业界中使用最多并发指出的模式分别是:  ①原生 map + 互斥锁 或者 读写锁。②  标准库 sync.Map (Go 1.9 及之后)。

        sync.Map的用法:声明后直接使用相应对的方法即可。

package main
 
import (
	"fmt"
	"sync"
)
 
func main() {
	var m sync.Map
 
	//Store
	m.Store(1,"a")
	m.Store(2,"b")
 
	//LoadOrStore
	//若key不存在,则存入key和value,返回false和输入的value
	v,ok := m.LoadOrStore("1","aaa")
	fmt.Println(ok,v) //false aaa
 
	//若key已存在,则返回true和key对应的value,不会修改原来的value
	v,ok = m.LoadOrStore(1,"aaa")
	fmt.Println(ok,v) //false aaa
 
	//Load
	v,ok = m.Load(1)
	if ok{
		fmt.Println("it's an existing key,value is ",v)
	} else {
		fmt.Println("it's an unknown key")
	}
 
	//Range
	//遍历sync.Map, 要求输入一个func作为参数
	f := func(k, v interface{}) bool {
		//这个函数的入参、出参的类型都已经固定,不能修改
		//可以在函数体内编写自己的代码,调用map中的k,v
 
			fmt.Println(k,v)
			return true
		}
	m.Range(f)
 
	//Delete
	m.Delete(1)
	fmt.Println(m.Load(1))
 
}

10. 说下GC三色标记算法?

        腾讯面试官问了这个问题,三色标记算法最初是在Java语言上出现的垃圾回收算法,该算法根据是否有对象引用把对象设置为黑,白,灰三种颜色。内容很多具体可以参考下面的文章。

JVM性能调优理论篇

可达性分析之三色标记算法详解_黄智霖-blog的博客-CSDN博客_三色标记算法

 11.手写golang协程池?(百度就爱考这个,让我现场手写)

      没准备的话就很难写出来,毕竟时间有限,也不让查资料,所以提前准备好,背下来。没背下来怎么办?没背下来就挂了。这里给出一篇参考。

文章目录:

1. 为什么需要协程池?

2. 简单的协程池

3. go-playground/pool

4. ants(推荐)

(2条消息) Golang学习篇——协程池_Word哥的博客-CSDN博客_协程池是什么

二、docker与k8s相关问题

1. 必问 创建pod或者创建deployment流程?

        这个问题几乎是每一家公司必须要问的问题,作为k8s的一个基础,从这个问题可以考察出基础能力如何。

        创建pod流程:

1、客户端提交创建请求,可以通过API Server的Restful API,也可以使用kubectl命令行工具。支持的数据类型包括JSON和YAML。
2、API Server处理用户请求,存储Pod数据到etcd。
3、调度器通过API Server查看未绑定的Pod。尝试为Pod分配主机。
4、过滤主机 (调度预选):调度器用一组规则过滤掉不符合要求的主机。比如Pod指定了所需要的资源量,那么可用资源比Pod需要的资源量少的主机会被过滤掉。
5、主机打分(调度优选):对第一步筛选出的符合要求的主机进行打分,在主机打分阶段,调度器会考虑一些整体优化策略,比如把容一个Replication Controller的副本分布到不同的主机上,使用最低负载的主机等。
6、选择主机:选择打分最高的主机,进行binding操作,结果存储到etcd中。
7、kubelet根据调度结果执行Pod创建操作: 绑定成功后,scheduler会调用APIServer的API在etcd中创建一个boundpod对象,描述在一个工作节点上绑定运行的所有pod信息。运行在每个工作节点上的kubelet也会定期与etcd同步boundpod信息,一旦发现应该在该工作节点上运行的boundpod对象没有更新,则调用Docker API创建并启动pod内的容器。

  创建deployment流程这个要回答出创建rs的过程:

1、准备好一个包含应用程序的Deployment的yml文件,然后通过kubectl客户端工具发送给ApiServer。
2、ApiServer接收到客户端的请求并将资源内容存储到数据库(etcd)中。
3、Controller组件(包括scheduler、replication、endpoint)监控资源变化并作出反应。
4、ReplicaSet检查数据库变化,创建期望数量的pod实例。
5、Scheduler再次检查数据库变化,发现尚未被分配到具体执行节点(node)的Pod,然后根据一组相关规则将pod分配到可以运行它们的节点上,并更新数据库,记录pod分配情况。
6、Kubelete监控数据库变化,管理后续pod的生命周期,发现被分配到它所在的节点上运行的那些pod。如果找到新pod,则会在该节点上运行这个新pod。
7、kuberproxy运行在集群各个主机上,管理网络通信,如服务发现、负载均衡。例如当有数据发送到主机时,将其路由到正确的pod或容器。对于从主机上发出的数据,它可以基于请求地址发现远程服务器,并将数据正确路由,在某些情况下会使用轮训调度算法(Round-robin)将请求发送到集群中的多个实例。
kubectl提交一个请求,来创建RC,此时Controller Manager通过API server里的接口监听到这个RC事件,分析之后,发现当前集群中还没有它对应的Pod实例,于是根据RC里的Pod模板定义 个Pod对象;接下来,此事件被Scheduler发现,它立即执行一个复杂的调度流程,为这个新Pod选定一个落户的Node,这个过程可称为绑定;随后模板Node上运行的Kubelet进程通过API Server监测到这个“新生的”Pod并按照它的定义,启动Pod并负责后期的管理;
随后我们通过Kubectl提交一个映射到该Pod的Server的创建请求,Controller Manager会通过Label标签查询到相关联的Pod实例,然后生成Service的Endpoints信息;接下来,所有Node上运行的Proxy进程通过API Server查询并监听Service对象及其对应的Endpoints信息,建立一个负载均衡器来实现Service访问到后端Pod的流量转发功能;

2.k8s中pod之间是怎么通信的?

 金山云问了这个问题,主要考察一些基础的网络模式,

  1. 同一个Pod内的多个容器之间:lo(通过localhost回环地址通信)
  2. 各Pod之间的通讯:overlay Network (覆盖网络)
  3. Pod与 Service之间的通讯:各节点的 Iptables规则

3.k8s中的pod中OOM机制有了解过吗,原理?

      蚂蚁金服的oceanbase数据库产品问了这个问题,当时被问还是有点点蒙的。这个涉及到pod的QOS的相关知识。阿里面试官首先介绍了系统中进程的OOM机制,会给每个进程进行打分,然后kill掉得分最高的那一个进程,然后问pod的OOM是怎么样的?

    当系统 OOM上时对于处理不同 OOMScore 的进程表现不同,OOMScore 是针对 memory 的,当宿主上 memory 不足时系统会优先 kill 掉 OOMScore 值高的进程,可以使用  $ cat /proc/$PID/oom_score 查看进程的 OOMScore。OOMScore 的取值范围为 [-1000, 1000],Guaranteed pod 的默认值为 -998,Burstable pod 的值为 2~999,BestEffort pod 的值为 1000,也就是说当系统 OOM 时,首先会 kill 掉 BestEffort pod 的进程,若系统依然处于 OOM 状态,然后才会 kill 掉  Burstable pod,最后是 Guaranteed pod;        

4. k8s的基本组件及其作用。

一个kubernetes集群主要是由控制节点(master)、工作节点(node)构成,每个节点上都会安装不同的组件。

master:集群的控制平面,负责集群的决策 ( 管理 )

ApiServer : 资源操作的唯一入口,接收用户输入的命令,提供认证、授权、API注册和发现等机制

Scheduler : 负责集群资源调度,按照预定的调度策略将Pod调度到相应的node节点上

ControllerManager : 负责维护集群的状态,比如程序部署安排、故障检测、自动扩展、滚动更新等

Etcd :负责存储集群中各种资源对象的信息,k/v方式存储,所有的 k8s 集群数据存放在此

Kuberctl: 命令行配置工具

node:集群的数据平面,负责为容器提供运行环境 ( 干活 ) 

Kubelet : 负责维护容器的生命周期,即通过控制docker,来创建、更新、销毁容器,会按固定频率检查节点健康状态并上报给 APIServer,该状态会记录在 Node 对象的 status 中。

KubeProxy : 负责提供集群内部的服务发现和负载均衡

Docker : 负责节点上容器的各种操作。

 5.kubevirt的基本组件及其作用

virt-api:kubevirt是以CRD形式去管理VM Pod,virt-api就是所有虚拟化操作的入口,这里面包括常规的CDR更新验证、以及console、vm start、stop等操作。

virt-controller:virt-controller会根据vmi CRD,生成对应的virt-launcher Pod,并且维护CRD的状态。与kubernetes api-server通讯监控VMI资源的创建删除等状态。

virt-handler:virt-handler会以deamonset形式部署在每一个节点上,负责监控节点上的每个虚拟机实例状态变化,一旦检测到状态的变化,会进行响应并且确保相应的操作能够达到所需(理想)的状态。virt-handler还会保持集群级别VMI Spec与相应libvirt域之间的同步;报告libvirt域状态和集群Spec的变化;调用以节点为中心的插件以满足VMI Spec定义的网络和存储要求。

virt-launcher:每个virt-launcher pod对应着一个VMI,kubelet只负责virt-launcher pod运行状态,不会去关心VMI创建情况。virt-handler会根据CRD参数配置去通知virt-launcher去使用本地的libvirtd实例来启动VMI,随着Pod的生命周期结束,virt-lanuncher也会去通知VMI去执行终止操作;其次在每个virt-launcher pod中还对应着一个libvirtd,virt-launcher通过libvirtd去管理VM的生命周期,这样做到去中心化,不再是以前的虚拟机那套做法,一个libvirtd去管理多个VM。

virtctl:virtctl是kubevirt自带类似kubectl的命令行工具,它是越过virt-launcher pod这一层去直接管理VM虚拟机,可以控制VM的start、stop、restart。

6.Etcd的写数据流程

 天翼云问了这个问题,Etcd写数据流程,这个很细节,不准备的话基本就不会了

总体上的请求流程从上至下依次为客户端 → API 接口层 → etcd Server → etcd raft 算法库。

读请求
客户端通过负载均衡选择一个 etcd 节点发出读请求,API 接口层提供了 Range RPC 方法,etcd 服务端拦截到 gRPC 读请求后,调用相应的处理器处理请求。

写请求
客户端通过负载均衡选择一个 etcd 节点发起写请求,etcd 服务端拦截到 gRPC 写请求,涉及一些校验和监控,之后 KVServer 向 raft 模块发起提案,内容即为写入数据的命令。经过网络转发,当集群中的多数节点达成一致并持久化数据后,状态变更且 MVCC 模块执行提案内容。
 

7.在异构架构下,比如有些主机是x86,有些主机是arm架构,k8s怎么保证异构架构下这些主机拉起不同的架构的镜像?

         天翼云问了这个问题,这里当时不知道怎么回答,后来了解到docker的manifest机制。

          docker每一个镜像包含了一个这个文件包含了有关于镜像信息,如层、大小和摘要。docker manifest命令还向用户提供附加信息,比如构建镜像的操作系统和体系结构。而manifest list是一个镜像清单列表,用于存放多个不同os/arch的镜像信息。我们主要用到manifest的目的,其实还是多用于存放不同的os/arch信息,也就是方便我们在不同的CPU架构(arm或者x86)或者操作系统中,通过一个镜像名称拉取对应架构或者操作系统的镜像,这个尤其是在K8S中,对于异构CPU的服务器中的镜像显得尤为有效。
        具体大家可以参考这篇文章,写的不错,从介绍到实战一应俱全。(11条消息) docker manifest 使用实战_嫌疑人X的解忧杂货店的博客-CSDN博客_docker manifest

8.kubebuilder初始化项目的流程?整体说一下?list和watch在哪个模块中?

开发流程大致有以下几个过程:

  1. 初始化项目结构(可根据 sample controller 修改)
  2. 定义 CRD
  3. 生成代码
  4. 初始化 controller
  5. 实现 controller 具体逻辑

 list and watch 在client-go中。

 9.Prometheus相关问题

         这个主要考察了pro的基本数据结构,基本组件等等问题,做边缘计算,物联网好多推送方式用的push-gateway的方式以改善弱网环境下得状态。

pro的四种数据结构: Counter,Gauge,Histogram,Summary

Prometheus 组成及架构
Prometheus 生态圈中包含了多个组件,其中许多组件是可选的:
Prometheus Server: ------服务端 ---处理,储存数据
负责收集和存储时间Prometheus 组成及架构序列数据(time series data),并且提供查询接口。
Jobs/Exporters: ------客户端 ---采集数据
客户端,用于暴露已有的第三方服务的 metrics 给 Prometheus。
监控并采集指标,对外暴露HTTP服务(/metrics);目前已经有很多的软件原生就支持Prometjeus,提供/metrics,可以直接使用;对于像操作系统已经不提供/metrics的应用,可以使用现有的exporters或者开发自己的exporters来提供/metrics服务;
Push Gateway: -----相当于代理---转发数据
针对push系统设计,Short-lived jobs定时将指标push到Pushgateway,再由Prometheus Server从Pushgateway上pull;
主要用于短期的 jobs。由于这类 jobs 存在时间较短,可能在 Prometheus 来 pull 之前就消失了。为此,这次 jobs 可以直接向 Prometheus server 端推送它们的 metrics。这种方式主要用于服务层面的 metrics,对于机器层面的 metrices,需要使用 node exporter。
Alertmanager: ----告警方式---实现告警
报警组件,从 Prometheus server 端接收到 alerts 后,会进行去除重复数据,分组,并路由到对收的接受方式,发出报警。常见的接收方式有:电子邮件,pagerduty,OpsGenie, webhook 等。
Web UI:
Prometheus内置一个简单的Web控制台,可以查询指标,查看配置信息或者Service Discovery等,实际工作中,查看指标或者创建仪表盘通常使用Grafana,Prometheus作为Grafana的数据源;

三、天翼云笔试

       天翼云笔试分3个模块。耗时还是比较久的,可能都做下来要几个小时。

        1.性格测评

        这部分符合社会主义核心价值观就行,其余的随意发挥。选择题。

        2.智力测验

        也是选择题,有给你一段话,让你选出哪一句是对的。图形推理题,数据推理题。类似于公务员考试,时间很紧张,可能出现看不完题目,来不及算就过去了,那么就蒙一个就行,不影响最后结果。

        3.专业笔试

        60道选择题,还有4-5道简答题。主要考察golang的相关知识。

        发现了一个押题率60%的文档,大家自己悄咪咪看就好。

        goLang 精编 选择、填空、判断 共100题_戴国进的博客-CSDN博客_golang精编100题

        简答题考了:

        1. golang控制并发怎么做?让你写一段程序

        2. 怎样处理连接2个字符串。

        3. golang中正则表达式过滤字符串的用法。

四、网络相关

        天翼云研发三部二面是一个光头领导,20分钟左右,问了如下问题:

1. HTTP协议1.0和2.0的区别是啥?是哪一层的协议?

总的区别就是:

  1. HTTP/2采用二进制格式而非文本格式
  2. HTTP/2是完全多路复用的,而非有序并阻塞的——只需一个连接即可实现并行
  3. 使用报头压缩,HTTP/2降低了开销
  4. HTTP/2让服务器可以将响应主动“推送”到客户端缓存中

 2. 同步IO和异步IO的区别?

同步:

所谓同步,就是在发出一个功能调用时,在没有得到结果之前,该调用就不返回。也就是必须一件一件事做,等前一件事做完了才能做下一件事。

异步:
异步的概念和同步相对。当一个异步过程调用发出后,调用者不能立刻得到结果。实际处理这个调用的部件在完成后,通过状态、通知和回调来通知调用者。

3.网络层有哪些协议?应用?

网络层有四个协议:ARP协议,IP协议,ICMP协议,IGMP协议。ARP协议为IP协议提供服务,IP协议为ICMP协议提供服务,ICMP协议为IGMP协议提供服务。 

ARP协议应用:根据目的IP地址来解析MAC地址,进行二层通讯.

IP协议应用:IP协议是一个用于网络之间互连的协议。IP是Internet Protocol(网际互连协议)的缩写,设计IP的目的是提高网络的可扩展性;IP只为主机提供一种无连接、不可靠的、尽力而为的数据包传输服务.

ICMP协议应用:ICMP协议主要用来检测网络通信故障和实现链路追踪,最典型的应用就是Ping和tracerooute。

IGMP协议应用:

  • IGMP用来在接收者主机和直接相邻的组播路由器之间建立和维护组播组成员的关系。

  • 作用2
    IGMP通过在接收者主机和组播路由器之间交互IGMP报文实现组成员管理功能,IGMP报文封装在IP报文中。

4. awk命令知道干啥的不?

      awk是一种处理文本文件的语言,是一个强大的文本分析工具。 

       三剑客功能:

        grep : 过滤文本

        sed : 修改文本

        awk : 处理文本

5. linux系统中查看系统资源用啥命令?  

vmstat 、dmesg、free、uptime、uname、lsb_release、lsof、top等这些命令可以查一下他们的作用。

        字节一面面试官问了如下问题:

6.HTTP与HTTPS的区别?端口有何不同?

      HTTP协议以明文方式发送内容,不提供任何方式的数据加密。HTTP协议不适合传输一些敏感信息,比如:信用卡号、密码等支付信息。https则是具有安全性的ssl加密传输协议。http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。并且https协议需要到ca申请证书。HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,要比http协议安全。端口分别是80和443.

五、数据库相关

1.mysql的事务隔离机制

         字节跳动飞书人力套件面试官问了这个问题,mysql是业务代码考核的重点。

mysql的四大特性分别是:原子性,一致性,隔离性和数据持久化

原子性:事务是数据库的逻辑工作单位,事务中包含的各操作要么都做,要么都不做

一致性:事务开始前和结束后,数据库的完整性约束没有被破坏

隔离性:个事务的执行不能被其它事务干扰。即一个事务内部的操作及使用的数据对其它并发事务是隔离的,并发执行的各个事务之间不能互相干扰。

持久化:指一个事务一旦提交,它对数据库中的数据的改变就应该是永久性的。接下来的其它操作或故障不应该对其执行结果有任何影响

mysql四大隔离级别:

分别是:读未提交(READ UNCOMMITTED )、读提交( READ COMMITTED)、可重复读(REPEATABLE READ)、串行化(SERIALIZABLE)
 

2.Redis的key删除策略有哪些?

第一种策略:被动删除

当读/写一个key时,redis首先会检查这个key是否存在,如果存在且已过期,则直接删除这个key并返回nil给客户端。

第二种策略:定期删除

redis中有一系列的定期任务(serverCron),这些任务每隔一段时间就会运行一次,其中就包含清理过期key的任务,运行频率由配置文件中的hz参数来控制,取值范围1~500,默认是10,代表每秒运行10次。

第三种策略:强制删除

如果redis使用的内存已经达到maxmemory配置的值时,会触发强制清理策略,清理策略由配置文件的maxmemory-policy参数来控制。

3.Redis的基本数据结构

 要包括常见的5种数据类型,分别是:String、List、Set、Zset、Hash。

 4.有了mysql为啥还用etcd优势在哪些地方?

我觉得有必要回答一下。这个问题其实并不简单,因为本质原因涉及到分布式系统的特性。

MySQL 只保证最终一致性 eventual consistency(而且是不可配置的),因为它采用的是异步复制 asynchronous replication,系统中有过读写分离经验的同学知道当你写入数据库后立刻去读如果命中的 slave 节点没有同步到最新数据,那么返回的可能是空数据。虽然一个节点可能落后,但保证最终一致性意味着,除非网络错误或其他一些问题,否则任何落后的节点最终都会赶上其他节点,并且所有节点最终都会获得一致的视图。但是分布式系统中的一致性要求每个节点在给定时间具有相同的数据视图,这非常重要。MySQL 存储的可以是大量内容数据或者业务数据,而 Kubernetes 这些服务存储的是控制平面的数据,后者数量级少一些但是要求强一致性。


etcd KV API guarantees

etcd tries to ensure the strongest consistency and durability guarantees for a distributed system. 
etcd ensures  strict serializability, which is the strongest isolation guarantee of distributed transactional database systems. Read operations will never observe any intermediate data. 
etcd ensures  linearizability as consistency of replicas basically. As described below, exceptions are watch operations and read operations which explicitly specifies serializable option.

etcd 试图提供最强的一致性和持久性的保证,确保严格的可串行化 strict serializability,这是分布式事务数据库系统的最强隔离保证,读取操作永远不会观察任何中间数据。

Cassandra ScyllaDB MySQL 完全不在竞争之列,因为它们只是最终一致性。大多数 MVCC 的数据库都几乎不适用于强一致的场景。

2.etcd 的定位符合场景

官方网站中写的“一个为分布式系统中极为重要的数据提供分布式可靠的 kv 存储”。通常不会是一些内容数据比如文本信息,更多的存储一些不经常更新状态的相对少量几个G左右的控制数据。

3.云原生场景适用。

六、其他问题

1.说下死锁,怎样打破?

一组进程中,每个进程都无限等待被该组进程中的另一进程所占有的资源,因而永远无法得到资源,这种现象称为进程死锁,这一组进程就称为死锁进程。死锁会导致大量资源浪费。

互斥使用(资源独占) :一个资源每次只能给一个进程使用
占有且等待(请求和保持) :进程在申请新的资源的同时保持对原有资源的占有
不可抢占:资源申请者不能强行的从资源占有者手中夺取资源,资源只能由占有者自愿释放
循环等待:存在一个进程等待队列P1,P2,…Pn,其中P1等待P2占有的资源,P2等待P3占有的资源,…,Pn等待P1的资源,形成一个等待环路。

四个条件打破一个就能避免死锁。

2.CAP原则,redis集群满足CA还是CP?

         天翼云一面问了,首先带领大家了解一下,CAP原则又叫CAP定理,是指在分布式系统中,数据一致性,可用性,分区容错性,这3个要素最终只能同时满足两点,不可能三者兼顾。

        Base理论的官方解释为:BASE理论是对CAP中的一致性和可用性的一个权衡的结果,其核心的思想是:我们既然无法做到强一致,但每个应用可以根据自身的业务特点,采用适当的方式来使系统达到最终一致性。

        redis集群满足AP

  • AP : 对一致性要求不高,但仍需保证最终一致性

    eg :redis分布式集群,(大多数网站采用,因为可用性很影响用户体验)

 3. 说下go的优点缺点,最近学哪些新技术?

         kata的面试官问了这个问题,属于开放式的问题,我就说了几个重点.
① 高性能-协程

golang 源码级别支持协程,实现简单;对比进程和线程,协程占用资源少,能够简洁高效地处理高并发问题。

②  生态

背靠谷歌,生态丰富,轻松 go get 获取各种高质量轮子。用户可以专注于业务逻辑,避免重复造轮子。

③  部署

部署简单,源码编译成执行文件后,可以直接运行,减少了对其它插件依赖。不像其它语言,执行文件依赖各种插件,各种库,研发机器运行正常,部署到生产环境,死活跑不起来 。

④  跨平台

很多语言都支持跨平台,把这个优点单独拿出来,貌似没有什么值得称道的,但是结合上述优点,它的综合能力就非常强了。

⑤  代码极简

个人认为 golang 是 C / C++ / python 的结合体,它是一门全新的语言,入门和使用相对简单,是性能和代码极简之间的一种平衡。

缺点:

①右大括号不允许换行,否则编译报错

②不允许有未使用的包或变量

③错误处理原始,虽然引入了defer、panic、recover处理出错后的逻辑,函数可以返回多个值,但基本依靠返回错误是否为空来判断函数是否执行成功,if err != nil语句较多,比较繁琐,程序没有java美观。(官方解释:提供了多个返回值,处理错误方便,如加入异常机制会要求记住一些常见异常,例如IOException,go的错误Error类型较统一方便)

④[]interface{}不支持下标操作

⑤struct没有构造和析构,一些资源申请和释放动作不太方便

⑥仍然保留C/C++的指针操作,取地址&,取值*
学习哪些新技术:Rust

4.学习k8s都看哪些资料? 

 阿里二面问了这个问题,开放式的问题,社区,官网,kubernetes.io,kubevirt.io等。

七、简历如何修改增加过筛率?

        一点建议:①简历的每一个字都要字斟句酌,比方说Java不是JAVA,这种细节要注意。建议至少花个3天时间好好修改简历。

                          ②熟悉xxx直接改为精通XXX,不要怕面试官diss,即使挂了,学习一下,把他搞会就行了。

八、参考资料

[1] kube-apiserver 的设计与实现 · 田飞雨

[2]爆肝整理的Golang面试题,拿走不谢 - 知乎

[3]MySQL 精选 60 道面试题(含答案)_小虾米啊的博客-CSDN博客_mysql面试题

[4]​​​​​​​后Kubernetes时代的虚拟机管理技术之kubevirt篇

  • 6
    点赞
  • 69
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值