Nacos 是阿里巴巴推出来的一个新开源项目,这是一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。
Nacos 致力于帮助您发现、配置和管理微服务。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据及流量管理。
Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。 Nacos 是构建以“服务”为中心的现代应用架构 (例如微服务范式、云原生范式) 的服务基础设施。
看它的github上很多的公司都在使用,其中不乏一些知名的互联网厂商,如果 rpcx 支持 Nacos, 那么众多的厂商可以利用公司既有的服务发现基础设置,直接方便的使用rpcx实现微服务,以及编写客户端实现服务治理。现在,这种可能编成了现实,rpcx 现在支持 Nacos作为注册中心,底层使用[nacos-sdk-go](https://github.com/nacos-group/nacos-sdk-go)访问 Nacos服务。
微博内部其实有一个类似的基础平台, 叫Vintage, 微博的所有的 Motan 服务都依赖它。 设计的特性和概念 和 Nacos 类似,只可惜没有开源。
现在,让我们看看使用 Nacos 注册中心是多么的方便, 本文使用公开的 console.nacos.io
作为 Nacos服务, 你也可以下载 Nacos应用自己部署一套 N
acos环境。 如果你的公司已经部署了 Nacos,你也可以使用自己公司的 Nacos 。
服务端实现
服务器端需要增加serverplugin.NacosRegisterPlugin
插件,它负责自动把服务注册到Nacos上,所以这里我们增加了一个addRegistryPlugin
方法配置Nacos插件。
NacosRegisterPlugin
的配置也很简单, 你需要配置clientConfig
,这是 nacos client的一些参数,超时设置、缓存设置、日志等等。serverConfig
定义了nacos服务器的地址和端口。如果你的服务区分cluster, 你还可以定义cluster参数。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
|
package main
import (
"flag"
"log"
"github.com/nacos-group/nacos-sdk-go/common/constant"
example "github.com/rpcx-ecosystem/rpcx-examples3"
"github.com/smallnest/rpcx/server"
"github.com/smallnest/rpcx/serverplugin"
)
var (
addr = flag.String("addr", "127.0.0.1:8972", "server address")
)
func addRegistryPlugin(s *server.Server) {
clientConfig := constant.ClientConfig{
TimeoutMs: 10 * 1000,
ListenInterval: 30 * 1000,
BeatInterval: 5 * 1000,
NamespaceId: "public",
CacheDir: "./cache",
LogDir: "./log",
UpdateThreadNum: 20,
NotLoadCacheAtStart: true,
UpdateCacheWhenEmpty: true,
}
serverConfig := []constant.ServerConfig{{
IpAddr: "console.nacos.io",
Port: 80,
}}
r := &serverplugin.NacosRegisterPlugin{
ServiceAddress: "tcp@" + *addr,
ClientConfig: clientConfig,
ServerConfig: serverConfig,
Cluster: "test",
}
err := r.Start()
if err != nil {
log.Fatal(err)
}
s.Plugins.Add(r)
}
|
我们还是使用Arith
服务做例子,它有一个Mul
乘法服务和一个Add
服务。只需要下面几行代码,我们就把一个Go struct对象暴露成rpcx服务。
1
2
3
4
5
6
7
8
9
10
11
12
13
|
func main() {
flag.Parse()
s := server.NewServer()
addRegistryPlugin(s)
s.RegisterName("Arith", new(example.Arith), "")
err := s.Serve("tcp", *addr)
if err != nil {
panic(err)
}
}
|
客户端的实现
对应的,客户端也需要配置Nacos插件。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
package main
import (
"context"
"flag"
"log"
"time"
"github.com/nacos-group/nacos-sdk-go/common/constant"
example "github.com/rpcx-ecosystem/rpcx-examples3"
"github.com/smallnest/rpcx/client"
)
func configNacos() client.ServiceDiscovery {
clientConfig := constant.ClientConfig{
TimeoutMs: 10 * 1000,
ListenInterval: 30 * 1000,
BeatInterval: 5 * 1000,
NamespaceId: "public",
CacheDir: "./cache",
LogDir: "./log",
UpdateThreadNum: 20,
NotLoadCacheAtStart: true,
UpdateCacheWhenEmpty: true,
}
serverConfig := []constant.ServerConfig{{
IpAddr: "console.nacos.io",
Port: 80,
}}
return client.NewNacosDiscovery("Arith", "test", clientConfig, serverConfig)
}
|
因为需要访问 Nacos服务,这里也需要ClientConfig
和ServerConfig
两个配置, 如果需要cluster配置,也把cluster的值传给Nacos插件,插件的第一个参数是要访问的服务的名称。
现在你就可以访问服务了,client不知道服务器的地址和端口,它是通过nacos查询到的:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
func main() {
flag.Parse()
d := configNacos()
xclient := client.NewXClient("Arith", client.Failover, client.RoundRobin, d, client.DefaultOption)
defer xclient.Close()
args := &example.Args{
A: 10,
B: 20,
}
for {
reply := &example.Reply{}
err := xclient.Call(context.Background(), "Mul", args, reply)
if err != nil {
log.Printf("failed to call: %v\n", err)
time.Sleep(5 * time.Second)
continue
}
log.Printf("%d * %d = %d", args.A, args.B, reply.C)
time.Sleep(5 * time.Second)
}
}
|
你可以看log文件,结果被输出到日志文件中。