美文网首页
32 服务发现与注册 nacos

32 服务发现与注册 nacos

作者: 滔滔逐浪 | 来源:发表于2020-07-24 17:25 被阅读0次

    Nacos 分布式注册与发现功能|分布式配置中心
    产生背景rpc远程调用中。服务的url 的治理
    rpc的远程调用框架: HttpClient,grpc,dubbo,rest,openfeign
    传统的rpc 调用有哪些问题:
    1,超时问题
    2,安全问题
    3,服务与服务之间url地址管理

    在我们微服务架构通讯,服务之间依赖关系非常大,如果通过传统的方式管理我们服务的url地址的情况下,一旦地址发生变化的情况下,还需要人工修改rpc远程调用地址。
    每个服务的url管理地址发出复杂,所以这是我们采用服务url治理技术,可以实现对我们整个实现动态服务注册与发现、本地负载均衡、容错等。


    image.png

    服务治理的基本概念

    服务治理的基本概念:
    在rpc的远程调用中,服务与服务之间的依赖关系非常大,服务url地址管理非常复杂,所以这时候需要我们对服务的url实现治理。通过服务治理可以实现服务注册与发现,负载均衡,容错等。


    image.png

    rpc远程调用中, 地址中包括 域名和端口号/调用的方法名称
    192.168.111.111:8080/getUser
    把每个服务器地址和端口人工放到数据库表中:
    Id serviced ip 端口号
    Mayikt-member 192.168... 8082
    Mayikt-member 192.168... 8081
    基于数据库形式实现服务url治理
    缺点: 维护成本高, 没有完全绝对的实现动态智能。
    思考是否有更好的方案?
    微服务的注册中心
    整个微服务架构中最为核心的肯定是 注册中心
    注册中心实际上就是存放我们的服务的地址信息,能够实现动态感知:
    注册中心: Dubbo依赖zookeeper,Eureka,Consul,Nacos,Redis 数据库


    image.png

    服务注册中心的概念:
    每次调用该服务的时候如果地址写死了,一点接口发生了改变的情况下,这时候需要重新发布版本才连接接口调用地址,所以需要一个注册中心统一管理沃恩的服务注册与发现。
    注册中心,我们的服务注册到我们的的注册中心,key为服务名称,value为该服务 调用地址,该类型为集合类型。Eureka,consul,zookeeper,nacos等
    服务注册: 我们生产者项目启动的时候,会将当前服务自己的信息地址注册到注册中心。

    服务发现: 消费者从我们的注册中心获取生产者调用的地址(集合),在使用负载均衡策略获取集群中某个地址实现本地的rpc的远程调用。

    微服务调用接口常用名词

    Nacos与Eureka区别:

    (1)springcloud eureka是注册中心,负责微服务的注册与发现,起到承上启下的作用,在微服务架构中相当于人体的 大脑,很重要,nacos是阿里巴巴出的,功能类似eureka,

    (2)nacos的部署方式与springcloud eureka不太一样,euraka是需要创建springboot项目,然后将euraka服务端通过gav的方式加载进来,然后部署项目。

    (3)nacos是直接从阿里巴巴nacos的官网下载jar包,启动服务。

    Eureka与Zookeeper的区别:
    Zookeeper的设计理念就是分布式协调服务,保证数据(配置数据,状态数据)在多个服务系统之间保证一致性,这也不难看出Zookeeper是属于CP特性(Zookeeper的核心算法是Zab,保证分布式系统下,数据如何在多个服务之间保证数据同步)。Eureka是吸取Zookeeper问题的经验,先保证可用性。

    生产者: 提供接口被其他服务的调用
    消费者: 调用生产者接口实现消费
    服务注册: 将当前服务地址注册到服务发现。


    image.png

    服务注册原理和实现:
    1,生产者启动的时候key=服务站的名称 value ip和端口号注册到我们的微服务注册中心上。
    mayikt-member 192.168.0.149:8080
    mayikt-member 192.168.0.149:8081

    2,注册存放服务地址列表类型: key唯一,列表是list集合。

    May<Key,List(String)>{Mayikt-member:["192.168.0.149"]}
    3,我们的消费者从我们注册中心上根据服务名称查询服务地址列表(集合)
    mayikt-member ==["192.168.0.149:8080" " 192.168.0.149:8081"]
    4,消费者获取到集群列表后采用负载均衡器选择一个地址实现rpc 远程调用。

    N****acos的****基本的介绍

    Nacos可以实现分布式服务注册与发现/分布式配置中心框架。

    官网的介绍: <u>https://nacos.io/zh-cn/docs/what-is-nacos.html</u>

    N****acos的****环境的准备

    Nacos可以在linux/windows/Mac版本上都可以安装

    具体安装教程地址:<u>https://nacos.io/zh-cn/docs/quick-start.html</u>

    手动实现服务注册与发现
    1.实现服务注册 发送post请求:

    'http://127.0.0.1:8848/nacos/v1/ns/instance?serviceName=nacos.naming.serviceName&ip=20.18.7.10&port=8080'

    2.实现服务发现

    <u>http://127.0.0.1:8848/nacos/v1/ns/instance/list?serviceName=nacos.naming.serviceName</u>

    详细步骤操作:<u>https://nacos.io/zh-cn/docs/quick-start.html</u>

    image.png

    Nacos整合SpringCloud
    maven 依赖信息:

    <?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.8.RELEASE</version>
            <relativePath/> <!-- lookup parent from repository -->
        </parent>
        <groupId>com.taotao</groupId>
        <artifactId>meite-member</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <name>meite-member</name>
        <description>Demo project for Spring Boot</description>
    
        <properties>
            <java.version>1.8</java.version>
            <spring-cloud-alibaba.version>2.2.1.RELEASE</spring-cloud-alibaba.version>
        </properties>
    
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</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-test</artifactId>
                <scope>test</scope>
                <exclusions>
                    <exclusion>
                        <groupId>org.junit.vintage</groupId>
                        <artifactId>junit-vintage-engine</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
        </dependencies>
    
        <dependencyManagement>
            <dependencies>
                <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>
            </dependencies>
        </dependencyManagement>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    
    </project>
    
    
    

    会员服务注册:

    package com.taotao.meitemember.service;
    
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    /**
     * 
     * @author aping
     * @time 2020/7/24 12:38
     */
    @RestController
    public class MemberService {
    
        @RequestMapping("/getUser")
        public  String getUser(Integer userId){
            return "麦田的守望者";
        }
    }
    
    
    

    接口完成后对会员进行注册:
    拿到配置文件,对项目命名:

    spring:
       application:
         name:  meitem-member
       cloud:
         nacos:
           discovery:
             server-addr: 127.0.0.1:8848
    
    

    再进行代码测试,自动实现对服务进行注册

    package com.taotao.meitemember;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
    
    
    @SpringBootApplication
    public class MeiteMemberApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(MeiteMemberApplication.class, args);
        }
    
    }
    
    
    

    会员服务(生产者)
    服务接口

    package com.taotao.meitemember.service;
    
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    /**
     *
     * @author aping
     * @time 2020/7/24 12:38
     */
    @RestController
    public class MemberService {
        @Value("${server.port}")
        private String serverport;
    
        @RequestMapping("/getUser")
        public  String getUser(Integer userId){
            return "麦田的守望者的端口:"+serverport;
        }
    }
    
    

    配置文件
    application.yml文件

    
    spring:
       application:
         name:  meitem-member
       cloud:
         nacos:
           discovery:
             server-addr: 127.0.0.1:8848
    server:
        port: 8084
    

    订单服务消费者
    订单调用会员服务
    pom

    <?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.8.RELEASE</version>
            <relativePath/> <!-- lookup parent from repository -->
        </parent>
        <groupId>com.taotao</groupId>
        <artifactId>meite-order</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <name>meite-order</name>
        <description>Demo project for Spring Boot</description>
    
        <properties>
            <java.version>1.8</java.version>
            <spring-cloud-alibaba.version>2.2.1.RELEASE</spring-cloud-alibaba.version>
        </properties>
    
        <dependencies>
            <!-- https://mvnrepository.com/artifact/com.netflix.ribbon/ribbon-loadbalancer -->
            <dependency>
                <groupId>com.netflix.ribbon</groupId>
                <artifactId>ribbon-loadbalancer</artifactId>
                <version>2.7.13</version>
                <scope>runtime</scope>
            </dependency>
    
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</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-test</artifactId>
                <scope>test</scope>
                <exclusions>
                    <exclusion>
                        <groupId>org.junit.vintage</groupId>
                        <artifactId>junit-vintage-engine</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
        </dependencies>
    
        <dependencyManagement>
            <dependencies>
                <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>
            </dependencies>
        </dependencyManagement>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    
    </project>
    
    
    
    

    配置yml

    spring:
       application:
         name:  meitem-order
       cloud:
         nacos:
           discovery:
             server-addr: 127.0.0.1:8848
    server:
        port: 8083
    
    

    启动类:

    package com.taotao.meiteorder;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.context.annotation.Bean;
    import org.springframework.web.client.RestTemplate;
    
    @SpringBootApplication
    public class MeiteOrderApplication {
        @Bean
        public RestTemplate restTemplate() {
            return new RestTemplate();
        }
        public static void main(String[] args) {
            SpringApplication.run(MeiteOrderApplication.class, args);
        }
    
    }
    
    
    

    调用接口:

    package com.taotao.meiteorder.order;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.cloud.client.ServiceInstance;
    import org.springframework.cloud.client.discovery.DiscoveryClient;
    import org.springframework.cloud.client.loadbalancer.LoadBalanced;
    import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    import org.springframework.web.client.RestTemplate;
    
    
    import java.net.URI;
    import java.util.List;
    
    /**
     * @author aping
     * @time 2020/7/24 12:56
     */
    @RestController
    public class OrderService {
        @Autowired
        private RestTemplate restTemplate;
        @Autowired
        private DiscoveryClient discoveryClient;
        @Autowired
        private LoadBalancerClient loadBalancerClient;
    
        @RequestMapping("/orderToMember")
        public String orderToMember() {
            // 从注册中心上获取该注册服务列表
            List<ServiceInstance> serviceInstanceList = discoveryClient.getInstances("meitem-member");
            ServiceInstance serviceInstance = serviceInstanceList.get(0);
            URI rpcMemberUrl = serviceInstance.getUri();
            String result = restTemplate.getForObject(rpcMemberUrl + "/getUser?userId="+66, String.class);
            return "订单调用会员获取结果:" + result;
        }
    
    
    }
    
    
    
    image.png

    负载均衡算法

    package com.taotao.meiteorder.order;
    
    import org.springframework.cloud.client.ServiceInstance;
    
    import java.util.List;
    
    /**
     * @author aping
     * @time 2020/7/24 17:08
     */
    public interface LoadBalancer {
        ServiceInstance geySingleAddres(List<ServiceInstance> serviceInstanceList);
    }
    
    
    
    package com.taotao.meiteorder.order;
    
    import org.springframework.cloud.client.ServiceInstance;
    import org.springframework.stereotype.Component;
    
    import java.util.List;
    import java.util.concurrent.atomic.AtomicInteger;
    
    /**
     * @author aping
     * @time 2020/7/24 17:10
     */
    @Component
    public class RotationLoadBalancer implements  LoadBalancer {
      private AtomicInteger atomicInteger=new AtomicInteger(0);
        @Override
        public ServiceInstance geySingleAddres(List<ServiceInstance> serviceInstanceList) {
           int index=atomicInteger.incrementAndGet()%2;
           ServiceInstance serviceInstance=serviceInstanceList.get(index);
            return serviceInstance;
        }
    }
    
    
    
    package com.taotao.meiteorder.order;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.cloud.client.ServiceInstance;
    import org.springframework.cloud.client.discovery.DiscoveryClient;
    import org.springframework.cloud.client.loadbalancer.LoadBalanced;
    import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    import org.springframework.web.client.RestTemplate;
    
    
    import java.net.URI;
    import java.util.List;
    
    /**
     * @author aping
     * @time 2020/7/24 12:56
     */
    @RestController
    public class OrderService {
        @Autowired
        private RestTemplate restTemplate;
        @Autowired
        private DiscoveryClient discoveryClient;
        @Autowired
        private LoadBalancer loadBalancer;
    
        @RequestMapping("/orderToMember")
        public String orderToMember() {
            // 从注册中心上获取该注册服务列表
            List<ServiceInstance> serviceInstanceList = discoveryClient.getInstances("meitem-member");
            ServiceInstance serviceInstance = serviceInstanceList.get(0);
            URI rpcMemberUrl = serviceInstance.getUri();
            String result = restTemplate.getForObject(rpcMemberUrl + "/getUser?userId="+66, String.class);
            return "订单调用会员获取结果:" + result;
        }
        @RequestMapping("/orderToMember2")
        public  String orderToMember2(){
            //从注册中心获取注册列表
            List<ServiceInstance> serviceInstances=discoveryClient.getInstances("meitem-member");
            ServiceInstance serviceInstance=loadBalancer.geySingleAddres(serviceInstances);
            URI uri=serviceInstance.getUri();
            //使用rest形式实现rpc调用
            String result=restTemplate.getForObject(uri+"/getUser?userId="+66,String.class);
            return  "顶顶那会员获取结果:"+result;
    
        }
    
    
    }
    
    
    

    http://localhost:8083/orderToMember2

    rpc远程调用设计到本地负载均衡的算法
    1,从注册中心获取服务集群的列表
    2,从列表中选择一个
    负载均衡的算法有哪些?
    1,一致性hash 计算
    2, 轮询,权重
    3,随机。
    采用设计模式
    假设我们有2台服务器集群:
    访问次数%集群size
    1%2=1
    2%2=0
    3%2=1
    4%2=0

    1%1=0


    image.png

    Nacos 与其他注册对比分析:
    访问之后在服务列表发现2个集群。下线原理是在把他的集合中移除:


    image.png

    故障转移:集合中取下一个值
    编程思维能力就是 举一反三

    相关文章

      网友评论

          本文标题:32 服务发现与注册 nacos

          本文链接:https://www.haomeiwen.com/subject/gdzhlktx.html