基于spring cloud alibaba 搭建微服務闸天。
父工程的創(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磁滚。
服務治理中心
如上圖所示的微服務群恨旱,各個微服務往服務治理中心注冊服務坝疼,即充當服務提供者角色钝凶;然后其它微服務通過服務治理中心獲取其它服務的信息,并調(diào)用這些服務掂名,此時充當服務消費者角色饺蔑。其中服務治理中心使用naocs實現(xiàn)嗜诀。
nacos下載1.2.1,因為使用的alibaba版本发皿,對應的nacos可以選擇1.2.1:
下載后解壓到一個位置穴墅,然后雙擊bin\startup.cmd
即啟動服務治理中心,通過http://localhost:8848/nacos
即可訪問皇钞,默認訪問端口是8848
鹅士,用戶名和密碼均是nacos
惩坑。
服務提供者
使用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項目:
spring:
cloud:
nacos:
discovery:
server-addr: nacos的ip或者域名:nacos的端口
application:
name: provider #指定當前項目的名稱侣集,便于在nacos中顯示
啟動項目世分,即可在nacos網(wǎng)頁中缀辩,即可看見運行的服務提供者:
服務消費者
父工程中創(chuàng)建一個子模塊臀玄,創(chuàng)建和修改繼承關(guān)系和提供者一樣健无,而且應為需要通過nacos獲取服務,所以也需要添加和提供者一樣的nacos服務募胃。消費者調(diào)用提供者的方法有幾個方法畦浓,下面一次列舉讶请,消費者的端口定義為8180:
方法一夺溢,獲取所有服務提供者:
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上所注冊的所有服務提供者嘉汰,provider
為服務器提供者的application-name
状勤。
方法二持搜,調(diào)用服務提供者的某些方法:
服務提供方:
@RestController
public class ProviderController {
@Value("${server.port}")
private String port;
@GetMapping("/index")
public String index(){
//實現(xiàn)一個簡單的返回服務提供者的端口功能
return this.port;
}
}
消費者:
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 服務消費者葫盼,調(diào)用服務提供者的方法,獲取其返回的端口數(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 需要手動注入钱反,通過添加配置類實現(xiàn)
@Autowired
private RestTemplate restTemplate;
/**
* 通過nacos獲取“provider”服務面哥,如果該服務有集群,則隨機獲取其中一個
**/
@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";//服務提供者的接口
//指定String.class是因為服務提供者返回的是字符串
return "調(diào)用的端口是"+serviceInstance.getPort()+"的服務归榕,返回結(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();
}
}
服務消費者照普通spring boot項目啟動后吱涉,訪問index
接口即對服務提供者產(chǎn)生了調(diào)用。
Ribbon優(yōu)化服務消費者
在使用springcloud的時候怎爵,就已經(jīng)加載了Ribbon鳖链,然后修改兩個地方即有效的使用Ribbon進行負載均衡,這是客戶端負載均衡狂秦,而且比上面的客戶端使用隨機數(shù)調(diào)用服務者更優(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)用方式使用了負載均衡甜孤。此處默認使用了輪詢的方式缴川。
@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()+"的服務描馅,返回結(jié)果是:"+ restTemplate.getForObject(url, String.class);
return this.restTemplate.getForObject("http://provider/index", String.class);
}
只需指明服務提供者的地址即可铭污,其中訪問地址中的provider
使用的是服務提供者的application name
值嘹狞。
P.S. 課程參考