跳到主要内容

· 阅读需 11 分钟
# 背景介绍 Istio是目前主流的Service Mesh组件。Istio基于Service Mesh的理念,承担着服务发现、服务通信、负载均衡、限流熔断、监控等等功能。让应用不用关心这些底层逻辑,专注于业务的开发和访问即可。软件行业的趋势一定是让业务的开发越来越轻松和简便,所以从这个角度看以Istio为代表的Service Mesh一定会越来越流行。至于目前存在的一些包括性能和设计复杂的问题,一定可以通过技术手段解决。# 总体架构

MCP协议推出的背后,是Pilot意图重构以解决之前架构带来的代码维护、测试、扩展及稳定性等多方面的问题。在之前的架构中,Pilot内嵌了与K8S的交互逻辑以及其他扩展的注册中心和配置中心的逻辑。这样导致Pilot内部逻辑比较复杂、承担职责不够清晰。同时与各个组件的交互协议也不统一,导致Pilot难以维护这些代码,对于后面的扩展组件接入,也望而却步。在Pilot的重构设计文档中,对于Pilot目前存在的问题是这么总结的[1]

  • Pilot is more difficult to test than is necessary. It requires a dependency on K8S Apiserver in order to write more complex unit or simple integration tests.
  • We have smeared logic for dealing with the vagaries of K8S CRDs across Pilot, Mixer & Citadel. Common concerns like K8S integration, resource validation and API versioning do not share a common implementation. The proposal to resurrect Galley is primarily motivated by an obvious need to improve our user-facing API experience.
  • Consuming the K8S API client in Pilot is a source of bloat and represents a production risk. Moving that risk to Galley while isolating the network control plane from it should be a performance and stability win.
  • The contract between Pilot, Kubernetes and other platforms is under-specified. We implicitly consume the totality of the K8S API surface even if we don’t need it.
  • Writing extensions to Pilot requires developers to consume our build process and this has proven to be a barrier to adoption for partners. This is analogous to the recent architectural shift in Mixer to use out-of-process adapters for the same reasons.



Istio在Pilot重构设计文档中,展示了基于MCP协议的内部组件架构。在这个架构中,Pilot与Envoy还是使用Envoy定义的ADS协议,Pilot与Galley、外部的注册中心、配置中心以及其他的Pilot之间,都是通过MCP协议进行通讯:

![image.png](https://cdn.nlark.com/yuque/0/2019/png/333810/1574243165093-102c6f18-c565-4e0f-a2dc-a374ccc412d4.png#align=left&display=inline&height=383&name=image.png&originHeight=766&originWidth=1256&search=&size=414042&status=done&width=628)

这样的设计比较好的定义了Pilot的职责,就是整个Service Mesh的控制面,但是不感知任何Istio以外的组件,即使是K8S也是如此。所有与外部组件包括注册中心和配置中心的交互逻辑,都移到了Pilot进程以外,通过运行特定的MCP Server来与Pilot进行通讯。Galley的职责,我认为是Pilot中默认的配置来源的MCP Server,目前是实现了与K8S数据的对接。这个文档中还定义了Pilot与Pilot之间的数据访问也是通过MCA(基于MCP协议定义的API),但是文档里没有提供更多的细节,会不会是Pilot未来会支持数据的分片以提高Pilot整体的数据容量?

# 协议定义 看完了Pilot的整体演进架构,我们来看一下MCP协议的设计[2],MCP协议在设计上参考了与Envoy的交互协议xDS。
![image.png](https://cdn.nlark.com/yuque/0/2019/png/333810/1574243165174-59e66666-d992-440d-b066-89d1825abc38.png#align=left&display=inline&height=424&name=image.png&originHeight=594&originWidth=944&search=&size=67856&status=done&width=674)

在MCP协议中,定义了两个身份:Sink和Source。Sink指代的是数据的接收端,Source指代的是数据的发送端即数据源。MCP协议基于gRPC双向流协议进行定义,Sink端和Source端都可以随时往对端发送数据,相互不会阻塞。从上图的协议交互也可以看出,Sink端可以主动发送RequestResources请求来向Source端要求数据,同时Source端也可以主动将Resources数据发送给Sink端。Sink端在收到数据后会返回一个ACK确认。在RequestResources请求和ACK响应中,主要有两个字段:

  • collection:表示此次请求需要的数据类型,目前Istio定义了17种类型(测试得出,实际数据以Istio官方说法为准),其中包含了serviceentries作为服务发现的数据等。
  • nonce:类似于请求的ID,用来与响应或者请求进行匹配。

而在返回的数据中,还有一个字段就是resources字段,里面包含真正的数据,具体的数据格式和collection的类型有关。

同时MCP协议还定义了增量推送的能力,如下图所示。可以在RequestResouces请求中增加incremental=true字段,这样Sink在收到数据后,会根据增量的形式进行数据的更新。协议的文档中还指出,必须在RequestResouces请求中包含incremental=true的情况下,才能返回给Sink增量的数据,否则Sink端对于该数据的处理将是未知的。目前社区的Pilot还没有支持增量的MCP数据推送,从下一节的源码分析中可以看到,Pilot对于每一个Source(Pilot可以配置多个Source,每个Source之间的数据是隔离的)发送的数据,都是整体替换更新的。目前社区的一个进展是正在进行serviceentries类型数据的增量更新的支持,而且是endpoints粒度的增量更新[3]

image.png

# Pilot Sink端启动流程

Pilot在启动的时候,会根据ConfigMap里的配置,进行MCP Server的初始化。主要的逻辑可以参考下图:

# ![istio mcp.png](https://cdn.nlark.com/yuque/0/2019/png/333810/1574243165184-426a4245-ef40-4c44-9bbe-d36326e3151a.png#align=left&display=inline&height=1151&name=istio%20mcp.png&originHeight=1151&originWidth=951&search=&size=94058&status=done&width=951) Pilot启动时,会调用server.NewServer来新建Pilot Server。在此过程中,会去读取ConfigSource配置里面的address。由于可能会配置多个address,那么Pilot在这里会循环去创建多个Sink客户端①,每一个Sink客户端拥有独立的数据。在这里有一点要注意的是,这个循环中会尝试与每个MCP Server建立gRPC连接,而如果其中一个MCP Server连接不上的话,整个循环就会推出,并返回error。也就是说如果Pilot在启动过程中无法连上每一个MCP Server,那么Pilot就会处于不健康状态,而在运行时没有这个限制②。当Sink客户端都新建完以后,就会再次循环异步调用每个Sink客户端的run方法,进行数据的收发了。

Sink端的run方法主要是调用EstablishResouceStream方法来建立双向流连接。在连接建立后,会调用creatIntialRquests请求来创建一次初始请求③,也就是说Pilot不会在启动时阻塞的去从每个MCP Server拉取数据,更新完后再提供服务,而是异步的进行数据的请求。事实上,Pilot也只会主动发这一次数据的请求④,接下来的数据更新都依赖于MCP Server的主动推送。在收到数据后,则进行handleResponse方法进行数据的更新⑤。

# Pilot Sink端处理流程

下面介绍的是Pilot的Sink端在接收到数据的处理逻辑。从下图中可以看出,在接收到数据后,会先判断是否返回了错误,如果返回错误则直接结束数据的更新。如果没有错误,则进入Apply(change)方法。在这个方法中,会先新建一个innerStore的Map来保存更新到的数据。然后会将原来的configStore里对应collection类型的数据直接由这个innerStore进行替换。因此可以看出Pilot目前还不支持增量的MCP数据推送。在更新完数据后,则调用serviceEntryEvents或者ClearDiscoveryServerCache来通知Envoy等组件进行数据的更新。

istio mcp2.png

# 总结与展望 目前Source端可以参考的代码有Galley,以及Nacos开发的独立MCP Server,用于进行MCP功能的测试和压测[4],以及和Nacos Server一起部署的Java版本的MCP Server[5]。本文不做详细介绍,有兴趣的同学可以自行阅读相关源代码。

整体来看目前Pilot MCP协议还处于快速的更新和迭代阶段,未来可能还会有很多的变化。但是Istio基于MCP协议进行重构的大方向应该是不会跑了。Nacos团队目前也在密切关注着Istio及其他云原生组件的发展方向,同时将会陆续发布相关的功能,敬请期待。

[1] Pilot重构设计文档 https://docs.google.com/document/d/1S5ygkxR1alNI8cWGG4O4iV8zp8dA6Oc23zQCvFxr83U/edit#
[2] MCP协议介绍 https://github.com/istio/api/tree/master/mcp
[3] Pilot serviceentries增量推送的PR https://github.com/istio/istio/pull/12276
[4] Nacos提供的独立的MCP Server,Go语言开发 https://github.com/nacos-group/nacos-istio
[5] Nacos对接Istio的issue,以及相关的commits https://github.com/alibaba/nacos/issues/1409

· 阅读需 8 分钟

Nacos是阿里巴巴开源的服务发现与配置管理项目,本次发布的1.1.4版本,主要带来的是与Istio的对接功能,使用的是Istio最新的MCP协议。本文将介绍包括这个功能在内的新版本发布的功能。

## 升级指南#### 服务端 0.8.0及以上版本:
  1. 解压安装包后替换{nacos.home}/target/nacos-server.jar
  2. 逐台重启Nacos Server即可

0.8.0以下版本,先升级到1.0.0版本。

#### 客户端 替换pom依赖即可。## 支持Istio MCP协议 这是本次版本最大的更新,主要是实现了Nacos服务数据往Istio下发的功能,也是目前业界所有注册中心里面第一个由官方提供的MCP协议对接版本。Pilot最新的设计中,是使用MCP协议来与所有后端的数据源进行交互的。这样做的好处是可以解耦所有扩展组件的代码,Pilot保持轻量的逻辑,在代码质量、组件稳定性及扩展性方面都大幅提升。我们可以看一下Pilot官方提供的Pilot设计图(地址:[https://docs.google.com/document/d/1S5ygkxR1alNI8cWGG4O4iV8zp8dA6Oc23zQCvFxr83U/edit#heading=h.k34grc1as8vr](https://docs.google.com/document/d/1S5ygkxR1alNI8cWGG4O4iV8zp8dA6Oc23zQCvFxr83U/edit#heading=h.k34grc1as8vr)):
![image.png](https://cdn.nlark.com/yuque/0/2019/png/333810/1572940023007-e19f92da-a5a1-41f0-b37e-db8a678ad57f.png#align=left&display=inline&height=455&name=image.png&originHeight=659&originWidth=1080&search=&size=360963&status=done&width=746)
图1 Pilot的最新设计概念图

虽然在设计图中,Pilot后端的MCP Server已经有了Consul、Eureka等,但是这些项目目前都没有官方支持的MCP Server。Nacos是目前首个官方支持Istio MCP协议的项目。

关于MCP协议的设计,可以参考Istio的文档。Nacos实现的MCP Server,目前使用的是单个服务编号,全量服务推送的模式,因为目前Pilot还不支持增量的服务数据推送(Nacos 1.1.4发布之后,Pilot已经支持了endpoint级别的增量推送,Nacos也会在下个版本支持)。实现的逻辑就是启动一个gRPC Server来进行MCP数据的传输,代码可以参考:https://github.com/alibaba/nacos/tree/develop/istio

image.png
图2 Nacos MCP Server架构

使用Nacos MCP Server的方式如下:

  1. 下载最新的Nacos 1.1.4安装包,解压;
  2. 配置application.properties,然后重启Nacos;
nacos.istio.mcp.server.enabled=true

注意:如果Nacos是集群部署,则只需要配置一台Server启动MCP Server即可,因为每台Nacos Server的数        据都是全量的。同时Nacos MCP Server使用的端口是18848,请注意端口是否冲突;

  1. 配置Pilot使用Nacos MCP Server:
configSources
-- address: x.x.x.x:18848
  1. 重启Pilot;
## 自定义实例ID 在之前的版本中,Instance类的instanceId字段,是用来作为唯一标识这个instance的属性,它的值默认是不能由客户端来指定的。在1.1.4版本中,我们支持了允许客户端自定义ID以及一个新增加的instanceId生成算法:一个服务内唯一的整数,这个整数可以用来作为实例在服务内的唯一索引。这个功能由vettal-wu贡献,非常感谢。

这个整形instanceId的使用方式为在注册时配置instance的metadata,指定使用该id生成算法,样例代码如下:

Instance instance = new Instance();
instance.setIp("1.1.1.1");
instance.setPort(80);
// 必须设置ephemeral=false,来保证服务端使用的是严格的一致性协议,否则可能会导致生成的instance id冲突:
instance.setEhpemeral(false);
instance.setMetadata(new HashMap<String, String>());
instance.getMetadata().put(PreservedMetadataKeys.INSTANCE_ID_GENERATOR, Constants.SNOWFLAKE_INSTANCE_ID_GENERATOR);

Nacos在这个版本也有一些关于代码质量上的优化更新,具体可以参考1.1.4版本issue列表:https://github.com/alibaba/nacos/issues?q=is%3Aissue+milestone%3A1.1.4

## 如何共建

为了实现这一目标,你需要积极参与Nacos社区。如果您在文档中发现拼写错误,在代码中发现错误,或想要新功能或想要提供建议,您可以在GitHub上创建一个issues

如果您想开始着手,可以选择github仓库中有以下标签的issues。

  • good first issue:对于新手来说是非常好的入门issues。
  • contribution welcome:非常需要解决的问题和非常重要的模块,但目前缺少贡献者,欢迎贡献者来贡献。
## 蓬勃发展的 Nacos 社区

DISS is cheap, show me your hand 比吐槽更重要的是搭把手,参与社区一起发展Nacos

  • 作为用户关注和加入 Nacos 社区

Nacos 社区正在蓬勃发展,截止到发文为止,Nacos 短短几个月已经有 9 个微信群,其中 7 个已满员,1个QQ群,1个钉钉群,关注 Nacos 的社区人数已经近5000人,在 Nacos 群里跟 “道(基)友” 切磋技术,交流经验,招聘交友,抢抢红包...不亦乐乎。

image.png

  • 作为代码贡献者加入 Nacos 社区

从Nacos用户发展而成贡献者顺理成章,而Nacos开发团队也确实在日趋壮大,从开始的只有4个代码contributor发展到目前的40多个,1.1.4版本中,参与Nacos仓库贡献的开发者有:stackisok,loadchange, ly641921791, EZLippi, rushsky518, universefeeler, nkorange, vettal-wu, beldon等。

## 新人时刻 - "什么是Nacos?"

还不知道什么是Nacos? 没关系,在github上star一下跟程序猿兄弟打个招呼吧!!

Nacos 是阿里巴巴于2018年7月份新开源的项目,Nacos的主要愿景是期望通过提供易用的 动态服务发现服务配置管理服务共享与管理 的基础设施,帮助用户在云原生时代更好的构建、交付、管理自己的微服务平台。

image.png

github项目地址在 这里

## 更多与 Nacos 相关的开源项目信息## 下期预告 Nacos的下个版本是1.2.0版本,将会支持社区广泛关注的权限控制功能,敬请期待。

· 阅读需 6 分钟

为什么要支持confd,老的应用配置管理模式是启动时读取配置文件,然后重新读取配置文件需要应用重启。一般的配置管理系统都是代码侵入性的,应用接入配置管理系统都需要使用对应的SDK来查询和监听数据的变更。对于一些已经成熟的系统来说,接入SDK来实现动态配置管理是很难实现的,Nacos通过引入配置管理工具confd可以实现系统的配置变更做到无代码侵入性。

confd是一个轻量级的配置管理工具,可以通过查询后端存储系统来实现第三方系统的动态配置管理,如Nginx、Tomcat、HAproxy、Docker配置等。confd目前支持的后端有etcd、ZooKeeper等,Nacos 1.1版本通过对confd定制支持Nacos作为后端存储。

confd能够查询和监听后端系统的数据变更,结合配置模版引擎动态更新本地配置文件,保持和后端系统的数据一致,并且能够执行命令或者脚本实现系统的reload或者重启。

安装confd插件

confd的安装可以通过源码安装方式,confd基于Go语言编写,其编译安装依赖Go,首先需要确保本地安装了Go,版本不低于v1.10 创建confd目录,下载confd源码,编译生成可执行文件

mkdir -p $GOPATH/src/github.com/kelseyhightower
cd $GOPATH/src/github.com/kelseyhightower
wget https://github.com/nacos-group/nacos-confd/archive/v0.19.1.tar.gz
tar -xvf v0.19.1.tar.gz
mv nacos-confd-0.19.1 confd
cd confd
make

复制confd文件到bin目录下,启动confd

sudo cp bin/confd /usr/local/bin
confd

confd结合Nacos实现nginx配置管理示例

本文介绍使用Nacos结合confd实现Nginx配置管理,为简单起见以Nginx的黑名单功能为演示示例,Nacos使用官网部署的服务,域名为console.nacos.io。Nginx的安装可以参考网上文章

image

  • 1.创建confd所需目录

confd配置文件默认在/etc/confd中,可以通过参数-confdir指定。目录中包含两个子目录,分别是:conf.d templates

mkdir -p /etc/confd/{conf.d,templates}
  • 2.创建confd配置文件

confd会先读取conf.d目录中的配置文件(toml格式),然后根据文件指定的模板路径去渲染模板。

vim /etc/confd/conf.d/nginx.toml

内容为如下,其中nginx.conf.tmpl文件为confd的模版文件,keys为模版渲染成配置文件所需的配置内容,/usr/local/nginx/conf/nginx.conf为生成的配置文件

[template]
src = " nginx.conf.tmpl"
dest =
"/usr/local/nginx/conf/nginx.conf"
keys = [
"/nginx/conf",
]
check_cmd = "/usr/local/nginx/sbin/nginx -t
-c {{.src}}"
reload_cmd = "/usr/local/nginx/sbin/nginx
-s reload"
  • 3.创建模版文件

拷贝Nginx原始的配置,增加对应的渲染内容

cp /usr/local/nginx/conf/nginx.conf
/etc/confd/templates/nginx.conf.tmpl
vim /etc/confd/templates/nginx.conf.tmpl

增加内容为:

···
{{$data := json (getv "/nginx/conf")}}
{{range $data.blackList}}
deny {{.}};
{{end}}
···
  • 4.在Nacos上创建所需的配置文件

在public命名空间创建dataId为nginx.conf的配置文件,group使用默认的DEFAULT_GROUP即可,配置内容为json格式

{
"blackList":["10.0.1.104","10.0.1.103"]
}

image

  • 5.启动confd

启动confd,从Nacos获取配置文件,渲染Nginx配置文件。backend设置成nacos,node指定访问的Nacos服务地址,watch让confd支持动态监听

confd -backend nacos -node http://console.nacos.io:80 -watch
  • 6.查看Nginx配置文件,验证Nginx启动

查看生成的/usr/local/nginx/conf/nginx.conf配置文件是否存在如下内容

...
deny 10.0.1.104;

deny 10.0.1.103;
...

curl命令访问Nginx,验证是否返回正常。http响应状态码为200说明访问Nginx正常

curl http://$IP:8080/ -i
HTTP/1.1 200 OK
...
  • 7.查看本机Ip,加到Nacos配置文件黑名单中

假设本机的Ip为30.5.125.107,将本机的Ip加入到Nginx黑名单

{
"blackList":["10.0.1.104","10.0.1.103","30.5.125.107"]
}
  • 8.查看Nginx配置文件,验证黑名单是否生效

查看生成的/usr/local/nginx/conf/nginx.conf配置文件是否存在如下内容

...
deny 10.0.1.104;

deny 10.0.1.103;

deny 30.5.125.107;
...

curl命令访问Nginx,访问应该被拒绝,返回403

curl http://$IP:8080/ -i
HTTP/1.1 403 Forbidden
...

总结

本文介绍了使用Nacos结合confd来做自动化管理,confd作为轻量级的配置管理工具可以做到对第三方系统无代码侵入性。本文只是简单使用Nginx的黑名单功能来演示Nacos+confd的使用方式,当然Nginx还具有限流、反向代理等功能以及其他的系统比如Naproxy、Tomcat、Docker等也同样可以使用Nacos+confd做管理,大家可以到Nacos官网贡献相应的demo或者方案。

· 阅读需 15 分钟

近日,Netflix 公司在 github 上公告 Eureka 2.0 开源工作停止,继续使用风险自负。这一消息在spring cloud 开发者中引起了一些担心和忧虑。

同时在阿里巴巴正式宣布其开源计划, 将通过 Nacos 项目将阿里巴巴在建设共享服务体系中使用的服务发现、配置及服务管理平台贡献给开源社区,通过打造 Dubbo + Nacos 的经典组合进一步释放 Dubbo 在云原生及 Service Mesh 时代中,在大规模微服务治理、流量治理、服务集成与服务共享等服务平台能力建设上的威力,同时 Nacos 会非常关注对主流开源社区,如 Spring Cloud 和 Kubernetes 云原生体系的无缝对接与支持。

ANS (alibaba naming service) 是 nacos 组件中的服务发现部分。开源流程正在紧张地进行中。同时 ANS 与 spring cloud 结合的 spring cloud starter ans 也将同时开源到 spring cloud 官方孵化器

ANS 同样也支持 spring cloud 应用的服务注册与发现,同时默认集成了负载均衡组件 Ribbon,Eureka 用户可以简单地通过替换 maven 项目中 pom.xml 文件中的依赖来实现无缝迁移。

想抢先体验?来试试商业版的 EDAS Ans starter 吧!

快速开始

服务提供者

  1. 创建一个 Spring Cloud 工程,命名为 service-provider。这里我们以 spring boot 1.5.8 和 spring cloud Dalston.SR4 为例。在 pom.xml 中引入需要的依赖内容。
    其他版本如 spring boot 2 + spring cloud Finchley 也同样支持,请您自行修改版本号和替换相应的组件依赖。

    <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.5.8.RELEASE</version>
    <relativePath/>
    </parent>


    <dependencies>
    <dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-ans</artifactId>
    <version>1.1.3</version>
    </dependency>
    <dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-alibaba-edas-starter</artifactId>
    <version>1.1.3</version>
    </dependency>
    </dependencies>

    <dependencyManagement>
    <dependencies>
    <dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-dependencies</artifactId>
    <version>Dalston.SR4</version>
    <type>pom</type>
    <scope>import</scope>
    </dependency>
    </dependencies>
    </dependencyManagement>
  1. 编码服务提供端的启动类,其中 @EnableDiscoveryClient 注解表明此应用需开启服务注册与发现功能。

    @SpringBootApplication
    @EnableDiscoveryClient
    public class ServerApplication {

    public static void main(String[] args) {
    SpringApplication.run(ServerApplication.class, args);
    }
    }
  2. 既然是服务提供者,所以我们还需要提供一个简单的服务。这里 EchoController 的逻辑很简单,将收到的参数回显给调用者。

    @RestController
public class EchoController {
@RequestMapping(value = "/echo/{string}", method = RequestMethod.GET)
public String echo(@PathVariable String string) {
return string;
}
}
  1. 权限配置,配置阿里云账号的 AccessKey、SecretKey,以及 EDAS 的命名空间信息。

    1. 配置阿里云 AccessKey 和 SecretKey

      登陆 阿里云AK管理控制台。找到 用户信息管理 下的 安全信息管理

      复制 AccessKey IDAccess Key Secret,分别对应配置项中的 alibaba.cloud.access-key 和 alibaba.cloud.secret-key。

      安全凭证信息格式如下:

      alibaba.cloud.access-key=xxxxxxxxxx
      alibaba.cloud.secret-key=xxxxxxxxxx

      2.png

1. 配置 EDAS 的命名空间

登录 [EDAS 控制台](https://edas.console.aliyun.com/#/home)。未开通EDAS的用户需要先开通EDAS,**EDAS 标准版促销进行中,每月仅需1元。**

在左侧导航栏中单击**命名空间**。在命名空间列表页面选择**地域**,并找到您想发布到的命名空间,复制其**命名空间ID**,对应配置项中的 **alibaba.edas.namespace**。

alibaba.edas.namespace=xxxxxxxxxx

![1.png](https://cdn.yuque.com/lark/0/2018/png/54319/1531104049757-c3d2aefd-5d57-4434-a04f-2cd939cf58b0.png)
  1. 综上,我们的配置文件 application.properties 内容最后是这样的。

    spring.application.name=service-provider
    server.port=18081
    alibaba.cloud.access-key=xxxxxxxxxx
    alibaba.cloud.secret-key=xxxxxxxxxx
    alibaba.edas.namespace=cn-hangzhou
  1. 启动 service-provider 服务,在 EDAS 页面查看服务注册的信息。

    可以看到服务列表中已经存在的实例 service-provider,从详情页可以看到IP地址是本机的地址192.168.0.107,端口是 18081。

    3.JPG

    4.png

服务消费者

这个例子中,我们将不仅仅是演示服务发现的功能,同时还将演示 ANS 服务发现 与 RestTemplate、AsyncRestTemplate 和 FeignClient 这三个客户端是如何结合的。因为实际使用中,我们更多使用的是用这三个客户端进行服务调用。

  1. 创建一个 Spring Cloud 工程,命名为 service-consumer。首先在 pom.xml 中引入需要的依赖内容:

    <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.5.8.RELEASE</version>
    <relativePath/>
    </parent>

    <dependencies>
    <dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-ans</artifactId>
    <version>1.1.3</version>
    </dependency>
    <dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-alibaba-edas-starter</artifactId>
    <version>1.1.3</version>
    </dependency>
    </dependencies>

    <dependencyManagement>
    <dependencies>
    <dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-dependencies</artifactId>
    <version>Dalston.SR4</version>
    <type>pom</type>
    <scope>import</scope>
    </dependency>
    </dependencies>
    </dependencyManagement>

    因为在这里我们要演示 FeignClient 的使用,所以与 service-provider 相比,pom.xml 文件中的依赖增加了一个 spring-cloud-starter-feign。

  1. 完成以下四个步骤,配置好 RestTemplate 、 AsyncRestTemplate 和 FeignClient。

    1. 在使用 FeignClient 之前,我们还需要对它的配置,配置服务名以及方法对应的 HTTP 请求,示例代码如下

      @FeignClient(name = "service-provider")
      public interface EchoService {
      @RequestMapping(value = "/echo/{str}", method = RequestMethod.GET)
      String echo(@PathVariable("str") String str);
      }
    2. 在启动类中,使用 @EnableDiscoveryClient 注解启用服务注册与发现

    3. 在启动类中,使用 @EnableFeignClients 注解激活 FeignClient

    4. 在启动类中,添加 @LoadBalanced 注解将 RestTemplate 与 AsyncRestTemplate 与服务发现结合。

    最终启动类的代码如下

    @SpringBootApplication
    @EnableDiscoveryClient
    @EnableFeignClients
    public class ConsumerApplication {
    @LoadBalanced
    @Bean
    public RestTemplate restTemplate() {
    return new RestTemplate();
    }

    @LoadBalanced
    @Bean
    public AsyncRestTemplate asyncRestTemplate(){
    return new AsyncRestTemplate();
    }

    public static void main(String[] args) {
    SpringApplication.run(ConsumerApplication.class, args);
    }

    }
  2. 创建一个Controller,供我们演示和验证服务发现功能使用。

    @RestController
    public class TestController {

    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private AsyncRestTemplate asyncRestTemplate;
    @Autowired
    private EchoService echoService;

    @RequestMapping(value = "/echo-rest/{str}", method = RequestMethod.GET)
    public String rest(@PathVariable String str) {
    return restTemplate.getForObject("http://service-provider/echo/" + str, String.class);
    }
    @RequestMapping(value = "/echo-async-rest/{str}", method = RequestMethod.GET)
    public String asyncRest(@PathVariable String str) throws Exception{
    ListenableFuture<ResponseEntity<String>> future = asyncRestTemplate.
    getForEntity("http://service-provider/echo/"+str, String.class);
    return future.get().getBody();
    }
    @RequestMapping(value = "/echo-feign/{str}", method = RequestMethod.GET)
    public String feign(@PathVariable String str) {
    return echoService.echo(str);
    }

    }
  3. 最后,添加应用基本配置和阿里云 AK、SK 以及 EDAS 的 namespace。

    spring.application.name=service-consumer
    server.port=18082
    alibaba.cloud.access-key=xxxxxxxxxx
    alibaba.cloud.secret-key=xxxxxxxxxx
    alibaba.edas.namespace=cn-hangzhou
  4. 启动服务,首先查看EDAS控制台,查询服务,可以看到,服务注册成功了。

    再对我们的演示 API 分别进行调用,可以看到调用都成功了。 5.png

    6.png

Demo 下载

service-provider

service-consumer

更多配置项

配置项key默认值说明补充说明
服务名spring.cloud.ans.domsspring.application.name当此项未配置时,默认从spring.application.name中获取
需要发布多个服务时,中间用英文的 , 号隔开
production
是否注册spring.cloud.ans.register-enabledtrue当只需要发现,不需要注册时,可以通过将值设置成false来关闭注册production
想要注册的IPspring.cloud.ans.ip当需要指定本机注册的IP时,通过此值来配置,优先级最高production
想要注册的IP所属的网卡spring.cloud.ans.interface-name当确定需要发布哪块网卡对应的IP地址时,通过此参数配置,值为网卡名production
想要注册的端口spring.cloud.ans.port想要注册的端口production
注册的权重spring.cloud.ans.weight1数值越大权重越高,取值范围为test
集群spring.cloud.ans.clusterDEFAULT可以通过集群来分别标记服务test
租户环境spring.cloud.ans.envDEFAULT相同租户的相同环境下的服务才能互相发现test

工作原理

下面我们将从 服务注册中心寻址、服务注册与下线、客户端结合、高可用、安全等多个方面来分析原理。

服务注册中心寻址

配置阿里云的 AccessKey 和 SecretKey 之后,再指定 EDAS 的命名空间,那么程序会在启动的过程中去调用 EDAS 的接口,获取到此命名空间对应的账号权限信息和地址服务器的地址。

ANS 客户端通过地址服务器就能拿到 ANS Server端的地址。

服务注册与下线

服务注册的通信协议是 HTTP 协议,在 Spring 启动过程中,收到 EmbeddedServletContainerInitializedEvent 或 ServletWebServerInitializedEvent 事件时,会将服务注册到 ANS Server 端。

服务注册成功后,ANS client 端将会主动向 server 端发送心跳,当超过一定时间内 server 端没有收到 client 端的心跳时,会将服务标记成不可用,这样其他 client 在查询时就能发现此服务当前处于不可用的状态。
如果短时间内,大量 client 与 server 心跳失败,则会出发降级保护机制,服务会暂时不被标记成不可用的状态。

当应用程序停止时,收到 ContextClosedEvent 事件后,ANS client 会调用 server 端的反注册接口,将此服务下线。

客户端结合

与客户端结合的方式, ans starter已经实现自动与 Ribbon 组件的结合。

Ribbon的关键接口有下面三个:

属性提供的功能
ServerList提供 getInitialListOfServers 和 getUpdatedListOfServers 方法,获取和刷新 serverList。
IRule选择出一个服务节点
IPing提供 isAlive 方法,负责探测serverList中节点是否可用

目前 ans-starter 在 spring context 中默认实例化了一个 AnsServerList。AnsServerList 实现了 Ribbon 的 ServerList<Server> 接口。

@Bean
@ConditionalOnMissingBean
public ServerList<Server> ribbonServerList(IClientConfig config) {
AnsServerList serverList = new AnsServerList(config.getClientName());
return serverList;
}

如果您有其他需求,可以自行实现 Ribbon 的接口,或者直接在 github 上通过 issue 向我们提需求,我们评估通过后会加上此功能。

高可用实现

服务端高可用

ANS作为分布式系统,服务端高可用包含以下几个方面:

  • 集群内机器数据对等,每台机器存储全量数据;
  • 支持机房容灾功能,即一个集群中的某个机房内的机器全部挂掉不影响服务;
  • 服务端异常自动探测,一旦某个机器挂了,该机器相关的任务(如健康检查)自动漂移到其他机器;

客户端高可用

ANS 为了保证高可用,在客户端高可用方面同样做了很多工作,以应对不同场景的异常情况。

  • 推空保护,当客户端收到服务端推送的空数据时,忽略掉该数据,使用上次的数据;

  • 本地内存缓存,当运行时与服务注册中心的连接丢失或服务注册中心完全宕机,仍能正常地调用服务。

  • 本地缓存文件,当应用与服务注册中心发生网络分区或服务注册中心完全宕机后,应用进行了重启操作,内存里没有数据,此时应用可以通过读取本地已落盘持久化的数据来获取到最后一次订阅到的内容。

  • 本地容灾文件夹。正常的情况下,容灾文件夹内是没有内容的。当服务端完全宕机且长时间不能恢复,同时服务提供者又发生了很大的变更时,可以通过在容灾文件夹内添加文件的方式来开启本地容灾。此时客户端会忽略原有的本地缓存文件,只从本地容灾文件中读取配置。极端情况下,服务端完全不可用时,可以通过修改缓存文件的方式达到支持服务发布变更的目的。

安全的实现

EDAS 服务注册发现组件,结合 EDAS 已有的安全功能,在每次注册、心跳和查询请求中都添加了验签鉴权的操作,保护了服务的安全性。

所以如果您发现您配置的权限信息都无误,但是运行文档中的 Demo 却注册失败了。则可能是由于您本机的时间不准确,从而导致验签鉴权失败。此时您需要校正本机的时间,建议打开时间自动同步功能。

FAQ

问:为什么我的服务注册总是失败?

答:如果您在确认账号信息都准确无误的情况下,但是运行此文档中的 Demo 却注册失败了。有可能是由于您本机的时间不准确,从而导致验签鉴权失败。此时您需要校正本机的时间,建议打开时间自动同步功能。

· 阅读需 15 分钟

Nacos 是阿里巴巴开源的配置中心和服务发现产品,开源距今已经超过一年的时间。本次1.1.0的发布,带来了许多重量级的特性更新,包括灰度配置等社区呼声很高的特性,下面会介绍1.1.0版本发布的新特性和每个特性的使用方式。

## 升级指南#### Server端 0.8.0及以上版本:
  1. 解压安装包后替换{nacos.home}/target/nacos-server.jar
  2. 删除{nacos.home}/plugins/cmdb/及{nacos.home}/plugins/health/下的所有文件
  3. 逐台重启Nacos Server即可

0.8.0以下版本,先升级到1.0.0版本。

#### Client端 请使用最新的1.1.1版本,修复了1.1.0版本的一个客户端版本显示问题。## 新增特性
  • 灰度配置
  • 配置导入导出及配置同步 
  • 地址服务器模块
  • 服务订阅者列表
  • 自定义实例心跳周期
  • Config监听器优化
  • Nacos Go SDK发布
### 灰度配置 @yanlinly @loadchange

灰度配置指的是指定部分客户端IP进行新配置的下发,其余客户端配置保持不变,用以验证新配置对客户端的影响,保证配置的平稳发布。灰度配置是生产环境中一个比较重要的功能,对于保证生产环境的稳定性非常重要。在1.1.0中,Nacos支持了以IP为粒度的灰度配置,具体使用步骤如下:

  1. 在配置列表页面,点击某个配置的“编辑配置”按钮:

image.png

  1. 勾选“Beta发布”,在文本框里填入要下发配置配置的IP,多个IP用逗号分隔:

image.png

  1. 修改配置内容,点击“发布Beta”按钮,即可完成灰度配置的发布:

image.png

  1. 点击“发布Beta”后,“发布Beta”按钮变灰,此时可以选择“停止Beta”或者“发布”。“停止Beta”表示取消停止灰度发布,当前灰度发布配置的IP列表和配置内容都会删除,页面回到正常发布的样式。“发布”表示将灰度配置在所有客户端生效,之前的配置也会被覆盖,同时页面回到正常发布的样式:

image.png

### 配置导入导出及配置同步 @KeRan213539

配置管理的另一个常见需求是能够将一个集群的配置同步到另外一个集群,或者从一个命名空间同步到另外一个命名空间。来自社区的贡献者KeRan213539贡献这个非常实用的功能,具体使用步骤如下:

  1. 导出查询结果。可以根据查询条件,将当期查询出的所有结果打包为一个文件:

image.png

  1. 导出选中的配置:

image.png

  1. 导入配置,可以选择相同配置的处理策略。

image.png

当发现有相同的配置时,会有相应的提示:
image.png

同时如果导入的配置文件格式不符合要求,也会有相应的提示:
image.png

  1. 配置同步,选取想要同步的配置,点击“克隆”,然后再选择要同步的目标命名空间,就可以将配置同步到对应的命名空间:

image.png

image.png

  1. 导入导出文件格式说明。均为zip压缩包,压缩包内有多个目录,目录名为配置的group,目录下有具体的文件,文件名为配置的dataId,每个文件的内容为配置具体的内容:

image.png

### 地址服务器模块 @pbting

1.1.0的安装包列表里多了一个nacos-address-server-1.1.0。这个安装包的作用是作为地址服务器模块,单独部署。关于地址服务器的介绍可以参考Nacos官网地址服务器文章,这里只做一个简单的说明。

一般中间件产品,客户端寻址服务端的方式都是在客户端配置服务端的地址列表,这样有一个缺点是当服务端的地址发生变动时,客户端无法实时的感知到,也无法动态调整访问的服务端集群。而在阿里巴巴的一种比较常见的客户端寻址服务端的方式是地址服务器。简单的说就是部署单独的地址服务器,地址服务器提供接口,获取相关中间件产品服务端集群的地址。由于地址服务器功能比较单一,因此稳定性比较容易保证。客户端只需要配置地址服务器的域名,通过地址服务器获取想要访问的中间件的集群地址,这样既保证能够感知中间件集群的动态变化,也能够为客户端配置更灵活的集群访问策略。

下面介绍地址服务器模块的使用。

  1. 部署地址服务器
  2. 将安装包列表里的nacos-address-server.tar.gz或者nacos-address-server.zip解压。
  3. 单机模式启动:执行 sh bin/startup.sh -m standalone -s nacos-address 以 standalone 的方式启动 address server。
  4. 集群模式启动:在 conf 目录下 将 cluster.conf.example 重名名为 cluster.conf,然后加入其它 server 的节点。加完后,执行 sh bin/startup.sh -s nacos-address 即可。
  5. 配置地址服务器域名:将部署好的地址服务器集群IP挂载到一个域名下,我们假设为address.nacos.com
  6. 在地址服务器上配置Nacos集群的地址列表:
# Add IP to nacos cluster:
curl -X POST '$ADDRESS_SERVER:8080/nacos/v1/as/nodes?ips=1.1.1.1:8848,2.2.2.2:8848,3.3.3.3:8848'

# Remove IP from nacos cluster:
curl -X DELETE '$ADDRESS_SERVER:8080/nacos/v1/as/nodes?ips=1.1.1.1:8848,2.2.2.2:8848,3.3.3.3:8848'
  1. 客户端配置endpoint为该地址服务器集群域名:在构造Nacos客户端时,除了可以通过指定serverAddr来访问Nacos集群外,还可以配置endpoint属性,将这个属性的值设为address.nacos.com,这样就可以达到和配置serverAddr相同的效果。
  2. 通过源码构建地址服务器安装包,在Nacos工程根目录下执行:
mvn -Prelease-address clean install -Dmaven.test.skip=true

安装包会生成在distribution/target目录下。

### 服务订阅者列表 @nicholas2015

服务订阅者列表是1.1.0增加的另外一个功能,就是可以在控制台上查看一个服务的消费者,执行步骤如下:

  1. 在服务列表页面,找到想要查询订阅者的服务:

image.png

  1. 进入订阅者列表页面,在“服务名称”输入框输入想要查询的服务名,在“分组名称”输入框输入服务的分组名(默认为DEFAULAT_GROUP),点击“查询”后,得到订阅者的信息,包括IP和端口、客户端版本和应用名。

image.png

### 服务自定义心跳周期 @lanCao

之前的版本中,客户端注册服务时,不能自定义上报心跳的周期以及客户端下线时自动删除实例的间隔。在1.1.0中,我们支持了这个特性,应用可以在注册时,通过设置实例的metadata,来指定心跳周期、健康检查过期时间及删除实例时间。具体举例如下:

String serviceName = randomDomainName();

Instance instance = new Instance();
instance.setIp("1.1.1.1");
instance.setPort(9999);
Map<String, String> metadata = new HashMap<String, String>();
// 设置心跳的周期,单位为秒,这里将心跳间隔设置为3秒:
metadata.put(PreservedMetadataKeys.HEART_BEAT_INTERVAL, "3000");
// 设置心跳超时时间,单位为秒,这里将心跳超时时间设为6秒,
// 即服务端6秒收不到客户端心跳,会将该客户端注册的实例设为不健康:
metadata.put(PreservedMetadataKeys.HEART_BEAT_TIMEOUT, "6000");
// 设置实例删除的超时时间,单位为秒,这里将实例删除超时时间设为9秒,
// 即服务端9秒收不到客户端心跳,会将该客户端注册的实例删除:
metadata.put(PreservedMetadataKeys.IP_DELETE_TIMEOUT, "9000");
instance.setMetadata(metadata);

naming.registerInstance(serviceName, instance);
### Config 监听器的优化 @chuntaojun
当存在程序启动之初,如果用户通过`ConfigService.getConfig`获取配置的同时,又注册了监听器,那么会存在监听器再次通知用户刚刚获取的配置信息。因此在`version 1.1.0`版本中,增加了新的接口以及一个系统参数(使用户无需修改现有代码) ```java String getConfigAndSignListener(String dataId, String group, long timeoutMs, Listener listener) throws NacosException; ```

该方法在获取配置后,随即注册一个监听器,避免监听器通知用户刚刚才拉取的配置信息
nacos.enableRemoteSyncConfig=true | false
设置该系统参数,将在监听器注册时主动去向远端拉取当前最新的配置信息,但是存在一定的网络开销,因此建议用户采取接口的方式

### Nacos Go SDK @lzp0412 @peggypig @atlanssia

Nacos上周还发布了Go语言的SDK,目前发布了0.1.0-beta版本,仓库地址是:https://github.com/nacos-group/nacos-sdk-go。Nacos Go SDK是单独的仓库,由Nacos Committer参与维护,在代码上不属于Nacos 1.1.0。在此也非常欢迎社区的Go语言高手,参与Nacos Go SDK的演进。

## 如何共建

为了实现这一目标,你需要积极参与Nacos社区。如果您在文档中发现拼写错误,在代码中发现错误,或想要新功能或想要提供建议,您可以在GitHub上创建一个issues

如果您想开始着手,可以选择github仓库中有以下标签的issues。

  • good first issue:对于新手来说是非常好的入门issues。
  • contribution welcome:非常需要解决的问题和非常重要的模块,但目前缺少贡献者,欢迎贡献者来贡献。
## 蓬勃发展的 Nacos 社区

DISS is cheap, show me your hand 比吐槽更重要的是搭把手,参与社区一起发展Nacos

  • 作为用户关注和加入 Nacos 社区

Nacos 社区正在蓬勃发展,截止到发文为止,Nacos 已经有 9 个微信群,其中 7 个已满员,1个QQ群,1个钉钉群,关注 Nacos 的社区人数已经近5000人,在 Nacos 群里跟 “道(基)友” 切磋技术,交流经验,招聘交友,抢抢红包...不亦乐乎。

image.png

  • 作为代码贡献者加入 Nacos 社区

为了能够与代码贡献者更方便的交流,我们组建了钉钉群“Nacos社区核心贡献小组(23335652)”,这个群里都是都是对Nacos贡献非常感兴趣的小伙伴,如果你也想成为Nacos贡献者,甚至成为Committer,欢迎加入这个群和群里的小伙伴一起切磋!

在Nacos官网 nacos.io 中,已经添加团队介绍页,里面包括Nacos的开发者角色定义及职责划分,同时包含了Naocs的开发者们介绍和靓照哦,欢迎大家加入Nacos社区,贡献社区。用Apache的话说,“社区高于代码”!

## 新人时刻 - "什么是Nacos?"

还不知道什么是Nacos? 没关系,在github上star一下跟程序猿兄弟打个招呼吧!!

Nacos 是阿里巴巴于2018年7月份新开源的项目,Nacos的主要愿景是期望通过提供易用的 动态服务发现服务配置管理服务共享与管理 的基础设施,帮助用户在云原生时代更好的构建、交付、管理自己的微服务平台。

image.png

github项目地址在 这里

## 更多与 Nacos 相关的开源项目信息

· 阅读需 7 分钟

Nacos是阿里巴巴2018年开源的服务发现和配置管理项目,并于今年的4月10号GA,距今已经过去了快两个月时间了。Nacos GA代表着用户可以在生产环境上大规模使用,目前也已经有众多用户登记使用。在GA之后,Nacos并未停下前进的脚步,不断的开发新的功能和优化用户体验。与此同时,Nacos倾听社区的声音,每一次迭代和发布都会包含用户关心的功能点。根据Nacos既定的演进方向,以及在与社区进行充分的讨论后,Nacos接下来的版本计划也浮出水面。Nacos在今年还将发布6到7个大版本,每个版本包含的重要特性如下:

#### 1.1.0
  • Go SDK发布: Go语言SDK
  • 地址服务器: 使用地址服务器模式进行Nacos服务端集群寻址
  • 灰度配置: 设置灰度的机器IP来进行配置的灰度发布

1.2.0

  • 配置权限控制: 对配置的读写进行权限的控制,支持对接三方权限系统
  • DNS协议,支持K8S服务域名解析: 通过支持DNS协议访问,无侵入的解决服务发现问题,并支持K8S域名解析
  • Service Mesh打通: 对接开源流行的Service Mesh组件,支持作为服务发现后端和配置管理后端

1.3.0

  • 服务权限控制: 对服务的注册注销及查询进行权限的控制,支持对接三方权限系统
  • Mysql依赖可替换为其他存储: 支持将MySQL依赖替换为Oracle等常见数据库系统依赖
  • gRPC服务发现支持: 通过Go SDK和Java SDK支持gRPC和gRPC-java的服务注册与发现

1.4.0

  • 配置加密: 敏感配置加密存储和传输,保证数据安全
  • confd模式模板渲染: 支持将配置或者服务数据渲染到文件模板,适配异构系统
  • 健康检查SPI化,可以使用K8S健康检查: 支持使用Kubernetes自带的健康检查方式来检查服务实例的健康状态

1.5.0

  • 配置发布审批: 配置发布管控体系,减少人为失误引起的故障
  • IPv6支持: 支持在IPv6网络环境下进行服务的注册与发现和配置的管理
  • 长连接推送通道重构: 重构推送通道,提升SLA
  • configMap对接: 和Kubernetes的配置进行打通

1.6.0

  • Thrift服务发现: 支Thrift服务框架服务注册于发现
  • 支持Region、AZ等类似信息存储: 支持进行环境信息的注册,根据环境进行自定义访问策略
  • 运维命令行: 使用更简洁的方式,进行集群的运维
  • 打标支持,对接K8S label: 能够打自定义标签,能够理由Kubernetes的label进行负载均衡及灰度配置等

1.7.0

  • 无状态化: 存储和计算分离,让系统本身无状态
  • 一致性协议抽象及Raft协议替换: 全新的Raft协议,支持替换
### 增强现有功能,提供更多生产环境需求特性 目前用户集中反馈的需求有灰度配置、权限控制、发布审批等功能,这些特性我们都会在接下来的版本以最高优先级实现。这些特性基本上用户在以往的生产经验中都有所接触,这里不再做详细的介绍。

同时,为了最大化降低用户的部署运维成本,我们会先支持多种数据库的依赖,包括Oracle等数据库,这样可以让用户不需要为了使用Nacos再单独搭建一套MySQL集群。后面我们会更进一步,将外部数据库依赖彻底去除,支持Nacos完全使用本地存储。包括无状态化,也会在未来的版本支持,争取让用户以最低成本的方式运行Nacos。

### 与更多生态进行对接,形成联动优势,提升用户效率 一个产品的成功,往往是因为一个生态的成功。Nacos目前架构的优势之一,就是可以比较平滑的支持多个生态。目前已经支持的有Dubbo生态、Spring Cloud生态,而正在打通的有gRPC和Kubernetes,未来还计划支持Thrift等服务框架。我们的目标是用户无论在哪种生态下,都不需要为注册中心或者配置中心的选型烦恼。### 云原生领域布局和组件打通 云原生是当前非常火热的一个概念。在CNCF、Pivotal等机构相继定义和大力推动云原生的背景下,用户对整个软件的生命周期管理都有了全新的认知。云原生是一个极具潜力的理念,Nacos也会在接下来的演进中对云原生做重点支持。### 内核升级,提升性能和稳定性 Nacos目前的内核,包括自建Raft、MySQL依赖,长轮询及UDP推送等,都会在接下来进行重新设计,目标是优化到最合理的架构,提升整体的性能和稳定性。

· 阅读需 14 分钟

CMDB在企业中,一般用于存放与机器设备、应用、服务等相关的元数据。一般当企业的机器及应用达到一定规模后就需要这样一个系统来存储和管理它们的元数据。有一些广泛使用的属性例如机器的IP、主机名、机房、应用、region等,这些数据一般会在机器部署时录入到CMDB,运维或者监控平台会使用这些数据进行展示或者相关的运维操作。

在服务进行多机房或者多地域部署时,跨地域的服务访问往往延迟较高,一个城市内的机房间的典型网络延迟在1ms左右,而跨城市的网络延迟,例如上海到北京大概为30ms。此时自然而然的一个想法就是能不能让服务消费者和服务提供者进行同地域访问。阿里巴巴集团内部很早就意识到了这样的需求,在内部的实践中,这样的需求是通过和CMDB打通来实现的。在服务发现组件中,对接CMDB,然后通过配置的访问规则,来实现服务消费者到服务提供者的同地域优先,这样的调用每天都在阿里巴巴集团内部大量执行。


图1 服务的同地域优先访问

这实际上就是一种负载均衡策略,在Nacos的规划中,丰富的服务端的可配置负载均衡策略是我们的重要发展方向,这与当前已有的注册中心产品不太一样。在设计如何在开源的场景中,支持就近访问的时候,与企业自带的CMDB集成是我们考虑的一个核心问题。除此之外,我们也在考虑将Nacos自身扩展为一个实现基础功能的CMDB。无论如何,我们都需要能够从某个地方获取IP的环境信息,这些信息要么是从企业的CMDB中查询而来,要么是从自己内置的存储中查询而来。

## [](https://yuque.alibaba-inc.com/nacos/opensource/uk8inc/edit#pwyxgn)CMDB插件机制

先不考虑如何将CMDB的数据应用于负载均衡,我们需要首先在Nacos里将CMDB的数据通过某种方法获取。在实际使用中,基本上每个公司都会通过购买或者自研搭建自己的CMDB,那么为了能够解耦各个企业的CMDB具体实现,一个比较好的策略是使用SPI机制,约定CMDB的抽象调用接口,由各个企业添加自己的CMDB插件,无需任何代码上的重新构建,即可在运行状态下对接上企业的CMDB。


图2 Nacos CMDB SPI机制原理

如图2所示,Nacos定义了一个SPI接口,里面包含了与第三方CMDB约定的一些方法。用户依照约定实现了相应的SPI接口后,将实现打成jar包放置到Nacos安装目录下,重启Nacos即可让Nacos与CMDB的数据打通。整个流程并不复杂,但是理解CMDB SPI接口里方法和相应概念的含义不太简单。在这里对CMDB机制的相关概念和接口含义做一个详细说明。

CMDB抽象概念

实体(Entity)

实体是作为CMDB里数据的承载方,在一般的CMDB中,一个实体可以指一个IP、应用或者服务。而这个实体会有很多属性,例如IP的机房信息,服务的版本信息等。

实体类型(Entity Type)

我们并不限定实体一定是IP、应用或者服务,这取决于实际的业务场景。Nacos有计划在未来支持不同的实体类型,不过就目前来说,服务发现需要的实体类型是IP。

标签(Label)

Label是我们抽象出的Entity属性,Label定义为一个描述Entity属性的K-V键值对。Label的key和value的取值范围一般都是预先定义好的,当需要对Label进行变更,如增加新的key或者value时,需要调用单独的接口并触发相应的事件。一个常见的Label的例子是IP的机房信息,我们认为机房(site)是Label的key,而机房的集合(site1, site2, site3)是Label的value,这个Label的定义就是:site: {site1, site2, site3}。

实体事件(Entity Event)

实体的标签的变更事件。当CMDB的实体属性发生变化,需要有一个事件机制来通知所有订阅方。为了保证实体事件携带的变更信息是最新准确的,这个事件里只会包含变更的实体的标识以及变更事件的类型,不会包含变更的标签的值。

CMDB约定接口

在设计与CMDB交互接口的时候,我们参考了内部对CMDB的访问接口,并与若干个外部客户进行了讨论。我们最终确定了以下要求第三方CMDB插件必须实现的接口:

获取标签列表

Set<String> getLabelNames();

这个方法将返回CMDB中需要被Nacos识别的标签名集合,CMDB插件可以按需决定返回什么标签个Nacos。不在这个集合的标签将会被Nacos忽略,即使这个标签出现在实体的属性里。我们允许这个集合会在运行时动态变化,Nacos会定时去调用这个接口刷新标签集合。

获取实体类型

Set<String> getEntityTypes();

获取CMDB里的实体的类型集合,不在这个集合的实体类型会被Nacos忽略。服务发现模块目前需要的实体类似是ip,如果想要通过打通CMDB数据来实现服务的高级负载均衡,请务必在返回集合里包含“ip”。

获取标签详情

Label getLabel(String labelName);

获取标签的详细信息。返回的Label类里包含标签的名字和标签值的集合。如果某个实体的这个标签的值不在标签值集合里,将会被视为无效。

查询实体的标签值

String getLabelValue(String entityName, String entityType, String labelName);
String getLabelValues(String entityName, String entityType);

这里包含两个方法,一个是获取实体某一个标签名对应的值,一个是获取实体所有标签的键值对。参数里包含实体的值和实体的类型。注意,这个方法并不会在每次在Nacos内部触发查询时去调用,Nacos内部有一个CMDB数据的缓存,只有当这个缓存失效或者不存在时,才会去访问CMDB插件查询数据。为了让CMDB插件的实现尽量简单,我们在Nacos内部实现了相应的缓存和刷新逻辑。

查询实体

String getAllEntities();
Entity getEntity(String entityName, String entityType);

查询实体包含两个方法:查询所有实体和查询单个实体。查询单个实体目前其实就是查询这个实体的所有标签,不过我们将这个方法与获取所有标签的方法区分开来,因为查询单个实体方法后面可能会进行扩展,比查询所有标签获取的信息要更多。

查询所有实体则是一次性将CMDB的所有数据拉取过来,该方法可能会比较消耗性能,无论是对于Nacos还是CMDB。Nacos内部调用该方法的策略是通过可配置的定时任务周期来定时拉取所有数据,在实现该CMDB插件时,也请关注CMDB服务本身的性能,采取合适的策略。

查询实体事件

List<EntityEvent> getEntityEvents(long timestamp);

这个方法意在获取最近一段时间内实体的变更消息,增量的去拉取变更的实体。因为Nacos不会实时去访问CMDB插件查询实体,需要这个拉取事件的方法来获取实体的更新。参数里的timestamp为上一次拉取事件的时间,CMDB插件可以选择使用或者忽略这个参数。

CMDB插件开发流程

参考 https://github.com/nacos-group/nacos-examples,这里已经给出了一个示例plugin实现。
具体步骤如下:

  1. 新建一个maven工程,引入依赖nacos-api:
<dependency>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-api</artifactId>
<version>0.7.0</version>
</dependency>
  1. 引入打包插件:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
  1. 定义实现类,继承com.alibaba.nacos.api.cmdb.CmdbService,并实现相关方法。

  2. 在src/main/resource/目录下新建目录:META-INF/services

  3. 在src/main/resources/META-INF/services目录下新建文件com.alibaba.nacos.api.cmdb.CmdbService,并在文件里将第三步中创建的实现类全名写入该文件:

  4. 代码自测完成后,执行命令进行打包:
mvn package assembly:single -Dmaven.test.skip=true
  1. 将target目录下的包含依赖的jar包上传到nacos CMDB插件目录:
{nacos.home}/plugins/cmdb
  1. 在nacos的application.properties里打开加载插件开关:
nacos.cmdb.loadDataAtStart=true
  1. 重启nacos Server,即可加载到您实现的nacos-cmdb插件获取您的CMDB数据。

使用Selector实现同机房优先访问

在拿到CMDB的数据之后,就可以运用CMDB数据的强大威力来实现多种灵活的负载均衡策略了,下面举例来说明如何使用CMDB数据和Selector来实现就近访问。

假设目前Nacos已经通过CMDB拿到了一些IP的机房信息,且它们对应的标签信息如下:

11.11.11.11
site: x11

22.22.22.22
site: x12

33.33.33.33
site: x11

44.44.44.44
site: x12

55.55.55.55
site: x13

11.11.11.11、22.22.22.22、33.33.33.33、44.44.44.44和55.55.55.55.55都包含了标签site,且它们对应的值分别为x11、x12、x11、x12、x13。我们先注册一个服务,下面挂载IP11.11.11.11和22.22.22.22。

图3 服务详情

然后我们修改服务的“服务路由类型”,并配置为基于同site优先的服务路由:

图4 编辑服务路由类型

这里我们将服务路由类型选择为标签,然后输入标签的表达式:

CONSUMER.label.site = PROVIDER.label.site

这个表达式的格式和我们抽象的Selector机制有关,具体将会在另外一篇文章中介绍。在这里您需要记住的就是,任何一个如下格式的表达式:

CONSUMER.label.labelName = PROVIDER.label.labelName

将能够实现基于同labelName优先的负载均衡策略。

然后假设服务消费者的IP分别为33.33.33.33、44.44.44.44和55.55.55.55,它们在使用如下接口查询服务实例列表:

naming.selectInstances("nacos.test.1", true)

那么不同的消费者,将获取到不同的实例列表。33.33.33.33获取到11.11.11.11,44.44.44.44将获取到22.22.22.22,而55.55.55.55将同时获取到11.11.11.11和22.22.22.22。

· 阅读需 10 分钟

随着Nacos 0.8版本的release,Nacos离正式生产版本又近了一步(其实已经有不少企业已经上了生产,如虎牙)。一般而言,企业研发的流程一般是这样的:先在测试环境开发和测试功能,然后再灰度,最后发布到生产环境。并且,为了生产环境的稳定,测试环境需要跟生产环境隔离;必然要遇到一个问题:多环境问题,即多个环境的数据(如测试环境和生产环境)如何隔离?如何优雅的隔离(不需要用户做任何改动)。下文将就Nacos环境隔离问题,向大家介绍阿里在这方面的实践经验。

什么是环境?

说到环境隔离,首先应该搞清楚什么环境。 环境这个词目前还没有一个比较统一的定义,有些公司叫环境,在阿里云上叫region,在kubernetes架构中叫namespace等等。本文认为,环境是逻辑上或物理上独立的一整套系统,这套系统中包含了处理用户请求的全部组件(网关、服务框架、微服务注册中心、配置中心、消息系统、缓存、数据库等),可以处理指定类别的请求。举个栗子,很多网站都会有用户id的概念,可以按照用户id划分,用户id以偶数结尾的请求全部由一套系统处理,而奇数结尾的请求由另一套系统处理。如下图所示。 我们这里说的环境隔离是指物理隔离,即不同环境是指不同的机器集群。

环境隔离有什么用

上一节定义了环境的概念,即一套包含了处理用户请求全部必要组件的系统,用来处理指定类别的请求。本节跟大家讨论一下环境隔离有哪些好处。从概念的定义可以看出,环境隔离至少有三个方面的好处:故障隔离、故障恢复、灰度测试;

故障隔离

首先,因为环境是能够处理用户请求的独立组件单元,也就是说用户请求的处理链路有多长,都不会跳出指定的机器集群。即使这部分机器故障了,也只是会影响部分用户,从而把故障隔离在指定的范围内。如果我们按照用户id把全部机器分为十个环境,那么一个环境出问题,对用户的影响会降低为十分之一,大大提高系统可用性。

故障恢复

环境隔离的另一个重要优势是可以快速恢复故障。当某个环境的服务出现问题之后,可以快速通过下发配置,改变用户请求的路由方向,把请求路由到另一套环境,实现秒级故障恢复。当然,这需要一个强大的分布式系统支持,尤其是一个强大的配置中心(如Nacos),需要快速把路由规则配置数据推送到全网的应用进程。

灰度测试

灰度测试是研发流程中不可或缺的一个环节。传统的研发流程中,测试和灰度环节,需要测试同学做各种各样的配置,如绑定host、配置jvm参数、环境变量等等,比较麻烦。经过多年的实践,阿里巴巴内部的测试和灰度对开发和测试非常友好,通过环境隔离功能来保证请求在指定的机器集群处理,开发和测试不需要做任何做任何配置,大大提高了研发效率。

Nacos如何做环境隔离

前面两节讲到了环境的概念、环境隔离有哪些作用,本节将向大家介绍如何把Nacos按照前面的思路隔离成多个环境。Nacos脱胎于阿里巴巴中间件部门的软负载小组,在环境隔离方面我们有多年的经验。下面简单介绍下把Nacos隔离为多个物理集群,nacos客户端不需要做任何代码改动即可实现环境自动路由。

原理

在开始前,我们先做一些约束:

  • 一台机器上部署的应用都在一个环境内;
  • 一个应用进程内默认情况下只连一个环境的Nacos;
  • 通过某种手段可以拿到客户端所在机器ip;
  • 用户对机器的网段有规划;

下面简单介绍一下基本原理:

  • 我们知道网络中32位的ipv4可以划分为很多网段,如192.168.1.0/24这种,并且一般稍大型的公司都会有网段规划,按照一定的用途划分网段。我们可以利用这个原理做环境隔离,即不同网段的IP属于不同的环境,如192.168.1.0/24属于环境A, 192.168.2.0/24属于环境B等。
  • 使用过Nacos的应该知道,有两种方式初始化Nacos客户端实例,一种是直接告诉客户端nacos服务端的IP;另一种是告诉客户端一个endpoint,客户端通过HTTP请求到endpoint查询nacos服务端IP列表。我们利用Nacos第二种初始化方式。
  • 增强endpoint的功能。在endpoint端配置网段和环境的映射关系,endpoint在接收到客户端的请求之后,根据客户端的来源IP所属网段,计算出该客户端所属环境,然后找到对应环境的IP列表返回给客户端。如下图

一个环境隔离server的示例

上面讲了基于IP段做环境隔离的约束和基本原理,那么如何实现一个地址服务器呢。最简单的方法是基于nginx实现,利用nginx的geo模块,做IP端和环境的映射,然后利用nginx返回静态文件内容。

geo $env {
default "";
192.168.1.0/24 -env-a;
192.168.2.0/24 -env-b;
}
  • 配置nginx根路径及转发规则,这里只需要简单的返回静态文件的内容;
# 在http模块中配置根路径
root /tmp/htdocs;

# 在server模块中配置
location / {
rewrite ^(.*)$ /$1$env break;
}
  • 配置Nacos服务端IP列表配置文件,在/tmp/hotdocs/nacos目录下配置以环境名结尾的文件,文件内容为IP,一行一个
$ll /tmp/hotdocs/nacos/
total 0
-rw-r--r-- 1 user1 users 0 Mar 5 08:53 serverlist
-rw-r--r-- 1 user1 users 0 Mar 5 08:53 serverlist-env-a
-rw-r--r-- 1 user1 users 0 Mar 5 08:53 serverlist-env-b

$cat /tmp/hotdocs/nacos/serverlist
192.168.1.2
192.168.1.3
  • 验证
curl 'localhost:8080/nacos/serverlist'
192.168.1.2
192.168.1.3

至此, 一个简单的根据IP网段做环境隔离的示例已经可以工作了,不同网段的nacos客户端会自动获取到不同的Nacos服务端IP列表,实现环境隔离。这种方法的好处是用户不需要配置任何参数,各个环境的代码和配置是一样的,但需要提供底层服务的同学做好网络规划和相关配置。

总结

本文简单介绍了环境隔离的概念,环境隔离的三个好处以及Nacos如何基于网段做环境隔离。最后,给出了一个基于nginx做endpoint服务端的环境隔离配置示例。本文只是列出了一种可行的方法,不排除有更优雅的实现方法,如果大家有更好的方法可以看到nacos社区或官网贡献方案。

· 阅读需 14 分钟

经过 3 个 RC 版本的社区体验之后,Nacos 正式发布 1.0.0 GA 版本,在架构、功能和 API 设计上进行了全方位的重构和升级。

1.0.0 版本的发布标志着 Nacos 已经可以大规模地生产环境中使用,新版本不仅针对社区的需求和集群的稳定性相应地增加了一些新特性,而且还发布了服务发现模块的性能测试报告,以及完整的 API 列表和架构设计文档。

Nacos 演进历程

Nacos 自 2018 年 7 月份开源以来,有赖于社区的大力关注和参与,在不到一年的时间里,已经演进了 10+ 个版本。同时也有很多企业客户一直都使用 Nacos 作为生产环境的注册中心和配置中心。

Nacos 源于阿里巴巴内部近十年的生产环境打磨的核心中间件,在开源之前就支撑着双十一等大型业务场景。Nacos 开源不仅是为了丰富整个微服务生态,也是为了打造一款真正能够应对大规模、高并发和复杂环境下复杂需求的生产级服务注册中心和配置管理平台。在 1.0.0 GA 版本发布之际,在此回顾一下 Nacos 的演进历程:

  • 2018.07.20 - Nacos 0.1.0:支持基本的服务发现功能和配置管理功能。

  • 2018.09.15 - Nacos 0.2.0:正式支持 SpringCloud 生态。

  • 2018.10.26 - Nacos 0.3.0:提供控制台界面。

  • 2018.11.19 - Nacos 0.5.0:开源 DNS-F,支持 DNS 协议服务发现。

  • 2018.12.06 - Nacos 0.6.0:正式支持 Dubbo 客户端注册服务,支持 K8S 部署。

  • 2018.12.18 - Nacos 0.7.0:支持 CMDB 元数据管理,支持 Node.js 客户端。

  • 2019.01.22 - Nacos 0.8.0:PRE-GA 支持控制台账号登录,支持命名空间,Nacos-Sync 打通 Eureka 和 Zookeeper。

  • 2019.04.10 - Nacos 1.0.0 GA :同时支持 AP 和 CP 一致性,发布压测报告,稳定性加强和体验优化。

Nacos 1.0.0 新增的特性

注册实例支持ephemeral字段

Nacos 1.0.0 版本在 instance 级别上增加了一个ephemeral字段,该字段表示注册的实例是临时实例还是持久化实例。如果是临时实例,则不会在Nacos服务端持久化存储,需要通过上报心跳的方式进行保活,如果一段时间内没有上报心跳,则会被Nacos服务端摘除。在被摘除后如果又开始上报心跳,则会重新将这个实例注册。持久化实例则会持久化到Nacos服务端,此时即使注册实例的客户端进程不在,这个实例也不会从服务端删除,只会将健康状态设为不健康。

同一个服务下可以同时有临时实例和持久化实例,这意味着当这服务的所有实例进程不在时,会有部分实例从服务上摘除,剩下的实例则会保留在服务下。

由于老版本客户端注册实例时不会上传 ephemeral 字段,需要在 Nacos 服务端设置一个默认的 ephemeral 值。Nacos 1.0.0 里 ephemeral 的默认值为 true,即老版本客户端默认注册的是临时实例。如果需要让老客户端注册的实例类型是持久化实例,可以设置开关:

curl -X PUT '$NACOS_SERVER:8848/nacos/v1/ns/operator/switches?entry=defaultInstanceEphemeral&value=false'

注意事项:当从老版本Nacos升级到Nacos 1.0.0时,从磁盘加载的实例数据会被置为持久化实例。

注册实例支持 groupName 字段

客户端注册实例时,可以在方法级别指定要注册的分组名,这个分组名和服务名是对服务的一个二维的标识,二者共同定位一个服务。一个典型的使用分组的例子如下:

namingService.registerInstance("nacos.test.1", "group1", instance);

不指定分组的接口依然是支持的,此时会在服务端为这个服务分配一个默认的分组:DEFAULT_GROUP。

增加了Server状态的设置

Nacos 增加了对 Server 状态的控制,所有的状态都定义在 com.alibaba.nacos.naming.cluster.ServerStatus

类里。

各个状态的含义介绍如下:

  • UP:Server 一切正常,读写请求都会被接受;
  • DOWN:Server 异常,所有请求会返回 HTTP 503 错误;
  • STARTING:Server 还在启动中,所有请求返回 HTTP 503 错误;
  • PAUSED:Server 被人工暂停,区别于 DOWN 可能是系统自己检测到异常然后设置 DOWN 状态,PAUSED 状态表示当前 Server 可能是没问题的,只是人工进行了干预;
  • WRITE_ONLY:只有非 GET 请求会被接受;
  • READ_ONLY:只有 GET 请求会被接受;

用户可以使用如下接口来修改集群所有机器的状态,如果再加上 debug=true 参数,则只修改当前机器的状态。

curl -X PUT '$NACOS_SERVER:8848/nacos/v1/ns/operator/switches?entry=overriddenServerStatus&value=READ_ONLY'

同时这个状态是会自适应进行修改的,比如启动时这个状态为 STARTING,等到数据装载完毕,则会自动将状态置为 UP,在运行过程中,如果检测到系统异常如磁盘满,则又会将状态置为 DOWN。不过自适应的状态值优先级要低于使用接口设置的状态值,因此当你想恢复自适应的状态调节的时候,记得将接口 overriddenServerStatus 设置为空。

增加全局推送开关

支持了全局推送开关,可以打开或者关闭服务变更的推送,调用接口如下:

curl -X PUT '$NACOS_SERVER:8848/nacos/v1/ns/operator/switches?entry=pushEnabled&value=false'

关闭推送后,客户端依然会通过轮询的方式来更新到数据,只是更新的速度没有推送那么快。

支持启动时数据预热

在老版本的 Nacos 中,只要 Server 启动成功就会开始对外提供服务,此时服务的数据并不一定完全加载完成,这样可能会导致客户端接收到的数据并不完整。1.0.0 版本增加了数据预热的逻辑,对于持久化数据,则会等待所有数据从磁盘加载完成;对于临时实例这样的非持久化数据,则会等待从其他Server拉取到完整数据。所有数据都准备好之后,才会将 Server 状态置为 UP。

注意事项:

对于临时实例的预热,实现机制是 Server 在启动时会从其他Server节点拉取数据,拉取成功则启动成功。但是当从老版本 Server 升级到 1.0.0 时,由于这个拉取全量数据的接口在老版本 Server 中不存在,那么第一个升级的机器将无法拉到任何数据,从而后面升级的机器也无法从第一个升级的机器拉取到数据。此时建议使用调用 API 将 Server 的运行状态设置为 WRITE_ONLY,允许客户端数据逐步汇聚补偿上来,但是要阻止任何查询的流量,直到集群数据准备好以后,再将这个运行状态清空,集群自动调整运行状态,最后就会提供完整服务。

元数据编辑框优化

此前的元数据编辑框需要用户按照指定格式来编辑,容易出错,如下图所示:

1.0.0 版本对服务页面的元数据编辑框进行了优化,在调整编辑框大小的同时,增加语法高亮,方便用户进行编辑和识别格式问题,编辑框预览图如下:

支持 MySQL 8.0

Nacos 1.0.0 支持了 MySQL 8.0 驱动。您只需要将8.0版本的驱动jar包放置在{nacos.home}/plugins/mysql/下即可,不需要其他改动。

Nacos 1.0.0 实现大规模生产可用

API 完整列表开放,模型和架构设计文档更新

服务发现和配置管理的完整 API 列表会发布到官网

地址:https://nacos.io/zh-cn/docs/open-API.html

除了核心功能外,也包含部分运维接口,方便开发者进行集成。同时对于 Nacos 的数据模型、集群模型、架构设计及模块设计文档进行了更新

地址:https://nacos.io/zh-cn/docs/architecture.html

性能测试报告发布

Nacos 1.0.0 进行了性能测试,针对服务发现和配置管理的读写能力进行了大规模场景的压力测试。目前得到的测试数据是:

  • 容量:服务实例数 100 万+,配置数 100 万+,支持客户端连接 100 万+;

  • 读写TPS:1 万+;

  • 节点扩展能力:100 节点+;

  • 推送能力:1 万客户端订阅同一配置/服务,3 秒内收到变更通知比例 99.9%;

目前压测报告已经更新到官网:

https:**//nacos.io/zh-cn/docs/nacos-naming-benchmark.html

https:**//nacos.io/zh-cn/docs/nacos-config-benchmark.html

100+ 企业用户已经上线生产环境

目前 Nacos 作为服务发现和配置中心已经有 100 多个用户的生产环境中服役,包含阿里巴巴、虎牙 等企业已经将 Nacos 大规模应用在核心业务场景中。

升级建议

Nacos 1.0.0 服务端个别接口与 0.8.0 以前的版本不兼容,0.8.0之前版本需要先升级到0.8.0,再升级到1.0.0。对客户端而言,Nacos 1.0.0 兼容 0.5.0 及以上的版本的客户端访问。

如何共建


  1. 如果您在文档中发现拼写错误,在代码中发现错误,想要新功能或想要提供建议,您可以在GitHub上创建一个 issues

    地址:https://github.com/alibaba/Nacos/issues/new

  2. 或者可以选择 GitHub 仓库中有以下标签的 issues 入手:

  • good first issue:对于新手来说是非常好的入门 issues。
  • contribution welcome:亟待解决的问题和非常重要的模块,但目前缺少贡献者,欢迎贡献者来贡献。

img 感谢贡献者们

Nacos 开发团队正在日益壮大,从最开始的只有 4 个代码 Contributor,发展到目前的 40 多个。在 1.0.0 版本的开发中,社区同学贡献了很大的力量,在此表示感谢,他们是(排序不分先后):

yanlinly、xuechaos、hxy1991、jifengnan、nkorange、neatlife、loadchange、TsingLiang、jameslcj、duansheli、pbting、mingyixu、paderlol、nanamikon 等。

img

DISS is cheap, show me your hand 比吐槽更重要的是搭把手,参与社区一起发展Nacos

扫码进群,现在就加入我们。img

img

新人时刻 - 什么是 Nacos ?


Nacos 是阿里巴巴于 2018 年 7 月份新开源的项目,Nacos 的主要愿景是期望通过提供易用的 动态服务发现、 服务配置管理、 服务共享与管理的基础设施,帮助用户在云原生时代更好的构建、交付、管理自己的微服务平台。

img

与 Nacos 相关的开源项目

Nacos(点击“阅读原文”可进入)

https://github.com/alibaba/nacos

Dubbo Registry Nacos

https://github.com/dubbo/dubbo-registry-nacos

Nacos DNS-F

https://github.com/nacos-group/nacos-coredns-plugin

Nacos Spring Project

https://github.com/nacos-group/nacos-spring-project

Nacos Spring Boot

https://github.com/nacos-group/nacos-spring-boot-project

Spring Cloud Alibaba

https://github.com/spring-cloud-incubator/spring-cloud-alibaba

Dubbo

http://dubbo.apache.org/en-us/

Sentinel

https://github.com/alibaba/Sentinel

Spring Cloud

https://spring.io/projects/spring-cloud

Nepxion Discovery

https://github.com/Nepxion/Discovery

Spring Cloud Gateway Nacos

https://github.com/SpringCloud/spring-cloud-gateway-nacoshttps://github.com/SpringCloud/spring-cloud-gateway-nacos)

本文作者:

朱鹏飞(花名:敦谷)

Github ID: nkorange,阿里巴巴中间件高级开发工程师,Nacos 开源项目负责人,Nacos 注册中心等模块主要贡献者。

· 阅读需 10 分钟

天下武功,唯快不破,Nacos一直秉承着稳定性和快速迭代,Nacos 0.9.0版本于上周正式发布release,功能围绕着,Nacos-Sync的稳定性、Server功能拆分部署、Nacos python语言体系的支持,并且在此基础之上,Nacos首次发布核心团队人员,并在持续招募中。

Nacos-Sync稳定性提升

Nacos-Sync简介

Nacos-Sync是Nacos的核心组件,作用是多注册中心数据同步的功能工具,目前支持的同步注册中心包括 Nacos、Zookeeper、Eureka和Consul,主要场景,包括多注册中心数据互相同步,注册中心升级过程的数据迁移,官网提供迁移操作手册

0.9.0 增强稳定性

Nacos 0.9的主线功能加强Nacos-Sync的稳定性,一方面增强Nacos-Sync的基础测试用例覆盖面,保证Nacos-Sync以后的快速迭代过程中主线功能稳定性,另一方面通过监控体系的完善,对接了Prometheus通过metrics暴露数据,并且天然集成grafana监控,保证了Nacos-Sync生产级别稳定性。 随着Nacos 0.9.0版本发布,Nacos-Sync 0.3版本支持了metrics监控,能通过metrics数据观察Nacos-Sync服务的运行状态,提升了Nacos-Sync的在生产环境的监控能力。

使用Prometheus采集Nacos-Sync metrics数据

继 Kubernetes 之后,Prometheus成为第二个正式从 CNCF 毕业的开源项目。Nacos及Nacos-Sync支持Prometheus metrics也是Nacos拥抱云原生的第一步。Prometheus作为新一代的云原生监控系统,除了能对Kubernetes容器集群进行监控之外,也能对容器中的应用进行监控。不过Prometheus的数据展示能力比较差,一般会借助第三方数据监控平台。

grafana监控Nacos-Sync

Grafana是一款强大的数据可视化开源软件,能通过非常漂亮的图表和曲线展示监控数据,支持多种数据源,包括Prometheus。

和Nacos监控一样,官网给Nacos-Sync也提供了监控模版,简单的几步就可以很方便地在Grafana上监控Nacos-Sync

Nacos-Sync监控同样也分为三个模块:

  • nacos-sync monitor展示核心监控项 monitor
  • nacos-sync detail和alert两个模块的展示监控曲线和告警 detail

Nacos Server功能拆分部署

为什么要拆分部署

一般公司随着业务规模的不断膨胀,我们建议业务对注册中心和配置中心进行拆分部署,在Nacos 0.9.0版本以后,支持注册中心模块和配置中心模块的拆分部署,在启动命令进行加入参数,来指定启动指定Nacos 功能模块,默认全部功能启用,目前支持指定配置中心模块和注册中心模块。

使用方法

启动Nacos server时候,增加-f参数,意思是function mode,和对应模块标示来进行启动,如果不传,或者传入有误,都将启动全部功能。 配置中心参数对应config,注册中心参数对应naming

启动命令

sh startup.sh -m standalone -f naming

启动之后,你可以通过启动日志头看到是否正确启动了功能模块,并且Nacos console将只展现启动的对应模块。

  • Nacos启动日志头信息
  • 单独启动配置中心的控制台示例
  • 单独启动注册中心的控制台示例

Nacos python语言体系的支持

Nacos开始支持python语言体系,兼容Nacos0.8.0版本,Nacos-sdk—Python在github上的Nacos-Group中,支持的Python版本包括 2.7、3.6和3.7,操作简单,一行命令安装,可以在仓库中看到详细的使用说明,感谢周文同学的贡献。

Nacos 团队页悄悄上线

在Nacos 0.9.0的版本中,Nacos官网 nacos.io上线了Nacos社区的核心Committer团队首次和大家见面,Nacos 核心团队页,并且社区团队在持续扩大中,Nacos的社区有着自己的社区共建规范,并且在吸收新人上,不仅仅是需要开发者,还需要测试大牛、文档贡献者和社区管理者。我们鼓励大家积极参与Nacos社区,社区有一套机制可以使您,从用户角色到提交者角色,甚至是PMC角色。

如何共建

为了实现这一目标,你需要积极参与Nacos社区。如果您在文档中发现拼写错误,在代码中发现错误,或想要新功能或想要提供建议,您可以在GitHub上创建一个issues

如果您想开始着手,可以选择github仓库中有以下标签的issues。

  • good first issue:对于新手来说是非常好的入门issues。
  • contribution welcome:非常需要解决的问题和非常重要的模块,但目前缺少贡献者,欢迎贡献者来贡献。

除了以上的通用标签,还可以关注Nacos目前重点关注的多语言共建招募,C++、PHP的多语言核心贡献者招募,和并且还有社区群组负责人招募,欢迎大家加入Nacos社区,贡献社区。用Apache的话说,“社区高于代码”!

蓬勃发展的 Nacos 社区

DISS is cheap, show me your hand 比吐槽更重要的是搭把手,参与社区一起发展Nacos

  • 作为用户关注和加入 Nacos 社区

Nacos 社区正在蓬勃发展,截止到发文为止,Nacos 短短几个月已经有 9 个微信群,其中 7 个已满员,1个QQ群,1个钉钉群,关注 Nacos 的社区人数已经近5000人,在 Nacos 群里跟 “道(基)友” 切磋技术,交流经验,招聘交友,抢抢红包...不亦乐乎。

要加入 Nacos 微信社区,你可以通过扫下面的“超哥”“超哥”** 帮你拉入 “Nacos社区微信交流群”

  • 作为代码贡献者加入 Nacos 社区

从Nacos用户发展而成贡献者顺理成章,而Nacos开发团队也确实在日趋壮大,从开始的只有4个代码contributor发展到目前的39个,在0.9.0 版本的开发中,社区同学贡献了很大的力量,在此特别感谢,他们的githubId是(注:不分先后) paderlol、jifengnan、loadchange、nkorange、hxy1991、huangyunbin、darkness463、luoxn28、TsingLiang、xuechaos、nanamikon、systp、jameslcj、pader.zhang,相信后续有跟多同学参与到Nacos社区的共建中。

新人时刻 - "什么是Nacos?"

还不知道什么是Nacos? 没关系,在github上star一下跟程序猿兄弟打个招呼吧!!

Nacos 是阿里巴巴于7月份新开源的项目,Nacos的主要愿景是期望通过提供易用的 动态服务发现服务配置管理服务共享与管理 的基础设施,帮助用户在云原生时代更好的构建、交付、管理自己的微服务平台。

github项目地址在 这里

更多与 Nacos 相关的开源项目信息