【微服务】- Nacos - 注册中心

微服务 - 注册中心 - Nacos

生命不息,写作不止
继续踏上学习之路,学之分享笔记
总有一天我也能像各位大佬一样
一个有梦有戏的人 @怒放吧德德
分享学习心得,欢迎指正,大家一起学习成长!

上一次介绍了Nacos的简介以及简要理解,这次就来使用Nacos整合SpringCloud Alibaba。
努力克制自己,拒绝摆烂!

在这里插入图片描述

注册中心 - Nacos

  • 微服务 - 注册中心 - Nacos
    • 什么是服务注册
    • 什么是服务发现
    • 实例
      • 创建父工程
      • 创建服务
      • 编写模拟api

什么是服务注册

服务注册表是注册中心的核心,它用来记录各个微服务实例的信息,例如微服务的名称、IP、端口等。服务注册表提供查询API和管理API,查询API用于查询可用的微服务实例,管理API用于服务的注册与注销。提供者将服务注册到注册中心,注册中心会对服务进行实例健康监控,消费者通过注册中心进行服务发现,在进行服务调用。通常服务调用会使用负载均衡,常见负载均衡有ribbon或者feign。
【微服务】- Nacos - 注册中心_第1张图片
对于注册中心的理解,可以看一下 CSDN:10分钟带你彻底搞懂注册中心_Apple_Web的博客-CSDN博客_什么是注册中心

什么是服务发现

在微服务架构中,整个系统会按职责能力划分为多个服务,通过服务之间协作来实现业务目标。这样在我们的代码中免不了要进行服务间的远程调用,服务的消费方要调用服务的生产方,为了完成一次请求,消费方需要知道服务生产方的网络位置(IP地址和端口号)。
【微服务】- Nacos - 注册中心_第2张图片
再看这图,将每个服务集群都注册到注册中心,由其统一管理。在服务中心就会有服务注册表,在服务实例本身并不记录服务生产方的网络地址,所有服务实例内部都会包含服务发现客户端。

1)、在每个服务启动的时候,服务会向注册中心(Nacos)注册服务,上报自己的网络地址(服务名,端口号等)信息。服务中心就会形成服务注册表,这是服务发现的核心。它是存储了所有服务实例的数据库。
2)、客户端会定期从服务中心拉取服务注册表,缓存在客户端。
3)、如果一个服务有许多实例集群,那就需要设置负载均衡策略,从中选出一个来。

在微服务环境中,由于服务运行实例的网络地址是不断动态变化的,服务实例数量的动态变化 ,因此无法使用固定的配置文件来记录服务提供方的网络地址,必须使用动态的服务发现机制用于实现微服务间的相互感知。各服务实例会上报自己的网络地址,这样服务中心就形成了一个完整的服务注册表,各服务实例会通过服务发现中心来获取访问目标服务的网络地址,从而实现服务发现的机制。

实例

在之前已经更新了一篇 【微服务】Nacos初体验,里面介绍了Nacos的基础使用,现在来通过SpringCloud实现一个实例。

创建父工程

创建父级springcloud工程,pom.xml文件如下,这里需要注意的是版本问题,可以在springcloud-alibaba的开源项目中查看具体地址:版本说明
【微服务】- Nacos - 注册中心_第3张图片


<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.0modelVersion>
    <packaging>pompackaging>
    <modules>
        <module>service-goodsmodule>
        <module>service-storemodule>
    modules>
    <parent>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-parentartifactId>
        <version>2.4.2version>
        <relativePath/> 
    parent>
    <groupId>com.lydgroupId>
    <artifactId>spring-cloud-demoartifactId>
    <version>0.0.1-SNAPSHOTversion>
    <name>spring-cloud-demoname>
    <description>Demo project for Spring Bootdescription>
    <properties>
        <java.version>1.8java.version>
        <spring-cloud.version>2020.0.1spring-cloud.version>
        <spring-cloud-alibaba.version>2021.1spring-cloud-alibaba.version>
    properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-starterartifactId>
        dependency>

        <dependency>
            <groupId>org.projectlombokgroupId>
            <artifactId>lombokartifactId>
            <optional>trueoptional>
        dependency>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-testartifactId>
            <scope>testscope>
        dependency>
        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-starter-bootstrapartifactId>
        dependency>
    dependencies>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloudgroupId>
                <artifactId>spring-cloud-dependenciesartifactId>
                <version>${spring-cloud.version}version>
                <type>pomtype>
                <scope>importscope>
            dependency>
            <dependency>
                <groupId>com.alibaba.cloudgroupId>
                <artifactId>spring-cloud-alibaba-dependenciesartifactId>
                <version>${spring-cloud-alibaba.version}version>
                <type>pomtype>
                <scope>importscope>
            dependency>
        dependencies>
    dependencyManagement>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-maven-pluginartifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombokgroupId>
                            <artifactId>lombokartifactId>
                        exclude>
                    excludes>
                configuration>
            plugin>
        plugins>
    build>
project>

创建服务

创建一个maven模块,编写启动类和bootstrap.yml配置文件
需要在pom添加以下依赖坐标:

  • spring-cloud-starter-alibaba-nacos-discovery:将 Nacos 作为注册中心,并实现对它的自动配置与服务发现
  • spring-boot-starter-web:web启动器,为我们提供了嵌入的 Servlet 容器以及 SpringMVC 的依赖,并为 Spring MVC 提供了大量自动配置,可以适用于大多数 Web 开发场景。
<dependencies>
    <dependency>
        <groupId>com.alibaba.cloudgroupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
    dependency>
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-webartifactId>
    dependency>
dependencies>

启动器类需要添加注解
@EnableDiscoveryClient: 将微服务注册到服务发现组件上,能够让注册中心能够发现,扫描到改服务。

package com.lyd.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
/**
 * @author: lyd
 * @description: 启动类
 * @Date: 2022/9/20
 */
@EnableDiscoveryClient
@SpringBootApplication
public class GoodsApplication {
    public static void main(String[] args) {
        SpringApplication.run(GoodsApplication.class, args);
    }
}

在bootstrap.yml文件上编写一些配置
修改端口号,服务名字等。ephemeral:表示注册的实例的属性,默认是true

server:
  port: 8000
spring:
  application:
    name: service-goods
  cloud:
    nacos:
      server-addr: 127.0.0.1:8848
      discovery:
        ephemeral: false # false为永久实例,true表示临时实例开启,注册为临时实例

在View/Tool Windows 下面有个services可以打开查看服务,有时候会有提示打开,在添加springboot就行。
【微服务】- Nacos - 注册中心_第4张图片
通过右键copy Configuration 可以赋值多个实例,在VM-options中写 -Dserver.port=???来配置新的实例的端口号
【微服务】- Nacos - 注册中心_第5张图片
运行启动,就会吧服务注册到nacos注册中,此时可以在nacos网页中查看。
【微服务】- Nacos - 注册中心_第6张图片
这里能够显示服务的集群、状态等信息,也可以进行其他操作。
接下来编写服务的一些具体模拟业务,在让服务之间相互调用。

编写模拟api

在service-store中有这么一个控制类,通过/api/store/id返回访问的端口和一个integer数值

package com.lyd.demo.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;
/**
 * @author: lyd
 * @description: api
 * @Date: 2022/9/21
 */
@RestController
@RequestMapping("/api/store")
public class StoreController {
    @Value("${server.port}")
    private String currentPort;
    @GetMapping("/{id}")
    public Map<String, Object> getStoreNum(@PathVariable String id) {
        Map<String, Object> map = new HashMap<>();
        map.put("port", currentPort);
        map.put("num", 10);
        return map;
    }
}

在server-goods服务中需要有一个实体类,模拟请求的数据实体。

package com.lyd.demo.entity;
import lombok.Data;
/**
 * @author: lyd
 * @description: 商品实体类
 * @Date: 2022/9/21
 */
@Data
public class GoodsDto {
    private Long uid;
    private Integer number;
    private String name;
    private String code;
    private String size;
    private Double price;
    private String currentPort;
    private String serverPort;
}

编写控制类,暴露api接口,等下就是调用这个接口,并且通过RestTemplate.getForObject来进行服务间的调用,在此需要导入负载均衡策略的坐标。并且可以在启动器中注入bean,开启负载均衡。


<dependency>
    <groupId>org.springframework.cloudgroupId>
    <artifactId>spring-cloud-starter-loadbalancerartifactId>
dependency>

在启动类中去注入bean并且加上注解@LoadBalanced

@Bean
@LoadBalanced
public RestTemplate restTemplate() {
    return new RestTemplate();
}

具体控制类代码如下:
注意URL是http://service-store/api/store/通过服务名来的,这样restTemplate就能使用负载均衡策略。

package com.lyd.demo.controller;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.lyd.demo.entity.GoodsDto;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import java.util.Map;
/**
 * @author: lyd
 * @description: api
 * @Date: 2022/9/21
 */
@RestController
@RequestMapping("/api")
public class GoodsController {
    @Autowired
    private RestTemplate restTemplate;
    @Value("${server.port}")
    private String currentPort;
    @GetMapping("/{uid}")
    public GoodsDto getGoodsNum(@PathVariable String uid) throws JsonProcessingException {
        GoodsDto goodsDto = new GoodsDto();
        goodsDto.setUid(1L);
        goodsDto.setName("笔记本");
        goodsDto.setCode("note:1");
        goodsDto.setSize("A6");
        goodsDto.setPrice(5.88);
        // 向service-store服务请求数据
        String object = restTemplate.getForObject("http://service-store/api/store/" + uid, String.class);
        ObjectMapper objectMapper = new ObjectMapper();
        Map map = objectMapper.readValue(object, Map.class);
        Integer number = (Integer) map.get("num");
        String port = (String) map.get("port");
        goodsDto.setNumber(number);
        goodsDto.setCurrentPort("请求的端口:" + port);
        goodsDto.setServerPort("当前的端口:" + currentPort);
        return goodsDto;
    }
}

启动Nacos服务器后就可以启动这些服务,为了模拟负载均衡的效果,store服务实例就复制了两个
在这里插入图片描述
启动之后访问:http://localhost:8000/api/1 就可以看到输出的结果,每次输出的请求端口都不一样。
【微服务】- Nacos - 注册中心_第7张图片
【微服务】- Nacos - 注册中心_第8张图片

今天算是挺坎坷的,之前用来启动若依框架的nacos服务器不知为什么就不能用了,于是搞了好久干脆重新安装一个Nacos服务器,最后才成功。

创作不易,可能有些语言不是很通畅,如有错误请指正,感谢观看!记得点赞哦!

你可能感兴趣的:(Alibaba,springcloud,微服务,java,spring,cloud,Nacos,注册中心)