# 背景
在前面一节课中,我们指定了consul作为微服务的注册组件,并在consul中看到了注册的新服务。这其中还包含其他内容,本节课我们继续来看。
# 代码实现consul配置
上节课中,我们使用的–registry选项配置的形式来指定注册到consul组件中,其实这一配置也可以在代码中进行实现。上节课说了go-micro在创建服务时提供了很多可选项配置,其中就包含服务组件的指定。指定注册到consul的编程代码实现如下:
...
//创建一个新的服务对象实例
service := micro.NewService(
micro.Name("student_service"),
micro.Version("v1.0.0"),
micro.Registry(consul.NewRegistry()),
)
...
2
3
4
5
6
7
8
通过micro.Registry可以指定要注册的发现组件,这里我们注册到consul,因此调用consul.NewRegistry。
# 插件化
在前面的go-micro介绍课中,我们提到过go-micro是支持插件化的基础的微服务框架,不仅仅是go-micro,整个的micro都被设计成为“可插拔”的机制。
在上一节课的案例中,我们使用–registry选项指定将服务注册到对应的服务发现组件,我们选择的是注册到consul中。这里的–registry就是是“可插拔”的插件化机制的体现。因为在2019年最新的代码中,go-micro中默认将服务注册到mdns中,同时支持开发者手动指定特定的服务发现组件。
我们可以看到在这个过程中,我们的服务的程序没有发生任何变化,但是却轻松的实现了服务注册发现组件的更换,这就是插件化的优势,利用插件化能最大限度的解耦。
在go-micro框架中,支持consul,etcd,zookeeper,dns等组件实现服务注册和发现的功能。如果有需要,开发者可以根据自己的需要进行服务发现组件的替换。
# 服务注册发现的原理
让我们再回顾一下服务注册与发现的原理:服务注册发现是将所有的服务注册到注册组件中心,各服务在进行互相调用功能时,先通过查询方法获取到要调用的服务的状态信息和地址,然后向对应的微服务模块发起调用。我们学习过consul的工作原理和环境搭建,congsul的工作原理图如下所示:
# 未发现服务错误
回顾完了服务注册发现的原理,我们就可以知道,如果请求发起端程序不能在服务组件中发现对应的服务,则会产生错误。接下来我们利用程序演示错误。
首先,通过终端命令启动consul节点服务,以方便服务注册:
consul agent -dev
指定服务程序注册到consul
我们利用已经学习过的服务注册可选项指定注册到consul组件,详细命令如下:
go run main.go --registry=consul
通过该命令,可以成功将服务注册到consul组件,并启动服务开始运行。
运行客户端服务
由于服务端程序已经注册到consul,因此客户端程序在执行时也需要到consul中查询才能正确执行。运行客户端并注册到consul组件的命令是:
go run client.go --registry=consul
通过以上命令,程序可以正确得到执行,并输出正确结果。
未发现服务错误
我们可以主动让程序发生错误,来验证未发现的错误,以此来验证我们所学习的服务注册与发现的原理。在执行客户端程序时,我们不指定–registry选项,默认使用mdns,则命令为:
go run client.go
我们执行上述命令,运行客户端程序。由于我们的客户端程序会连接对应的服务的方法,但是对应的服务并没有注册到mdns中,因此,程序会发生错误。本案例中,客户端程序执行错误如下:
{"id":"go.micro.client","code":500,"detail":"error selecting student_service node: not found","status":"Internal Server Error"}
我们可以看到,程序返回了错误信息,提示我们服务未找到。
通过这个主动错误的示范,我们能更加深刻的理解go-micro与consul的插件式协同工作和微服务内部的原理。
# 弊端与解决方法
服务实例与发现组件的工作机制是:当服务开启时,将自己的相关信息注册到发现组件中,当服务关闭时,发送卸载或者移除请求。在实际生产环境中,服务可能会出现很多异常情况,发生宕机或者其他等情况,往往服务进程会被销毁,或者网络出现故障也会导致通信链路发生问题,在这些情况下,服务实例会在服务发现组件中被移除。
TTL和间隔时间
为了解决这个问题,go-micro框架提供了TTL机制和间隔时间注册机制。TTL是Time-To-Live的缩写,指定一次注册在注册组件中的有效期,过期后便会删除。而间隔时间注册则表示定时向注册组件中重新注册以确保服务在线。
指令方式 这两种注册方式都可以通过可选项指令来实现配置,具体的命令如下:
go run main.go --registry=consul --register_ttl=10 --register_interval=5
1该命令表示我们每间隔5秒钟向服务注册组件注册一次,每次有效期限是10秒。
编码方式 除了使用指令的方式以外,还可以在代码中实现这两种参数的设定,在微服务创建时通过配置来完成。具体代码如下:
... service := micro.NewService( micro.Name("student_service"), micro.Version("v1.0.0"), micro.RegisterTTL(10*time.Second), micro.RegisterInterval(5*time.Second), ) ...
1
2
3
4
5
6
7
8分别通过micro.RegisterTTL和micro.RegisterInterval来实现两个选项的设置。