24 服务发现与注册 nacos

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

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

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

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

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

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

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

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

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

2.实现服务发现

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

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

image.png

Nacos整合SpringCloud
maven 依赖信息:



    4.0.0
    
        org.springframework.boot
        spring-boot-starter-parent
        2.2.8.RELEASE
         
    
    com.taotao
    meite-member
    0.0.1-SNAPSHOT
    meite-member
    Demo project for Spring Boot

    
        1.8
        2.2.1.RELEASE
    

    
        
            org.springframework.boot
            spring-boot-starter-web
        
        
            com.alibaba.cloud
            spring-cloud-starter-alibaba-nacos-discovery
        

        
            org.springframework.boot
            spring-boot-starter-test
            test
            
                
                    org.junit.vintage
                    junit-vintage-engine
                
            
        
    

    
        
            
                com.alibaba.cloud
                spring-cloud-alibaba-dependencies
                ${spring-cloud-alibaba.version}
                pom
                import
            
        
    

    
        
            
                org.springframework.boot
                spring-boot-maven-plugin
            
        
    




会员服务注册:

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



    4.0.0
    
        org.springframework.boot
        spring-boot-starter-parent
        2.2.8.RELEASE
         
    
    com.taotao
    meite-order
    0.0.1-SNAPSHOT
    meite-order
    Demo project for Spring Boot

    
        1.8
        2.2.1.RELEASE
    

    
        
        
            com.netflix.ribbon
            ribbon-loadbalancer
            2.7.13
            runtime
        


        
            org.springframework.boot
            spring-boot-starter-web
        
        
            com.alibaba.cloud
            spring-cloud-starter-alibaba-nacos-discovery
        

        
            org.springframework.boot
            spring-boot-starter-test
            test
            
                
                    org.junit.vintage
                    junit-vintage-engine
                
            
        
    

    
        
            
                com.alibaba.cloud
                spring-cloud-alibaba-dependencies
                ${spring-cloud-alibaba.version}
                pom
                import
            
        
    

    
        
            
                org.springframework.boot
                spring-boot-maven-plugin
            
        
    





配置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 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 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 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 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 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

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

你可能感兴趣的:(24 服务发现与注册 nacos)