一、cloud組件
二、環(huán)境搭建
2.1 創(chuàng)建父工程
2.2 支付模塊構(gòu)建
2.3 消費者模塊構(gòu)建
2.3.1 引入RestTemplate
@Configuration
public class ApplicationContextConfig {
// 配置bean 不然后面沒法依賴注入,就像以前ssm整合時配置依賴注入一樣,
// 需要在配置文件配置之后,代碼中才可以依賴注入
// 當(dāng)前文件就是spring的配置文件
@Bean
// @LoadBalanced //讓這個RestTemplate在請求時擁有客戶端負載均衡的能力 //將此注解注釋掉,使用自己的輪詢算法不使用默認的
public RestTemplate getRestTemplate() {
return new RestTemplate();
}
}
2.3.2 遠程調(diào)用支付模塊
@RestController
public class OrderController {
public static final String PAYMENT_URL = "http://localhost:8001";
public static final String PAYMENT_URL = "http://CLOUD-PAYMENT-SERVICE";
@Resource
private RestTemplate restTemplate;
@GetMapping("/testRPC/{id}")
public CommonResult<Payment> getPayment(@PathVariable("id") String id) {
return restTemplate.getForObject(PAYMENT_URL + "/test/" + id, CommonResult.class);
}
}
三、Eureka
3.1 基礎(chǔ)知識
前面我們沒有服務(wù)注冊中心,也可以服務(wù)間調(diào)用,為什么還要服務(wù)注冊?
當(dāng)服務(wù)很多時,單靠代碼手動管理是很麻煩的,需要一個公共組件,統(tǒng)一管理多服務(wù),包括服務(wù)是否正常運行,等
Eureka用于**服務(wù)注冊,目前官網(wǎng)已經(jīng)停止更新**
3.2 單機版Eureka安裝
創(chuàng)建項目cloud-eureka-server-7001
引入依賴
<dependencies>
<!-- 服務(wù)注冊中心的服務(wù)端 eureka-server -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
</dependencies>
yml配置文件
server:
port: 7001
# 單機版
eureka:
instance:
hostname: localhost #eureka服務(wù)端的實例名字
client:
register-with-eureka: false #表示不向注冊中心注冊自己
fetch-registry: false #表示自己就是注冊中心,職責(zé)是維護服務(wù)實例,并不需要去檢索服務(wù)
service-url:
#設(shè)置與eureka server交互的地址查詢服務(wù)和注冊服務(wù)都需要依賴這個地址
defaultZone: http://${eureka.instance.hostname}:${server.port}
啟動類
/**
* @author WSKH
* @date 2020/12/19 14:12
* @description 注冊中心
*/
@SpringBootApplication
@EnableEurekaServer // 啟動Eureka服務(wù)
public class CloudEurekaServer7001Application {
public static void main(String[] args) {
SpringApplication.run(CloudEurekaServer7001Application.class, args);
System.out.println("啟動成功!");
}
}
3.3 服務(wù)注冊
引入依賴
<!-- 服務(wù)注冊中心的客戶端端 eureka-client -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
yaml配置
server:
port: 8001
spring:
application:
name: cloud-payment-service
eureka:
client:
register-with-eureka: true #是否向注冊中心注冊自己
fetchRegistry: true #是否從注冊中心抓取已有的注冊信息 默認true,集群必須設(shè)置為true
service-url:
# 設(shè)置與eureka server交互的地址查詢服務(wù)和注冊服務(wù)都需要依賴這個地址
defaultZone: http://localhost:7001 #單機版
instance:
instance-id: payment8001
prefer-ip-address: true #訪問路徑可以顯示IP地址
# Eureka客戶端向服務(wù)端發(fā)送心跳的時間間隔,單位為秒(默認是30秒)
# lease-renewal-interval-in-seconds: 1
# Eureka服務(wù)端在收到最后一次心跳后等待時間上限,單位為秒(默認是90秒),超時將剔除服務(wù)
# lease-expiration-duration-in-seconds: 2
啟動類
@SpringBootApplication
@EnableEurekaClient // 指定成為Eureka客戶端
@EnableDiscoveryClient // 開啟服務(wù)發(fā)現(xiàn)
@Slf4j
public class CloudProviderPayment8001Application {
public static void main(String[] args) {
SpringApplication.run(CloudProviderPayment8001Application.class, args);
log.info("cloud-provider-payment-8001 啟動成功!");
}
}
3.4 Eureka集群
單機版注冊中心會出現(xiàn)單點故障,故一般都采用集群
兩臺或以上的Rureka互相注冊,相互守望,對外暴露端口
3.4.1 Eureka端配置
7001的yaml配置
server:
port: 7001
#集群版
eureka:
instance:
hostname: eureka7001 #eureka服務(wù)端的實例名字(實際好像不起作用,DS Replicas是直接截取URL中冒號前面的部分,當(dāng)作隊友名,如http://localhost:7001,那就截取localhost當(dāng)作隊友名)
client:
register-with-eureka: false #表示不向注冊中心注冊自己
fetch-registry: false #表示自己就是注冊中心,職責(zé)是維護服務(wù)實例,并不需要去檢索服務(wù)
service-url:
#設(shè)置與eureka server交互的地址查詢服務(wù)和注冊服務(wù)都需要依賴這個地址
# defaultZone: http://eureka7001.com:7001
defaultZone: http://localhost:7002 #這個是集群版開啟 互相注冊
# server:
## 關(guān)閉自我保護機制,保證不可用服務(wù)被及時踢除
# enable-self-preservation: false
# eviction-interval-timer-in-ms: 2000
7002的yaml配置
server:
port: 7002
#集群版
eureka:
instance:
hostname: eureka7002 #eureka服務(wù)端的實例名字(實際好像不起作用,DS Replicas是直接截取URL中冒號前面的部分,當(dāng)作隊友名,如http://localhost:7001,那就截取localhost當(dāng)作隊友名)
client:
register-with-eureka: false #表識不向注冊中心注冊自己
fetch-registry: false #表示自己就是注冊中心,職責(zé)是維護服務(wù)實例,并不需要去檢索服務(wù)
service-url:
#設(shè)置與eureka server交互的地址查詢服務(wù)和注冊服務(wù)都需要依賴這個地址
defaultZone: http://localhost:7001
3.4.2 微服務(wù)端配置
server:
port: 80
spring:
application:
name: cloud-order-service
eureka:
client:
register-with-eureka: true #是否向注冊中心注冊自己
fetchRegistry: true #是否從注冊中心抓取已有的注冊信息 默認true,集群必須設(shè)置為true
service-url:
#設(shè)置與eureka server交互的地址查詢服務(wù)和注冊服務(wù)都需要依賴這個地址
defaultZone: http://localhost:7001,http://localhost:7002 #集群版
server:
port: 8001
spring:
application:
name: cloud-payment-service
eureka:
client:
register-with-eureka: true #是否向注冊中心注冊自己
fetchRegistry: true #是否從注冊中心抓取已有的注冊信息 默認true,集群必須設(shè)置為true
service-url:
# 設(shè)置與eureka server交互的地址查詢服務(wù)和注冊服務(wù)都需要依賴這個地址
defaultZone: http://localhost:7001,http://localhost:7002 #集群版
instance:
instance-id: payment8001
prefer-ip-address: true #訪問路徑可以顯示IP地址
# Eureka客戶端向服務(wù)端發(fā)送心跳的時間間隔,單位為秒(默認是30秒)
# lease-renewal-interval-in-seconds: 1
# Eureka服務(wù)端在收到最后一次心跳后等待時間上限,單位為秒(默認是90秒),超時將剔除服務(wù)
# lease-expiration-duration-in-seconds: 2
3.4.3 restTemplate負載均衡
加入@LoadBalanced注解即可開啟負載均衡
@Configuration
public class ApplicationContextConfig {
// 配置bean 不然后面沒法依賴注入,就像以前ssm整合時配置依賴注入一樣,
// 需要在配置文件配置之后,代碼中才可以依賴注入
// 當(dāng)前文件就是spring的配置文件
@Bean
@LoadBalanced //讓這個RestTemplate在請求時擁有客戶端負載均衡的能力 //將此注解注釋掉,使用自己的輪詢算法不使用默認的
public RestTemplate getRestTemplate() {
return new RestTemplate();
}
}
測試
@RestController
public class OrderController {
// http://服務(wù)名大寫
public static final String PAYMENT_URL = "http://CLOUD-PAYMENT-SERVICE";
@Resource
private RestTemplate restTemplate;
@GetMapping("/testLoadBalancedRpc/{id}")
public CommonResult<Payment> testLoadBalancedRpc(@PathVariable("id") String id) {
return restTemplate.getForObject(PAYMENT_URL + "/test/"+id, CommonResult.class);
}
}
最后發(fā)送請求 http://127.0.0.1:80/testLoadBalancedRpc/id=123 進行測試
發(fā)現(xiàn)會自動均衡地訪問8001和8002
3.4.4 主機名修改和ip地址顯示
3.5 服務(wù)發(fā)現(xiàn)Discovery
開啟服務(wù)發(fā)現(xiàn)
使用DiscoveryClient完成服務(wù)發(fā)現(xiàn)
// 注入DiscoveryClient對象
@Resource
DiscoveryClient discoveryClient;
@GetMapping("/testDiscoveryClient")
public void testDiscoveryClient(){
// 從注冊中心獲取所有服務(wù)的名稱
List<String> services = discoveryClient.getServices();
services.forEach(System.out::println);
// 根據(jù)服務(wù)名稱找到其下的所有實例
List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");
// 遍歷輸出實例信息
instances.forEach(instance -> {
System.out.println(instance.getServiceId() + "\t" + instance.getHost() + "\t" + instance.getPort() + "\t" + instance.getUri());
});
}
測試 http://127.0.0.1:8001/testDiscoveryClient
3.6 Rureka自我保護機制
3.7 禁止Eureka自我保護
#集群版
eureka:
instance:
hostname: eureka7001 #eureka服務(wù)端的實例名字
client:
register-with-eureka: false #表示不向注冊中心注冊自己
fetch-registry: false #表示自己就是注冊中心,職責(zé)是維護服務(wù)實例,并不需要去檢索服務(wù)
service-url:
#設(shè)置與eureka server交互的地址查詢服務(wù)和注冊服務(wù)都需要依賴這個地址
# defaultZone: http://eureka7001.com:7001/eureka/
defaultZone: http://localhost:7002 #這個是集群版開啟 互相注冊
# server:
## 關(guān)閉自我保護機制,保證不可用服務(wù)被及時踢除
# enable-self-preservation: false
# eviction-interval-timer-in-ms: 2000
四、Zookeeper
五、Consul
5.1 簡介
5.2 安裝
中文官網(wǎng): https://www.spring.cloud.cc/spring-cloud-consul.html
英文官網(wǎng):https://www.consul.io
需要下載一個安裝包
查看版本
啟動是一個命令行界面,需要輸入consul agent -dev啟動
http://localhost:8500
5.3 搭建項目
引入依賴
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
yaml配置
server:
port: 8006
spring:
application:
name: consul-provider-payment
cloud:
consul:
host: localhost
port: 8500
discovery:
service-name: ${spring.application.name}
啟動類
@SpringBootApplication
@EnableDiscoveryClient //該注解用于向使用consul或者zookeeper作為注冊中心時注冊服務(wù)
public class CloudProviderconsulPayment8006Application {
public static void main(String[] args) {
SpringApplication.run(CloudProviderconsulPayment8006Application.class, args);
System.out.println("啟動成功");
}
}
啟動App,查看服務(wù)注冊情況
六、三個注冊中心的異同點
七、Ribbon
7.1 入門介紹
7.2 使用Ribbon
默認我們使用eureka的新版本時,它默認集成了ribbon:
這個starter中集成了reibbon了
我們也可以手動引入ribbon
7.3 RestTemplate類
RestTemplate的:
xxxForObject()方法,返回的是響應(yīng)體中的數(shù)據(jù)
xxxForEntity()方法.返回的是entity對象,這個對象不僅僅包含響應(yīng)體數(shù)據(jù),還包含響應(yīng)體信息(狀態(tài)碼等)
7.4 Ribbon常用負載均衡算法
IRule接口,Riboon使用該接口,根據(jù)特定算法從所有服務(wù)中,選擇一個服務(wù),
Rule接口有7個實現(xiàn)類,每個實現(xiàn)類代表一個負載均衡算法
7.5 Ribbon負載均衡規(guī)則替換
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-jqERrsdi-1686926847827)(…/…/AppData/Roaming/Typora/typora-user-images/image-20220423202944560.png)]
配置類
@Configuration
public class MySelfRule {
@Bean
public IRule myRule() {
// 此處將ribbon默認使用的輪詢策略改為隨機策略
return new RandomRule();
}
}
啟動類
@SpringBootApplication
@EnableEurekaClient
@EnableDiscoveryClient
// 啟動CLOUD-PAYMENT-SERVICE服務(wù)時去加載自定義的ribbon配置
@RibbonClient(name = "CLOUD-PAYMENT-SERVICE", configuration = MySelfRule.class)
@Slf4j
public class CloudConsumerOrder80Application {
public static void main(String[] args) {
SpringApplication.run(CloudConsumerOrder80Application.class, args);
log.info("cloud-consumer-order-80 啟動成功!");
}
}
7.6 輪詢算法原理
7.7 源碼分析
7.8 手寫輪詢算法
public interface MyLoadBalancer {
/**
* 收集服務(wù)器總共有多少臺能夠提供服務(wù)的機器,并放到list里面
*
* @param serviceInstances
* @return ServiceInstance
* @author WSKH
* @date 2020/12/23 9:24
*/
ServiceInstance instances(List<ServiceInstance> serviceInstances);
}
@Component
public class MyLB implements MyLoadBalancer {
// 原子類
private final AtomicInteger atomicInteger = new AtomicInteger(0);
/**
* @author WSKH
* @date 2020/12/23 10:07
* @description 判斷時第幾次訪問
*/
public final int getAndIncrement() {
int current;
String a = "current";
int next = 0;
do {
current = atomicInteger.get();
// 防止越界
next = current >= Integer.MAX_VALUE ? 0 : current + 1;
} while (!atomicInteger.compareAndSet(current, next));
System.out.println("*****第幾次訪問,次數(shù)next: " + next);
return next;
}
/**
* 負載均衡算法:rest接口第幾次請求數(shù) % 服務(wù)器集群總數(shù)量 = 實際調(diào)用服務(wù)器位置下標(biāo), 每次服務(wù)重啟動后rest接口計數(shù)從1開始。1
*
* @param serviceInstances
* @return ServiceInstance
* @author WSKH
* @date 2020/12/23 9:51
*/
@Override
public ServiceInstance instances(List<ServiceInstance> serviceInstances) {
int index = getAndIncrement() % serviceInstances.size();
return serviceInstances.get(index);
}
}
// 注入自定義的負載均衡規(guī)則
@Resource
private MyLoadBalancer myLoadBalancer;
@Resource
private DiscoveryClient discoveryClient;
/**
* @author WSKH
* @date 2020/12/23 10:27
* @description 測試自定義的負載均衡規(guī)則
*/
@GetMapping(value = "/payment/lb")
public String getPaymentLB() {
List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");
if (instances == null || instances.isEmpty()) {
return null;
}
// 調(diào)用自定義的負載均衡策略
ServiceInstance serviceInstance = myLoadBalancer.instances(instances);
URI uri = serviceInstance.getUri();
return restTemplate.getForObject(uri + "/payment/lb", String.class);
}
八、OpenFeign
8.1 什么是OpenFeign
文章來源:http://www.zghlxwxcb.cn/news/detail-497807.html
8.2 OpenFeign服務(wù)調(diào)用
未完待續(xù)...
文章來源地址http://www.zghlxwxcb.cn/news/detail-497807.html
到了這里,關(guān)于【后端開發(fā)】尚硅谷 SpringCloud 學(xué)習(xí)筆記的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!