golang八股文

Golang goroutine内存泄漏 slice导致 获取长字符串中的一段,导致字符串未释放; 获取长slice中的一段导致长slice未释放; 在长切片中新建sllice导致泄漏 channel导致 发送不接受,接收不发送,nil channel 从 channel 里读,但是同时没有写入操作 向 无缓冲 channel 里写,但是同时没有读操作 向已满的 有缓冲 channel 里写,但是同时没有读操作 select操作在所有case上都阻塞() goroutine进入死循环,一直结束不了 向 nil channel 发送和接收数据都将会导致阻塞。这种情况可能在我们定义 channel 时忘记初始化的时候发生。 可见,很多都是因为channel使用不当造成阻塞,从而导致goroutine也一直阻塞无法退出导致的。 传统同步方式sync.mutex,sync.waitgroup导致 用了mutex加lock之后忘记unlock; 在一开始设置了具体数目的wg.wait(n),但是有没有写够足够数量n的wg.Done(),导致wg.Wait()一直等待下去。(正确方式可以使用wg.Add(1)配合wg.Done使用) Go调度器的GMP 在Go语言中,GPM通常指的是Goroutine、Processor和Machine,这是Go调度器(scheduler)的核心组成部分。下面是对每个部分的详细介绍: Goroutine (G): Goroutine是Go语言中的轻量级线程,由Go运行时管理。它们是并发的基本单位,可以被创建和销毁,而无需操作系统级别的线程开销。Goroutine的创建和销毁非常快速,因此可以轻松地创建成千上万个Goroutine。 Goroutine的调度是协作式的,这意味着一个Goroutine在执行时会自愿放弃CPU,让其他Goroutine有机会执行。这种协作式调度使得Go语言能够高效地利用多核处理器。 Processor (P): Processor是Go调度器中的一个抽象概念,代表一个逻辑处理器。每个P都有一个本地运行队列,用于存储待执行的Goroutine。P的数量可以通过环境变量或运行时设置来调整,通常设置为CPU的核心数。 P的主要作用是管理Goroutine的执行。当一个Goroutine被调度到P上时,P会将其分配给一个可用的Machine(M)来执行。 Machine (M): Machine代表一个操作系统线程。M与P关联,负责执行Goroutine。一个M可以与多个P关联,但在任何给定时间,一个M只能执行一个P的Goroutine。 M的主要作用是执行Goroutine的代码。当一个Goroutine被调度到M上时,M会执行该Goroutine的代码,直到该Goroutine自愿放弃CPU或被抢占。 Go调度器的工作原理是将Goroutine(G)分配到Processor(P)上,然后由Machine(M)执行。这种设计使得Go语言能够高效地利用多核处理器,并实现高并发。 在 Go 语言的运行时系统中,Goroutine(简称 G)有多种状态,用于描述它在不同时间点的执行情况。这些状态在 Go 的调度器(GMP 模型)中扮演重要角色。GMP 模型由 Goroutine(G)、工作线程(M)和处理器(P)三部分组成。以下是 G 的主要状态及其转变过程,以及它们与 GMP 模型的关系。 G 的状态 _Gidle:空闲状态。Goroutine 尚未被使用或已经完成执行,等待被分配新任务。 _Grunnable:可运行状态。Goroutine 已经准备好运行,等待被调度器选中运行。 _Grunning:运行状态。Goroutine 正在运行中。 _Gsyscall:系统调用状态。Goroutine 正在执行系统调用,处于阻塞状态,不会被调度器调度。 _Gwaiting:等待状态。Goroutine 在等待某个条件(例如通道操作、定时器、网络 I/O 等)完成。 _Gdead:死亡状态。Goroutine 已经完成执行,无法再被重新使用。 _Gcopystack:堆栈复制状态。Goroutine 的堆栈正在被复制,以调整其大小。 状态转变及其与 GMP 的关系 创建 Goroutine _Gidle -> _Grunnable 创建一个新的 Goroutine,并将其状态设置为 _Grunnable,表示该 Goroutine 准备好运行。 由 P 将新的 Goroutine 添加到其本地运行队列或全局运行队列中。 g := newGoroutine() g....

June 12, 2024 · 3 min · 498 words · sirius1y

system-design-prime

system-design-prime 可用性模式 有两种支持高可用性的模式: 故障切换(fail-over)和复制(replication)。 故障切换 工作到备用切换(Active-passive) 关于工作到备用的故障切换流程是,工作服务器发送周期信号给待机中的备用服务器。如果周期信号中断,备用服务器切换成工作服务器的 IP 地址并恢复服务。 宕机时间取决于备用服务器处于“热”待机状态还是需要从“冷”待机状态进行启动。只有工作服务器处理流量。 工作到备用的故障切换也被称为主从切换。 双工作切换(Active-active) 在双工作切换中,双方都在管控流量,在它们之间分散负载。 如果是外网服务器,DNS 将需要对两方都了解。如果是内网服务器,应用程序逻辑将需要对两方都了解。 双工作切换也可以称为主主切换。 缺陷:故障切换 故障切换需要添加额外硬件并增加复杂性。 如果新写入数据在能被复制到备用系统之前,工作系统出现了故障,则有可能会丢失数据。 复制 主─从复制和主─主复制 这个主题进一步探讨了数据库部分: 主─从复制 主─主复制 CDN 内容分发网络 内容分发网络 CDN(英语:Content Delivery Network或Content Distribution Network)是一个全球性的代理服务器分布式网络,它从靠近用户的位置提供内容。通常,HTML/CSS/JS,图片和视频等静态内容由 CDN 提供,虽然亚马逊 CloudFront 等也支持动态内容。CDN 的 DNS 解析会告知客户端连接哪台服务器。 CDN 的分类 Pull CDN 当用户第一次访问CDN的时候,CDN上是没有资源的,这时候CDN会去向服务器拉取资源。之后的访问就直接在CDN服务器中返回就可以。 push CDN 服务器可以在用户访问资源之前,把资源push给CDN服务器。 如何选择哪种CDN? 关于使用哪种 CDN 类型的决定在很大程度上取决于流量和下载量。从长远来看,托管视频和播客(又名大量下载)的旅游博客会发现推送 CDN 更便宜、更高效,因为在您主动将其推送到 CDN 之前,CDN 不会重新下载内容。拉式 CDN 可以通过在 CDN 服务器上保留最受欢迎的内容来帮助高流量小下载的网站。内容的后续更新(或“拉取”)频率不足以使成本超过推送 CDN 的成本。 LoadBlancer 负载均衡器 负载均衡器将传入的请求分发到应用服务器和数据库等计算资源。无论哪种情况,负载均衡器将从计算资源来的响应返回给恰当的客户端。负载均衡器的效用在于: 防止请求进入不好的服务器 防止资源过载 帮助消除单一的故障点 通常会设置采用工作─备用 或 双工作 模式的多个负载均衡器,以免发生故障。...

June 12, 2024 · 1 min · 106 words · sirius1y

计算机基础知识

计算机网络 TCP TCP为什么要进行三次握手? 三次握手是建立网络连接的过程,确保双方能够正确地进行数据传输。 第一次握手SYN:客户端向服务端发送SYN请求同步信号,并初始化客户端序列号; 第二次握手SYN+ACK:服务端收到了客户端发送的SYN信号后回复ACK确认收到,同时也发送SYN,指定自己的初始序列号; 第三次握手ACK:客户端收到服务端的ACK+SYN后,回复一个ACK,表示已经收到服务端的ACK+SYN。这个包的序列会加一,表示客户端已经准备好和服务端进行数据传输了。 为什么是三次握手?不是两次或者四次 原因1:阻止重复的历史连接初始化 如果是两次握手的话,因网络堵塞的问题,客户端发送了两次SYN给服务端,服务端收到了第一个SYN的时候,就回复SYN+ACK给客户端,并进入了ESTABLISHED状态。而客户端这边收到了服务端旧的ACK+SYN,会认为这是历史连接从而发送RST报文,使服务端断开连接。 原因2:同步双方的序列号 TCP协议的双方都必须要维护一个序列号。两次握手只能保证一方的序列号被接收。 原因3:避免资源浪费 如果是两次握手,那么服务端在收到SYN后回复ACK的时候就要主动建立连接,要是网络堵塞,对面发了好多个SYN来,那完蛋了,建立了好多个TCP连接,造成了资源浪费。 TCP的四次挥手 四次挥手是指在TCP断开连接的过程中发生的,一般是由客户端发起,服务端完成最后的断开。 因为TCP是全双工通信,所以需要两边都要通知对方停止数据传输,故需要四次挥手保证断开连接。 具体流程:(刚开始双方都处于ESTABLISHED状态) 1.客户端向服务端发起FIN报文,表示客户端不再发送数据;(客户端进入FIN_WAIT_1中状态) 2.服务端收到FIN报文后,回复一个ACK表示收到;(服务端进入CLOSED_WAIT状态,客户端收到ACK后进入FIN_WAIT_2状态) 3.服务端向客户端发起FIIN报文,表示服务端也不再发送数据;(服务端进入LAST_ACK状态) 4.客户端收到服务端的FIN报文后,也回复一个ACK。(客户端进入TIME_WAIT状态) 发送端在最后会进入到TIME_WAIT的状态, 为什么有TIME_WAIT状态? 原因1:保证历史连接中的数据不会干扰下一次连接。 原因2:保证被动关闭连接。如果服务端没有TIME_WAIT状态直接close的话,要是服务端没有收到客户端最后一次发送的ACK会重发FIN,如果服务器已经处于CLOSE状态,就会返回RST报文,RST报文会被服务端认定为错误。 为什么TIME_WAIT的时间是2MSL? MSL是报文的最大生存时间,超过这个时间的报文都会被丢弃。两个MSL时间可以保证客户端发送的ACK报文可以到达服务端+服务端要是在第一个MSL中没有收到ACK可以重发一次FIN到客户端,并保证能够到达客户端。 HTTP GET方法和POST方法有什么区别? 用途:GET方法一般用于请求服务器上的数据;POST方法用于向服务器提交数据。 请求参数:GET方法的请求参数一般放在URL中,POST的请求参数一般放在请求体中。 幂等:多次执行相同的操作,结果都相同。 幂等行:GET方法是安全幂等的,POST不是幂等的。 缓存机制:GET请求会被浏览器主动cache,如果下一次传输的数据相同,就会返回浏览器中的内容;而POST不会。 GET的请求参数会被保存在浏览器的历史记录中,而POST中的参数不会保留 时间消耗:GET产生一个TCP数据包,浏览器会把header和data一起发送出去,服务器相应200; POST产生两个TCP数据包,浏览器先发送hader,服务器相应100(继续发送),浏览器再发送data,服务器相应200 什么情况下会使用POST读取数据? 当查询的数据量很多,GET方式的URL太长太大,GET方式大概是4KB,POST上限是8MB 当对数据的安全性有更高要求的时候,可以在POST的请求体中对数据进行加密 HTTP版本对比 HTTP/0.9 只支持GET方法 HTTP/1.0 支持多种请求方式 引入了请求头和响应头 引入状态码 不支持长连接 HTTP/1.1 支持长连接 管道网络传输(可以同时发送A、B请求,不必等待A响应) 但是管道网络传输存在队头阻塞的问题 头部冗余 没有请求优先级 请求只能通过客户端推送,服务器不能主动推送 HTTP/2 使用HPACK进行头部压缩 把数据部分压缩成头信息帧和数据帧 并发传输:引入了stream的概念,多个Stream复用一条TCP连接,通过streamID识别,不同stream的帧可以乱序发送 支持服务器推送 HTTPS 和HTTP对比 优点 安全性更高 缺点 HTTPS涉及到了加解密的过程,所以对服务器的负荷会高一些; 握手阶段的延迟比较高,因为还有SSL/TLS握手; 加密过程 HTTPS采用了对称加密+非对称加密的混合加密模式...

May 10, 2024 · 5 min · 987 words · sirius1y