一个故事,一段代码告诉你如何使用不同语言(Golang&C#)提供相同的能力基于Consul做服务注册与发现

引言

趁着最近休息写一篇关于微服务架构中特别重要一环服务注册与发现示例来互相探讨学习。

什么是微服务

传统服务

  • 举个栗子: 传统服务就类似于你们家附近的商店,这个商店可以提供你基本日常所需。你可以在里面买牙膏、零食、饮料、袜子、充电器等。
  • 优点
    1. 产品固定的情况下方便打理 (开发/维护效率高)
    2. 生意不错的情况下可按照当前模式快速在其他地方开分店 (易于部署)
  • 缺点
    1. 如果收银系统出问题就会导致商店无法正常营业 (宕机)
    2. 在店面商品已经放满的情况下添加新产品要么先存放在其他商品分类下 (耦合度高),要么只能扩大店面 (纵向扩展)

微服务

  • 举个栗子微服务就类似于一个商场,这个商场会有统一的入口,会有保安,导购台。商场里面会按照不同的商品类型开不同的“店”,例如卖“牙膏”、“牙刷”的一个店,卖“袜子”、“拖鞋”的一个店,卖“手机”、“充电器”的一个店。假设你想买一部手机,进入商场时你问了下门口的保安“哪个店可以买手机”,这时保安会说“出示一下健康码”(ApiGateway鉴权),绿码通过后,保安问了下身后的导购员 (服务发现),得到答案时保安就会告诉你哪一层哪个店卖手机。然后你就可以按照他的指引进去购买了。
  • 优点
    1. 当卖手机的店收银系统出现了问题,不影响其他店运营,也不会导致整个商场打烊 (服务隔离,分而治之)
    2. 如果哪天华为手机大卖,商场一个手机店不能承载用户消费了,可以在商场中再开一个手机店 (横向扩展)
  • 缺点
    1. 维护一个商场的治安、卫生较难 (可维护性较差)
    2. 商场发现小偷,寻找起来较麻烦 (线上问题修复时间长)

什么是服务注册与服务发现

服务注册与发现就类似于上面微服务例子中的导购员角色。她可以告诉访问者指定服务微服务系统中的哪个位置。

举个栗子:
最近放假,商场的咖啡店生意不错。于是我就拉着小明去商场开了两个咖啡店准备赚一笔。为什么开同时开两个呢,生意太好,如果小明那边客户比较多的话,就可以让部分客户到我这边来买 (负载均衡) 。还有如果哪天晚上我打游戏打晚了,早上起不来,小明就正常营业。或者是小明有事呢,我就正常营业 (熔断)
说干就干,两个咖啡店已经被我们如火如荼的置办起来了 (完成服务开发),我们给它起了个名字叫“三泡咖啡” (服务名称),小明的店在商场入口旁边门牌号是302,我的店在商场后面门牌号是609 (服务ID)
开业以后呢,每天早上,我和小明都会分别到导购台那边和导购小姐姐说“今天我们店正常营业”(不是撩小姐姐),这时导购小姐姐就会在小本本上记上我们的店和门牌号 (服务注册),之后进入商场的客人如果想买“三泡咖啡”,小姐姐就会按照她登记的信息告诉客人 (服务发现) 咖啡店在哪一层哪一号。
导购小姐姐呢也会定时来看我们店有没有存在突发情况,影不影响正常营业 (健康检查)。例如我这家店的收银系统今天出现问题了,导致无法正常营业了,那么导购小姐姐就会拿出小本本备注一下,下次再有客人想喝“三泡咖啡”,导购小姐姐就会将客人指向小明那家店了。

为什么要使用不同的语言提供相同的服务能力

本来我是想和小明分别购置一个自动咖啡机来为用户提供咖啡的,可是预算不足只能买一个。但没办法,我是老板,所以就给小明买了一个手磨咖啡机来做咖啡。不是说自动咖啡机一定比手磨咖啡机做的好,也不能说手磨咖啡机一定比自动咖啡机做出来的香。它们做出来的味道一样,只是结合了实际情况来定的。你说对吗? phper。

服务协调器

服务协调器就类似于上面例子中的导购员,常用的服务协调器有:ConsulEurekaZookeeperEtcd等。这个例子中我们就选用Consul来实现我们的服务注册与发现。

consulgoogle开源的一个使用go语言开发的服务发现、配置管理中心服务。内置了服务注册与发现框 架、分布一致性协议实现、健康检查、Key/Value存储、多数据中心方案,不再需要依赖其他工具(比如ZooKeeper等)。服务部署简单,只有一个可运行的二进制的包。每个节点都需要运行agent,他有两种运行模式serverclient。每个数据中心官方建议需要3或5个server节点以保证数据安全,同时保证server-leader的选举能够正确的进行。

安装部署方式就请参考官方文档或百度一下吧。

官方地址:https://www.consul.io/

我这里是使用Docker部署的三个Consul实例
image

服务注册

Golang

使用Golang创建一个coffee-service服务,ID为coffee-service1

打开IDE在src目录下创建一个文件夹coffee,并添加coffeeServer.go文件,输入如下代码

package main

import (
	"fmt"
	"github.com/hashicorp/consul/api"
	"net/http"
)

func main()  {
   
	consulConfig := api.DefaultConfig()
	consulConfig.Address = "consul.insipid.top"				// consul 地址

	consulClient, err := api.NewClient(consulConfig)
	if err != nil {
   
		fmt.Println("new consul client err:", err)
		return
	}

	// 服务注册配置
	registerService := api.AgentServiceRegistration{
   
		ID:      "coffee-service1",							// id唯一
		Name:    "coffee-service",							// 服务名称,相同服务多实例注册下名称相同
		Tags:    []string{
   "demo"},							// tag
		Port:    8082,										// 当前服务端口
		Address: "39.99.248.231",
		Check: &api.AgentServiceCheck{
   						// 健康检查相关配置
			HTTP:      "http://39.99.248.231:8082/health",  // 健康检查接口,response code = 200表示检查通过
			Timeout:  "5s",									// 超时时间
			Interval: "5s",									// 检查间隔
			DeregisterCriticalServiceAfter: "10s",			// 检查失败后指定时间自动踢出无效服务
		
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: package mainimport ( "fmt" "net/http" )func main() { http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hello World") }) http.ListenAndServe(":8080", nil) } ### 回答2: 当使用Go语言编写一个简单的HTTP服务器时,我们需要使用`net/http`包。下面是一个例子,展示了如何使用Go语言创建HTTP服务器并提供一个简单的"Hello, World!"页面: ```go package main import ( "net/http" ) func main() { http.HandleFunc("/", helloHandler) // 将根路径"/"绑定到helloHandler函数 http.ListenAndServe(":8080", nil) // 在本地监听8080端口并开始接收HTTP请求 } func helloHandler(w http.ResponseWriter, r *http.Request) { w.Write([]byte("Hello, World!")) // 返回"Hello, World!"作为响应 } ``` 在上述代码中,我们定义了一个`helloHandler`函数,该函数会处理来自根路径的HTTP请求,并向客户端(通过`w http.ResponseWriter`)返回一个包含"Hello, World!"的响应。`http.HandleFunc`函数用于将根路径"/"绑定到`helloHandler`函数。 然后,我们使用`http.ListenAndServe`函数来监听端口8080,并启动HTTP服务器,以便开始接收来自客户端的请求。这可以通过访问http://localhost:8080/来测试。会返回"Hello, World!"的响应。 此代码片段只是一个简单的示例,你可以在这个基础上进行更多的HTTP路由和请求处理的开发。 ### 回答3: package main import ( "fmt" "net/http" ) func helloHandler(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hello, World!") } func main() { http.HandleFunc("/", helloHandler) err := http.ListenAndServe(":8080", nil) if err != nil { fmt.Println("Error starting HTTP server:", err) } } 以上是一个使用Golang实现的简单的HTTP服务代码。 在main函数中,我们调用了http包中的HandleFunc方法,将根路径"/"与一个名为helloHandler的处理函数关联起来。这个处理函数接收两个参数,一个是http.ResponseWriter,用于构建HTTP响应,另一个是*http.Request,用于获取HTTP请求的信息。 helloHandler函数中使用了fmt包中的Fprintf方法,将字符串"Hello, World!"写入到http.ResponseWriter中,作为HTTP响应返回给客户端。 最后,我们调用了http包中的ListenAndServe方法,指定监听的端口号为8080,并将nil作为第二个参数传递,该参数表示使用默认的路由器。如果启动HTTP服务失败,将打印错误信息到控制台。 通过运行以上代码,可以在本地启动一个简单的HTTP服务器,当访问http://localhost:8080时,服务器将返回"Hello, World!"字符串。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Simple Han

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值