基于spring cloud alibaba 搭建微服務(wù)。
父工程的創(chuàng)建
父工程選擇使用spring boot 2.3.0.RELEASE,JDK 8,idea 2021,Windows 10。
<?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>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.0.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.noel.cloud</groupId>
<artifactId>alibaba</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>alibaba</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</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>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Hoxton.SR3</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.2.1.RELEASE</version>
</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>
編輯器生成代碼后,添加cloudHoxton.SR3和alibaba cloud。spring boot-> spring cloud-> spring cloud alibaba。
服務(wù)治理中心

如上圖所示的微服務(wù)群,各個微服務(wù)往服務(wù)治理中心注冊服務(wù),即充當(dāng)服務(wù)提供者角色;然后其它微服務(wù)通過服務(wù)治理中心獲取其它服務(wù)的信息,并調(diào)用這些服務(wù),此時充當(dāng)服務(wù)消費(fèi)者角色。其中服務(wù)治理中心使用naocs實(shí)現(xiàn)。
nacos下載1.2.1,因?yàn)槭褂玫腶libaba版本,對應(yīng)的nacos可以選擇1.2.1:

下載后解壓到一個位置,然后雙擊bin\startup.cmd即啟動服務(wù)治理中心,通過http://localhost:8848/nacos即可訪問,默認(rèn)訪問端口是8848,用戶名和密碼均是nacos。
服務(wù)提供者
使用springboot 創(chuàng)建子模塊,不用選擇依賴,生成代碼后更改繼承關(guān)系,更改<parent>數(shù)據(jù):

然后添加nacos依賴:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>2.2.1.RELEASE</version>
</dependency>
最后配置spring boot項(xiàng)目:
spring:
cloud:
nacos:
discovery:
server-addr: nacos的ip或者域名:nacos的端口
application:
name: provider #指定當(dāng)前項(xiàng)目的名稱,便于在nacos中顯示
啟動項(xiàng)目,即可在nacos網(wǎng)頁中,即可看見運(yùn)行的服務(wù)提供者:

服務(wù)消費(fèi)者
父工程中創(chuàng)建一個子模塊,創(chuàng)建和修改繼承關(guān)系和提供者一樣,而且應(yīng)為需要通過nacos獲取服務(wù),所以也需要添加和提供者一樣的nacos服務(wù)。消費(fèi)者調(diào)用提供者的方法有幾個方法,下面一次列舉,消費(fèi)者的端口定義為8180:
方法一,獲取所有服務(wù)提供者:
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.RestController;
@RestController
public class ConsumerController {
@Autowired
private DiscoveryClient discoveryClient;
@GetMapping("/instance")
public List<ServiceInstance> instances(){
List<ServiceInstance> providers = this.discoveryClient.getInstances("provider");
return providers;
}
}

獲取nacos上所注冊的所有服務(wù)提供者,provider為服務(wù)器提供者的application-name。
方法二,調(diào)用服務(wù)提供者的某些方法:
服務(wù)提供方:
@RestController
public class ProviderController {
@Value("${server.port}")
private String port;
@GetMapping("/index")
public String index(){
//實(shí)現(xiàn)一個簡單的返回服務(wù)提供者的端口功能
return this.port;
}
}
消費(fèi)者:
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.RestController;
import org.springframework.web.client.RestTemplate;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
/**
* @Description 服務(wù)消費(fèi)者,調(diào)用服務(wù)提供者的方法,獲取其返回的端口數(shù)據(jù)。
* @Author noel
* @Date 2021/7/19
* Version 1.0
**/
@RestController
public class ConsumerController {
//使用springboot 集成的Nacos客戶端發(fā)現(xiàn)功能,自動注入
@Autowired
private DiscoveryClient discoveryClient;
//restTemplate 需要手動注入,通過添加配置類實(shí)現(xiàn)
@Autowired
private RestTemplate restTemplate;
/**
* 通過nacos獲取“provider”服務(wù),如果該服務(wù)有集群,則隨機(jī)獲取其中一個
**/
@GetMapping("/index")
public String index(){
List<ServiceInstance> provider = this.discoveryClient.getInstances("provider");
int index = ThreadLocalRandom.current().nextInt(provider.size());
ServiceInstance serviceInstance = provider.get(index);
String url = serviceInstance.getUri()+ "/index";//服務(wù)提供者的接口
//指定String.class是因?yàn)榉?wù)提供者返回的是字符串
return "調(diào)用的端口是"+serviceInstance.getPort()+"的服務(wù),返回結(jié)果是:"+ restTemplate.getForObject(url, String.class);
}
}
// ========================================
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
/**
* @Description 將RestTemplate配置為Bean
* @Author noel
* @Date 2021/7/22
* Version 1.0
**/
@Configuration
public class RestTemplateConfig {
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
服務(wù)消費(fèi)者照普通spring boot項(xiàng)目啟動后,訪問index接口即對服務(wù)提供者產(chǎn)生了調(diào)用。
Ribbon優(yōu)化服務(wù)消費(fèi)者

在使用springcloud的時候,就已經(jīng)加載了Ribbon,然后修改兩個地方即有效的使用Ribbon進(jìn)行負(fù)載均衡,這是客戶端負(fù)載均衡,而且比上面的客戶端使用隨機(jī)數(shù)調(diào)用服務(wù)者更優(yōu)雅。
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
@Configuration
public class RestTemplateConfig {
@Bean
@LoadBalanced //增加的注解,
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
在RestTemplate配置類中,添加@LoadBalanced注解,即表明調(diào)用方式使用了負(fù)載均衡。此處默認(rèn)使用了輪詢的方式。
@GetMapping("/index")
public String index(){
// List<ServiceInstance> provider = this.discoveryClient.getInstances("provider");
// int index = ThreadLocalRandom.current().nextInt(provider.size());
// ServiceInstance serviceInstance = provider.get(index);
// String url = serviceInstance.getUri()+ "/index";
// return "調(diào)用的端口是"+serviceInstance.getPort()+"的服務(wù),返回結(jié)果是:"+ restTemplate.getForObject(url, String.class);
return this.restTemplate.getForObject("http://provider/index", String.class);
}
只需指明服務(wù)提供者的地址即可,其中訪問地址中的provider使用的是服務(wù)提供者的application name值。
P.S. 課程參考