支付宝手机网站支付/seo搜索引擎优化工程师招聘

支付宝手机网站支付,seo搜索引擎优化工程师招聘,大连哪家做网站比较好,沧州哪里做网站本文目录 1.序2.引入etcd缓存流程项目结构 3.gocachepb.proto4.服务注册register.go5.服务发现discover.go6.gRPC客户端client.gopeers.goclient.go 7.gRPC服务端实现server.go一些问题缓存获取流程缓存设置流程为什么要带超时的上下文? 1.序 GeeCache项目并没有引…

在这里插入图片描述

本文目录

  • 1.序
  • 2.引入etcd
    • 缓存流程
    • 项目结构
  • 3.gocachepb.proto
  • 4.服务注册register.go
  • 5.服务发现discover.go
  • 6.gRPC客户端client.go
    • peers.go
    • client.go
  • 7.gRPC服务端实现server.go
  • 一些问题
    • 缓存获取流程
    • 缓存设置流程
    • 为什么要带超时的上下文?

1.序

GeeCache项目并没有引入服务发现,对于现代分布缓存系统,服务发现和节点间通信是两个重要环节,所以可以引入etcd和gRPC来使得系统更加健壮和高效。

etcd作为一个高可用的分布式键值存储系统,扮演着服务注册与发现的角色。通过etcd,缓存节点可以动态地注册自己的存在,同时发现其他节点的位置。这种机制使得系统能够自动适应节点的加入和退出,无需手动配置。

而且etcd的租约机制提供了节点健康检查的能力,当某个节点宕机时,系统能够及时感知并进行相应调整,保证整个缓存集群的可用性。

gRPC则解决了节点间高效通信的问题。相比传统的HTTP/JSON通信方式,gRPC基于HTTP/2协议和Protocol Buffers序列化格式,提供了更高的性能和更低的延迟。传输前使用 protobuf 编码,接收方再进行解码,可以显著地降低二进制传输的大小。另外一方面,protobuf 可非常适合传输结构化数据,便于通信字段的扩展。GeeCache中只是单纯用了protobuf进行通信。

在缓存系统中,节点间需要频繁交换数据,如缓存查询、更新等操作,gRPC的高效通信能力显著提升了系统的吞吐量。

本文所参考的部分实现代码是Github上的cache项目,原地址:https://github.com/Spr1n9/springcache

2.引入etcd

缓存流程

  • 当一个节点需要获取不在本地缓存的数据时,它会通过一致性哈希算法选择一个节点
  • 使用 etcd 进行服务发现,获取该节点的地址
  • 建立 gRPC 连接并调用远程节点的 Get 方法获取数据
  • 如果远程节点也没有缓存该数据,它会从数据源获取并返回

项目结构

这里我们需要编写几个新的文件,分别是:

cachepb.proto Protocol Buffers定义文件,用于定义gRPC服务接口和消息格式。

  • 定义了 SpringCache 服务,包含 Get 和 Set 两个RPC方法
  • 定义了请求和响应的消息结构: GetRequest 、 GetResponse 、 SetRequest 和 SetResponse
  • 这个文件是gRPC通信的基础,通过protoc工具生成Go代码

server.go 服务端核心实现,负责处理来自其他节点的缓存请求。

  • 实现了gRPC服务接口,处理 Get 和 Set 请求
  • 管理节点间的通信和缓存数据的分发
  • 使用一致性哈希算法选择节点
  • 启动gRPC服务器,接收来自其他节点的请求

client.go 客户端实现,负责向其他节点发送请求。

  • 封装了gRPC客户端调用逻辑
  • 实现了 PeerGetter 接口,用于从远程节点获取或设置缓存
  • 处理与远程节点的连接和通信

discover.go 服务发现相关功能,负责发现和连接其他节点。

  • 提供 DialPeer 函数,用于建立与其他节点的gRPC连接
  • 提供 GetAddrByName 函数,通过etcd查询服务名对应的地址
  • 使用etcd的服务发现机制获取节点信息

register.go 服务注册相关功能,负责将节点注册到etcd。

  • 提供 Etcd 结构体,封装etcd客户端操作
  • 实现租约创建、绑定和续约功能
  • 提供 RegisterServer 方法,将服务注册到etcd

3.gocachepb.proto

在这里插入图片描述

首先来看看proto文件,定义了整个系统的RPC接口和消息格式。

GeeCache一样,有两个GetRequestGetResponse,是用来Get获取缓存的请求和响应。

value :缓存的值,使用 bytes 类型可以存储任意二进制数据。

SetRequestSetResponse 是设置缓存的请求消息和响应消息。

这里请求消息有:group 缓存组名、key 缓存键、 value 缓存值、expire 过期时间戳(Unix时间戳格式)、ishot 是否为热点数据。

设置缓存的响应消息有:ok 返回bool格式操作是否成功。

service SpringCache {rpc Get(GetRequest) returns (GetResponse);rpc Set(SetRequest) returns (SetResponse);
}

Get :获取缓存,接收 GetRequest 参数,返回 GetResponse, Set :设置缓存,接收 SetRequest 参数,返回 SetResponse

使用protoc工具生成对应的两个代码如下,生成的代码将被服务端和客户端使用,服务端( server.go )实现了 SpringCacheServer 接口,处理 Get 和 Set 请求,客户端( client.go )使用 SpringCacheClient 接口向远程节点发送请求。

  • springcachepb.pb.go :包含消息类型的定义和序列化/反序列化代码
  • springcachepb_grpc.pb.go :包含 gRPC 客户端和服务端接口代码

4.服务注册register.go

在这里插入图片描述

Etcd 结构体是对 etcd 客户端的封装,包含了与 etcd 交互所需的核心组件。其中 EtcdClietcd 的客户端实例,用于执行各种 etcd 操作; leaseId 存储租约 ID,用于后续的租约管理; ctxcancel 则用于控制上下文和超时处理。将 etcd 的操作封装在一个结构体中,便于统一管理和使用。

NewEtcd 函数负责初始化 etcd 客户端连接。它接收 etcd 服务器的地址列表,创建一个新的 etcd 客户端实例,并设置连接超时时间。这里使用了 clientv3.New 方法创建客户端,这是 etcd v3 API 的标准做法。还创建一个带超时的上下文,用于控制后续操作的超时行为。这是与分布式系统交互的常见模式,可以避免因网络问题导致的长时间阻塞。

DialTimeout 是客户端尝试连接到 etcd 服务时的超时时间。如果在指定时间内无法建立连接,客户端会返回错误。

在这里插入图片描述
CreateLease 为注册在etcd上的节点创建租约。 由于服务端无法保证自身是一直可用的,可能会宕机,所以与etcd的租约是有时间期限的,租约一旦过期,服务端存储在etcd上的服务地址信息就会消失。

如果服务端是正常运行的,etcd中的地址信息又必须存在,因此发送心跳检测,一旦发现etcd上没有自己的服务地址时,请求重新添加(续租)。

CreateLease 函数实现了 etcd 的租约创建机制。在分布式系统中,租约是一种重要的机制,用于表示节点的存活状态。该函数调用 Grant 方法向 etcd 申请一个指定过期时间的租约,并将获得的租约 ID 保存在 Etcd 结构体中。租约机制是 etcd 实现服务健康检查的基础,一旦租约过期,与之关联的键值对会被自动删除,这样就能自动清理已经宕机的节点信息。

在这里插入图片描述
BindLease 函数将服务信息与租约绑定。它使用 Put 方法将服务名称和地址作为键值对存储到 etcd 中,并通过 clientv3.WithLease 选项将这个键值对与之前创建的租约关联起来。这样,当租约过期时,这个服务信息也会被自动删除。这种机制确保了 etcd 中只保存活跃节点的信息,是实现服务自动注册和注销的关键。

在这里插入图片描述

KeepAlive 函数实现了租约的续约机制。它调用 etcdKeepAlive 方法,定期向 etcd 发送心跳,以延长租约的有效期。该函数启动一个 goroutine 持续监听续约响应通道,如果收到 nil 响应,表示续约失败,服务可能已经与 etcd 断开连接。这种心跳机制是分布式系统中保持节点活跃状态的标准做法,确保了只要服务正常运行,其信息就会一直保存在 etcd 中。

在这里插入图片描述

RegisterServer 函数是服务注册的入口,它整合了前面几个函数的功能,完成服务的完整注册流程。首先创建租约,然后将服务信息与租约绑定,接着启动心跳保持租约活跃,最后使用 etcdendpoints 管理器注册服务端点。

使用 endpoints.NewManager 创建一个管理器,用于管理同一服务的所有实例。通过 AddEndpoint 方法,将当前实例的信息添加到服务组织中,并使用之前的租约进行关联。

em 会将所有 UserService 的实例组织在一起,以 UserService/ 为前缀存储在 etcd 中。通过 AddEndpoint,可以动态地添加服务实例。如果后续有更多实例(如 192.168.1.2:8080 和 192.168.1.3:8080),可以继续调用 AddEndpoint 将它们添加到 etcd 中。比如下面的。

/CacheService/instance1:8001  (leaseID: 123)/instance2:8002  (leaseID: 456)/instance3:8003  (leaseID: 789)

每个实例都有自己的租约保证存活,而 Manager 则负责将这些实例组织在一起,方便 gRPC 客户端进行服务发现和负载均衡。

5.服务发现discover.go

在这里插入图片描述

DialPeer 函数负责建立与远程服务节点的 gRPC 连接。它接收 etcd 客户端和服务名称作为参数,返回一个 gRPC 连接。函数首先创建一个 etcd resolver 构建器,这是 gRPC 服务发现的核心组件。然后设置一个带超时的上下文,确保连接操作不会无限期阻塞。最后,使用 grpc.DialContext 方法建立连接,其中 "etcd:///"+service 表示使用 etcd 作为服务发现机制,并指定要连接的服务名称。

DialPeer 函数中, resolver.NewBuilder(c) 创建了一个 etcd resolver 构建器。这个构建器实现了 gRPC 的 resolver.Builder 接口,能够解析 etcd 中存储的服务信息。当使用 "etcd:///"+service 作为目标地址时,gRPC 会使用这个 resolveretcd 中查找所有注册在该服务名下的实例地址。这种机制使得客户端可以通过服务名而非具体 IP 地址进行通信,实现了服务发现的解耦。

在这里插入图片描述
GetAddrByName 函数提供了一种更直接的服务发现方式。它接收 etcd 客户端和服务名称作为参数,直接从 etcd 中查询该服务名对应的地址。函数首先创建一个带超时的上下文,然后使用 etcd 的 Get 方法查询指定键(服务名)的值(服务地址)。这种方式适用于简单的键值查询,不依赖 gRPCresolver 机制。

这两种方式分别满足不同场景的需求。例如, DialPeer 用于建立 gRPC 连接进行缓存操作,而 GetAddrByName 则用于服务器启动时发现其他节点。

两个函数都使用了 context.WithTimeout 创建带超时的上下文,这是 Go 语言中处理超时的标准模式。在分布式系统中,网络延迟和服务不可用是常见问题,设置适当的超时可以避免长时间阻塞,提高系统的可用性和响应速度。在这个文件中,超时时间设置为 2 秒,这是一个较为合理的值,既能容忍一定的网络延迟,又不会因等待过长而影响用户体验。

6.gRPC客户端client.go

peers.go

在这里插入图片描述


client.go

在这里插入图片描述

Client 结构体是对远程节点通信客户端的封装,包含两个关键字段: Name 表示目标服务节点的名称,用于在 etcd 中查找对应的服务地址; Etcdetcd 客户端的引用,用于进行服务发现。

在这里插入图片描述
Get 函数实现了从远程节点获取缓存数据的功能。它首先通过 DialPeer 函数利用 etcd 进行服务发现,获取目标节点的 gRPC 连接。然后创建 gRPC 客户端,构造请求参数,并设置超时上下文,最后发起 RPC 调用并处理响应。这个函数展示了 gRPC 客户端的标准使用模式,以及如何将 etcd 服务发现与 gRPC 调用结合起来。

在这里插入图片描述
Set 函数实现了向远程节点设置缓存数据的功能。它的流程与 Get 函数类似,也是先通过 etcd 获取连接,然后创建 gRPC 客户端发起调用。不同的是,它需要处理更多的参数,包括缓存值、过期时间和热点标记。这个函数展示了如何处理复杂的 RPC 参数,以及如何处理 RPC 调用的错误和响应。

var _ PeerGetter = (*Client)(nil)

通过这种方式验证 Client 结构体是否实现了 PeerGetter 接口。

这是 Go 语言中常用的接口实现检查技巧,如果 Client 没有完全实现 PeerGetter 接口,编译器会报错。这种静态检查可以早期发现接口实现的问题,提高代码质量。

7.gRPC服务端实现server.go

在这里插入图片描述

Server 结构体是 分布式缓存系统的服务端核心组件,它实现了 gRPC 服务接口和节点选择功能。结构体中包含多个重要字段: status 标记服务运行状态; self 记录自身 IP 地址; peers 是一致性哈希环,用于节点选择; etcdetcd 客户端实例,用于服务发现; clients 存储了所有远程节点的客户端实例。

NewServer 函数负责创建并初始化一个 Server 实例。它接收服务名称、自身地址和 etcd 客户端作为参数,初始化一致性哈希环和客户端映射。

在这里插入图片描述

GetSet 方法实现了 gRPC 服务接口,分别用于处理远程缓存获取和设置请求。当其他节点通过 gRPC 调用这些方法时,服务器会从本地缓存组中获取或设置数据,并返回相应的结果。这两个方法是分布式缓存系统中节点间数据交换的核心实现,它们将 gRPC 请求转换为本地缓存操作,实现了远程调用与本地存储的桥接。

在这里插入图片描述

SetPeers 方法是服务发现和节点管理的关键。它接收一组节点名称,通过 etcd 查找每个节点的 IP 地址,然后将这些地址添加到一致性哈希环中,并创建对应的客户端实例。这个方法展示了如何使用 etcd 进行服务发现:通过 GetAddrByName 函数查询 etcd 中存储的服务地址信息。
在这里插入图片描述

PickPeer 方法实现了 connect.PeerPicker 接口,用于根据键选择合适的远程节点。它使用一致性哈希算法确定键应该存储在哪个节点上,然后返回该节点的客户端实例。这个方法是分布式缓存系统中数据分片的核心实现,它确保了相同的键总是被路由到相同的节点,提高了缓存的命中率和一致性。

在这里插入图片描述

StartServer 方法负责启动 gRPC 服务器。它首先检查服务是否已经启动,然后初始化 TCP 监听器,创建 gRPC 服务器实例,注册服务处理器,最后开始监听和处理请求。这个方法是服务器组件的入口点,它将所有组件组合在一起,形成一个完整的服务节点。

一些问题

缓存获取流程

当客户端通过 API 请求获取缓存数据时:

  1. HTTP 服务器接收请求,调用 group.Get 方法获取数据。

  2. group.Get 首先尝试从本地缓存获取数据,如果命中则直接返回。

  3. 如果本地缓存未命中, group.Get 会调用 group.load 方法加载数据。

  4. group.load 会先检查是否有远程节点负责存储该键的数据:

    • 如果有,则通过 PeerPicker.PickPeer 选择合适的节点
    • 然后通过 PeerGetter.Get 从远程节点获取数据
    • 这个过程涉及 gRPC 调用,由 Client.Get 方法实现
  5. 如果远程节点获取失败或没有远程节点负责该键,则调用回调函数从数据源获取数据。

  6. 获取到数据后,将其存储到本地缓存并返回给客户端。

缓存设置流程

当客户端通过 API 请求设置缓存数据时:

  1. HTTP 服务器接收请求,解析参数,调用 group.Set 方法设置数据。

  2. group.Set 会根据键选择合适的节点:

    • 如果是本地节点,则直接设置本地缓存
    • 如果是远程节点,则通过 PeerGetter.Set 设置远程节点的缓存
    • 这个过程也涉及 gRPC 调用,由 Client.Set 方法实现
  3. 设置成功后,返回成功响应给客户端。

为什么要带超时的上下文?

可以看到,这里我们经常使用上下文,并且还要加入超时的设定。

使用带超时的上下文(context.WithTimeout)是一种非常重要的编程实践,它能有效防止系统因为某些操作卡住而导致资源耗尽。

ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()

创建一个新的上下文,它会在2秒后自动超时。同时返回一个cancel函数,可以手动取消这个上下文。defer cancel() 确保无论函数如何返回,都会调用cancel函数释放资源。

打个比方,假设我们去餐厅点餐,如果没有超时控制 :你告诉服务员"我要一份牛排",然后一直等,不管厨房是否忙碌、是否缺货,你可能会一直等下去。

有超时控制 :你告诉服务员"我要一份牛排,但我只能等15分钟"。如果15分钟内上菜了,太好了;如果没有,你就可以取消订单离开,不用无限期等待。

如果没有超时控制,当目标节点宕机或网络异常时,请求可能会一直阻塞,有了2秒的超时控制,即使目标节点无响应,最多也只会等待2秒就返回错误。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/897595.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Pytorch系列教程:可视化Pytorch模型训练过程

深度学习和理解训练过程中的学习和进步机制对于优化性能、诊断欠拟合或过拟合等问题至关重要。将训练过程可视化的过程为学习的动态提供了有价值的见解,使我们能够做出合理的决策。训练进度必须可视化的两种方法是:使用Matplotlib和Tensor Board。在本文…

18 | 实现简洁架构的 Handler 层

提示: 所有体系课见专栏:Go 项目开发极速入门实战课;欢迎加入我的训练营:云原生AI实战营,一个助力 Go 开发者在 AI 时代建立技术竞争力的实战营;本节课最终源码位于 fastgo 项目的 feature/s14 分支&#x…

STM32之I2C硬件外设

注意:硬件I2C的引脚是固定的 SDA和SCL都是复用到外部引脚。 SDA发送时数据寄存器的数据在数据移位寄存器空闲的状态下进入数据移位寄存器,此时会置状态寄存器的TXE为1,表示发送寄存器为空,然后往数据控制寄存器中一位一位的移送数…

不用 Tomcat?SpringBoot 项目用啥代替?

在SpringBoot框架中,我们使用最多的是Tomcat,这是SpringBoot默认的容器技术,而且是内嵌式的Tomcat。 同时,SpringBoot也支持Undertow容器,我们可以很方便的用Undertow替换Tomcat,而Undertow的性能和内存使…

基于SpringBoot的“体育购物商城”的设计与实现(源码+数据库+文档+PPT)

基于SpringBoot的“体育购物商城”的设计与实现(源码数据库文档PPT) 开发语言:Java 数据库:MySQL 技术:SpringBoot 工具:IDEA/Ecilpse、Navicat、Maven 系统展示 系统总体模块设计 前台用户登录界面 系统首页界面…

go context学习

1.Context接口2.emptyCtx3.Deadline()方法4.Done()方法5.Err方法6.Value方法()7.contex应用场景8.其他context方法 1.Context接口 Context接口只有四个方法,以下是context源码。 type Context interface {Deadline() (deadline time.Time, …

在VMware Workstation Pro上轻松部署CentOS7 Linux虚拟机

首先我们需要下载VM虚拟机和Centos7的镜像 下载并安装VMware Workstation Pro 访问VMware Workstation Pro官网下载 https://www.vmware.com/ 第二步:下载centos7镜像 访问centos官网下载 https://www.centos.org/ 开始部署Centos7 点击创建新的虚拟机 这里是Cen…

Android AudioFlinger(五)—— 揭开AudioMixer面纱

前言: 在 Android 音频系统中,AudioMixer 是音频框架中一个关键的组件,用于处理多路音频流的混音操作。它主要存在于音频回放路径中,是 AudioFlinger 服务的一部分。 上一节我们讲threadloop的时候,提到了一个函数pr…

从0开始的操作系统手搓教程27:下一步,实现我们的用户进程

目录 第一步:添加用户进程虚拟空间 准备冲向我们的特权级3(用户特权级) 讨论下我们创建用户线程的基本步骤 更加详细的分析代码 用户进程的视图 说一说BSS段 继续看process.c中的函数 添加用户线程激活 现在,我们做好了TSS…

Node 使用 SSE 结合redis 推送数据(echarts 图表实时更新)

1、实时通信有哪些实现方式? 特性轮询(Polling)WebSocketSSE (Server-Sent Events)通信方向单向(客户端 → 服务端)双向(客户端 ↔ 服务端)单向(服务端 → 客户端)连接方…

Android Native 之 文件系统挂载

一、文件系统挂载流程概述 二、文件系统挂载流程细节 1、Init启动阶段 众所周知,init进程为android系统的第一个进程,也是native世界的开端,要想让整个android世界能够稳定的运行,文件系统的创建和初始化是必不可少的&#xff…

Redis--Set类型

目录 一、引言 二、介绍 三、命令 1.sadd,smembers,sismember 2.spop,srandmember 3.smove,srem 4.sinter,sinterstore 5.sunion,sunionstore,sdiff,sdiffstore 四、内部编码 1.intset 2.hashtable 五、应用场景 1.使用Set保存用…

Faster R-CNN原理详解以及Pytorch实现模型训练与推理

《------往期经典推荐------》 一、AI应用软件开发实战专栏【链接】 项目名称项目名称1.【人脸识别与管理系统开发】2.【车牌识别与自动收费管理系统开发】3.【手势识别系统开发】4.【人脸面部活体检测系统开发】5.【图片风格快速迁移软件开发】6.【人脸表表情识别系统】7.【…

使用dockerfile创建镜像

1.什么是Dockerfile Dockerfile 是一个用于指导 Docker 镜像构建过程的脚本文件。它通过一系列指令来详细描述了构建镜像所需的步骤和配置细节。利用 Dockerfile,我们可以精确地设定容器的运行环境,安装必要的软件,复制项目文件,…

大脑宏观结构中的富集俱乐部:图论分析视角

摘要 大脑是一个高度复杂的网络。越来越多的证据支持大脑网络中一组重要脑区的关键作用,这些脑区通常被称为大脑的“核心”或“枢纽”区域。这些区域不仅能量消耗较高,而且在神经信息传递方面的效率也极高,因此被称为“富集俱乐部”。富集俱乐…

Redis7——进阶篇(五)

前言:此篇文章系本人学习过程中记录下来的笔记,里面难免会有不少欠缺的地方,诚心期待大家多多给予指教。 基础篇: Redis(一)Redis(二)Redis(三)Redis&#x…

光谱相机检测肉类新鲜度的原理

光谱相机通过分析肉类样本在特定波长范围内的光谱反射特性,结合化学与生物指标的变化规律,实现对其新鲜度的无损检测。其核心原理可概括为以下方面: 一、光谱特征与物质成分的关联性 ‌物质特异性吸收/反射‌ 不同化学成分(如水分…

c#面试题整理9

1.遍历xml文档 2.解释一下这段 String s new String("xyz"); 这段在C#平台中,编译失败 3.说明一下抽象类 抽象类可以有构造函数 抽象类不能是静态和密封的类,密封的类表示无法继承,抽象类本身就不可实例化,加不好…

《React 属性与状态江湖:从验证到表单受控的实战探险》

属性初识 属性能解决两个大问题&#xff1a;通信和复用 props.js: import React, { Component } from react import Navbar from ./Navbarexport default class App extends Component {state {a:100}render() {return (<div><div><h2>首页</h2>&l…

Qwen/QwQ-32B 基础模型上构建agent实现ppt自动生成

关心Qwen/QwQ-32B 性能测试结果可以参考下 https://zhuanlan.zhihu.com/p/28600079208https://zhuanlan.zhihu.com/p/28600079208 官方宣传上是该模型性能比肩满血版 DeepSeek-R1&#xff08;671B&#xff09;&#xff01; 我们实现一个 使用Qwen/QwQ-32B 自动生成 PowerPoi…