zoukankan      html  css  js  c++  java
  • 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刷新原理:

    https://so.csdn.net/so/search/blog?q=nacos%E5%AE%A2%E6%88%B7%E7%AB%AF%E8%A7%A6%E5%8F%91%E6%9C%8D%E5%8A%A1%E5%88%B7%E6%96%B0%E5%8E%9F%E7%90%86&t=blog&p=1&s=0&tm=0&lv=-1&ft=0&l=&u=wangwei19871103

    文章根据源码,介绍了Nacos是怎么更新列表和动态刷新配置的(主要是和Ribbon结合)

    这里我想提两点

    懒加载

    看过上面原理,可以看到Nacos是怎么懒加载的

    发现在其第一次用restTemplate发送请求时(请求一直会到Ribbon包下的SpringClientFactory中,调用SpringCloud包下的NamedContextFactory),动态创建了AnnotationConfigApplicationContext,进行上下文的刷新,将配置动态注入了Spring中
    NamedContextFactory中创建AnnotationConfigApplicationContext
     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注意的点(这些内容有的网上可不好找,也没人告诉你),具体怎么搭建使用网上很多资料,希望能帮到大家

    学习和点赞一样,可不能下次一定啊! 感谢你的三连~
  • 相关阅读:
    C#中将全部代码一次性折叠
    C#中图片单击旋转事件
    块参照重命名
    补强圈设计
    c# winform 按名称取得控件
    获得某控件的父控件(容器)中的所有控件
    回车键当Tab键使用
    替换CAD中原有命令为开发人员自己开发的命令的方法
    窗体设置
    判断控件的tag是否为空的方法
  • 原文地址:https://www.cnblogs.com/top-housekeeper/p/14785329.html
Copyright © 2011-2022 走看看