😄生命不息,写作不止
🔥 继续踏上学习之路,学之分享笔记
👊 总有一天我也能像各位大佬一样
🏆 一个有梦有戏的人 @怒放吧德德
🌝分享学习心得,欢迎指正,大家一起学习成长!
上一次介绍了Nacos的简介以及简要理解,这次就来使用Nacos整合SpringCloud Alibaba。
努力克制自己,拒绝摆烂!
什么是服务注册
服务注册表是注册中心的核心,它用来记录各个微服务实例的信息,例如微服务的名称、IP、端口等。服务注册表提供查询API和管理API,查询API用于查询可用的微服务实例,管理API用于服务的注册与注销。提供者将服务注册到注册中心,注册中心会对服务进行实例健康监控,消费者通过注册中心进行服务发现,在进行服务调用。通常服务调用会使用负载均衡,常见负载均衡有ribbon或者feign。
对于注册中心的理解,可以看一下 CSDN:10分钟带你彻底搞懂注册中心_Apple_Web的博客-CSDN博客_什么是注册中心
什么是服务发现
在微服务架构中,整个系统会按职责能力划分为多个服务,通过服务之间协作来实现业务目标。这样在我们的代码中免不了要进行服务间的远程调用,服务的消费方要调用服务的生产方,为了完成一次请求,消费方需要知道服务生产方的网络位置(IP地址和端口号)。
再看这图,将每个服务集群都注册到注册中心,由其统一管理。在服务中心就会有服务注册表,在服务实例本身并不记录服务生产方的网络地址,所有服务实例内部都会包含服务发现客户端。
1)、在每个服务启动的时候,服务会向注册中心(Nacos)注册服务,上报自己的网络地址(服务名,端口号等)信息。服务中心就会形成服务注册表,这是服务发现的核心。它是存储了所有服务实例的数据库。
2)、客户端会定期从服务中心拉取服务注册表,缓存在客户端。
3)、如果一个服务有许多实例集群,那就需要设置负载均衡策略,从中选出一个来。
在微服务环境中,由于服务运行实例的网络地址是不断动态变化的,服务实例数量的动态变化 ,因此无法使用固定的配置文件来记录服务提供方的网络地址,必须使用动态的服务发现机制用于实现微服务间的相互感知。各服务实例会上报自己的网络地址,这样服务中心就形成了一个完整的服务注册表,各服务实例会通过服务发现中心来获取访问目标服务的网络地址,从而实现服务发现的机制。
实例
在之前已经更新了一篇 【微服务】Nacos初体验,里面介绍了Nacos的基础使用,现在来通过SpringCloud实现一个实例。
创建父工程
创建父级springcloud工程,pom.xml文件如下,这里需要注意的是版本问题,可以在springcloud-alibaba的开源项目中查看具体地址:版本说明
<?xml version="1.0" encoding="UTF-8"?>
<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.0</modelVersion>
<packaging>pom</packaging>
<modules>
<module>service-goods</module>
<module>service-store</module>
</modules>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.2</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.lyd</groupId>
<artifactId>spring-cloud-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring-cloud-demo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>2020.0.1</spring-cloud.version>
<spring-cloud-alibaba.version>2021.1</spring-cloud-alibaba.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring-cloud-alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</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.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</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就行。
通过右键copy Configuration 可以赋值多个实例,在VM-options中写 -Dserver.port=????来配置新的实例的端口号
运行启动,就会吧服务注册到nacos注册中,此时可以在nacos网页中查看。
这里能够显示服务的集群、状态等信息,也可以进行其他操作。
接下来编写服务的一些具体模拟业务,在让服务之间相互调用。
编写模拟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.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</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服务器不知为什么就不能用了,于是搞了好久干脆重新安装一个Nacos服务器,最后才成功。
👍创作不易,可能有些语言不是很通畅,如有错误请指正,感谢观看!记得点赞哦!👍