【微服務】- Nacos - 註冊中心
- 2022 年 9 月 21 日
- 筆記
- JAVA, SpringCloud
微服務 - 註冊中心 - Nacos
😄生命不息,寫作不止
🔥 繼續踏上學習之路,學之分享筆記
👊 總有一天我也能像各位大佬一樣
🏆 一個有夢有戲的人 @怒放吧德德
🌝分享學習心得,歡迎指正,大家一起學習成長!
上一次介紹了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="//maven.apache.org/POM/4.0.0" xmlns:xsi="//www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="//maven.apache.org/POM/4.0.0 //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是//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("//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服務實例就複製了兩個

啟動之後訪問://localhost:8000/api/1 就可以看到輸出的結果,每次輸出的請求埠都不一樣。


今天算是挺坎坷的,之前用來啟動若依框架的nacos伺服器不知為什麼就不能用了,於是搞了好久乾脆重新安裝一個Nacos伺服器,最後才成功。
👍創作不易,可能有些語言不是很通暢,如有錯誤請指正,感謝觀看!記得點贊哦!👍
