目錄
一、微服務(wù)搭建
1.1 服務(wù)提供者與服務(wù)消費(fèi)者
1.2 依賴關(guān)系
?
二、服務(wù)注冊與負(fù)載均衡使用
2.1 Nacos 實現(xiàn)服務(wù)的注冊與發(fā)現(xiàn)
2.2 Loadbalancer負(fù)載均衡、Feign聲明式服務(wù)調(diào)用
2.3 示例綜合實現(xiàn)
2.3.1 服務(wù)注冊與發(fā)現(xiàn)測試
2.3.2 負(fù)載均衡測試?
一、微服務(wù)搭建
1.1 服務(wù)提供者與服務(wù)消費(fèi)者
服務(wù)提供者 | 服務(wù)的被調(diào)用方(即:為其他微服務(wù)提供接口的微服務(wù)) |
服務(wù)消費(fèi)者 | 服務(wù)的調(diào)用方(即:調(diào)用其他微服務(wù)接口的微服務(wù)) |
?就以圖(僅供娛樂,無不良影響)為例搭建一個簡單的微服務(wù)項目,可以看到一下項目結(jié)構(gòu):
cloud (父級項目,這樣為了更好管理項目資源):
- basketball (生產(chǎn)者)?
- common (公共資源)
- ikun (消費(fèi)者)
1.2 依賴關(guān)系
1、Cloud頂級模塊pom文件 (完整) :
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>cloud</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<!--定義子模塊-->
<modules>
<module>ikun</module>
<module>basketball</module>
<module>common</module>
</modules>
<!--依賴版本-->
<properties>
<spring-boot.version>2.4.2</spring-boot.version>
<spring-cloud.version>2020.0.1</spring-cloud.version>
<spring-cloud-alibaba.version>2021.1</spring-cloud-alibaba.version>
</properties>
<dependencies>
<!--nacos服務(wù)注冊-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!--Orika是java Bean映射框架,可以實現(xiàn)從一個對象遞歸拷貝數(shù)據(jù)至另一個對象。-->
<dependency>
<groupId>ma.glasnost.orika</groupId>
<artifactId>orika-core</artifactId>
<version>1.4.6</version>
</dependency>
<!--提供負(fù)載均衡的支持-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-loadbalancer</artifactId>
</dependency>
<!--簡化 Java 代碼的工具庫-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!--開啟負(fù)載均衡-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
</dependencies>
<!--聲明的依賴版本號可以被子模塊引用,但不會自動引入這些依賴-->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<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>
</project>
????????在父級中指定了子模塊,子模塊需要引用父級模塊就能同步使用父級依賴,這樣就可以把所有子模塊共同依賴同意管理。
2、ikun子模塊pom:?(basketball如同)
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
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>
<groupId>com.example</groupId>
<artifactId>ikun</artifactId>
<version>0.0.1-SNAPSHOT</version>
<!--引用父模塊依賴-->
<parent>
<groupId>org.example</groupId>
<artifactId>cloud</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--引入公共模塊-->
<dependency>
<groupId>org.example</groupId>
<artifactId>common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring-boot.version}</version>
<configuration>
<mainClass>com.example.ikun.IkunApplication</mainClass>
</configuration>
<executions>
<execution>
<id>repackage</id>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
????????
二、服務(wù)注冊與負(fù)載均衡使用
? ? ?以上的操作只是建造了一個空殼,我們需要通過一些組件來繼續(xù)完善微服務(wù)體系結(jié)構(gòu)。
2.1 Nacos 實現(xiàn)服務(wù)的注冊與發(fā)現(xiàn)
Nacos下載:Releases · alibaba/nacos · GitHub
1、添加依賴
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
2、配置服務(wù)提供者,從而服務(wù)提供者可以通過 Nacos 的服務(wù)注冊發(fā)現(xiàn)功能將其服務(wù)注冊到 Nacos server 上。
basketball(服務(wù)提供者)配置Nacos server 的地址:
server:
port: 8080
spring:
cloud:
nacos:
server-addr: localhost:8848
application:
name: basketball
?通過 Spring Cloud 原生注解?@EnableDiscoveryClient
?開啟服務(wù)注冊發(fā)現(xiàn)功能:
package com.example.basketball;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class BasketballApplication {
public static void main(String[] args) {
SpringApplication.run(BasketballApplication.class, args);
}
}
3、配置服務(wù)消費(fèi)者,從而服務(wù)消費(fèi)者可以通過 Nacos 的服務(wù)注冊發(fā)現(xiàn)功能從 Nacos server 上獲取到它要調(diào)用的服務(wù)。
ikun(服務(wù)消費(fèi)者)中配置 Nacos server 的地址:
server:
port: 8081
spring:
cloud:
nacos:
server-addr: localhost:8848
application:
name: ikun
通上在啟動類上添加?Spring Cloud 原生注解?@EnableDiscoveryClient
?開啟服務(wù)注冊發(fā)現(xiàn)功能。
2.2 Loadbalancer負(fù)載均衡、Feign聲明式服務(wù)調(diào)用
因為兩個子模塊都需要此組件,所以直接在父模塊cloud添加負(fù)載均衡依賴:
<!--提供負(fù)載均衡的支持-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-loadbalancer</artifactId>
</dependency>
<!--遠(yuǎn)程服務(wù)通信-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
在兩個子模塊啟動類添加注釋開啟服務(wù)通信
@EnableFeignClients
2.3 示例綜合實現(xiàn)
那么所有配置都已搭建好,接下來編寫api接口來實現(xiàn)服務(wù)通信與負(fù)載均衡:
1、準(zhǔn)備一個實體與dto類,因為本次示例并沒有連接數(shù)據(jù)庫,僅僅編寫一個類用于實例化數(shù)據(jù)。這里我準(zhǔn)備了一個公共模塊(common)用來放置公共所需的類
package pojo.dto;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author 云村小威
* @create 2024-01-06 15:52
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class IkunDto {
private Long id;
private String account;
private String password;
private Integer age;
private String hobby;
}
消費(fèi)者 遠(yuǎn)程調(diào)用 生產(chǎn)者 : 需要網(wǎng)絡(luò)傳輸,使用DTO同一封裝對象 原理與SpringBoot啟動類相同
- 將DTO對象封裝到公共DTO模塊
- 為需要的項目引入公共DTO模塊
<!--引入公共模塊-->
<dependency>
<groupId>org.example</groupId>
<artifactId>common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
注意點:
- 不需要繼承父模塊(重復(fù)引用問題)
- 打包方式為jar
- 不需要添加啟動類的編譯?
?VO(View Object):視圖對象,用于展示層,它的作用是把某個指定頁面(或組件)的所有數(shù)據(jù) 封裝起來。
DTO(Data Transfer Object):數(shù)據(jù)傳輸對象,這個概念來源于J2EE的設(shè)計模式,原來的目的是 為了EJB的分布式應(yīng)用提供粗粒度的數(shù)據(jù)實體,以減少分布式調(diào)用的次數(shù),從而提高分布式調(diào)用的 性能和降低網(wǎng)絡(luò)負(fù)載,但在這里,我泛指用于展示層與服務(wù)層之間的數(shù)據(jù)傳輸對象。
DO(Domain Object):領(lǐng)域?qū)ο?,就是從現(xiàn)實世界中抽象出來的有形或無形的業(yè)務(wù)實體。 PO(Persistent Object):持久化對象,它跟持久層(通常是關(guān)系型數(shù)據(jù)庫)的數(shù)據(jù)結(jié)構(gòu)形成一 一對應(yīng)的映射關(guān)系,如果持久層是關(guān)系型數(shù)據(jù)庫,那么,數(shù)據(jù)表中的每個字段(或若干個)就對應(yīng) PO的一個(或若干個)屬性。
2、服務(wù)提供者(basketball)
提供接口方法和返回結(jié)果
package com.example.basketball.controller;
import pojo.dto.IkunDto;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import java.util.Map;
@Slf4j
@RestController
@RequestMapping("/kun")
public class CXKController {
@RequestMapping("/{account}")
public String getByPath(@PathVariable String account) {
log.info("account:" + account);
return "kun : 唱";
}
@RequestMapping("/param")
public String getByParam(@RequestParam("account") String account,
@RequestParam("password") String password) {
log.info("param:" + account + "\t" + password);
return "kun : 跳";
}
@RequestMapping("/pojo")
public String getByPojo(@RequestBody IkunDto ikunDto) {
log.info("dto:" + ikunDto);
return "kun : rep";
}
@RequestMapping("/more")
public String getByMore(@RequestBody Map<String, Object> map) {
log.info("more:" + map);
return "??";
}
}
3、服務(wù)消費(fèi)者(ikun)?
I. 創(chuàng)建Server,并使用Feign表示其需要遠(yuǎn)程對接的服務(wù)名稱,并使用@RequestMapping表示其映射的 路徑?
package com.example.ikun.serice;
import pojo.dto.IkunDto;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.Map;
/**
* 連接生產(chǎn)者 Controller
*
* @author 云村小威
* @create 2024-01-06 15:40
*/
@FeignClient("basketball") //連接服務(wù)器名稱(服務(wù)提供者yml設(shè)置)
@RequestMapping("/kun")
public interface FeginKunService {
@RequestMapping("/{account}")
public String getByPath(@PathVariable(value = "account") String account);
@RequestMapping("/param")
public String getByParam(@RequestParam("account") String account,
@RequestParam("password") String password);
@RequestMapping("/pojo")
public String getByPojo(@RequestBody IkunDto ikunDto);
@RequestMapping("/more")
public String getByMore(@RequestBody Map<String, Object> map);
}
?II. 消費(fèi)者行為接口測試
package com.example.ikun.controller;
import com.example.ikun.serice.FeginKunService;
import pojo.dto.IkunDto;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;
@RestController
public class TestController {
@Autowired
private FeginKunService kunService;
@RequestMapping("/play01")
public String play() {
return kunService.getByPath("姬霓太美");
}
@RequestMapping("/play02")
public String play02() {
return kunService.getByParam("小黑子", "123");
}
@RequestMapping("/play03")
public String play03() {
return kunService.getByPojo(new IkunDto(1L, "純路人", "123", 5 / 2, "music"));
}
@RequestMapping("/play04")
public String play04() {
Map<String, Object> paramMap = new HashMap<>();
paramMap.put("真愛粉", new IkunDto(2L, "梅麗貓", "321", 5 / 2, "唱、跳、rep、籃球"));
return kunService.getByMore(paramMap);
}
}
III. 先啟動Nacos服務(wù)、在啟動項目
這里注意Nacos默認(rèn)為集群模式,本次示例并沒有連接數(shù)據(jù)庫,所以要修改為單機(jī)模式啟動
windows指令?: startup.cmd -m standalone
?
接著輸入nacos地址進(jìn)行登錄,賬號與密碼默認(rèn)為:nacos?
接著就可以看到已注冊的服務(wù)
最后接口測試:
2.3.1 服務(wù)注冊與發(fā)現(xiàn)測試
Nacos服務(wù)注冊與發(fā)現(xiàn)的流程:
1、服務(wù)注冊:
- 在微服務(wù)啟動時,它會向 Nacos 服務(wù)注冊自己的信息,包括 IP 地址、端口號、服務(wù)名稱等。
- 通過 Nacos 的客戶端 SDK 或與之集成的框架(如 Spring Cloud)來完成服務(wù)注冊。
2、服務(wù)發(fā)現(xiàn):
- 當(dāng)一個服務(wù)需要調(diào)用另一個服務(wù)時,它會向 Nacos 發(fā)送一個服務(wù)發(fā)現(xiàn)請求,請求特定服務(wù)名稱的所有可用實例。
- Nacos 會返回該服務(wù)名稱對應(yīng)的所有服務(wù)實例信息,包括 IP 地址和端口號。
- 調(diào)用方可以根據(jù)負(fù)載均衡策略選擇一個實例進(jìn)行調(diào)用,從而實現(xiàn)服務(wù)間的通信。
2.3.2 負(fù)載均衡測試?
為了更好體現(xiàn)負(fù)載均衡的作用,這里將basketball與ikun兩個模塊進(jìn)行打包運(yùn)行測試
Tip:
請看上面這張動圖:首先我啟用了兩個生產(chǎn)者(basketball)和一個消費(fèi)者(ikun),在ikun調(diào)用basketball方法時,它是實現(xiàn)了負(fù)載均衡的(各自權(quán)重都為1)。而我把一個basketball關(guān)掉之后,它并立刻沒有把服務(wù)下線。原因是服務(wù)它會時刻會向Nacos發(fā)送心跳證明我還活著,如果關(guān)掉某個服務(wù),Nacos會給服務(wù)10秒的等待時間,10秒內(nèi)服務(wù)沒有向Nacos發(fā)送心跳就會把他下線不在使用此服務(wù)。文章來源:http://www.zghlxwxcb.cn/news/detail-777473.html
文章來源地址http://www.zghlxwxcb.cn/news/detail-777473.html
到了這里,關(guān)于【SpringCloud Alibaba】Nacos服務(wù)管理與Feign負(fù)載均衡的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!