微服务架构-SpringCloudAlibaba-093:Nacos实现服务注册与发现

093:Nacos实现服务注册与发现

1 SpringCloudalibaba与SpringCloud区别

课程内容:

  1. 微服务架构核心设计思想服务治理
  2. 基于Nacos实现服务注册与发现
  3. 使用Rest模版实现RPC调用
  4. 手写Rpc客户端负载均衡算法

SpringCloud与SpringCloudAlibaba的区别
SpringCloidAlibaba实际上对SpringCloud实现了扩展组件,能够完美整合到SpringCloud开发的组件中。

  1. nacos 分布式注册中心、分布式配置中心,SpringCloud中Eureka+Config组合;
  2. 如果使用了SpringCloudAlibaba,建议最好使用alibaba整个体系的产品。
    总结:SpringCloud Alibaba实际上对SpringCloud做扩展组件开发:naocs、seata分布式事务解决框架、SchedulerX、Alibaba Cloud OSS等,目的是推广阿里云的产品。

2 微服务服务治理核心概念

Nacos分布式注册与发现功能|分布式配置中心
产生背景:rpc远程调用中,服务的url的治理。
Rpc的远程调用框架:HttpClient、gprc、dubbo、rest、openfeign等。

传统的rpc远程调用中存在哪些问题?

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

3 传统服务注册中心实现方式

rpc远程调用中,地址中包括:域名和端口号/调用的方法名称
eg: 192.168.212.110:8080/getUser
传统服务注册中心实现方式:基于数据库形式实现服务url治理,把每个服务地址信息和端口号人工存放到数据库表中。
Id serviceId ip 端口号
1 Mayikt-member 192.168… 8082
2 Mayikt-member 192.168… 8081
缺点:维护成本非常高、没有完全绝对实现动态化智能化

4 分布式注册中心的实现原理

思考是否有更好的方案:微服务中的注册中心。
整个微服务架构中最为核心的组件肯定是注册中心。

注册中心:实际就是存放整个微服务中服务的地址信息,能够实现动态感知。
注册中心实现方式:Dubbo依赖Zookeeper、Eureka 、Consul、Nacos、Redis、数据库

注册中心实现原理:
服务注册:提供服务接口地址信息存放
生产者:提供接口被其他的服务调用
消费者:调用接口实现消费。
微服务架构-SpringCloudAlibaba-093:Nacos实现服务注册与发现
服务注册原理实现:

  1. 生产者启动的时候,将“key=服务的名称,value=ip和端口号”注册到微服务注册中心上。
    Mayikt-member 192.168.212.110:8080
    Mayikt-member 192.168.212.110:8081
  2. 注册存放服务地址列表类型: key唯一,列表是list集合。
    Map<Key,List(String)>
    {Mayikt-member:[“192.168.212.110:8080”,“ 192.168.212.110:8081”]}
  3. 消费者从注册中心上根据服务名称查询服务地址列表(集合)
    Mayikt-member = [“192.168.212.110:8080”,“ 192.168.212.110:8081”]
  4. 消费者获取到集群列表之后,采用负载均衡器选择一个地址实现rpc远程调用。

5 Nacos的基本的介绍

Nacos的基本的介绍
Nacos可以实现分布式服务注册与发现/分布式配置中心框架
官网的介绍: https://nacos.io/zh-cn/docs/what-is-nacos.html
默认的端口号:8848 访问地址http://127.0.0.1:8848/nacos
默认的账号和密码:nacos nacos

6 使用命令形式对Nacos实现注册

模拟实现服务注册与发现
服务注册:
http://127.0.0.1:8848/nacos/v1/ns/instance?serviceName=meite-member &ip=192.168.212.110&port=8080
http://127.0.0.1:8848/nacos/v1/ns/instance?serviceName=meite-member &ip=192.168.212.110&port=8081
服务查询
http://127.0.0.1:8848/nacos/v1/ns/instance/list?serviceName=meite-member
测试效果:
微服务架构-SpringCloudAlibaba-093:Nacos实现服务注册与发现

7 创建生产者实现服务的注册

Nacos整合SpringCloud
Maven依赖信息

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.0.0.RELEASE</version>
</parent>
<dependencies>
    <!--  springboot 整合web组件-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        <version>0.2.2.RELEASE</version>
    </dependency>
</dependencies>

application.yml

spring:
  application:
    ## 服务名称
    name: mayikt-member
  cloud:
    nacos:
      discovery:
        ## nacos注册地址
        server-addr: 127.0.0.1:8848
server:
  port: 8080

会员服务(生产者)

@RestController
public class MemberService {

    @Value("${server.port}")
    private String serverPort;

    /**
     * 会员服务提供接口被订单服务调用
     *
     * @param userId
     * @return
     */
    @RequestMapping("/getUser")
    public String getUser(Integer userId) {
        return "每特教育|蚂蚁课堂,端口号为:" + serverPort;
    }
}
@SpringBootApplication
public class AppMember {
    public static void main(String[] args) {
        SpringApplication.run(AppMember.class);
    }
}

8 创建消费者调用生产者服务

application.yml

spring:
  application:
    ## 服务名称
    name: mayikt-order
  cloud:
    nacos:
      discovery:
        ## nacos注册地址
        server-addr: 127.0.0.1:8848
server:
  port: 8090

订单服务(消费者)

@RestController
public class OrderService {

    @Autowired
    private DiscoveryClient discoveryClient;
    @Autowired
    private RestTemplate restTemplate;

    /**
     * 订单服务调用会员服务接口
     *
     * @return
     */
    @RequestMapping("/orderToMember")
    public Object orderToMember() {
        // 1.根据服务名称从注册中心上获取集群列表地址
        List<ServiceInstance> instances = discoveryClient.getInstances("mayikt-member");
        // 2.列表中任意选择实现本地rpc调用 rest
        ServiceInstance serviceInstance = instances.get(0);
        String result = restTemplate.getForObject(serviceInstance.getUri() + "/getUser", String.class);
        return "订单调用会员返回结果:" + result;
    }
}
@SpringBootApplication
public class AppOrder {
    public static void main(String[] args) {
        SpringApplication.run(AppOrder.class);
    }
    @Bean
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }
}

RestTemplate不是SpringCloud写的,本身Spring支持Http协议调用。

测试结果:
微服务架构-SpringCloudAlibaba-093:Nacos实现服务注册与发现

9 纯手写本地负载均衡器轮询算法

从注册中心获取服务集群的列表,从列表选择一个,负载均衡算法有哪些:
一致性hash计算、轮询、权重、随机
采用什么设计模式:策略模式
轮询算法:访问次数%集群size。
假设有两台服务器集群,1%2=1;2%2=0;3%2=1;4%2=0

public interface LoadBalancer {
    /**
     * 从注册中心集群列表中获取单个地址
     * @param serviceInstances
     * @return
     */
    ServiceInstance getSingleAddress(List<ServiceInstance> serviceInstances);
}
@Component
public class RotationLoadBalancer implements LoadBalancer {

    // 从0开始计数
    private AtomicInteger atomicInteger = new AtomicInteger(0);

    @Override
    public ServiceInstance getSingleAddress(List<ServiceInstance> serviceInstances) {
        int index = atomicInteger.incrementAndGet() % serviceInstances.size();
        return serviceInstances.get(index);
    }
}
@RestController
public class OrderService {

    @Autowired
    private DiscoveryClient discoveryClient;
    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private LoadBalancer loadBalancer;

    /**
     * 订单服务调用会员服务接口
     *
     * @return
     */
    @RequestMapping("/orderToMember")
    public Object orderToMember() {
        // 1.根据服务名称从注册中心上获取集群列表地址
        List<ServiceInstance> instances = discoveryClient.getInstances("mayikt-member");
        // 采用负载均衡算法
        ServiceInstance singleAddress = loadBalancer.getSingleAddress(instances);
        URI rpcMemberUrl = singleAddress.getUri();
        String result = restTemplate.getForObject(rpcMemberUrl + "/getUser", String.class);
        return "订单调用会员返回结果:" + result;
    }
}
上一篇:SpringCloudAlibaba(毕业版)(一)集成Dubbo+Nacos


下一篇:springCloudAlibaba之nacos