1、Nacos
基本概念
官网:https://nacos.io/zh-cn/docs/quick-start.html
GitHub: https://github.com/alibaba/nacos
Nacos(Naming&Configuration&Service) 致力于帮助您发现、配置和管理微服务。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据及流量管理。
常见的注册中心
服务注册与发现框架 | CAP模型 | 控制台管理 | 社区活跃度 |
---|---|---|---|
Eureka | AP(可用,分区容错) | 支持 | 低,2.x版本闭源 |
Zookeeper专业级的独立产品,Dubbo | CP(数据一致性,分区容错) | 不支持 | 中 |
Consul (Go语言),使用参考我这篇博客 | CP | 支持 | 高 |
Nacos | AP和CP模式切换的 | 支持 | 高 |
Nacos的主要功能
1、服务发现和服务健康监测()
2、动态配置服务
3、动态DNS服务
4、服务及元数据管理
与SpringCloud Netflix全家桶对比:Eureka(注册) + Config(配置) + Bus(数据总线) = Nacos
一图看懂:
架构图:
下载安装
Nacos依赖于Java环境,所以必须安装Java环境。然后从官网下载Nacos的解压包,安装稳定版的,下载地址:https://github.com/alibaba/nacos/releases
目前最新版本是1.2.1
解压后文件的/bin目录下,windows系统点击startup.cmd就可以启动nacos。linux或mac执行以下命令启动nacos。
# 停止
./shutdown.sh
tar -zxvf nacos-server-1.1.4.tar.gz
cd nacos/bin
# 单机模式启动,不带standalone就是集群模式
./startup.sh -m standalone
# 启动好后可以直接访问了
http://localhost:8848/nacos
# 端口默认:8848,用户名密码:nacos/nacos
nacos的启动端口为8848,在启动时要保证端口不被占用。 启动成功,在浏览器上访问:http://localhost:8848/nacos 会跳转到登陆界面,
默认的登陆用户名密码都是nacos : nacos。
集群模式参考官方文档配置https://nacos.io/zh-cn/docs/cluster-mode-quick-start.html
使用Nacos注册服务
在springcloud的官网上,有Spring Cloud Alibaba 的使用文档
edu-edu和edu-vod 俩个服务都注册到nacos
1、pom.xml导入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>0.9.0.RELEASE</version>
</dependency>
2、配置文件appliation.properties增加nacos server地址配置
# 具体的Nacos实例地址
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
3、启动类开启注解@EnableDiscoveryClient
// @EnableEurekaClient 只有Eureka可以用
// 通过 Spring Cloud 原生注解 @EnableDiscoveryClient 开启服务注册发现功能
@SpringBootApplication
@ComponentScan(basePackages = {"com.coding.edu","com.coding.common"})
@EnableDiscoveryClient
public class EduApplication {
public static void main(String[] args) {
SpringApplication.run(EduApplication.class,args);
}
}
4、启动测试,成功注册到nacos
使用Nacos做配置中心
回看自己写的这篇博客
Springcloud之前是config+bus+github来及进行配置中心设置的,现在直接使用Nacos一个服务就能搞定前面三个的工作了,
1、项目中导入依赖
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
2、配置bootstrap.yml文件
server:
port: 30001
spring:
application:
name: nacos-provider
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
config:
server-addr: 127.0.0.1:8848
file-extension: yml
一定要配置bootstrap.yml文件,系统级别的优先级比application.yml高
配置application.yml
management:
endpoints:
web:
exposure:
incloud: '*'
spring:
profiles:
active: dev # 获取dev的配置
3、Controller 添加注解@RefreshScope,是为了让程序中通过@Value从Nacos配置中心获取的值可以动态刷新
@RestController
//配置支持动态更新
@RefreshScope
public class ProviderController {
@Value("${config.info}")
private String config;
@Value("${server.port}")
private String server_port;
@GetMapping("sayhello")
public String getInfo(){
return "say hello: "+server_port+" config: "+config;
}
}
Nacos的配置文件格式
${prefix}-${spring.profile.active}.${file-extension}
- prefix:默认就是spring.application.name的值,也可以通过配置项:spring.cloud.nacos.config.prefix来配置
- spring.profile.active:为当前环境对应的profile,如果这个为空整个的格式就会变为:${prefix}.${file-extension}
- file-extension:为配置内容的数据格式,可以通过配置项spring.cloud.nacos.config.file-extension来配置,目前支持properties和yaml,不配置的话,默认是properties,官方文档上有说,文件后缀名一定要保持一致
在Nacos新建一个配置
Nacos分组的概念
命名空间 -> 分组 ->服务,可以按照命名空间和组的关系进行相应服务的隔离
默认访问DEFAULT_GROUP,在bootstrap.yml修改访问的组名
server:
port: 30001
spring:
application:
name: nacos-provider
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
config:
server-addr: 127.0.0.1:8848
file-extension: yml
group: DEV_GROUP
Nacos命名空间的概念
默认有一个public的空间
新建一个命名空间gavinspace
在gavinspace新建配置文件
在springboot项目的bootstrap.yml修改访问的命名空间
server:
port: 30001
spring:
application:
name: nacos-provider
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
config:
server-addr: 127.0.0.1:8848
file-extension: yml
namespace: c6de805f-0548-441a-8e6f-f2d87afc3d37
Nacos集群化
首先要考虑的问题,
- 将nacos配置的数据中心化,放到mysql,也可以是mycat。
- 不是所有的节点都对外提供服务的,它需要一个节点来管理Nacos集群,做负载均衡
下面用一台服务器启动3个Nacos实例,当然3台服务器3个Nacos实例也是如此的操作。
1、首先修改conf目录下的cluster.conf.example更改为cluster.conf,并在文件里增加以下内容
[root@helloworld conf]# cp cluster.conf.example cluster.conf
[root@helloworld conf]# vim cluster.conf
# 如果不指定端口,那就是默认的8848
# 注意,这里的ip不能写127.0.0.1,如果是127的话,服务都注册不上
172.16.0.3:8848
172.16.0.3:8858
172.16.0.3:8868
2、配置Mysql数据库
集群模式必须使用MySQL
数据库,生产使用建议至少主备模式
,或者采用高可用数据库
。
-
初始化数据库
在nacos的conf目录下有个脚本文件
nacos-mysql.sql
,创建数据库nacos_config,再执行脚本文件创建表 -
添加数据库连接
在conf目录下的配置文件application.properties中将以下配置填入
spring.datasource.platform=mysql db.num=1 db.url.0=jdbc:mysql://127.0.0.1:3306/nacos_config?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true db.user=root db.password=gavin # db.num 为数据库实例数量 # db.url.0 指定第一个数据库连接 # 如果有多个数据库实例通过 db.url.0、db.url.1… 指定不同的数据库连接
3、修改bin目录下的startup.sh 如下内容,增加ip的输入
[root@helloworld bin]# vim startup.sh
while getopts ":m:f:s:p:" opt
do
case $opt in
m)
MODE=$OPTARG;;
f)
FUNCTION_MODE=$OPTARG;;
s)
SERVER=$OPTARG;;
p)
PORT=$OPTARG;; # 传入端口的参数
?)
echo "Unknown parameter"
exit 1;;
esac
done
在startup.sh 最下面增加脚本,使用命令传入的端口启动Nacos:-Dserver.port=${PORT}
[root@helloworld bin]# vim startup.sh
echo "$JAVA ${JAVA_OPT}" > ${BASE_DIR}/logs/start.out 2>&1 &
nohup $JAVA -Dserver.port=${PORT} ${JAVA_OPT} nacos.nacos >> ${BASE_DIR}/logs/start.out 2>&1 &
echo "nacos is starting,you can check the ${BASE_DIR}/logs/start.out"
4、启动三台Nacos服务,端口要和cluster.conf文件里配置一致
./bin/startup.sh -p 8848
./bin/startup.sh -p 8858
./bin/startup.sh -p 8868
这时随便访问一个nacos实例都是可以的
使用Nginx做负载均衡来访问
修改nginx的配置文件,增加nacos负载均衡的反向代理,默认策略时轮询访问
upstream nacos {
server 127.0.0.1:8848;
server 127.0.0.1:8858;
server 127.0.0.1:8868;
}
server {
listen 80;
server_name localhost;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
root html;
index index.html index.htm;
proxy_pass http://nacos;
}
}
# 关闭nginx
nginx -s stop
# 检查配置文件
nginx -t
# 启动nginx
nginx
访问http://139.199.13.139/nacos/#/login
Nacos的集群总结
- 需要将各个Nacos的配置保存节点数据从各自的Derby数据库移动到中心化的MySQL上
- 在Nacos服务的的conf里cluster.conf文件中配置集群的各个ip和端口
- 启动三个以上的Nacos节点,每个节点都要和cluster文件中配置的ip和端口一致
- 统一使用一个负载均衡节点比如Nginx或HAProxy来进行负载均衡链接Nacos
- 应用服务注册到Nacos,应该访问Nginx的IP来做负载均衡的HA,比如我这里的http://139.199.13.139/nacos
作业:配置一个Nacos集群并将配置数据存储到MySQL中
作业完成:
2、Feign调用删除阿里云视频
任务:edu 服务 feign调用vod服务删除阿里云上的视频
回顾Feign:
- 声明式、模板化、Http客户端! 作用: 微服务之间调用HTTP api!
- Ribbon(负载均衡,客户端),Hystrix (服务降级!) 无缝集成这两个!
1、edu-edu的pom.xml添加依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
2、edu-edu的主启动类添加 Feign的支持注解@EnableFeignClients
@SpringBootApplication
@ComponentScan(basePackages = {"com.jude.edu","com.jude.common"})
@EnableDiscoveryClient
@EnableFeignClients
public class EduApplication {
public static void main(String[] args) {
SpringApplication.run(EduApplication.class,args);
}
}
3、edu-edu的feign接口VodClient
@FeignClient(name = "edu-vod")
public interface VodClient {
// 直接调用服务中的请求
@DeleteMapping("/admin/vod/video/{videoId}")
R removeVideo(@PathVariable("videoId") String videoId);
}
4、edu-edu的业务层接口VideoService
void removeVideoById(String id);
接口实现类VideoServiceImpl
@Autowired
VodClient vodClient;
@Override
public void removeVideoById(String id) {
Video video = this.getById(id);
// 删除oss上的视频
String sourceId = video.getVideoSourceId();
if (!StringUtils.isEmpty(sourceId)){
// 调用vod微服务的方法,删除云端视频
R r = vodClient.removeVideo(sourceId);
if (r.getCode()!= 20000) { // 返回结果不是ok
throw new JudeException(r.getCode(),r.getMessage());
}
}
this.removeById(id);
}
5、edu-eud web层接口的定义
@ApiOperation(value = "根据id删除课时节点")
@DeleteMapping("{id}")
public R deleteById(@ApiParam(name = "id",value = "课时id",required = true) @PathVariable String id){
videoService.removeVideoById(id);
return R.ok();
}
测试服务调用
edu-admin-login也注册到nacos,启动nginx、nacos、edu-admin-login、edu-edu、edu-vod 和 前端后台vue工程edu-admin
xjwdeMacBook:jude-web-admin xjw$ npm run dev
DONE Compiled successfully in 7714ms 15:58:15
I Your application is running here: http://localhost:9528
3、Hystrix服务降级
Spring Cloud 调用接口的过程
Zuul -> Feign -> Hsystix -> Ribbon -> HttpClient,如下图:
1、edu-edu 开启熔断支持
feign.hystrixs.enabled=true
2、edu-edu编写降级方法
@Component
public class VodClientHystrixFallback implements VodClient {
@Override
public R removeVideo(String videoId) {
return R.error().message("服务降级,VodClientHystrixFallback...执行中");
}
}
3、edu-edu的feign接口VodClient添加失败回调
@FeignClient(name = "edu-vod",fallback = VodClientHystrixFallback.class)
public interface VodClient {
// 直接调用服务中的请求
@DeleteMapping("/admin/vod/video/{videoId}")
R removeVideo(@PathVariable("videoId") String videoId);
}
测试
把edu-vod服务关掉,删除视频
区分服务降级和服务熔断
- 服务降级:客户端调用服务无法访问,调用Hystrix的fallback方法,实现服务降级
- 服务熔断:服务端方法异常,调用 @HystrixCommand 的fallbackMethod,快速返回。