什么是注册中心(服务治理)
注册中心可以说是微服务架构中的”通讯录“,它记录了服务和服务地址的映射关系。在分布式架构中,服务会注册到这里,当服务需要调用其它服务时,就到这里找到服务的地址,进行调用。
为什么需要注册中心
在分布式系统中,不仅仅是需要在注册中心找到服务和服务地址的映射关系这么简单,还需要考虑更多更复杂的问题:
- 服务注册后,如何被及时发现
- 服务宕机后,如何及时下线
- 服务如何有效的水平扩展
- 服务发现时,如何进行路由
- 服务异常时,如何进行降级
- 注册中心如何实现自身的高可用
这些问题的解决都依赖于注册中心。简单看,注册中心的功能有点类似于DNS服务器或者负载均衡器,而实际上,注册中心作为微服务的基础组件,可能要更加复杂,也需要更多的灵活性和时效性。
常见的注册中心
主流的注册中心:zookeeper、Eureka、consul、etcd、Nacos
AlibabaCloud搭配最好的是Nacos,且服务的注册发现之外,还支持动态配置服务
参考图片(nacos官网)
本地启动Nacos
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依赖:
//3个服务分别添加依赖
<!--添加nacos客户端-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
配置Nacos地址
//给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页面中查看:
服务之间的调用
//修改之前订单服务的网络请求调用
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