Nacos导航
简介
最近都在弄微服务的东西,现在来记录下收获。我从一知半解到现在能从0搭建使用最大的感触有两点
1.微服务各大组件的版本很多,网上很多博客内容不一定适合你的版本,很多时候苦苦琢磨都是无用功
2.网上博客参差不齐,有些甚至错误的。更离谱的是,好的文章阅读量除非高出天际,不然就都很低,比那些复制粘贴,随便应付的都低(这个搜索推荐算法不知道基于什么的)
通过这段时间学习,我觉得最重要是从好的博客入手,先不要着急怎么组件怎么使用,而是先了解组件的作用,大概的原理,然后才是使用,这样搭建和尝试的过程中才能更好的定位问题,最后再次回到原理和一些实际问题的处理(不知道实际问题怎样的,直接搜那个组件的面试题往往效果最好)
接下来的内容,都以导航的形式展现给大家(毕竟优秀的轮子很多,直接看大佬写的不香嘛),再顺带提些自己的理解
传送门
更多微服务的介绍可点击下方链接
微服务介绍、Nginx导航、Nacos导航、Gateway导航、Ribbon导航、Feign导航、Sentinel导航
博主微服务git练手项目:https://github.com/NiceJason/SpringCloudDemo
Nacos介绍
微服务的特点就是一堆服务,那么多的服务如果我们亲自管理那太麻烦了。
例如现在有服务A,B,C各一个,我多添加2个服务A,得分别告诉B,C(具体就是修改B,C的配置或者代码,让它们访问A服务的时候会选择新增A服务的ip地址)
又例如现在A,B,C有些公共配置,好想把他放在一个地方,而不是复制3份,到时候改要3个地方去改,如果增加服务D,还得复制一份
针对上述问题,Nacos闪亮登场,主要负责就两件事:1.服务注册与发现、2.配置中心
具体可看:https://www.jianshu.com/p/02bd37de0221
Nacos作为阿里的一员,是真的简单好用(吹爆阿里系),官网使用文档:https://nacos.io/zh-cn/docs/quick-start.html
分享下自己遇到的坑
1.Nacos与其他框架结合
首先项目中只能选择一种来进行配置
即如果用了Nacos与Spring就不要用Nacos与Springboot和Nacos与SpringCloud
否则会有问题,他们之间的访问方式不同,所以注解等也不能通用(看以后的版本会不会兼容)
spring cloud 暂不支持@NacosXXX相关注解
要用spring cloud 要自己想办法解决问题,如果实现解决不了,就放弃,改用Springboot结合或者与Spring结合的类型
当时花了我不少时间去研究为什么注解不生效(毕竟注解这么方便嘤嘤嘤),结果是人家压根不支持SpringCloud
2.单机的Nacos固定ip启动
在conf配置文件下修改,这样单机ip就不会变了,不然经常变导致代码访问的ip得经常改,十分麻烦
3.Nacos配置
Nacos相关配置说明:https://www.jianshu.com/p/1bd0c1f7c581
有两个配置单独说下:
1 #Nacos服务端的地址,该服务向NACOS注册 2 spring.cloud.nacos.discovery.server-addr 3 4 #本服务注册的IP地址 优先级最高,意思是别的服务调用该服务所指的地址 5 spring.cloud.nacos.discovery.ip
这两个配置主要涉及到开发的问题,一般来说开发环境会部署一个Nacos(你们项目组或产品线公用这个Nacos),这样的好处在于联调方便,而且不用每个人都自己再部署nacos以及配置文件。当项目部署的时候,会在docker指定不同环境的nacos地址(意思是docker启动的时候可以动态修改参数)
现在有两种情况
a.我要开发其他功能,该功能和微服务无关,那此时就要本地的配置要指定spring.cloud.nacos.discovery.ip为开发环境里的ip,因为如果不指定,那么Nacos里服务就注册你本机的ip,别的小伙伴调用的时候有可能就会访问到你启动的项目
b.我要开发微服务功能,此时可以通过nacos的命名空间去区分你本机自己微服务联调
4.Nacos与SpringCloud结合常用类
//由于大多数注解都无效,所以要使用NacosConfigManager进行操作 @Autowired NacosConfigManager nacosConfigManager; //这个有值 @Autowired private NacosDiscoveryProperties nacosDiscoveryProperties; //这个有值 @Autowired NacosServiceManager nacosServiceManager;
想要代码里动态操作Nacos,用上面3个类就行,直接注入即可
Nacos刷新
Nacos刷新原理:
文章根据源码,介绍了Nacos是怎么更新列表和动态刷新配置的(主要是和Ribbon结合)
这里我想提两点
懒加载
看过上面原理,可以看到Nacos是怎么懒加载的
1 protected AnnotationConfigApplicationContext createContext(String name) { 2 AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); 3 ... 4 for (Map.Entry<String, C> entry : this.configurations.entrySet()) { 5 if (entry.getKey().startsWith("default.")) { 6 for (Class<?> configuration : entry.getValue().getConfiguration()) { 7 //这里注册了NacosRibbonClientConfiguration.class 8 context.register(configuration); 9 } 10 } 11 } 12 //这里注册了RibbonClientConfiguration.class 13 context.register(PropertyPlaceholderAutoConfiguration.class, 14 this.defaultConfigType); 15 //这里设置了ribbon.nacos.enabled的值 16 context.getEnvironment().getPropertySources().addFirst(new MapPropertySource( 17 this.propertySourceName, 18 Collections.<String, Object>singletonMap(this.propertyName, name))); 19 if (this.parent != null) { 20 // Uses Environment from parent as well as beans 21 context.setParent(this.parent); 22 // jdk11 issue 23 // https://github.com/spring-cloud/spring-cloud-netflix/issues/3101 24 context.setClassLoader(this.parent.getClassLoader()); 25 } 26 context.setDisplayName(generateDisplayName(name)); 27 //最后刷新上下文,将RibbonClientConfiguration.class 28 //和RibbonClientConfiguration.class重新加载 29 context.refresh(); 30 return context; 31 }
其中NacosRibbonClientConfiguration(代码第七行)上有注解ConditionalOnRibbonNacos,而ConditionalOnRibbonNacos上有注解
以此我们可以参考懒加载的实现,或者是动态刷新某些组件
动态刷新的局限
Nacos确实支持动态刷新,但这只是动态刷新值,并不会刷新代码的逻辑,对于有很多初始化的类和组件都是无用的,可以监听Nacos配置变化来再次初始化这些类,从而达到真正的动态刷新
1 //由于大多数注解都无效,所以要使用NacosConfigManager进行操作 2 @Autowired 3 NacosConfigManager nacosConfigManager; 4 5 @PostConstruct 6 public void init() throws NacosException { 7 ConfigService configService = nacosConfigManager.getConfigService(); 8 9 configService.publishConfig("动态发布配置ID","动态发布配置goup","动态发布内容"); 10 11 configService.addListener("user-service-dev.properties", "dev", new Listener() { 12 //这里正常的写法应该是传个线程池进来,不然每次监听到文件改动,都要重新建立线程,开销大 13 @Override 14 public Executor getExecutor() { 15 return new Executor() { 16 @Override 17 public void execute(Runnable command) { 18 command.run(); 19 } 20 }; 21 } 22 23 @Override 24 public void receiveConfigInfo(String configInfo) { 25 System.out.println("监听者获取到信息"+configInfo); 26 } 27 }); 28 }
每次最小单位都是以文件为准,Nacos会把改动的文件全部内容传回去,而不是只传被改动的那几个
小结
本篇博客主要说了Nacos注意的点(这些内容有的网上可不好找,也没人告诉你),具体怎么搭建使用网上很多资料,希望能帮到大家