nacos小结

nacos

启动服务器

  • Linux/Unix/Mac

启动命令(standalone代表着单机模式运行,非集群模式):

sh startup.sh -m standalone

如果您使用的是ubuntu系统,或者运行脚本报错提示[[符号找不到,可尝试如下运行:

bash startup.sh -m standalone
  • Windows

启动命令(standalone代表着单机模式运行,非集群模式):

startup.cmd -m standalone

​ ps:需要在bin目录下运行该命令,之后访问:http://localhost:8848/nacos,关闭时直接关闭cmd窗口就行

测试(OPEN API配置管理测试)

​ curl是一个命令行工具,用于http协议的测试,下载地址(windows):https://curl.haxx.se/windows/

  1. 发布配置

    curl -X POST "http://127.0.0.1:8848/nacos/v1/cs/configs?dataId=nacos.cfg.dataId&group=test&content=LaLaLa"

  2. 获取配置

    curl -X GET "http://127.0.0.1:8848/nacos/v1/cs/configs?dataId=nacos.cfg.dataId&group=test"

    结果如下:

    D:\curl\curl-7.74.0_2-win64-mingw\bin>curl -X GET "http://127.0.0.1:8848/nacos/v1/cs/configs?dataId=nacos.cfg.dataId&group=test"
    LaLaLa
    

    获取到了LaLaLa

编写程序获取配置
  1. 依赖

    <dependency>
                <groupId>com.alibaba.nacos</groupId>
                <artifactId>nacos-client</artifactId>
                <version>1.3.2</version>
    </dependency>
    

功能

  • 服务发现与服务健康检查

    服务发现不用说了(DNS、http访问),还提供服务的实时健康检查,防止像不健康的服务实例发送请求。

  • 动态配置管理

    消除了在更新配置时重新部署应用程序,这使配置的更改更加的高效、灵活

  • 动态DNS服务

    第一点提到的提供支持DNS的服务发现,旨在支持异构语言的服务发现,以域名的形式暴露,让三方应用方便的查阅

  • 服务和元数据管理

    管理数据中心的所有服务及元数据,包括服务的描述、生命周期、服务的静态依赖分析、服务的健康状态、服务的流量管理、路由及安全策略

针对微服务架构中的服务发现(已经用过)、配置管理(微服务架构中的配置中心)、服务治理的综合型解决方案。

ps:配置中心是对应用程序的配置进行一个统一管理,同一程序在不同的环境(开发、测试、生产)、不同集群(这个是什么,是多个注册中心的意思?比如eureka?)经常需要有不同的配置,所以需要有配置管理。

其他配置中心

市面上其他的主流的配置中心:springcloud config、Apollo、nacos和Disconf等(这个不再维护)。

对比springcloud configApollonacos
配置实时推送支持(springcloud bus)支持(http长轮询1s内)支持(http长轮询1s内)
版本管理支持(git),我知道支持支持
配置回滚支持(git)支持支持
灰度发布支持支持不支持
权限管理支持(依赖git)支持不支持
多集群支持支持支持
多环境支持支持支持
监听查询支持支持支持
语言只有Java主流语言,提供了Open API主流语言,提供了Open API
配置格式校验不支持支持支持
单机读(QPS)7(限流所致)900015000
单机写(QPS)5(限流所致)11001800
3节点读(QPS)21(限流所致)2700045000
3节点写(QPS)5(限流所致)33005600

ps:Apollo的功能完善;nacos的性能最好,优势是整合了注册中心、配置中心,推荐nacos与Apollo

配置管理

nacos的配置管理,通过namespace、group、Data Id能够定位到一个配置文件。

配置集(Data Id)

一个配置文件就是一个配置集

配置项

存在于配置集中,以key=value的形式存在

配置分组(group)

对配置集进行分组,通过一个又意义的字符串(如buy或trade)来表示,不同的配置分组下可以有相同的配置文件,在创建配置时,若未填写配置分组的名称,默认采用DEFAULT_GROUP。

命名空间(namespace)

用于进行不同环境的配置隔离:开发环境、测试环境和生产环境。也可用于隔离不同的开发人员(用同一个nacos管理各自的配置)。不同的命名空间下,可以存在相同名称的配置分组或配置文件。

  • 从一个用户的角度来看:开发、测试、生产环境

在这里插入图片描述

  • 从多个用户(租户)的角度来看,每个用户可能有自己的namespace,每个用户的配置数据以及注册的服务数据都会归属到自己的namespace下。如超级管理员分配了三个用户:掌三、里斯、亡吾,各用户用自己的账号密码登录后,创建自己的namespace,如下

  • 命名空间管理

    某公司拥有开发、测试、生产三套环境,那么建立三个namespace,建立好之后,在配置管理服务管理模块下所有页面,都会包含用于切换namespace的tab按钮,如下:

    在这里插入图片描述

    ps:public是默认的命名空间

配置文件的导出和导入(也可以克隆)

是界面操作,省略呵呵

配置文件回滚(历史版本不包含当前版本)

省略呵呵

监听

当配置信息发生变化的时候,nacos的服务端(注册中心)去通知客户端(正在运行中)

结果:

"C:\Program Files\Java\jdk1.8.0_45\bin\java.exe" "-javaagent:D:\Idea\IntelliJ IDEA 
common:
  config1:somethinglll
common:
  config1:somethinghhh

打印出了更改后的配置

登录管理
  1. 修改密码

    • 导入依赖

      <dependency>
                  <groupId>org.springframework.security</groupId>
                  <artifactId>spring-security-core</artifactId>
                  <version>5.1.4.RELEASE</version>
      </dependency>
      
    • 加密程序(这应该是MD5加密吧)

      //该程序会在每次生成密码时会加随机盐,所以生成密码每次可能不一样
      String encode = new BCryptPasswordEncoder().encode("123");
      

      密码就是123,在数据库不是123

    • 创建用户名和密码的时候,将上方的encode更新到数据库

      insert into users(username,password,enabled)values('nacos2','$2a$10$nMR1p1Agm9ZzlCEh.22Sj.r5ekpnaIdbr0wxmOS3WUeVaE4vR9u2e,true');
      insert into roles(username,role)values('nacos2','ROLE_ADMIN');  --管理员角色
      
  2. 可以将登录功能关闭

    spring.security.enabled=false #这个是spring的认证
    management.security=false
    security.basic.enabled=false
    nacos.security.ignore.urls=/**
    

    替换以上内容(如果没有应该可以增加)

应用于分布式系统(important!)

单体应用的坏处:

  • 复杂性逐渐变高,可维护性逐渐变差:业务模块都在一起,复杂度越来越高,修改时牵一发动全身
  • 版本迭代速度逐渐变慢:修改局部,需要将整个应用编译、部署,启动时间过长
  • 阻碍技术更新:若更新技术框架只能将系统全部重写,无法实现部分技术更新
  • 无法按需伸缩:通过冗余部署完整应用的方式来实现水平扩展,无法针对某业务按需伸缩

区别于单体应用,一个微服务一般完成某个特定的功能,比如订单服务、用户服务等等。每一个微服务都是完整的应用,都有自己的业务逻辑和数据库,一些微服务还会发布API给其他微服务和客户端使用。

微服务的好处:

  • 分而治之,易于团队的拆分和管理
  • 可伸缩,能够单独对指定服务进行伸缩
  • 局部容易修改,容易替换、部署,有利于持续集成和快速迭代
  • 不会受限于任何技术栈
  1. 架构

    在这里插入图片描述

  2. 发布配置

    两个服务:sevice1、service2

    service1

    namespace: dev
    dataId: service1.yaml
    group: TEST_GROUP
    格式:yaml
    内容:common:
    	   name: service1_config
    

    service2

    namespace: dev
    dataId: service2.yaml
    group: TEST_GROUP
    格式:yaml
    内容:common:
    	   name: service2_config
    
  3. 父工程的主要依赖

    <!--打包方式-->
        <packaging>pom</packaging>
        <properties>
            <spring-cloud.version>Edgware.SR4</spring-cloud.version>
            <spring-cloud-alibaba.version>1.5.0.RELEASE</spring-cloud-alibaba.version>
    
            <project.build.sourceEncoding>utf8</project.build.sourceEncoding>
            <maven.compiler.source>1.8</maven.compiler.source>
            <maven.compiler.target>1.8</maven.compiler.target>
            <junit.version>4.12</junit.version>
            <lombok.version>1.16.18</lombok.version>
            <log4j.version>1.2.17</log4j.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>${spring-cloud-alibaba.version}</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
    
                <!--springboot的依赖  因为springcloud的版本是Edgware.SR4-->
                <dependency>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-dependencies</artifactId>
                    <version>1.5.3.RELEASE</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
    
                <dependency>
                    <groupId>mysql</groupId>
                    <artifactId>mysql-connector-java</artifactId>
                    <version>5.1.47</version>
                </dependency>
                <!--数据源-->
                <dependency>
                    <groupId>com.alibaba</groupId>
                    <artifactId>druid</artifactId>
                    <version>1.1.10</version>
                </dependency>
                <!--springboot启动器-->
                <dependency>
                    <groupId>org.mybatis.spring.boot</groupId>
                    <artifactId>mybatis-spring-boot-starter</artifactId>
                    <version>1.1.1</version>
                </dependency>
                <!--单元测试  日志-->
                <dependency>
                    <groupId>ch.qos.logback</groupId>
                    <artifactId>logback-core</artifactId>
                    <version>1.2.3</version>
                </dependency>
                <dependency>
                    <groupId>junit</groupId>
                    <artifactId>junit</artifactId>
                    <version>${junit.version}</version>
                </dependency>
                <dependency>
                    <groupId>org.projectlombok</groupId>
                    <artifactId>lombok</artifactId>
                    <version>${lombok.version}</version>
                </dependency>
                <dependency>
                    <groupId>log4j</groupId>
                    <artifactId>log4j</artifactId>
                    <version>${log4j.version}</version>
                </dependency>
            </dependencies>
        </dependencyManagement>
    
  4. 微服务service1配置

    springcloud简介:

    利用springboot巧妙地简化了分布式系统基础设施得到开发,如服务注册发现、配置中心、断路器等,springcloud没有重复地造轮子,将各家公司比较成熟的框架组合起来,集成最多的要数Netflix公司,最终留下了一套简单易懂、易部署和维护的分布式系统开发工具包

    springcloud alibaba:

    springcloud alibaba是遵循springcloud微服务套件的标准所开发的一套微服务框架的集合。所以,springcloud alibaba和springcloud Netflix是springcloud微服务标准的实现,如果用springcloud alibaba,只需要加一些注解和少量配置,就可以将springcloud应用接入springcloud alibaba这一套方案,通过阿里的中间件来搭建分布式应用系统,nacos就是阿里的中间件,因此,开发springcloud微服务应用,使用springcloud alibaba来集成nacos的配置管理功能比较好。

    1)依赖

    <dependencies>
    	<dependency>
    		<groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
    	</dependency>
    	<dependency>
    		 <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-web</artifactId>
    	</dependency>
    </dependencies>
    

    2)bootstrap.yml

    因为使用了外部的配置中心,同时因为bootstrap.yml的优先级高于application.yml,所以此处使用bootstrap.yml

    server:
      port: 56010
      
    spring:
      application: 
        name: service1
      cloud:
        nacos:
          config:
            server-addr: 127.0.0.1:8080 #配置中心地址,也是注册中心
            file-extension: yaml #dataId是配置文件的名称,是application.name+扩展名(file-extension)                                        #如service1.yaml  准确的说应该是${prefix}-${spring.profiles.active}.${file-							  #extension}
            namespace: e12e455c-c01e-4c0e-bb8b-e30b286434f9 #dev环境的id
            group: TEST_GROUP #测试组
    

    3)动态获取更新的配置

     @Autowired
     ConfigurableApplicationContext applicationContext;
     applicationContext.getEnvironment().getProperty("common.name");
    

    小结:有问题可以去翻看日志,包括因手速过快拼错单词的问题

  5. 对在yml中配置时的namespace、group和dataId的理解

    1)namespace:在没有指定spring. cloud.nacos. config. namespace时,默认是public命名空间。

    2)group:在没有指定spring. cloud.nacos. config. group`时,默认是DEFAULT_GROUP组。

    ​ ps:两者指定内容时必须在bootstrap.yml/properties文件中,原因上文有提到

    3)dataId:${prefix}-${spring.profiles.active}.${file-extension}

    • prefix 默认为 spring.application.name 的值,也可以通过配置项 spring.cloud.nacos.config.prefix来配置。

    • spring.profiles.active 即为当前环境对应的 profile,详情可以参考 Spring Boot文档注意:当 spring.profiles.active 为空时,对应的连接符 - 也将不存在,dataId 的拼接格式变成 ${prefix}.${file-extension}

    • file-exetension 为配置内容的数据格式,可以通过配置项 spring.cloud.nacos.config.file-extension 来配置。目前只支持 propertiesyaml 类型。

      放置多个dataId(在一个微服务里增加配置文件)

      spring:
        application:
          name: service1
        cloud:
          nacos:
            config:
              server-addr: 127.0.0.1:8848 #配置中心地址,也是注册中心
              #增加的dataId在DEFAULT_GROUP,不支持动态刷新
              ext-config[0]:
              	data-id: ext-config-common01.properties
              #增加的dataId在GLOABLE_GROUP,不支持动态刷新
              ext-config[1]:
              	data-id: ext-config-common02.properties
              	group: GLOABLE_GROUP
              #增加的dataId在REFRESH_GROUP,支持动态刷新
              ext-config[2]:
              	data-id: ext-config-common03.properties
              	group: REFRESH_GROUP
              	refresh: true
      

      共享dataId(在多个微服务间共享dataId,不常用,只支持DEFAULT_GROUP)

      spring:
        application:
          name: service1
        cloud:
          nacos:
            config:
            	shared-dataids: ext-config-common01.properties,ext-config-common02.properties,ext-config-common03.properties
            	refreshable-dataids: ext-config-common01.properties
      

      shared-dataids共享dataId,refreshable-dataids可动态刷新的配置。多个配置文件都可用“,”隔开。

  6. 配置的优先级

    三种从nacos获取配置文件的方式

    1)根据${prefix}-${spring.profiles.active}.${file-extension}自动生成dataId

    2)ext-config[n]增加多个dataId,此处的优先级是n值越大,优先级越高(应该是覆盖导致的)

    3)shared-dataids配置共享dataId(不推荐)

    当上方三种方式一起使用的时候,优先级:1)> 2)> 3)

  7. 关闭配置

    设置spring. cloud.nacos. config.enabled = false来关闭配置

推荐的实践

namespace:代表环境,如:开发环境、测试环境和生产环境。

group:代表某项目,如xx电商项目。

Data Id:每个项目下往往有若干个工程,每个配置集(Data Id)是一个工程的主配置文件。

nacos集群部署

  1. 集群(3个及以上nacos节点才能构成集群)

    1)复制原来的nacos文件夹即可

    2)设置集群配置文件

    ​ 在nacos的conf目录下,有cluster.conf.example,将其命名为cluster.conf,并且在文件里设置好ip:port。

    # ip:port
    127.0.0.1:8848
    127.0.0.1:8849
    127.0.0.1:8850
    

    ps:这是单机的演示,同时需要更改nacos的conf目录下application.properties中的端口,防止端口冲突。

    ​ 如果服务器有多个ip也要指定具体的ip地址,如:nacos.inetutils.ip-address=127.0.0.1(绑定nacos的ip地址,在nacos的application.properties配置中有这个参数,因为我的电脑或者是服务器ip地址可能是多个)

    ​ 像这样:

    server.port=8850
     nacos.inetutils.ip-address=127.0.0.1
    

    3)在生产环境是这样的:

    在这里插入图片描述

    ​ 生产环境的数据库至少主备模式,能够使nacos拥有多个数据源,如下:

    ### Count of DB:
     db.num=2
    
    ### Connect URL of DB:
     db.url.0=jdbc:mysql://127.0.0.1:3306/nacos?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC
      db.url.1=jdbc:mysql://127.0.0.1:3306/nacos?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC
     db.user=root
     db.password=root
    

nacos配置管理小结

nacos配置管理主要是应用于微服务架构中配置中心的构建(应该是springcloud config的一种替代)

服务注册与发现

对比
功能nacoseurekaconsulzookeeper
一致性协议支持AP、CPAPCPCP
健康检查tcp/http/mysql/client beatclient beattcp/http/grpc/cmdkeep alive
负载均衡权重/metadata/selectorribbonfabio-
雪崩保护
自动注销实例支持支持不支持支持
访问协议http/dnshttphttp/dnstcp
监听支持支持支持支持支持
多数据中心支持支持支持不支持
跨注册中心同步支持不支持支持不支持

nacos以后将会支持springcloud+kubernetes(这是啥,百度百科:简称K8s,是一个开源的,用于管理云平台中多个主机上的容器化的应用,Kubernetes的目标是让部署容器化的应用简单并且高效,Kubernetes提供了应用部署,规划,更新,维护的一种机制)的组合

架构

不罗嗦了呵呵

回顾springcloud的服务发现

springcloud是使用feign+ribbon技术来实现服务间远程调用及负载均衡的,如图:

在这里插入图片描述

  1. 负载均衡就是将用户请求通过策略,分摊到多个服务实例上执行,是处理高并发、缓解网络压力和进行服务端扩容的重要手段,分为服务端负载均衡和客户端负载均衡

    • 服务端负载均衡

    在这里插入图片描述

    在负载均衡中维护一个服务清单,按照配置好的负载均衡算法(可以是默认的)选取一个去处理客户端的请求,这是服务端的负载均衡。以前老听到的nginx就是一个负载均衡的代理。

    • 客户端负载均衡

    在这里插入图片描述

    ribbon属于客户端负载均衡,在ribbon客户端有一个服务注册表,在发送请求前通过负载均衡算法选择一个服务,然后进行访问,这是客户端负载均衡。

    ribbon的核心是IRule,它是负载均衡策略接口,有如下实现(了解):

    实现类描述
    RoundRobinRule(默认)轮询,按顺序获取服务地址
    RandomRule随机,随机获取服务地址
    AvailabilityFilteringRule先过滤因为多次访问故障而处于断路器跳闸状态的服务和并发的连接数量超过阈值的服务,然后对剩余的服务按照轮询的策略进行访问
    WeightedResponseTimeRule根据平均响应时间计算所有服务的权重,响应时间越快,权重越大,被选中的几率越高;杠启动时,如果统计的信息不足,则使用RoundRobinRule(默认),等统计信息足够时,会切换到WeightedResponseTimeRule
    RetryRule先按照RoundRobinRule(默认)获取服务,如果获取失败,则在指定时间内会进行重试,获取可用服务
    BestAvailableRule先过滤因为多次访问故障而处于断路器跳闸状态的服务,然后选择一个并发量最小的服务
    ZoneAvoidanceRule默认规则,复合判断server所在区域的性能和server的可用性选择服务器(服务器?就这里不明白,应该是服务的意思)

    springboot修改默认的负载均衡策略(配置文件)

    xxx-service.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RandomRule

    ps:xxx-service是调用服务的名称,后面是固定的

  2. 远程调用。回顾之前写springcloud程序的时候使用的是RestTemplate去远程调用服务的,现在feign将其进一步简化。feign,它是声明式、模板化的http客户端,将http报文封装成了java接口,可快捷使用http协议。

    1)依赖

     <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-openfeign</artifactId>
     </dependency>
    

    ps:feign默认集成了ribbon,可以直接使用。

    2)声明feign客户端

    @FeignClient(value = "provider1")//服务提供方的名字
    public interface Provider1Agent{//生成动态代理对象
    
    	@GetMapping(value = "/service")
    	public String service();
    }
    

    3)业务调用

    @Autowired
    private Provider1Agent provider1Agent;
    ......
    

    4)在启动类(springcloud)中添加@EnableFeignClients,表明此项目开启feign客户端

    @SpringBootApplication
    @EnableDiscoveryClient
    @EnableFeignClients
    public class xxxx{
    	main函数
    }
    
    服务提供与消费实例
    1. provider1

      • 依赖

        <dependency>
                    <groupId>com.alibaba.cloud</groupId>
                    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <dependency>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
                    <groupId>org.springframework.cloud</groupId>
                    <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        
      • application.yml

        server:
          port: 56010
        
        spring:
          application:
            name: provider1
          cloud:
            nacos:
              discovery:
                server-addr: 127.0.0.1:8848
        logging:
          level:
            root: info
            org.springframework: info
        
      • 注解

        @EnableDiscoveryClient
        @EnableFeignClients
        @SpringBootApplication
        

        ps:期间有一个小问题,LoggerFactory.getLogger这个静态方法idea不提示,在yml配置文件里面也没有提示,应该是idea的一个bug

    2. consumer

      • 依赖和上面一致,application如下:

        server:
          port: 56020
        
        spring:
          application:
            name: consumer
          cloud:
            nacos:
              discovery:
                server-addr: 127.0.0.1:8848
        
      • Client接口

        @FeignClient("provider1")
        public interface Client {
        
            @GetMapping("/service")
            public String service();
        }
        
      • controller如下:

        @RestController
        public class ConsumerController {
        
            @Autowired
            Client client;
        
            @GetMapping("/service")
            public String service(){
                //调用provider1里面的controller
                String result = client.service();
                return "consumer调用:"+result;
            }
        }
        
      • 启动类与提供者一致

    3. 多个提供者负载均衡

      • 端口
      server:
        port: ${port:56010} #动态端口,启动是没有传入下方的参数就默认56010
      

      ​ VM options:-Dport=56011

      ​ 重这样就给provider1创建了两个服务(实例),相当于有provider2,因为启动了两次provider1

服务注册的模型

在这里插入图片描述

  • 服务

    提供的功能

  • 服务名

    通过该标识可以唯一确定其指代的服务

  • 实例(ip+port)

    可访问的进程,启动一个服务,就产生了一个服务实例

  • 元信息

    nacos数据(如配置和服务)描述信息,如服务版本、权重、容灾策略、负载均衡策略、鉴权配置、自定义标签,从作用范围来看分为服务级别的元信息、集群的元信息和实例的元信息。

    ps:元信息能够让nacos更具备扩展性,用户可自定义数据英语描述实例、服务、集群等

  • 集群

    服务实例的集合,服务实例组成一个默认集群,集群可以被进一步按需求划分,划分的单位可以是虚拟集群,相同集群下的实例才能相互感知。

    应用通过namespace、service、cluster(集群)的配置,描述了该服务向哪个环境(如开发环境)的哪个集群注册实例。

    集群作为实例的隔离,相同集群的实例才能相互感知。namespace、cluster-name若不填写都将采取默认值,namespace默认public,cluster-name默认为DEFAULT集群,如下用provider1开启两个端口的实例集群

    在这里插入图片描述

    将consumer注册到dev里面

    server:
      port: 56020
    
    spring:
      application:
        name: consumer
      cloud:
        nacos:
          discovery:
            server-addr: 127.0.0.1:8848
            namespace: e12e455c-c01e-4c0e-bb8b-e30b286434f9 #dev
            cluster-name: DEFAULT #默认集群,可不写
    
服务管理
  1. 权重

    代表了被选中的几率越高

  2. 元数据

    用户自定义信息,key-value的结果

  3. 下线(与权重为零一样的)

    如其名,略

springcloud、springcloud alibaba与dubbo

之前总结过springcloud与dubbo的区别,简言之,springcloud的功能比dubbo完善,使用dubbo同时想有springcloud的生态,但是二者整合起来的使用方案还是不完善,springcloudalibaba解决了这个问题。

ps:feign是基于http restful的调用,在高并发下的性能不够理想,想将rpc方案切换为dubbo(在微服务的设计中,一个服务A如果访问另一个Module下的服务B,可以采用HTTP REST传输数据,并在两个服务之间进行序列化和反序列化操作,服务B把执行结果返回过来。由于HTTP在应用层中完成,整个通信的代价较高,远程过程,即rpc,调用中如果直接基于TCP进行远程调用,数据传输在传输层TCP层完成,更适合对效率要求比较高的场景,RPC主要依赖于客户端和服务端之间建立Socket链接进行,底层实现比REST更复杂。)

架构(推荐的生产环境):

在这里插入图片描述

dubbo底层采用socket(tcp或udp)进行通信,所以相比http可以提升效率

zuul(springcloud的网关)

Zuul是一个微服务网关,首先是一个微服务。也是会在注册中心中进行服务的注册和发现。也是一个网关,请求应该通过Zuul来进行路由。

zuul网关其底层使用ribbon来实现请求的路由,并内置Hystrix,可选择性提供网关fallback逻辑。使用zuul的时候,并不推荐使用Feign作为application client端的开发实现。毕竟Feign技术是对ribbon的再封装,使用Feign本身会提高通讯消耗,降低通讯效率,只在服务相互调用的时候使用Feign来简化代码开发就够了。而且商业开发中,使用Ribbon+RestTemplate来开发的比例更高

工程结构
  • springcloud_nacos 原来的父工程

    • nacos-micro-service 整体父工程
      • gateway API网关,端口:56010
      • application1 应用1,端口:56020 对外暴露http接口
      • service-1 服务1父工程 对外暴露dubbo接口
        • service-1-api 服务1API
        • service-1-server 服务1实现,端口56030
      • service-2 服务2父工程 对外暴露dubbo接口
        • service-2-api 服务2API
        • service-2-server 服务2实现,端口56040
构建过程
  1. 整体父工程依赖

    <parent>
            <artifactId>springcloud_nacos</artifactId>
            <groupId>com.yyh</groupId>
            <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>nacos-micro-service</artifactId>
    <packaging>pom</packaging>
    
  2. application1

    依赖

     <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
     </dependency>
     <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
     </dependency>
     <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
     </dependency>
    

    配置文件

    server:
      port: 56020 #http的端口
      context-path: /application1
    spring:
      application:
        name: application1
      cloud:
        nacos:
          discovery:
            server-addr: 127.0.0.1:8848
            namespace: e12e455c-c01e-4c0e-bb8b-e30b286434f9 #dev
            cluster-name: DEFAULT
          config:
            server-addr: 127.0.0.1:8848
            file-extension: yaml
            namespace: e12e455c-c01e-4c0e-bb8b-e30b286434f9 #dev
            group: NACOS_MICROSERVICE_GROUP #xx业务组
    

    业务代码:

    @RestController
    public class Application1Controller {
    
        @GetMapping
        public String service(){
            return "test";
        }
    }
    
  3. service-1

    • service-1-api

      接口:

      public interface ConsumerService {
          
          public String service();
          
      }
      
    • service-1-server

      依赖

             <dependency>
                  <groupId>com.yyh</groupId>
                  <artifactId>service-1-api</artifactId>
                  <version>1.0-SNAPSHOT</version>
              </dependency>
              <dependency>
                  <groupId>com.alibaba.cloud</groupId>
                  <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
              </dependency>
              <dependency>
                  <groupId>com.alibaba.cloud</groupId>
                  <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
              </dependency>
              <dependency>
                  <groupId>com.alibaba.cloud</groupId>
                  <artifactId>spring-cloud-alibaba-dubbo</artifactId>
                  <version>2.1.1.RELEASE</version>
              </dependency>
      

      途中遇到个问题,dubbo的依赖最少2.0.0,idea无法自动识别添加依赖,需要自己去添加版本

      在这里插入图片描述

      接着出现另一个问题:

      java.lang.NoSuchMethodError: org.springframework.boot.SpringApplication.getWebApplicationType()Lorg/springframework/boot/WebApplicationType;
      

      ​ dubbo2.7及以上在apache,以下在alibaba,因为我时springboot1.5x,我只能用2.7以下,so,我好像明白了,那么相应的 starter也只能是alibaba的starter。

      ​ 参考文章:springboot与dubbo版本匹配问题

      把下方

      <dependency>
          <groupId>com.alibaba.cloud</groupId>
          <artifactId>spring-cloud-alibaba-dubbo</artifactId>
          <version>2.0.1.RELEASE</version>
      </dependency>
      

      换成

      <dependency>
          <groupId>com.alibaba</groupId>
          <artifactId>dubbo</artifactId>
          <version>2.6.5</version>
      </dependency>
      <dependency>
          <groupId>com.alibaba.boot</groupId>
          <artifactId>dubbo-spring-boot-starter</artifactId>
          <version>0.1.2.RELEASE</version>
      </dependency>
      <dependency>
          <groupId>com.alibaba</groupId>
          <artifactId>dubbo-registry-nacos</artifactId>
          <version>2.6.7</version>
      </dependency>
      
      

      终于ok了,555555555555,但是还是不够兼容,服务名无法更改(显示的是ConsumerServiceImpl的路径)

      再换

      		<dependency>
                  <groupId>org.apache.dubbo</groupId>
                  <artifactId>dubbo</artifactId>
                  <version>2.7.1</version>
              </dependency>
              <dependency>
                  <groupId>org.apache.dubbo</groupId>
                  <artifactId>dubbo-spring-boot-starter</artifactId>
                  <version>2.7.1</version>
              </dependency>
              <dependency>
                  <groupId>org.apache.dubbo</groupId>
                  <artifactId>dubbo-registry-nacos</artifactId>
                  <version>2.7.1</version>
              </dependency>
      

      然后。。。

      java.lang.NoClassDefFoundError: com/alibaba/nacos/client/naming/utils/StringUtils
      

      最后索性将爷爷的依赖拿到父级去,提高springcloud alibaba(1.5->2.1.0)、springcloud(Edgware.SR4->Greenwich.RELEASE)和springboot(1.5.3->2.1.3)的版本,问题大致上解决,虽然算不上好方法,但是问题大致解决

      	 <properties>
              <spring-cloud.version>Greenwich.RELEASE</spring-cloud.version>
              <spring-cloud-alibaba.version>2.1.0.RELEASE</spring-cloud-alibaba.version>
      
              <project.build.sourceEncoding>utf8</project.build.sourceEncoding>
              <maven.compiler.source>1.8</maven.compiler.source>
              <maven.compiler.target>1.8</maven.compiler.target>
              <junit.version>4.12</junit.version>
              <lombok.version>1.16.18</lombok.version>
              <log4j.version>1.2.17</log4j.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>${spring-cloud-alibaba.version}</version>
                      <type>pom</type>
                      <scope>import</scope>
                  </dependency>
      
                  <!--springboot的依赖-->
                  <dependency>
                      <groupId>org.springframework.boot</groupId>
                      <artifactId>spring-boot-dependencies</artifactId>
                      <version>2.1.3.RELEASE</version>
                      <type>pom</type>
                      <scope>import</scope>
                  </dependency>
      
                  <dependency>
                      <groupId>mysql</groupId>
                      <artifactId>mysql-connector-java</artifactId>
                      <version>5.1.47</version>
                  </dependency>
                  <!--数据源-->
                  <dependency>
                      <groupId>com.alibaba</groupId>
                      <artifactId>druid</artifactId>
                      <version>1.1.10</version>
                  </dependency>
                  <!--springboot启动器-->
                  <dependency>
                      <groupId>org.mybatis.spring.boot</groupId>
                      <artifactId>mybatis-spring-boot-starter</artifactId>
                      <version>1.1.1</version>
                  </dependency>
                  <!--单元测试  日志-->
                  <dependency>
                      <groupId>ch.qos.logback</groupId>
                      <artifactId>logback-core</artifactId>
                      <version>1.2.3</version>
                  </dependency>
                  <dependency>
                      <groupId>junit</groupId>
                      <artifactId>junit</artifactId>
                      <version>${junit.version}</version>
                  </dependency>
                  <dependency>
                      <groupId>org.projectlombok</groupId>
                      <artifactId>lombok</artifactId>
                      <version>${lombok.version}</version>
                  </dependency>
                  <dependency>
                      <groupId>log4j</groupId>
                      <artifactId>log4j</artifactId>
                      <version>${log4j.version}</version>
                  </dependency>
      
              </dependencies>
          </dependencyManagement>
      

      此方法有个问题,注册了三个端口一样的实例,原因未知:

      在这里插入图片描述

  4. 增加application1的依赖并且注入service

    		<dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-starter-dubbo</artifactId>
            </dependency>
            <dependency>
                <groupId>com.yyh</groupId>
                <artifactId>service-1-api</artifactId>
                <version>1.0-SNAPSHOT</version>
            </dependency>
    
    @RestController
    public class Application1Controller {
    
        //注入service(dubbo协议)
        @Reference
        ConsumerService consumerService;
        @GetMapping
        public String service(){
            String service = consumerService.service();
            return "test:"+service;
        }
    }
    

    ​ 此处的@Reference得是dubbo的,@Reference会生成代理对象,然后进行远程调用

  5. service-2与service-1类似,省略呵呵

  6. service-1调用service-2

    service-1-server添加依赖

    		<dependency>
                <groupId>com.yyh</groupId>
                <artifactId>service-2-api</artifactId>
                <version>1.0-SNAPSHOT</version>
            </dependency>
    

    在实现类这调用service-2

    @Service//必须是dubbo的service  标记此类为dubbo接口
    public class ConsumerServiceImpl implements ConsumerService{
    
        //注入servive-2
        @Reference//dubbo的
        ProviderService providerService;
    
        @Override
        public String service() {
            //service1调用service2
            String service = providerService.service();
            return "Consumer(service1)调用:"+service;
        }
    }
    

    至此,现在是application1->service-1(consumer)->service-2(provider)

  7. 网关

    网关为服务的统一入口,,它会对请求进行过滤、校验(校验请求的合法性不合法将被拦截,解决访问)、路由等处理,因此提高了微服务的安全性。

    在这里插入图片描述

    zuul是springcloud的网关,它实现了请求路由、负载均衡、校验、过滤等功能。

    在实际项目中zuul与nginx配合使用,nginx的作用是反向代理、负载均衡,zuul的作用是保障微服务的安全访问,拦截微服务请求、校验合法性和负载均衡,看图:

    在这里插入图片描述

    1)在gateway中添加依赖

    		<dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
            </dependency>
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-openfeign</artifactId>
            </dependency>
    

    2)在nacos界面新建gateway.yaml配置文件(配置路由),内容如下:

    zuul:
      routes: 
        application1:
          stripPrefix: false
          path: /application1/**
    

    path的意思是以application1开头的都转发到application1上面

    3)在启动类上面添加@EnableZuulProxy注解,欧了

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值