Alibaba之Nacos详解

上个月最后一天的凌晨,Spring Cloud Alibaba 正式入驻了 Spring Cloud 官方孵化器,并在 maven 中央库发布了第一个版本。

成都创新互联从2013年创立,是专业互联网技术服务公司,拥有项目成都网站制作、成都做网站、外贸营销网站建设网站策划,项目实施与项目整合能力。我们以让每一个梦想脱颖而出为使命,1280元钦北做网站,已为上家服务,为钦北各地企业和个人服务,联系电话:18982081108

目前 Spring Cloud Alibaba 还只能算是预览版吧,里边的坑肯定不少,不过我还是决定试试,看看 Alibaba 到底靠谱不靠谱。

Alibaba之Nacos详解

一、Spring Cloud Alibaba

目前 Spring Cloud Alibaba 项目还处于 Spring Cloud 官方孵化器中,打开它 Github 的就能看到 “亲切” 的中文文档。

它目前只有三个组件:

  • Sentinel:把流量作为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。

  • Nacos:一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。

  • AliCloud OSS: 阿里云对象存储服务(Object Storage Service,简称
    OSS),是阿里云提供的海量、安全、低成本、高可靠的云存储服务。您可以在任何应用、任何时间、任何地点存储和访问任意类型的数据。

看官方路线图上讲后边还会增加:

  • Dubbo:Apache Dubbo™ (incubating) 是一款高性能 Java RPC 框架。

  • RocketMQ:Apache RocketMQ™ 基于 Java 的高性能、高吞吐量的分布式消息和流计算平台。

  • Schedulerx:阿里中间件团队开发的一款分布式任务调度产品,支持周期性的任务与固定时间点触发任务。

  • AliCloud SLS:针对日志类数据的一站式服务,在阿里巴巴集团经历大量大数据场景锤炼而成。您无需开发就能快捷完成日志数据采集、消费、投递以及查询分析等功能,提升运维、运营效率,建立 DT 时代海量日志处理能力。

从数量上来看,Alibaba 的组件数量和目前 Netflix 的相比少了一多半,但是仔细看看各组件的功能描述,也就明白了。在没真正上手之前,我个人先大胆猜测一下:

  • Nacos = Eureka/Consule + Config + Admin
  • Sentinel = Hystrix + Dashboard + Turbine
  • Dubbo = Ribbon + Feign
  • RocketMQ = RabbitMQ
  • Schedulerx = Quartz
  • AliCloud OSS、AliCloud SLS 这三个应该是独有的
    链路跟踪(Sleuth、Zipkin)不知道会不会在 Sentinel 里
    以上只是猜测,待我从坑里爬出来之后再回来更新。也欢迎大家一起交流探讨~
    这里我就先试试 Nacos。

二、Nacos

Alibaba之Nacos详解

这是 Nacos 的架构图,可以看到它确实是融合了服务注册发现中心、配置中心、服务管理等功能,和我之前猜想的它是 Eureka/Consule + Config + Admin 的合体差不多。

另外通过官方文档发现,Nacos 除了可以和 Spring Cloud 集成,还可以和 Spring、SpringBoot 进行集成。

不过我们只关注于 Spring Cloud,别的就略过了,直接上手吧~

工程的目录结构如下:

alibaba
├── nacos-config
│   ├── pom.xml
│   └── src
├── nacos-consumer
│   ├── pom.xml
│   └── src
├── nacos-provider
│   ├── pom.xml
│   └── src
└── pom.xml

首先引入 Spring Cloud Alibaba 的 BOM


    org.springframework.boot
    spring-boot-starter-parent
    2.0.4.RELEASE
    


    Finchley.SR2
    0.2.0.RELEASE


    
        
            org.springframework.cloud
            spring-cloud-alibaba-dependencies
            ${spring-cloud-alibaba.version}
            pom
            import
        
        
            org.springframework.cloud
            spring-cloud-dependencies
            ${spring-cloud.version}
            pom
            import
        
    

这里版本号有坑,文档上说和 Spring Boot 2.0.x 版本兼容,但是实测 2.0.6.RELEASE 报错

java.lang.NoClassDefFoundError: org/springframework/core/env/EnvironmentCapable

三、Nacos Server

在使用 Nacos 之前,需要先下载 Nacos 并启动 Nacos Server。

Nacos Server 有两种运行模式:

  • standalone
  • cluster

不论哪种方式吧,都需要先去 https://github.com/alibaba/nacos/releases 下载最新的 release 包,然后解压,以 nacos-server-0.4.0.zip 为例

unzip nacos-server-0.4.0.zip
cd nacos

1、standalone 模式

此模式一般用于 demo 和测试,不用改任何配置,直接敲以下命令执行

sh bin/startup.sh -m standalone

Windows 的话就是

cmd bin/startup.cmd -m standalone

然后从 http://localhost:8848/nacos/index.html 进入控制台就能看到如下界面了

Alibaba之Nacos详解

2、cluster 模式

集群模式需要依赖 MySQL,然后改两个配置文件:

conf/cluster.conf
conf/application.properties

具体怎么改,在这里就先不展开了。我们先用 standalone 模式撸起来,享受 coding 的快感,然后再慢慢转到 cluster 上边。

四、配置管理

在 nacos/pom.xml 里添加依赖:


    
        org.springframework.boot
        spring-boot-starter-web
    
    
        org.springframework.cloud
        spring-cloud-starter-alibaba-nacos-config
    

启动类不用修改:

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

修改 bootstrap.yml

spring:
  application:
    name: nacos
  cloud:
    nacos:
      config:
        server-addr: 127.0.0.1:8848

注意:必须是写在 bootstrap.yml 中,配置在 application.yml 中不行,启动报错

java.lang.IllegalArgumentException: Could not resolve placeholder 'spring.application.name' in value "${spring.application.name}"

至于 bootstrap.yml 和 application.yml 的区别,之前讲过这里就不赘述了。

添加一个 Endpoint 便于观察

@RestController
@RequestMapping("/config")
@RefreshScope
public class ConfigController {

    @Value("${useLocalCache:false}")
    private boolean useLocalCache;

    @RequestMapping("/get")
    public boolean get() {
        return useLocalCache;
    }
}

注意一定要加@RefreshScope注解

小心!此处有坑!

这时候先别急着启动 NacosConfigApplication 的,需要需要通过调用 Nacos Open API 往 Nacos Server 里发布一个配置。dataId 为 nacos.properties,内容为useLocalCache=true

curl -X "POST" "http://127.0.0.1:8848/nacos/v1/cs/configs" \
     -H 'Content-Type: application/x-www-form-urlencoded; charset=utf-8' \
     --data-urlencode "dataId=nacos.properties" \
     --data-urlencode "group=DEFAULT_GROUP" \
     --data-urlencode "content=useLocalCache=true

dataId 的完整格式如下:

prefix−prefix−{spring.profile.active}.${file-extension}
  • prefix 默认为 spring.application.name 的值,也可以通过配置项 spring.cloud.nacos.config.prefix来配置。
  • spring.profile.active 即为当前环境对应的 profile,详情可以参考 Spring >Boot 文档。 注意:当 spring.profile.active 为空时,对应的连接符 - >也将不存在,dataId 的拼接格式变成 prefix.prefix.{file-extension}
  • file-exetension 为配置内容的数据格式,可以通过配置项 spring.cloud.nacos.config.file-extension 来配置。目前只支持 properties 和 yaml 类型。

然后启动 NacosConfigApplication,从启动日志里能看到

Located property source: CompositePropertySource {name='NACOS', propertySources=[NacosPropertySource {name='nacos.properties'}]}

如果 propertySources 里边是空的,那抱歉,你掉到坑里边了。 如果你能看到之前发布的 dataId,那恭喜,请求 http://localhost:8080/config/get 就可以看到返回内容 true 了。

再次调用 Nacos Open API 修改内容为useLocalCache=false

再次访问 http://localhost:8080/config/get ,此时返回内容为false,说明程序中的useLocalCache值已经被动态更新了。

当然,以上手动调用 Nacos Open API 的方式也可以通过 Nacos Console 的可视化界面来操作

Alibaba之Nacos详解

另外我们可以查询配置的历史记录并能快速回滚

Alibaba之Nacos详解

还能查询到某个配置当前的被监听状态(这里的分页有些 bug)

Alibaba之Nacos详解

五、数据源

经过了上边的一些简单操作,我们已经可以正常使用 Nacos 配置中心了。
但是不知道你有没有想过:配置数据是存在哪里呢?

我们没有对 Nacos Server 做任何配置,那么数据只有两个位置可以存储:

  • 内存
  • 本地数据库

如果我们现在重启刚刚在运行的 Nacos Server,会发现刚才加的 nacos.properties 配置还在,说明不是内存存储的。

这时候我们打开NACOS_PATH/data,会发现里边有个derby-data目录,Derby 是 Java 编写的数据库,属于 Apache 的一个开源项目。我们的配置数据现在就存储在这个库中。

Derby 我并不是很熟悉,那能不能将数据源改为我们熟悉的 MySQL 呢?当然可以了。

注意:不支持 MySQL 8.0 版本

这里我以本地运行的 MySQL 为例:

创建一个名为nacos_config的 database

将NACOS_PATH/conf/nacos-mysql.sql中的表结构导入刚才创建的库中,这几张表的用途就自己研究吧

修改NACOS_PATH/conf/application.properties,加入 MySQL 配置

db.num=1
db.url.0=jdbc:mysql://localhost:3306/nacos_config?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true
db.user=root
db.password=root

创建cluster.conf,填入要运行 Nacos Server 机器的 ip

192.168.100.155
192.168.100.156

我就是运行个 demo,没有多余机器来组建集群怎么办呢?

其实不用虚拟机,直接只填一个本地地址也是可以的(仅限于配置管理,服务发现不行)。

这里有两个坑:

Nacos Server 的数据源是用 Derby 还是 MySQL 完全是由其运行模式决定的:

standalone 的话仅会使用 Derby,即使在 application.properties 里边配置 MySQL 也照样无视;
cluster 模式会自动使用 MySQL,这时候如果没有 MySQL 的配置,是会报错的。
官方提供的 cluster.conf 示例如下

#it is ip
#example
10.10.109.214
11.16.128.34
11.16.128.36

从习惯来看,这个#号后边的应该就是注释的,但是抱歉哦,必须删掉,否则下面的异常就扑面而来

Caused by: java.lang.NumberFormatException: For input string: "it is ip:0"
  at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
  at java.lang.Long.parseLong(Long.java:589)
  at java.lang.Long.parseLong(Long.java:631)
  at com.alibaba.nacos.naming.core.DistroMapper.onServerStatusUpdate(DistroMapper.java:125)
  at com.alibaba.nacos.naming.core.DistroMapper.init(DistroMapper.java:100)
  at com.alibaba.nacos.naming.core.DistroMapper.(DistroMapper.java:65)
  ... 79 common frames omitted

以上配置结束后,运行 Nacos Server 就能看到效果了。

除了 MySQL 的数据表发生了变化,我们会发现NACOS_PATH/data下的目录结构也发生了变化,多了config-data/DEFAULT_GROUP/nacos_config这么一个文件,里边的内容就是我们的配置

useLocalCache=true

这是容错呢?还是缓存呢?只有等看过源码才知道了。

六、服务发现

服务注册中心和服务发现的服务端都是由 Nacos Server 来提供的,我们只需要提供 Service 向其注册就好了。

首先我们先将 Nacos Server 由伪分布式改为 standalone 模式,原因后边再说吧。

这里模拟提供两个 service:provider 和 consumer

alibaba
├── nacos-provider
│   ├── pom.xml
│   └── src
└── nacos-consumer
│   ├── pom.xml
│   └── src
└── pom.xml

首先在 provider 和 consumer 的 pom 添加依赖


    org.springframework.boot
    spring-boot-starter-web


    org.springframework.cloud
    spring-cloud-starter-alibaba-nacos-discovery

在两者的 bootstrap.yml 中添加配置

1、provider

spring:
  application:
    name: nacos-provider
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
server:
  port: 18080
consumer

spring:
  application:
    name: nacos-consumer
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
server:
  port: 18081

使用 Spring Cloud 的原生注解 @EnableDiscoveryClient 开启服务发现

@SpringBootApplication
@EnableDiscoveryClient
public class NacosProviderApplication {
    public static void main(String[] args) {
        SpringApplication.run(NacosProviderApplication.class, args);
    }
}

提供 Endpoint 以供访问


@RestController
@RequestMapping("/echo")
public class EchoController {

    @RequestMapping(value = "/{string}", method = RequestMethod.GET)
    public String echo(@PathVariable String string) {
        return "Hello Nacos Discovery " + string;
    }
}

2、Consumer

在 NacosConsumerApplication 中集成 RestTemplate 和 Ribbon

@LoadBalanced
@Bean
public RestTemplate restTemplate() {
  return new RestTemplate();
}

提供 Controller

@RestController
@RequestMapping("/echo")
public class TestController {

    private final RestTemplate restTemplate;

    @Autowired
    public TestController(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }

    @RequestMapping(value = "/{str}", method = RequestMethod.GET)
    public String echo(@PathVariable String str) {
        return restTemplate.getForObject("http://nacos-provider/echo/" + str, String.class);
    }

}

分别启动 NacosProviderApplication 和 NacosConsumerApplication ,调用 http://localhost:18080/echo/windmt 和 http://localhost:18081/echo/windmt ,返回内容均为 Hello Nacos Discovery windmt,说明服务发现成功了。

这时候查看 Nacos Console 也能看到已注册的服务列表及其详情

Alibaba之Nacos详解

Alibaba之Nacos详解

现在来讲一下为什么前边要将 Nacos Server 由伪分布式再改为 standalone 模式。

单个节点的 Nacos Server 伪分布式在配置管理运行的好好的,但是到了服务发现,它就失效了。

通过 log 可以发现一些端倪,单节点的在选主的时候,无法正确选出 leader

==> logs/naming-raft.log <==
2018-11-13 16:38:56,424 INFO leader timeout, start voting,leader: null, term: 1

从而导致 Client 无法正常注册

java.lang.IllegalStateException: failed to req API:/nacos/v1/ns/instance after all servers([127.0.0.1:8848]) tried
    at com.alibaba.nacos.client.naming.net.NamingProxy.reqAPI(NamingProxy.java:339) ~[nacos-client-0.3.0.jar:na]
    at com.alibaba.nacos.client.naming.net.NamingProxy.reqAPI(NamingProxy.java:272) ~[nacos-client-0.3.0.jar:na]
    at com.alibaba.nacos.client.naming.net.NamingProxy.registerService(NamingProxy.java:171) ~[nacos-client-0.3.0.jar:na]
    at com.alibaba.nacos.client.naming.NacosNamingService.registerInstance(NacosNamingService.java:161) ~[nacos-client-0.3.0.jar:na]
    ... ...

七、小结

当今年年初 Dubbo 进入 Apache 孵化器的时候,就有预感阿里要与 Spring Cloud 结缘。只是没想到这么快。

如今 Spring Cloud Alibaba 已经进入了 Spring Cloud 官方孵化器,相信等不了多久也就能正式发布了。虽然大家在生产环境必然还不会这么快速地接入,但是总归是多了一种选择。

而 Nacos 作为微服务核心的服务注册与发现中心,让大家在 Eureka 和 Consule 之外有了新的选择,开箱即用,上手简洁,暂时也没发现有太大的坑。但将配置中心融合也融合进来是好是坏,这个我先按下不表。

总而言之,Spring Cloud Alibaba 的入驻对于 Spring Cloud 生态总归是好的~


网页标题:Alibaba之Nacos详解
当前链接:http://hbruida.cn/article/jphojj.html