当前位置: 首页 > news >正文

Go基础(⑤Consul)

Consul 简单说就是个 “服务管家”,专门帮你管理服务器、App 这些 “服务” 的。

比如你公司有很多台服务器,上面跑着各种程序(像登录功能、支付功能),这些都叫 “服务”。Consul 能干这几件事:

找得到谁在线:它能自动发现哪些服务在运行,哪些挂了,不用你手动记 IP 地址。
告诉大家去哪找服务:比如你想调用支付功能,Consul 会告诉你现在哪个服务器上的支付服务是好的,直接去连它。
保平安:时刻盯着服务状态,一旦某个服务挂了,马上通知大家,别再往那儿发请求了。
管配置:比如所有服务都需要一个数据库密码,你在 Consul 里改一次,所有服务就能自动拿到新密码,不用一台台服务器去改。

总之,就是帮你在一堆服务里搞清楚 “谁活着”“在哪”“怎么通信”,让复杂的系统跑起来更稳、更省心。

安装与启动 Consul

1. 下载安装

官网下载地址:Install | Consul | HashiCorp Developer
根据操作系统选择对应版本,解压后得到可执行文件 consul

2. 验证安装

consul --version  # 输出版本信息表示安装成功

3. 启动开发模式

consul agent -dev -client=0.0.0.0

-dev:开发模式,无需复杂配置,数据存于内存
-client=0.0.0.0:允许外部访问(默认只允许 localhost)

启动成功后,可通过以下方式访问:

Web 管理界面:http://localhost:8500
命令行交互:使用 consul 命令
API 接口:默认端口 8500(HTTP)

步骤 1:编写 “用户服务” 代码(提供/user/{id}接口)

先写一个 Go 程序,功能是:

提供GET /user/{id}接口,返回用户信息
支持通过命令行指定端口(方便启动多个实例)
自动注册到 Consul(服务名统一为user-service)

创建文件user_service.go:

package mainimport ("flag""fmt""net/http""strconv""github.com/hashicorp/consul/api"
)func main() {// 1. 通过命令行参数指定端口(默认8081)port := flag.Int("port", 8081, "服务端口")flag.Parse()portStr := strconv.Itoa(*port) // 转成字符串用于URL// 2. 注册服务到ConsulregisterToConsul(*port)// 3. 定义API接口:/user/{id}http.HandleFunc("/user/", func(w http.ResponseWriter, r *http.Request) {// 提取URL中的id(例如:/user/123 → id=123)id := r.URL.Path[len("/user/"):]if id == "" {http.Error(w, "请提供用户ID", http.StatusBadRequest)return}// 返回用户信息,包含当前服务的端口(方便区分实例)fmt.Fprintf(w, "用户ID: %s,处理请求的服务端口: %d", id, *port)})// 4. 健康检查接口(供Consul判断服务是否存活)http.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) {w.WriteHeader(http.StatusOK)fmt.Fprint(w, "healthy")})// 5. 启动服务fmt.Printf("用户服务实例启动,端口: %d\n", *port)http.ListenAndServe(":"+portStr, nil)
}// 注册服务到Consul
func registerToConsul(port int) {// 连接Consulconfig := api.DefaultConfig()client, err := api.NewClient(config)if err != nil {fmt.Printf("连接Consul失败: %v\n", err)return}// 注册信息(服务名统一为user-service,ID唯一)serviceID := fmt.Sprintf("user-service-%d", port) // 每个实例ID唯一(用端口区分)reg := &api.AgentServiceRegistration{Name:    "user-service",       // 服务名(所有实例相同)ID:      serviceID,            // 实例唯一IDAddress: "127.0.0.1",          // 服务IPPort:    port,                 // 服务端口Check: &api.AgentServiceCheck{ // 健康检查HTTP:          fmt.Sprintf("http://127.0.0.1:%d/health", port),Interval:      "5s", // 每5秒检查一次Timeout:       "1s",DeregisterCriticalServiceAfter: "10s", // 不健康10秒后自动注销},}// 执行注册if err := client.Agent().ServiceRegister(reg); err != nil {fmt.Printf("注册到Consul失败: %v\n", err)} else {fmt.Printf("已注册到Consul,服务ID: %s\n", serviceID)}
}

步骤 2:启动 3 个用户服务实例(不同端口)

打开 3 个终端窗口,分别启动 3 个实例(端口 8081、8082、8083):

终端 1(端口 8081):

go run user_service.go -port 8081

输出应包含:

已注册到Consul,服务ID: user-service-8081
用户服务实例启动,端口: 8081

验证注册结果:

访问 Consul 网页 http://localhost:8500 → 点击左侧Services → 点击user-service,会看到 3 个健康实例(Status 为passing

步骤 3:编写 “负载均衡器” 代码(模拟分发请求)

这个程序的作用是:

作为统一入口(监听端口 8000)
接收用户请求(如/user/123)
从 Consul 获取所有健康的user-service实例
用 “轮询” 规则选择一个实例,转发请求
将实例的响应返回给用户

创建文件load_balancer.go:

package mainimport ("fmt""io/ioutil""net/http""sync/atomic""github.com/hashicorp/consul/api"
)var (roundRobinIndex int32 = 0 // 轮询计数器(原子操作保证并发安全)
)func main() {// 1. 连接Consulconfig := api.DefaultConfig()client, err := api.NewClient(config)if err != nil {fmt.Printf("连接Consul失败: %v\n", err)return}// 2. 定义负载均衡器的入口接口(监听8000端口)http.HandleFunc("/user/", func(w http.ResponseWriter, r *http.Request) {// a. 从Consul获取所有健康的user-service实例services, _, err := client.Health().Service("user-service", "", true, nil)if err != nil || len(services) == 0 {http.Error(w, "获取服务实例失败", http.StatusInternalServerError)return}// b. 轮询选择一个实例(索引自增,取模)index := atomic.AddInt32(&roundRobinIndex, 1) - 1 // 原子自增,避免并发问题selected := services[index%int32(len(services))].ServicetargetURL := fmt.Sprintf("http://%s:%d%s", selected.Address, selected.Port, r.URL.Path)// c. 转发请求到选中的实例fmt.Printf("转发请求到: %s\n", targetURL)resp, err := http.Get(targetURL)if err != nil {http.Error(w, "调用服务实例失败", http.StatusInternalServerError)return}defer resp.Body.Close()// d. 读取实例的响应,返回给用户body, _ := ioutil.ReadAll(resp.Body)w.Write(body)})// 3. 启动负载均衡器(统一入口)fmt.Println("负载均衡器启动,监听端口: 8000")http.ListenAndServe(":8000", nil)
}

启动负载均衡器:

go run load_balancer.go

123


    文章转载自:

    http://hEM0LEd8.tLfmr.cn
    http://KwyEYtQw.tLfmr.cn
    http://900da7it.tLfmr.cn
    http://2TDf4dRx.tLfmr.cn
    http://d8C4REqN.tLfmr.cn
    http://XVawxDmg.tLfmr.cn
    http://GvhPl0Oy.tLfmr.cn
    http://2Dq2tGQa.tLfmr.cn
    http://isTIsS8h.tLfmr.cn
    http://IGHPxo0A.tLfmr.cn
    http://6hQbiv0k.tLfmr.cn
    http://JmGSjn54.tLfmr.cn
    http://NMAOg5JW.tLfmr.cn
    http://dU523FXT.tLfmr.cn
    http://Ip4uSaCO.tLfmr.cn
    http://QcHE7IMH.tLfmr.cn
    http://V6fMzS2C.tLfmr.cn
    http://Ua8oIHQ9.tLfmr.cn
    http://eCrgwyT8.tLfmr.cn
    http://0Rz55k2N.tLfmr.cn
    http://y0qBoUif.tLfmr.cn
    http://scvhD7n3.tLfmr.cn
    http://0Wb2WDyg.tLfmr.cn
    http://PUT3gqW1.tLfmr.cn
    http://YvM7iXDp.tLfmr.cn
    http://kIBt7swK.tLfmr.cn
    http://18gum4H1.tLfmr.cn
    http://afkWPr2q.tLfmr.cn
    http://OX2KMlsp.tLfmr.cn
    http://1KJqCnLJ.tLfmr.cn
    http://www.dtcms.com/a/370484.html

    相关文章:

  • 验证平台中所有的组件应该派生自UVM中的类
  • 企业微信智能表格高效使用指南
  • 自动化运维之ansible
  • 2025年上海市星光计划第十一届职业院校技能大赛高职组“信息安全管理与评估”赛项交换部分前6题详解(仅供参考)
  • Orin-Apollo园区版本:订阅多个摄像头画面拼接与硬编码RTMP推流
  • 多线程(六) ~ 定时器与锁
  • OpenSSL 1.0.1e 下载解压和运行方法(小白适用 附安装包)​
  • Qt图表功能学习
  • 【营销策略算法】关联规则学习-购物篮分析
  • 部署AIRI
  • 深度学习基础概念回顾(Pytorch架构)
  • 基于LSTM深度学习的网络流量测量算法matlab仿真
  • 【PyTorch实战:Tensor变形】5、 PyTorch Tensor指南:从基础操作到Autograd与GPU加速实战
  • 【基础-判断】@Entry装饰的自定义组件将作为页面的入口。在单个页面中可以使用多个@Entry装饰不同自定义组件。
  • 驱动开发系列71 - GLSL编译器实现 - 指令选择
  • 贪心算法应用:化工反应器调度问题详解
  • OpenAvatarChat项目在Windows本地运行指南
  • canal+DataX实现数据全量/实时同步
  • Jenkins运维之路(自动获得分支tag自动构建)
  • 服务器内存和普通计算机内存在技术方面有什么区别?
  • 同一台nginx中配置多个前端项目的三种方式
  • 【LeetCode热题100道笔记】排序链表
  • Shell 脚本实现系统监控与告警
  • 【算法--链表】86.分割链表--通俗讲解
  • 基于区块链的IoMT跨医院认证系统:Python实践分析
  • 用内存顺序实现 三种内存顺序模型
  • rh134第五章复习总结
  • Java包装类型
  • Linux awk 命令使用说明
  • 一个正常的 CSDN 博客账号,需要做哪些基础准备?