golang进阶必知问题

在这里插入图片描述

目录

一、golang进阶问题

1、简述GMP模型

Go(也称为 Golang)是一种编程语言,它在并发编程方面具有独特的设计和模型,其中 GMP 模型是其并发模型的一部分。

GMP 模型是 Go 语言的并发调度模型,它包含三个主要的组件:

1.1. Goroutines:

  • Goroutines 是 Go 语言中轻量级的并发执行单位。与传统的线程相比,Goroutines 更加轻量且消耗较小的资源,可以高效地创建大量的并发任务。
  • Goroutines 使用关键字 go 来创建,可以在函数或方法前面加上 go 关键字来启动一个 Goroutine。例如:go myFunction()
  • Goroutines 由 Go 语言的运行时系统(Runtime)进行调度,实现了自动的任务切换和并发管理。

1.2. Channels:

  • Channels 是 Goroutines 之间通信的主要方式。它是一种类型安全的、阻塞式的通信机制,用于在不同的 Goroutines 之间传递数据。
  • 通过 make(chan Type) 来创建一个 Channel,可以在 Goroutines 之间使用 <- 操作符发送和接收数据。例如:myChannel <- datadata <- myChannel
  • Channels 可以用于同步 Goroutines 的执行顺序,实现数据共享和通信。

1.3. Scheduler:

  • Go 语言的运行时系统具有一个调度器,负责管理和调度 Goroutines 的执行。
  • 调度器使用称为 G-M-P 模型的架构。G 代表 Goroutines,M 代表操作系统的线程,P 代表处理器。其中,P 用于绑定 M 和 Goroutines,协调任务的执行。
  • 调度器根据一定的策略(例如工作窃取、抢占式调度等)来分配 Goroutines 给 M,以实现并发的调度。

总之,GMP 模型是 Go 语言并发编程的核心,通过轻量级的 Goroutines 和通信机制 Channels,以及调度器的协调管理,使得并发编程在 Go 中变得更加简单和高效。这种模型使得开发者能够利用多核处理器的优势,编写出高效且易于理解的并发代码。

在这里插入图片描述

2、go的逃逸分析算法

Go 语言的逃逸分析(Escape Analysis)是一种编译器优化技术,用于确定程序中的变量是否在函数栈上分配内存,还是需要在堆上分配内存。逃逸分析的目标是最小化堆内存的分配,从而提高程序的性能和内存利用率。

逃逸分析的算法通常分为以下几个步骤:

a. 标记阶段(Marking Phase):
在编译阶段,编译器会对函数进行标记,记录每个变量是否逃逸。如果变量在函数内部使用且不会被返回,它就可能被分配在栈上,否则可能被分配在堆上。

b. 逃逸分析阶段(Escape Analysis Phase):
编译器会分析函数内部的变量,检查它们的作用域和生命周期。如果发现变量在函数外部被引用(逃逸),则可能将其分配在堆上,以确保其在函数退出后仍然有效。

c. 决策阶段(Decision Phase):
根据逃逸分析的结果,编译器会做出决策,将变量分配在栈上还是堆上。栈上分配速度更快,但生命周期受限;堆上分配生命周期更长,但速度较慢。

逃逸分析的优点包括:

  • 减少堆内存分配:通过在栈上分配对象,减少了垃圾回收的压力和堆内存的碎片。
  • 提高局部性:栈上分配可以提高数据的局部性,从而提高缓存命中率。
  • 改善性能:避免了频繁的堆内存分配和回收操作,提高了程序的性能。

逃逸分析在 Go 语言中是默认开启的,并且在编译器的优化阶段自动进行。在编写代码时,开发者不需要显式指定变量的分配位置,编译器会根据逃逸分析的结果自动进行优化。

总之,Go 语言的逃逸分析算法是一项重要的编译器优化技术,可以帮助提高程序的性能和内存利用率,同时减少垃圾回收的开销。

可以在编译时加参数 -gcflags '-m -l ’ 查看有哪些变量发生了逃逸。例如:go build -gcflags '-m -l 'main.go

3、go的垃圾回收及相关的优化

go的垃圾回收采用的是标记清除(1.3版本)或三色标记(1.5版本)算法。
垃圾回收时会发生STW,造成卡顿,如果垃圾回收频率太高则会占用很大比例的CPU运行时间,不利于程序整体的吞吐。
垃圾回收发生的时机是,比如设置GOGC=100(这也是默认值),则新增内存达到上次垃圾回收后存活量的%100时发生垃圾回收。例如上次回收后,剩余1GB,则新增达到1GB,总共2GB时会再发生一次垃圾回收。
降低频率的设置可以把GOGC设置大一些,如1000,但如果每次的存活量差别较大,会有很大的不确定性,可能会造成OOM。
也可以使用ballast方案,这是官方推荐的方案,即GOGC使用默认值,然后初始化一个生命周期贯穿整个go程序生命周期的超大slice,如2GB~10GB,
这个slice只占虚拟内存,不占用物理内存,且会被GC线程(垃圾回收器)统计到。

背景知识:
go1.3 版本之前使用的是 标记-清除 算法,但是执行该算法时,需要停掉用户程序(STW),即保证 GC 和 用户程序 是串行 的。这种算法简单,但是会严重影响用户程序的执行。
go1.5 版本开始后提出了 三色标记法,它优化了标记过程,同时结合 屏障技术 极大的缩短了 STW 的时间,让 用户程序 和 GC 在 标记和清除阶段 可以并行运行。
并发的标记、清除算法已经把STW的时间大幅降低了,Go 垃圾回收的耗时还是主要取决于标记花费的时间的长短,清除过程是非常快的。
GOGC 设置的非常小,会频繁触发 GC 导致太多无效的 CPU 浪费,反应到程序的表现就会特别明显。

4、锁与channel都可以实现并发安全,使用时如何选择?

根据实际需求,如果需要多个goroutine的业务逻辑协作,偏重于数据的传递,选择channel,例如调度
如果不需要且对性能要求较高,且读取操作比写操作多,选RWmutex。
如果试图保护某个结构的内部状态,选mutex。如调度时worker的选择和任务的指派,会先上锁。

PS golang的互斥锁和读写锁
a. 互斥锁(Mutex):
互斥锁用于实现悲观锁的机制,它可以确保同一时刻只有一个 Goroutine 能够访问被保护的临界区。
b. 读写锁(RWMutex):
读写锁用于实现乐观锁的机制,允许多个 Goroutine 同时读取共享资源,但只允许一个 Goroutine 写入共享资源。

需要根据具体的需求来选择使用互斥锁还是读写锁。互斥锁适用于对共享资源的修改操作,但可能限制并发性能;读写锁适用于多读少写的场景,可以提高并发读取性能。

5、golang如何应用开闭原则?

开闭原则是面向对象设计中的一个重要原则,它指出软件实体(类、模块、函数等)应该对扩展开放,对修改关闭。在 Go 语言中,应用开闭原则可以通过以下几种方式实现:

5.1. 使用接口抽象:
定义接口来描述不同实现的共同行为,然后在代码中使用这些接口。当需要新增一种实现时,只需要实现接口并注册到程序中,而不需要修改已有的代码。

5.2. 使用函数回调:
将变化的部分封装成函数,并将这些函数作为参数传递给其他函数。这种方式允许通过传递不同的函数实现来实现不同的行为,从而在不修改现有代码的情况下扩展功能。

6、是否遇到过并发问题,如何解决的?

7、进程、线程、协程的概念和区别?

8、map、slice、channel的底层实现?

在 Go 语言中,map、slice 和 channel 都是非常重要的数据结构,它们在底层的实现上有一些共同点和差异。

Map 的底层实现:
Go 的 map 是基于散列表(hash table)实现的,用于存储键值对。底层使用了哈希函数来映射键到特定的桶(bucket),每个桶存储一个链表或红黑树,用于解决哈希冲突。在插入、查询和删除操作时,通过哈希函数来定位桶,然后在桶内进行操作。

Slice 的底层实现:
Go 的 slice 是对数组的一个封装,底层是一个数组指针和长度信息。当创建一个 slice 时,会分配一个底层数组,并记录 slice 的长度和容量。如果 slice 需要扩展,会创建一个新的底层数组,并将数据复制到新的数组中,以便支持可变长度。这种动态数组的特性使得 slice 在性能和内存利用方面都有良好的表现。

Channel 的底层实现:
Go 的 channel 是用于 Goroutine 之间通信的管道,底层实现依赖于同步原语。通常使用一个等待队列(wait queue)来管理数据的发送和接收,以及一个缓冲区来存储数据。在无缓冲通道中,发送和接收操作会直接进行 Goroutine 的切换,实现同步通信。在有缓冲通道中,数据会先存储在缓冲区中,直到缓冲区满或者空时才会进行切换。

需要注意的是,这些底层实现细节可能会因 Go 版本和编译器优化而有所变化。这些数据结构在实际使用中非常常见,但了解底层实现并不是使用它们的必要前提。在编写 Go 代码时,重点关注它们的使用和性能特点更为重要。

9、从两百万个字符的slice中快速查找我们需要的子串

使用第三方库提供的高效查找算法。
例如实现了Boyer-Moore 算法的库,实现了KMP算法的库。

10、本地队列和全局队列的区别?从队列中取出goroutine是否需要加锁?

在 Go 语言中,"本地队列"和"全局队列"通常指的是调度器(Scheduler)中的工作队列,用于管理待执行的 Goroutine。在 Go 的运行时调度器中,这些队列起着重要的作用,以实现并发执行和任务调度。

本地队列(Local Queue):

每个逻辑处理器(P)都有一个本地队列,用于存储待执行的 Goroutine。
当一个 Goroutine被创建或者被调度器从其他 P 中抢占时,会被放入本地队列中。
本地队列的访问不需要加锁,因为每个 P 拥有自己的本地队列,不会出现并发访问的情况。

全局队列(Global Queue):

所有逻辑处理器共享一个全局队列,用于存储一部分待执行的 Goroutine。
当本地队列空闲时,会从全局队列中获取一部分 Goroutine 来执行。
全局队列的访问可能需要加锁,因为多个逻辑处理器可能同时竞争全局队列的资源。
从队列中取出 Goroutine 是否需要加锁取决于是从本地队列还是全局队列中取出。在从本地队列中取出时,因为每个逻辑处理器都有自己的本地队列,无需加锁。而在从全局队列中取出时,可能需要对全局队列进行加锁,以确保多个逻辑处理器之间的竞争安全。

11、如何通过context实现控制超时操作?

使用 context.WithTimeout 函数创建一个带有超时的 context.Context 对象。这个函数接受一个父级 Context 和一个超时时间作为参数,返回一个新的 Context 和一个 cancel 函数,用于取消操作。

12、sync.Map 和 map + mutex有何区别?

sync.Map 是 Go 语言标准库提供的一种并发安全的映射类型,它在内部使用了一些优化的机制来降低锁的竞争,从而提高性能。以下是 sync.Map 内部的一些优化机制:

12.1. 分片锁(Sharding Locks):
sync.Map 内部将整个映射分为多个片段,每个片段有自己的锁。这样可以降低锁的竞争,因为每个 Goroutine 在操作映射时只需要锁定特定的片段,而不会影响其他片段的操作。

12.2. 读写分离:
sync.Map 中,读操作和写操作是分开的。读操作可以同时进行,不需要加锁。写操作则需要使用锁来保护。这样可以在保证并发性的同时,提高读操作的性能。

12.3. 自旋锁(Spin Locks):
sync.Map 使用了一种自旋锁的技术,当发生轻微的竞争时,Goroutine 会进行自旋等待,而不是立即放弃 CPU 时间片。这可以在短时间内减少锁的竞争,提高性能。

12.4. MapEntry 的延迟删除:
sync.Map 中的键值对是通过 MapEntry 结构表示的。当执行删除操作时,并不会立即删除 MapEntry,而是将其标记为删除状态。这些标记的删除会在后续操作中进行清理,避免了在删除时立即进行昂贵的内存操作。

总之,sync.Map 利用分片锁、读写分离、自旋锁等优化机制,使得在高并发的情况下,对于读写操作的性能表现相对较好。当需要在并发环境中使用映射时,可以考虑使用 sync.Map 来获得更好的性能和并发安全性。

使用普通的 map 数据结构时,如果需要在多个 Goroutine 中进行并发访问,通常需要使用 mutex 来保护 map 的读写操作,以避免并发问题。
这种方式虽然可以实现并发安全,但在高并发情况下,由于整个 map 使用一个锁进行保护,可能会导致锁的竞争,从而影响性能。
使用 map 加 mutex 的方式可以适用于一些简单的场景,但在高并发和大规模数据集的情况下,可能会成为性能瓶颈。

13、golang如何进行单元测试?你会用mock吗?

14、当如下代码运行时,结果如何?

	a :=make([]int,0,2)
	b :=append(a,1)
	c :=append(a,2)
	fmt.Println(a,b,c)

结果是[] [2] [2]

15、context包能实现什么功能,context是并发安全的吗?

context包可用于上下文传递,管理并发goroutine,设置超时、取消信号。
是并发安全的,因为context是引用传递,多个goroutine共享一块数据,且context初始化后是不可变的,他内置了超时、取消机制。

二、Web2.0相关

1、Gin框架

1.1、与其他Go Web框架相比,Gin有哪些优势?

Gin是一个轻量的,性能高效的Web框架,并且有强大的路由引擎和丰富的中间件。

1.2、Gin路由是如何工作的?

我们可以实例化一个router对象,然后调用router.GET或Post方法实现http请求路由。
方法内的参数是路由路径和响应函数。如果有中间件,可以把中间件函数作为参数传入。
路由还支持分组。

1.3、什么是中间件,能解决什么问题?中间件的执行时机?

它可以在请求到达处理程序之前或响应返回客户端之前执行一些操作。中间件可以用于执行各种任务,例如身份验证、日志记录、错误处理、跨域请求处理等。

在中间件代码中,c.Next()方法代表了主逻辑,在此方法的前后可以写中间件的逻辑,分别代表了前置逻辑和后置逻辑。

中间件和主逻辑可看做使用了组合的设计模式。

1.4、什么是跨域?Gin框架如何解决跨域问题?

同源:协议、域名、端口相同。
跨域:浏览器有同源策略。js代码默认不允许访问不同源的资源。
跨域请求发生在浏览器从一个源(Origin)的网页向另一个源的服务器发送HTTP请求时。由于浏览器的同源策略,这种跨源请求默认是不允许的,但可以通过在服务器端添加相应的CORS头来允许这些请求。
Gin框架可以配置中间件,并在中间件中配置放行规则解决跨域问题。

1.5、Gin中的上下文(Context)是什么?如何在处理程序中使用上下文?

在Gin框架中,上下文(Context)是一个非常重要的概念。它代表了HTTP请求的上下文信息,包括请求参数、响应、请求头、状态等。每个HTTP请求都会创建一个唯一的上下文对象,Gin中的路由处理函数和中间件可以通过上下文对象来访问和操作请求和响应。
上下文主要用于以下方面:
1、获取请求参数;
2、设置响应;
3、在中间件中传递参数并按需修改;
4、错误处理;
5、传递其他业务参数;
上下文可以使用Set、Get方法设置和获取参数。

2、Go Kit框架

3、HTTPS、Socket、gRPC、Protobuf等协议

3.1、https为什么安全?

3.2、用http报文的形式描述一个你开发的接口

3.3、WebSocket的特点是什么?可靠性如何?

3.4、http是可靠连接吗?

http是应用层协议,每个http请求响应都是独立不持久连接,本身并不提供可靠性。提供可靠性的是传输层的TCP连接。

3.5、如何抓包?

3.6、如何解决TCP粘包?

3.7、http常见的响应码有什么?可以自定义吗?

200成功 ,404未找到,500服务器内部错误。可以自定义,与前端约定好就行。但一般不建议自定义http响应码。
项目中常规的做法是封装一个响应类对象,如ActResult,使用JSON格式返回数据。包括业务上请求失败时的自定义响应码。注意业务逻辑失败不等于http请求失败,http返回的仍然是200成功的响应码。

3.8、gRPC和protobuf是什么关系?

Protocol Buffers (protobuf):

Protocol Buffers是一种轻量级、高效的数据序列化格式。它是一种语言无关的格式,允许您定义数据结构、消息和接口,并使用proto文件来描述这些结构。
protobuf格式可以用于序列化结构化数据,例如配置文件、网络通信消息等。
protobuf生成的代码可以用于多种编程语言,使得不同语言的应用程序可以相互通信并共享数据。

gRPC:

gRPC是一个高性能的远程过程调用(RPC)框架,它使用protobuf作为默认的序列化格式。
gRPC允许客户端和服务器之间通过定义服务接口和消息类型来进行通信。这些接口和消息类型通常在proto文件中定义。
gRPC生成的代码允许开发者轻松地在客户端和服务器之间进行类型安全的远程调用。

关系总结:

Protocol Buffers用于定义数据结构和消息,以及它们的序列化和反序列化规则。
gRPC使用protobuf来定义通信接口和消息类型,以实现跨网络的远程调用。
gRPC生成的代码可以用于多种编程语言,以实现客户端和服务器之间的通信。

3.9、http可以建立长连接吗?什么情况下需要建立长连接?

http1.1 keep-alive可以建立长连接。适用于以下场景:
a、用户发起多次的一系列请求。
b、流式传输,如视频。
c、服务器推送。

3.10、http1.1/2.0/3.0的区别?

http1.1引入了长连接。
http2.0引入了多路复用。
http3.0是基于QUIC协议的。

三、云原生相关(容器、微服务、监控)

1、docker

1.1、什么是docker,有什么优势?

Docker是一种容器化平台,用于开发、部署和运行应用程序。
他的优势主要有:轻量、一致性、可移植、快速部署和资源隔离。

1.2、Docker容器和虚拟机之间的主要区别是什么?

docker是操作系统级别的虚拟化,与宿主操作系统共享内核。每个容器共享相同的内核,有不同的用户空间。而虚拟机是硬件级别的虚拟化,每个虚拟机都运行在虚拟化的硬件上。从这个角度说,docker更轻量,虚拟机比较重。docker需要的硬件资源少,虚拟机需要的硬件资源多。docker的性能高,部署、启动速度大大快于虚拟机。是秒和分钟级别的差异。虚拟机的隔离性比docker更强,docker容器之间共享系统内核,存在一定的隔离风险。docker比虚拟机更容易跨平台。

1.3. Docker的基本组件有哪些?

引擎、镜像、容器、注册表、组件

引擎负责容器的创建、运行和停止。
镜像提供了创建容器的模板,包括运行的操作系统、依赖库、环境变量配置等。
容器是从镜像基础上创建出来的可运行实例。
注册表是存储了各种docker镜像的仓库,docker hub是大型公共注册表。
组件指多个容器共同组成的一组服务。如web服务容器和MySQL容器可以共同组成一个compose组件。

1.4. docker镜像和容器的区别是什么?

镜像是一个只读的静态文件,包含了一个应用程序及运行该应用程序所需的所有依赖,包括操作系统、库和环境变量。
容器是基于镜像创建的可运行示例,容器包括了镜像及运行时状态。容器是可变的。
打个比方,镜像类似于虚拟机的快照,而容器像是运行中的虚拟机;又或者可以说镜像好比JAVA中的类,而容器是对象。

1.5. 什么是Docker Compose?如何使用它来定义和管理多个容器的应用程序?

Docker Compose 是一个用于定义和管理多个 Docker 容器的应用程序的工具。它允许您使用简单的 YAML 文件来描述应用程序的组件、服务、网络和卷,并使用单个命令启动和管理整个应用程序堆栈。Docker Compose 可以大大简化多容器应用程序的部署和管理过程。

使用docker compose定义管理应用程序的步骤是:
1、创建docker-compose.yml文件并配置多个docker的信息
2、使用docker-compose命令管理应用程序。包括如下命令:

docker-compose up    #用于创建、启动并管理服务,包括创建新的容器和镜像构建。
docker-compose ps          #查看应用程序中的容器状态。
docker-compose stop      #停止应用程序。
docker-compose start      #主要用于启动已经存在但处于停止状态的服务。
docker-compose down     #停止并删除应用程序中的容器、网络和卷。

1.6、 如何通过Dockerfile创建自定义Docker镜像?

要通过 Dockerfile 创建自定义 Docker 镜像,您可以按照以下步骤进行操作:

  1. 创建 Dockerfile

    首先,您需要创建一个文本文件,通常命名为 Dockerfile(注意大小写),并在其中定义构建镜像的指令。Dockerfile 是一个包含一系列指令的文本文件,这些指令描述了镜像的构建过程。

    以下是一个简单的示例 Dockerfile,用于创建一个基于 Ubuntu 操作系统的镜像,并在其中安装一个简单的 Nginx web 服务器:

    # 使用基础镜像
    FROM ubuntu:latest
    
    # 维护者信息
    LABEL maintainer="your-email@example.com"
    
    # 安装必要的软件包
    RUN apt-get update && apt-get install -y nginx
    
    # 复制本地文件到容器
    COPY index.html /var/www/html/
    
    # 暴露端口
    EXPOSE 80
    
    # 启动命令
    CMD ["nginx", "-g", "daemon off;"]
    

    在这个示例中,我们选择了基础镜像(Ubuntu),更新软件包列表并安装了 Nginx。然后,我们将一个本地的 index.html 文件复制到容器中,并暴露了端口 80。最后,我们定义了容器启动时执行的命令。

  2. 构建自定义镜像

    使用 docker build 命令来构建自定义镜像,命令的语法如下:

    docker build -t your-image-name:tag /path/to/Dockerfile-directory
    
    • -t 参数用于指定自定义镜像的名称和标签(tag)。
    • /path/to/Dockerfile-directory 是包含 Dockerfile 的目录路径。

    例如,要构建上面示例中的镜像,可以运行:

    docker build -t my-nginx:1.0 .
    

    这将构建一个名为 my-nginx,标签为 1.0 的自定义镜像,Dockerfile 位于当前目录 (.) 中。

  3. 运行容器

    一旦自定义镜像构建完成,您可以使用 docker run 命令来创建容器并运行它。例如:

    docker run -d -p 8080:80 my-nginx:1.0
    

    这将在端口 8080 上运行您的自定义 Nginx 容器。

  4. 推送到 Docker Hub(可选)

    如果您希望与他人共享您的自定义镜像,可以将其推送到 Docker Hub 或其他容器镜像仓库。首先,您需要使用 docker login 登录到 Docker Hub 帐户,然后使用 docker push 命令推送镜像。例如:

    docker login
    docker push your-username/your-image-name:tag
    

    这会将镜像上传到您的 Docker Hub 帐户。

1.7、什么是Docker网络,有哪些类型的Docker网络?

Docker 提供以下几种常见的网络类型:

  1. 桥接网络(Bridge Network):容器之间可以相互通信,但默认情况下无法从外部网络访问。

  2. 主机网络(Host Network):容器与宿主机共享网络配置,具有网络隔离,但可以访问外部网络。

  3. 覆盖网络(Overlay Network):用于多个宿主机上的容器之间的通信,适用于容器编排平台。

  4. 无桥接网络(None Network):容器与宿主机共享网络配置,没有网络隔离。

  5. 自定义网络(Custom Network):用户可以创建自定义网络,根据需求配置容器连接和通信。

这些网络类型可以根据具体应用场景和需求进行选择和配置。
PS:网络隔离的意思是不能直接通过网络互通。例如不同子网不能直接互通。

1.8、如何在Docker容器之间共享数据?

数据卷、绑定挂载、共享网络、共享卷容器、外部存储。

1.9、关于docker还有哪些问题

  1. Docker容器中的ENTRYPOINT和CMD有什么区别?

  2. 如何通过Docker卷(Volume)进行数据持久化?

  3. Docker Swarm和Kubernetes有什么不同?它们分别用于什么?

  4. 什么是Docker安全性最佳实践?如何确保Docker容器的安全性?

  5. 如何监视和日志记录Docker容器?

  6. 什么是Docker的自动化构建和部署工具,如Jenkins、Travis CI等如何与Docker集成?

  7. 如何创建多阶段构建的Docker镜像?它有什么优势?

  8. 如何在Docker中实现负载均衡?

  9. 如何将Docker容器部署到云平台(如AWS、Azure、Google Cloud等)?

  10. 如何使用Docker Machine来管理远程Docker主机?

  11. Docker的图形化管理工具有哪些,如何使用它们?

  12. 请描述Docker容器生命周期,包括创建、启动、暂停、停止和删除等阶段。

  13. Docker的限制和限制性资源的概念是什么?如何为容器分配资源限制?

2、K8S

基础知识:

什么是Kubernetes?它的主要目标是什么?
解释容器编排是什么,为什么它对大规模应用程序很重要?
请解释Kubernetes中的Pod、Node、Cluster、Namespace和Service的概念。
什么是Kubelet和Kube-proxy,它们在Kubernetes中的作用是什么?
什么是Kubectl?它的作用是什么?
架构和组件:

描述Kubernetes的主要组件,如API Server、Scheduler、Controller Manager和etcd等,以及它们的作用。
什么是Master节点和Worker节点,它们在Kubernetes中有何不同的职责?
解释Kubernetes的控制平面和数据平面的区别。
什么是etcd?为什么它对Kubernetes的高可用性很重要?
部署和配置:

如何在Kubernetes中创建和管理Pod?
什么是Deployment和StatefulSet,它们的区别是什么?
如何创建一个Service,并解释Service的类型(ClusterIP、NodePort、LoadBalancer、ExternalName)?
什么是ConfigMap和Secret,它们的作用是什么?如何在Pod中使用它们?
如何将应用程序的配置参数传递给容器?
扩展和自动化:

解释Kubernetes中的自动伸缩(Horizontal Pod Autoscaling)是什么,以及如何配置它?
如何设置和管理Pod的资源限制和请求?
什么是Kubernetes中的HPA(Horizontal Pod Autoscaler)和VPA(Vertical Pod Autoscaler)?
如何进行滚动更新和回滚应用程序的版本?
故障排除和监控:

如何排查Kubernetes中的故障?您会使用哪些工具和命令?
什么是Kubernetes中的日志记录和监控解决方案?例如,Prometheus和Grafana如何与Kubernetes集成?
安全性和权限:

什么是RBAC(基于角色的访问控制),以及它在Kubernetes中的作用是什么?
如何保护Kubernetes集群中的敏感数据,如Secrets?
如何实现容器内部和容器之间的网络隔离?

3、微服务、监控

3.1、简要介绍下面列出的几个技术,并解释他们的关系和适用场景,并从中选择合适的技术来解决电商活动瞬时高并发问题:docker K8S Istio Envoy Nginx Prometheus Grafana

以下是对列出的几个技术的简要介绍、关系和适用场景:

  1. Docker:

    • 简介:Docker是一个容器化平台,允许您打包应用程序和它们的依赖项成为容器,以便轻松部署和运行。
    • 适用场景:Docker适用于将应用程序容器化,提供一致的开发、测试和生产环境,有助于快速部署和扩展应用。
  2. Kubernetes (K8S):

    • 简介:Kubernetes是一个开源容器编排和管理平台,用于自动化应用程序的部署、扩展和管理。
    • 适用场景:Kubernetes适用于微服务架构,可以帮助您动态地扩展容器以应对高并发、容器故障恢复等需求。
  3. Istio:

    • 简介:Istio是一个开源的Service Mesh平台,用于连接、监视和保护微服务。
    • 适用场景:Istio适用于微服务架构,提供流量管理、故障恢复、安全性和可观测性,有助于处理高并发和复杂的微服务通信。
  4. Envoy:

    • 简介:Envoy是一个高性能的开源代理服务器,用于处理微服务之间的流量。
    • 适用场景:Envoy通常与Istio或Kubernetes一起使用,用于实现微服务的负载均衡、路由、故障恢复等。
  5. Nginx:

    • 简介:Nginx是一个高性能的Web服务器和反向代理服务器,也可以用作负载均衡器。
    • 适用场景:Nginx适用于反向代理、负载均衡、SSL终止等Web服务器相关的场景,可以用于处理电商网站的请求分发。
  6. Prometheus:

    • 简介:Prometheus是一个开源监控和警报工具,用于收集和存储应用程序性能数据。
    • 适用场景:Prometheus适用于实时监控应用程序性能和资源利用率,帮助您识别瓶颈和异常。
  7. Grafana:

    • 简介:Grafana是一个开源的数据可视化和监控仪表板工具,与Prometheus等数据源集成。
    • 适用场景:Grafana用于创建、共享和可视化监控仪表板,使您能够实时查看应用程序性能。

解决电商活动瞬时高并发问题的建议

对于电商活动的瞬时高并发问题,一个合适的技术堆栈可能包括:

  1. Docker和Kubernetes:使用Docker容器和Kubernetes进行应用程序容器化和自动扩展,以应对高并发请求。

  2. Nginx:在Kubernetes集群中使用Nginx作为反向代理,用于请求负载均衡和SSL终止,确保请求能够平均分发到后端容器。

  3. Prometheus和Grafana:使用Prometheus监控Kubernetes集群和应用程序性能,同时使用Grafana创建仪表板以实时查看性能数据和问题。

  4. Istio和Envoy:如果您的电商应用程序采用微服务架构,使用Istio和Envoy来处理微服务之间的流量管理、负载均衡和故障恢复,以确保高可用性和性能。

3.2、微服务架构有什么优势和挑战?

  1. 架构:微服务架构将一个大型应用程序拆分为多个小型、自治的服务,每个服务负责一个特定的功能或业务领域。这些服务之间通过API进行通信,可以使用不同的编程语言和技术栈。

  2. 优势

    • 灵活性:微服务允许团队独立开发、部署和维护各自的服务,提供了更大的灵活性。
    • 可扩展性:您可以根据需要独立扩展每个服务,以应对不同的负载。
    • 技术多样性:微服务允许使用最适合每个服务的技术和工具,促进了技术多样性。
    • 快速交付:小团队可以更快地交付新功能和更新,因为它们只需要关注自己的服务。
    • 容错性:一个服务的故障不会影响整个应用程序,因为其他服务可以继续工作。
  3. 挑战

    • 复杂性:微服务架构需要管理多个服务,涉及到服务发现、负载均衡、监控等复杂性任务。
    • 通信开销:微服务之间的通信可能涉及网络开销,需要有效地处理。
    • 数据一致性:确保微服务之间的数据一致性可能会更加复杂,需要仔细的设计和解决方案。
    • 部署和维护:管理多个服务的部署和维护可能会更具挑战性,需要适当的自动化工具。

3.3、什么是服务的注册、发现?微服务之间的通信方式是怎样的?

服务注册是指将一个微服务的实例信息(如服务名称、IP地址、端口号、健康状态等)注册到一个中心化的服务注册表或服务注册中心。
服务发现是指微服务在需要调用其他微服务时,通过查询服务注册中心来找到目标微服务的实例位置。
基于服务的注册和发现等机制,服务A调用服务B的接口,只需要用服务B在注册中心注册的名称+接口名+参数即可,不需要知道使用的到底是什么协议。
一旦确定要调用的服务实例,服务A会使用适当的通信协议来与服务B通信。通常,这可以是HTTP、gRPC、WebSocket等协议。

3.4、微服务之间如何处理数据一致性?

1、同步调用,可使用分布式锁实现,这种方法简化了一致性问题,防止了竞态条件,但也会导致性能下降和可用性问题,因为一个微服务的失败可能会影响到调用它的微服务。
2、异步消息传递,使用消息队列或消息总线来实现,允许微服务之间发送和接收消息,解耦微服务。特点是非阻塞,高可用,不严格的一致性,需谨慎处理幂等性。
(PS什么是幂等性?)
3、分布式事务,协调多个微服务的数据库操作,以确保它们要么全部成功,要么全部失败。常见的分布式事务管理器包括Saga模式和两阶段提交(2PC)等。
缺点是引入了复杂性和性能开销。
4、事件溯源,系统中的每个状态变化都表示为事件,并被存储。微服务通过订阅事件来保持数据一致性。
特点是松散耦合,但需要实现事件的序列化和传递,以及处理事件的冲突和幂等性问题。

总之,最佳方法是尽量避免分布式事务,采用异步消息传递、事件溯源等更具弹性和可扩展性的方法,以提高系统的性能和可用性。

3.5、微服务如何水平扩展、弹性伸缩?

微服务的水平扩展是一种通过增加服务实例数量来应对更高负载和提高性能的方法。

  1. 容器化和自动化部署

    • 使用容器技术(如Docker)部署和扩展。
    • 使用自动化部署工具(如Kubernetes)来管理和扩展容器化的微服务。Kubernetes可以自动调整实例数量以适应负载变化。
    • AWS、Azure、Google Cloud等云计算平台提供了自动扩展和负载均衡等服务。
  2. 负载均衡

    • 在微服务架构中,通常会使用负载均衡器来分发请求到不同的服务实例。
  3. 微服务架构设计

    • 在设计微服务时,考虑将功能模块化,以便更容易扩展和替换部分服务。
    • 考虑使用异步通信和消息队列,以减少微服务之间的直接依赖,提高系统的弹性。

3.6、微服务架构中,什么是负载均衡、容灾、限流、降级、超时、重试、断路器?

  1. 负载均衡(Load Balancing)

    • 负载均衡是一种分发网络请求到多个服务实例的技术,以确保负载在各个实例之间均匀分布,避免单个实例过载。
    • 负载均衡器可以采用不同的算法,如轮询、随机选择、加权轮询等,来选择目标服务实例。
  2. 容灾(Resilience)

    • 容灾是一种处理系统故障和异常的能力,以确保系统在面对故障时仍然能够提供有限的服务。
    • 容灾策略包括故障转移、备份、自动恢复等,以提高系统的可用性和可恢复性。
  3. 限流(Rate Limiting)

    • 限流是一种控制系统请求速率的技术,以防止过多的请求导致系统超载。
    • 通过设置请求速率限制,可以确保系统在承受范围内处理请求,同时提高系统的稳定性。
  4. 降级(Degradation)

    • 降级是一种在系统压力较大或故障时减少服务质量的策略,以确保核心功能仍然可用。
    • 降级可以包括缩短响应时间、返回默认值或错误消息等。
  5. 超时(Timeout)

    • 超时是指设置请求或操作的最长等待时间。如果在规定的时间内未完成操作,系统将返回超时错误。
    • 超时设置有助于避免请求无限期地等待,提高系统的可用性。
  6. 重试(Retry)

    • 重试是一种在请求失败时尝试重新发送请求的策略,以增加请求的成功概率。
    • 重试可以在短暂故障或网络问题后帮助恢复正常操作。
  7. 断路器(Circuit Breaker)

    • 断路器是一种用于保护系统免受连续故障请求的策略。当故障率达到一定阈值时,断路器将临时中断请求,防止继续发送到故障的服务。
    • 断路器允许系统在一段时间后重新尝试请求,以确定服务是否已经恢复正常。

3.7、什么是微服务的自治性?

微服务的自治性是指每个微服务在一定程度上具有自主决策和自我管理的能力,而不需要中央调度或控制。这意味着每个微服务可以独立运行、扩展、故障恢复和升级,而不会严重依赖其他微服务或中心化的管理系统。微服务的自治性有以下几个关键特点:

  1. 独立性:每个微服务都是一个独立的服务单元,它拥有自己的代码库、数据存储和运行环境。这使得微服务能够独立部署、运行和维护,而不受其他微服务的干扰。

  2. 自我扩展:自治性意味着微服务可以根据负载和需求自动或手动地扩展。微服务可以动态地增加或减少服务实例,以满足不同的性能和负载要求。

  3. 自我修复:微服务应该具备自我修复的能力,能够检测并处理自身的故障。这可以包括自动恢复、重试机制和故障转移策略。

  4. 自我保护:微服务应该能够自我保护,以避免过度负载或被恶意攻击。这可以包括限流、熔断和安全控制策略。

  5. 自我升级:微服务应该能够实现自身的升级,包括新版本的部署和回滚。这可以通过蓝绿部署、金丝雀发布等技术来实现。

  6. 自我监控和报警:微服务应该能够监控自身的性能和状态,并在出现问题时发出警报。这可以包括指标收集、日志记录和告警系统。

  7. 自我配置:微服务应该具备自我配置的能力,以允许动态地调整其行为和参数,而无需手动干预。

微服务的自治性有助于提高系统的弹性、可靠性和可维护性。它减少了单点故障,提高了系统的可用性,并使系统更容易适应不断变化的需求和负载。但与此同时,微服务的自治性也需要合适的监控、自动化和策略来确保各个微服务能够协同工作,以构建一个协调一致的分布式系统。

3.8、如何实现高效的并发写且确保唯一性?

全局序列生成器可以用来高效并发写入。其关键任务是确保生成的标识符在系统中是唯一的。通常用于解决微服务之间的数据冲突问题,特别是在并发写入或创建新实体时。通过分配唯一的序列号,可以避免重复或冲突的标识符,确保唯一性。

常见的全局序列生成器包括分布式ID生成器(如Snowflake算法)、数据库自增主键、基于数据库的序列生成器等。这些生成器通常是高效的,并且可以在分布式环境中确保唯一性。

4、Istio和Envoy

什么是Istio?

为什么需要使用服务网格(Service Mesh)?

Istio的主要组件是什么?

Istio如何实现流量管理?

Istio的故障注入(Fault Injection)是什么?

Istio如何处理服务之间的安全通信?

Istio的负载均衡功能是如何工作的?

Istio支持哪些路由规则和目标策略?

Istio如何进行监控和跟踪?

Istio如何处理服务的身份验证和授权?

Istio与Kubernetes的集成是怎样的?

Istio与微服务架构有什么关系?

Istio如何解决微服务通信中的问题,如超时、重试和断路器等?

Istio支持哪些常见的云平台,如AWS、GCP和Azure?

请解释Istio中的“Sidecar”代理是什么,以及它的作用是什么?

Istio如何处理流量加密和解密?

Istio是否支持多集群部署?

Istio的流量镜像功能是什么,有什么用途?

什么是Istio的网关(Gateway)和虚拟服务(VirtualService)?

请提供一个使用Istio解决的实际生产问题的案例或示例。

什么是Envoy?

Envoy的主要特点是什么?

Envoy与传统的反向代理服务器有什么不同之处?

Envoy的用途是什么?

Envoy是如何处理微服务通信的?

Envoy支持哪些协议?

Envoy的主要组件是什么?

请解释Envoy中的"Sidecar"代理是什么,以及它的作用是什么?

Envoy如何实现负载均衡?

Envoy如何处理流量路由?

Envoy支持哪些路由规则和目标策略?

Envoy如何处理故障检测和故障恢复?

Envoy如何处理流量加密和解密?

Envoy的过滤器(Filters)是什么,有什么作用?

请解释Envoy的中间件架构(Middleware Architecture)。

Envoy如何处理日志记录和监控?

Envoy是否支持多集群部署?

Envoy与Kubernetes、Docker和Service Mesh有什么关系?

请提供一个实际使用Envoy解决问题的案例或示例。

5、Prometheus和Grafana

在面试中,关于Prometheus和Grafana的问题通常涵盖了这两个流行的监控和可视化工具的基本概念、原理和用法。以下是一些可能会在面试中被提出的问题和主题:

关于Prometheus的问题:

  1. 什么是Prometheus?它用于解决什么问题?
  2. Prometheus的核心组件是什么?分别是什么作用?
  3. 什么是PromQL?它用于做什么?
  4. 如何配置Prometheus来监控一个应用程序或服务?
  5. Prometheus的数据模型是什么样的?有哪些基本数据类型?
  6. 什么是标签(Labels)和标签匹配器(Label Matchers)?它们在查询中的作用是什么?
  7. 如何在Prometheus中定义和配置警报规则(Alerting Rules)?
  8. Prometheus如何处理数据的存储和保留策略(Retention Policies)?
  9. 什么是Prometheus的Pushgateway?它的作用是什么?
  10. 如何部署和运行Prometheus的高可用集群?

关于Grafana的问题:

  1. 什么是Grafana?它用于做什么?
  2. Grafana支持哪些数据源?如何配置Grafana连接到不同的数据源?
  3. 如何在Grafana中创建和配置仪表盘(Dashboard)?
  4. Grafana的图表(Panel)可以用来显示哪些类型的数据?如何自定义图表的外观和样式?
  5. 什么是Grafana的模板变量(Template Variables)?如何在仪表盘中使用它们?
  6. Grafana支持警报通知吗?如何设置和配置警报规则以及通知通道?
  7. Grafana可以使用插件来扩展功能吗?可以举例说明一些常用的Grafana插件吗?
  8. 如何在Grafana中共享仪表盘和面板?是否支持团队协作?
  9. Grafana的权限和安全性是如何管理的?
  10. 如何备份和恢复Grafana的配置和仪表盘?

这些问题涵盖了Prometheus和Grafana的核心概念、用法和配置。在面试中,还可以根据候选人的经验和深度进一步展开有关这些工具的技术和实际应用的讨论。

四、区块链相关(共识算法、加密算法、链上数据交互、节点搭建、节点监控)

1、有哪些常见的哈希算法?

SHA-256, keccak-256(又叫SHA-3-256)

2、levelDB是什么?

LevelDB是一种开源的、轻量级的键值对数据库系统,区块链公链如比特币、以太坊使用LevelDB作为存储引擎。

LevelDB通过一系列的设计和优化来确保高性能的写入操作。以下是LevelDB如何实现高性能写入的关键原理和技术:

  1. MemTable:LevelDB使用一个内存中的数据结构称为MemTable,用于保存最新的键值对数据。由于内存操作速度非常快,MemTable能够快速接收和写入新数据,从而实现高性能的写入操作。写入的数据首先被追加到MemTable中。

  2. 日志:为了持久化写入操作,LevelDB会将每次写入操作记录在一个日志文件中。这个日志文件是追加写入的,因此写入速度非常快。写入操作首先被写入日志文件,然后在内存中的MemTable中进行处理。这确保了数据即使在内存中尚未刷新到磁盘时也不会丢失。

  3. SSTables:当MemTable达到一定大小后,LevelDB将其转换为一个不可变的SSTable(Sorted String Table),并将其写入磁盘。SSTables是按照键的有序顺序存储的,这有助于提高读取性能。LevelDB使用多个SSTables,它们以不同的大小和层级存在。

  4. 合并(Compaction):为了管理和维护多个SSTables,LevelDB定期执行合并操作,将多个SSTables合并成更大的SSTables,并删除过时的数据。这个过程被称为"合并"或"Compaction"。合并操作减少了SSTables的数量,提高了读取性能,并清理了过时的数据。

  5. Bloom Filters:LevelDB使用Bloom Filters来加速键的查找操作。Bloom Filters是一种数据结构,可以快速检查某个键是否可能存在于SSTables中,从而减少了磁盘读取的开销。

  6. Write-Ahead Logging(WAL):LevelDB采用Write-Ahead Logging(WAL)策略,这意味着在写入数据到SSTables之前,所有写入操作都首先被写入日志文件。这样可以确保数据持久性,并允许在崩溃或故障发生时进行恢复。

通过将内存中的数据结构与磁盘存储和合并操作相结合,LevelDB能够实现高性能的写入操作。它允许数据快速写入内存中的MemTable,然后定期将数据刷新到磁盘中的SSTables,并通过合并操作和Bloom Filters来优化读取性能。这些设计和技术使LevelDB成为一种适用于需要高性能写入的应用程序的有效存储引擎。

3、公链是如何保持节点之间的一致性的?节点之间靠什么通信?

3.1、公链是如何保持节点之间的一致性的?节点之间靠什么通信?

公链靠共识算法和分布式网络协议通信保证节点之间的一致性。
节点之间的通信有基于TCP/IP的自定义通信协议。

节点的加入一般是通过种子节点(或者叫引导节点)列表连接种子节点。

3.2、比特币使用什么通信协议,如何实现节点的发现?

在比特币中,种子节点列表是硬编码到客户端的,且由社区成员定期维护更新。
每个比特币节点都维护一个IP地址列表。
比特币出块的广播,会发送到邻居节点,邻居又会发送到邻居的邻居,直到发送到全网。
还有一些比特币节点提供DNS服务。

3.3、以太坊使用什么通信协议?

在以太坊中使用的是DevP2P协议解决节点的发现、消息的传递。

DevP2P(Developer Peer-to-Peer)是以太坊网络中使用的一种点对点(P2P)通信协议,它用于节点之间的通信、数据传输和状态同步。以下是DevP2P的一些关键原理和工作方式:

  1. 节点发现:DevP2P协议允许节点发现其他对等节点。节点通过连接到已知的引导节点或使用自动发现机制来加入网络。一旦加入网络,节点可以请求其他节点的IP地址列表,以建立更多的连接。

  2. 消息传递:DevP2P协议允许节点之间传递消息,包括交易、区块、状态和其他重要数据。消息可以使用DevP2P协议进行加密和传输,以确保安全性和隐私。

  3. 状态同步:以太坊节点使用DevP2P来进行状态同步,确保它们在区块链上具有相同的状态。这包括状态树的传输和验证,以确保网络中的所有节点都具有相同的区块链状态。

  4. 节点管理:DevP2P协议管理节点之间的连接,包括建立、维护和终止连接。这有助于确保网络的可靠性和稳定性。

  5. 发现协议:DevP2P使用一种称为"RLPx"(Recursive Length Prefix)的协议来编码和传输数据。RLPx是一种基于长度前缀的编码方式,用于封装和解封数据。

  6. 加密和身份验证:DevP2P协议支持数据的加密和节点的身份验证,以确保通信的安全性。节点可以使用加密密钥来保护通信,从而防止数据的篡改和窃取。

总的来说,DevP2P协议是以太坊网络中的核心通信协议,它支持节点之间的发现、消息传递、状态同步和连接管理。这些功能有助于确保以太坊网络的健康运行和安全性。 DevP2P协议是以太坊节点之间进行通信的基础,它使得网络中的节点能够相互交流并维护区块链的一致性。

3.3、IPFS和filecoin的通信协议是什么?

IPFS使用DHT解决节点的注册和发现。

DHT(分布式哈希表,Distributed Hash Table)是一种分布式计算和存储技术,用于管理大规模数据和资源的分布式网络。它允许在网络中存储和检索数据,将数据分布在多个节点上,并提供高度分散的数据存储和查找机制。

3.4、有哪些常见的共识算法?以比特币为例,说明POW共识算法如何保证节点一致性的。

常见的共识算法有POW POS POST等。

工作量证明(Proof of Work,PoW)是一种用于维护区块链共识的算法,它确保了在区块链网络中的出块过程和节点之间的一致性。下面我将详细说明在PoW共识算法下,区块链是如何从出块到节点同步的过程,包括节点之间的通信细节:

  1. 出块过程

    • 挖矿:一个节点决定尝试创建一个新的区块。它首先选择要打包进区块的待处理交易,然后开始挖矿过程。挖矿就是试图找到一个特定的数值,使得区块头的哈希值满足一定的条件,通常是小于目标难度值的条件。这个数值被称为“随机数”或“Nonce”。

    • 计算哈希:节点不断尝试不同的Nonce值,将区块头和Nonce值组合在一起,然后计算区块头的哈希值。这是一个计算密集型过程,通常需要多次尝试才能找到合适的Nonce值。

    • 找到有效哈希:当节点找到一个Nonce值,使得计算出的区块头哈希小于难度目标时,就意味着它已经找到了有效的哈希。此时,节点将有效的Nonce和哈希添加到新的区块中。

    • 广播区块:一旦节点找到有效的哈希,它会将新创建的区块广播到整个网络中,通知其他节点有新的区块可以添加到区块链上。

  2. 节点同步过程

    • 接收新区块:其他节点在接收到新区块后,会验证区块的有效性,包括检查区块头哈希是否满足难度条件,以及交易的有效性。

    • 验证工作量:其他节点会验证新区块的工作量,确保节点确实进行了计算工作,并找到了有效的哈希。这是PoW的关键部分,因为节点必须验证工作量以确保区块的合法性。

    • 接受或拒绝区块:如果其他节点验证通过,它们会接受新区块,并将其添加到自己的区块链中。如果验证失败,节点将拒绝区块,并不予接受。

    • 同步整个链:节点在不断地接收和验证新区块,逐渐构建整个区块链。节点会保持同步,确保它们的本地副本与网络中的其他节点保持一致。

总结来说,PoW共识算法下,节点通过解决复杂的数学问题来竞争创建新区块的权利,然后将新区块广播到网络中。其他节点验证工作量和区块的有效性,如果通过验证,就接受并添加到本地区块链中,从而保持节点之间的一致性。这个过程确保了区块链的安全性和一致性。

4、使用golang实现零知识证明示例

4.1、什么是同态加法?

同态加法指的是在加密数据的情况下,能够在密文上进行加法操作,而不需要解密数据。
同态加法是某些加密算法的特性。

满足同态加法的加密算法通常具有如下性质:
1.无法根据E(x)计算x,这是加密算法的密文安全性,又叫不可逆性。
2.若x!=y,则E(x)!=E(y),这叫不可区分性
3.E(x+y)=E(x)+E(y) ,这个性质是:同态加法。

注意:并非所有加密算法都满足上述性质。

另外与同态加法类似的,还有同态乘法。

满足同态加法的加密算法主要有以下几种:

  1. Rivest’s Cryptosystem(RSA):RSA是一种非对称加密算法,具有乘法同态性,但不支持通用的加法同态操作。
  2. ElGamal加密:ElGamal加密支持加法同态性。
  3. Paillier加密:Paillier加密支持加法同态性。
  4. Gentry的完全同态加密(Fully Homomorphic Encryption,FHE):完全同态加密是一种具有最强同态性质的加密算法,支持加法和乘法同态性。

注意:椭圆曲线加密不满足加法同态。

4.2、

5、使用golang实现椭圆曲线加解密、签名

6、以太坊从签名中能解析出公钥吗?是如何实现的?

7、比特币钱包有哪些具体实现?各自的特点是什么?

8、什么是TVL,TPS?

TVL(Total Value Locked):翻译成中文是 “总锁定价值”。TVL 是一种用于衡量去中心化金融(DeFi)应用程序或协议的指标,表示用户在这些应用程序或协议中锁定的总价值,通常以加密货币或数字资产的形式来表示。

TPS(Transactions Per Second):TPS是指每秒钟可以处理的交易数量。这个指标用于衡量一个区块链网络或支付系统的吞吐量。高TPS表示系统能够处理更多的交易,这对于需要处理大量交易的场景非常重要,例如支付系统或加密货币交易所。不同的区块链平台具有不同的TPS限制,这取决于其共识算法、网络架构和性能优化。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
很高兴回答你关于Golang语法进阶问题Golang是一门简洁高效的编程语言,下面我将分享一些Golang语法的进阶知识。 1. 嵌套结构体:在Golang中,你可以在一个结构体中嵌套另一个结构体。这样可以更好地组织和管理代码。例如: ```go type Person struct { Name string Age int } type Employee struct { Person Salary int } ``` 这里的Employee结构体嵌套了Person结构体,可以通过Employee结构体访问Person结构体的字段。 2. 接口和类型断言:Golang中的接口是一种约定,定义了一组方法。通过接口,你可以实现多态性。类型断言则用于检查接口变量是否实现了某个接口。例如: ```go type Shape interface { Area() float64 } type Circle struct { Radius float64 } func (c Circle) Area() float64 { return math.Pi * c.Radius * c.Radius } func main() { var shape Shape = Circle{Radius: 5} if circle, ok := shape.(Circle); ok { fmt.Println("Area of circle:", circle.Area()) } } ``` 3. 并发编程:Golang内置了并发编程的支持,通过goroutine和通道(channel)可以实现轻量级线程间通信。例如: ```go func worker(id int, jobs <-chan int, results chan<- int) { for j := range jobs { fmt.Println("Worker", id, "processing job", j) time.Sleep(time.Second) // 模拟耗时操作 results <- j * 2 } } func main() { jobs := make(chan int, 5) results := make(chan int, 5) // 启动三个goroutine for w := 1; w <= 3; w++ { go worker(w, jobs, results) } // 发送5个任务 for j := 1; j <= 5; j++ { jobs <- j } close(jobs) // 输出结果 for r := 1; r <= 5; r++ { fmt.Println(<-results) } } ``` 以上是Golang语法进阶的一些例子,希望对你有帮助!如果你有更多问题,欢迎继续提问。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值