01-SpringCloud Alibaba Start-Nacos

Spring Cloud Alibaba Start

Spring Cloud Alibaba入门

开源地址:https://github.com/TyCoding/spring-learn/tree/master/cloud-alibaba-start 欢迎star、fork支持作者

Intruduction

在学习SpringCloud Alibaba之前,你应该具有SpringCloud项目开发经验,那么学习起来将很轻松。如果读者对SpringCloud不是很熟悉,请移步看我的这个SpringCloud基础项目:https://github.com/TyCoding/cloud-template

Spring Cloud Alibaba官方介绍:https://github.com/alibaba/spring-cloud-alibaba/blob/master/README-zh.md

这里不再赘述,直接开始实战。

cloud-alibaba-start-dependencies

作为分布式项目,首先需要对整个项目做统一的依赖管理,也就是父工程。这里创建cloud-alibaba-start-dependencies项目作为parent dependencies

使用IDEA在cloud-alibaba-start根目录下创建cloud-alibaba-start-dependencies文件夹,并创建pom.xml

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
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

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

<groupId>cn.tycoding</groupId>
<artifactId>cloud-alibaba-start-dependencies</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>pom</packaging>

<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>

<spring-cloud.version>Hoxton.SR3</spring-cloud.version>
<com-alibaba-cloud.version>2.2.1.RELEASE</com-alibaba-cloud.version>
</properties>

<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${com-alibaba-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>

image-20200625170405547

Tips

可能有人疑惑,之前写分布式项目或Maven多模块项目,是直接在cloud-alibaba-start根目录下创建pom.xml作为parent dependencies。当然这样也是可以的,但推荐使用上述方式。

Nacos

在之前学习SpringCloud时,我们选用Eureka作为注册中心,而在今天,我们选择Nacos作为注册中心。

官方介绍文档:https://github.com/alibaba/Nacos 。这里以实战为主。

下载与安装

大家可以采取下载官方源码并编译:

1
2
3
git clone https://github.com/alibaba/nacos.git
cd nacos
mvn -Prelease-nacos clean install -U

最终将在/nacos/distribution/target/nacos-server-xx得到编译后的Nacos。

但在这里为了避免编译可能产生的未知错误,我选择下载官方的release版本:https://github.com/alibaba/nacos/releases

image-20200625171825670

解压缩后将得到如下文件:

image-20200625171949924

启动

目前,我们不需要做任何配置,直接在nacos/bin/找到start.up启动Nacos:

1
sh startup.sh -m standalone

image-20200625172248790

Nacos具体是否启动成功在这里看不到,请在/nacos/logs/start.out中查看启动是否报错,如果没有报错则证明启动成功。在浏览器上访问localhost:8848/nacos

image-20200625172852692

出现如上页面证明Nacos安装成功。(用户名和密码都是nacos

Tips

到目前,你会发现,Nacos是独立的应用(编译好的),并不需要我们再在项目中创建nacos项目,这和Eureka的区别比较大。如果需要修改Nacos默认配置,仅需在/nacos/conf中修改然后重启应用即可。

如何关闭Nacos?官方并没有提供shutdown.sh,我们可以查看8080端口信息,kill掉对用的进程即可:

image-20200625173649803

cloud-alibaba-start-nacos-provider

与SpringCloud类似,当部署好了注册中心,下面就开始创建服务生产者。创建生产者服务:cloud-alibaba-start-nacos-provider

导入依赖

cloud-alibaba-start下创建cloud-alibaba-start-nacos-provider文件夹,在pom.xml中写入:

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
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>cn.tycoding</groupId>
<artifactId>cloud-alibaba-start-dependencies</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>

<artifactId>cloud-alibaba-start-nacos-provider</artifactId>
<packaging>jar</packaging>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>

<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
</dependencies>
</project>
  • <parent>节点中<artifactId>cloud-alibaba-start-dependencies,证明此项目依赖cloud-alibaba-start-dependencies父工程,那么在父工程pom.xml<dependencyManagement>中定义的版本信息在此项目中也将生效,我们就无需再管理这些依赖版本了。
  • spring-cloud-starter-alibaba-nacos-discovery依赖是作为Nacos客户端所必须的(和Eureka类似)。要注意此依赖(2.2.1.RELEASE)来自com.alibaba.cloud,在一些老版本中填写的是org.springframework.cloud

创建Application

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**
* 服务提供者
*
* @author tycoding
* @date 2020/6/22
*/
@SpringBootApplication
@EnableDiscoveryClient
public class NacosProviderApplication {

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

细心的你会发现@EnableDiscoveryClient注解是来自org.springframework.cloud,而在SpringCloud开发中也是使用这个注解,也就是说,只要使用SpringCloud,无论你用的那种注册中心都是可以直接移植过来的。

创建application.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
spring:
application:
# 服务名称
name: nacos-provider
cloud:
nacos:
# 注册中心
discovery:
server-addr: 127.0.0.1:8848

# 服务端口
server:
port: 8081

# 监听端点
management:
endpoints:
web:
exposure:
include: "*"

和SpringCloud类似,这里仅需要关注nacos节点。其中discovery.server-addr代表注册中心的地址,因为我们本地部署的Nacos,所以注册中心地址就是127.0.0.1:8848

测试

随便创建一个Controller接口:

1
2
3
4
5
6
7
8
9
10
11
@RestController
public class NacosProviderController {

@Value("${server.port}")
private String port;

@GetMapping("/start/{author}")
public String start(@PathVariable(value = "author") String author) {
return "Start Nacos, by " + author + ", this port is " + port;
}
}

启动该项目,访问localhost:8081/start/tycoding

image-20200625175726918

如上,证明启动成功。观察Nacos控制台:

image-20200625175846303

证明cloud-alibaba-start-nacos-provider启动成功,且已注册到Nacos注册中心上。

cloud-alibaba-start-nacos-consumer

服务提供者创建完毕,创建服务消费者。

Sentinel

既然是微服务,那么必然出现不同服务之前的大量调用,为了实现高可用通常部署很多台服务器防止出现某台服务器挂掉。而即使部署了多台服务,但作为消费者并不能提前预知哪台服务已经挂了,当消费者不断向一台(或多台)挂掉的服务发送请求必然会导致请求一直得不到响应而影响整个系统运行。在SpringCloud开发阶段使用Hystrix解决服务熔断,原理就是当消费者发送请求给生产者,若此生产者已经挂掉连接不上,Hystrix会自动中断消费者与此服务的请求,分配到其他服务上,从而避免服务雪崩

在SpringCloud Alibaba中,使用Sentinel作为服务熔断器,并提供了Dashboard监控服务的运行状态。

安装

直接去官方仓库下载最新Release版本(当然也可以下载仓库源码再手动编译):https://github.com/alibaba/Sentinel/releases

image-20200625214032528

这里选用最新的1.7.2版本。这是一个标准的SpringBoot的应用,下载后的jar可以直接用java -jar命令运行。

1
java -Dserver.port=8100 -Dcsp.sentinel.dashboard.server=localhost:8100 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.7.2.jar

启动注意端口,避免冲突。

image-20200625214349323

在浏览器上访问:localhost:8100:(默认用户名密码都是sentinel

image-20200625214453233

以上,Sentinel控制台启动成功。要让Sentinel作为服务的熔断器,那么必须让需要熔断器的服务都被Sentinel监听到,下面在cloud-alibaba-start-nacos-consumer服务中将讲解如何配置Sentinel监听服务。

导入依赖

cloud-alibaba-start下创建cloud-alibaba-start-nacos-consumer文件夹,并在pom.xml写入:

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
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>cn.tycoding</groupId>
<artifactId>cloud-alibaba-start-dependencies</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>

<artifactId>cloud-alibaba-start-nacos-consumer</artifactId>
<packaging>jar</packaging>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>

<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
</project>

与服务提供者类似,这里增加了spring-cloud-starter-openfeign 依赖,学习过SpringCloud的朋友应该都知道Feign。

何为微服务?就是由很多个不同的子服务构成。那么服务与服务之前必然需要通信(数据交互),而Feign正是实现服务与服务间的通信。

spring-cloud-starter-alibaba-sentinel是Sentinel熔断器的依赖,若该服务需要使用熔断器那么必要要引入Sentinel依赖并配置使用。

创建Application

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
* 服务消费者
*
* @author tycoding
* @date 2020/6/22
*/
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class NacosConsumerApplication {

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

创建application.yml

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
spring:
application:
# 服务名称
name: nacos-consumer
cloud:
nacos:
# 注册中心
discovery:
server-addr: 127.0.0.1:8848
# sentinel dashboard监听
sentinel:
transport:
# 任意指定一个端口供dashboard监听(此应用作为一个服务端提供接口)
port: 8101
# sentinel dashboard启动的端口
dashboard: 127.0.0.1:8100

feign:
# 开启Feign对sentinel的支持
sentinel:
enabled: true

# 服务端口
server:
port: 8082

# 监听端点
management:
endpoints:
web:
exposure:
include: "*"

需要注意:

  • sentinel.transport.port:让此服务暴露一个端口供Sentinel监听,也就是此服务作为生产者,Sentinel作为消费者监听生产者。
  • sentinel.transport.dashboard:Sentinel Dashboard的IP端口。
  • feign.sentinel.enabled:当前此consumer服务作为消费者要通过Feign从生产者provider拿数据,因此必须要Feign允许Sentinel监控服务间通信。

创建Feign Service接口

前面提到了,此consumer消费者是从provider生产者服务那里拿数据的,两者必要通信,而服务间通信采用Feign。那么按照Feign的要求,consumer消费者仅需要写一个Feign接口,便可调用provider中的数据。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/**
* Feign访问接口
*
* @author tycoding
* @date 2020/6/22
*/
// `nacos-provider`和对应服务的`spring.name`相同
@FeignClient(value = "nacos-provider", fallback = NacosProviderFallback.class)
public interface NacosProviderService {

/**
* 和`服务消费者`Controller接口Path相同,保证`服务消费者`从`服务提供者`获取数据
*
* @param author 传递参数
* @return 该Feign接口自动将数据返回
*/
@GetMapping("/start/{author}")
public String start(@PathVariable(value = "author") String author);
}

和之前使用Hystrix一样,此处@FeignClient注解中要指定fallback熔断机制,这里我们采用的Sentinel作为熔断器:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**
* Sentinel 服务熔断机制
*
* @author tycoding
* @date 2020/6/22
*/
@Component
public class NacosProviderFallback implements NacosProviderService {

@Override
public String start(String author) {
return "request error, this from sentinel";
}
}

provider生产者服务连接不上,Sentinel将直接与服务熔断,避免其他服务再调用。

创建Controller

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@RestController
public class NacosConsumerController {

@Autowired
private NacosProviderService nacosProviderService;

/**
* 直接调用Feign提供的接口
* providerService(`consumer`服务) -> feign -> providerController(`provider`服务)
*
* @return
*/
@GetMapping("/start")
public String start() {
return nacosProviderService.start("tycoding");
}
}

可以看到:如果请求consumer服务的/start接口,则通过Feign将此请求转发到provider服务中,最终provider服务将响应结果返回。

说到这里,你是否有点晕了?下面我简单画图解释下:

image-20200625223127750

如果Feign Service调用Provider1发现连接失败,则将触发Sentinel Fallback熔断与Provider1的通信,继续调用Provider2….

那么在代码中是如何体现的?下图分析:

image-20200625224220659

测试

首先先正常启动cloud-alibaba-start-nacos-providercloud-alibaba-start-nacos-consumer两个服务:

image-20200625224436785

访问localhost:8082/start

image-20200625224600727

可以看到,虽然请求的8082服务,但最终响应的是8081服务的数据。如果此时关闭8081服务,再请求此接口:

image-20200625224755411

image-20200625224736950

可以看到请求立即被Sentinel熔断了,并返回熔断器响应数据。

交流

QQGroup:671017003

WeChatGroup: 关注公众号查看

联系

TyCoding wechat
欢迎关注公众号:程序员涂陌
如果你觉得这篇文章帮助到了你,你可以帮作者买一杯果汁表示鼓励

TOP