什么是注册中心(服务治理)

注册中心可以说是微服务架构中的”通讯录“,它记录了服务和服务地址的映射关系。在分布式架构中,服务会注册到这里,当服务需要调用其它服务时,就到这里找到服务的地址,进行调用。

为什么需要注册中心

在分布式系统中,不仅仅是需要在注册中心找到服务和服务地址的映射关系这么简单,还需要考虑更多更复杂的问题:

  • 服务注册后,如何被及时发现
  • 服务宕机后,如何及时下线
  • 服务如何有效的水平扩展
  • 服务发现时,如何进行路由
  • 服务异常时,如何进行降级
  • 注册中心如何实现自身的高可用

这些问题的解决都依赖于注册中心。简单看,注册中心的功能有点类似于DNS服务器或者负载均衡器,而实际上,注册中心作为微服务的基础组件,可能要更加复杂,也需要更多的灵活性和时效性。

常见的注册中心

主流的注册中心:zookeeper、Eureka、consul、etcd、Nacos
AlibabaCloud搭配最好的是Nacos,且服务的注册发现之外,还支持动态配置服务
参考图片(nacos官网)
nacosMap.png

本地启动Nacos

image.png
Linux/Mac/Windows安装Nacos
Nacos包:nacos-server-1.3.2.zip

  • 解压安装包
  • 进入bin目录
  • Linux/Mac启动:sh startup.sh -m standalone
  • Windows启动:cmd命令 startup.cmd -m standalone
  • 访问 localhost:8848/nacos
  • 默认账号密码 nacos/nacos

基于Nacos实现订单服务与视频服务之间的调用

项目集成Nacos实现服务直接的调用

给用户服务、订单服务、视频服务POM都添加上Nacos依赖:

  1. //3个服务分别添加依赖
  2. <!--添加nacos客户端-->
  3. <dependency>
  4. <groupId>com.alibaba.cloud</groupId>
  5. <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
  6. </dependency>

配置Nacos地址
image.png

//给3个服务都添加配置

spring:
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848

启动类增加注解

//给订单服务和视频服务的启动类加入注解:@EnableDiscoveryClient

@EnableDiscoveryClient
@SpringBootApplication
public class VideoApplication {
    public static void main(String[] args) {
        SpringApplication.run(VideoApplication.class, args);
    }
}

启动视频服务和订单服务,启动后在Nacos页面中查看:
image.png

服务之间的调用

//修改之前订单服务的网络请求调用

package com.study.controller;

import com.study.pojo.Video;
import com.study.pojo.VideoOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.util.List;

@RestController
@RequestMapping("/api/v1/video_order")
public class OrderController {

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private DiscoveryClient discoveryClient;

    @GetMapping("/save")
    public Object save(int videoId){
        //传入视频服务的名称 - 返回是list(集群)
        List<ServiceInstance> list = discoveryClient.getInstances("class-video-service");
        //取第一个
        ServiceInstance serviceInstance = list.get(0);
        //拼接URL
        String url = "http://" + serviceInstance.getHost() + ":" + serviceInstance.getPort() + "/api/v1/video/find_by_id?videoId=" + videoId;
        //网络请求
        Video video = restTemplate.getForObject(url, Video.class);
        VideoOrder videoOrder = new VideoOrder();
        videoOrder.setVideoId(videoId);
        videoOrder.setVideoTitle(video.getTitle());
        videoOrder.setCreateTime(video.getCreateTime());
        return videoOrder;
    }

}

访问订单服务测试

http://localhost:8000/api/v1/video_order/save?videoId=40