SpringCloud 微服務分佈式
軟件行業分類:
傳統軟件行業
互聯網軟件行業
軟件架構分類:
微服務
單體架構
單體應用
一個歸檔包(可以是JAR、WAR、EAR或其它歸檔格式)包含所有功能的應用程序,通常稱爲
單體應用。
優點
- 便於共享: 單個歸檔文件包含所有功能,便於在團隊之間以及不同的部署階段之間共享。
- 易於測試:
單體應用一旦部署,所有的服務或特性就都可以使用了,這簡化了測試過程。
因爲沒有額外的依賴,每項測試都可以在部署完成後立刻開始。- 易於部署: 只需將單個歸檔文件複製到單個目錄下。
缺點
- 複雜性高:
由於是單個歸檔文件,所以一個文件 等於 整個項目,文件包含的模塊非常多,導致模塊的邊界模糊。
依賴關係不清晰、代碼的質量參差不齊,混亂的堆在一起,使得整個項目非常複雜。
以致每次修改代碼,都非常小心,可能添加一個簡單的功能,或者修改一個Bug都會帶來隱藏的缺陷。- 技術債務:
隨着時間的推移、需求的變更和技術人員的更替,會逐漸形成應用程序的技術債務,並且越積越多。- 擴展能力受限:
單體應用只能作爲一個整體進行擴展,無法根據業務模塊的需要進行伸縮。
(爲了提高項目性能可以, 將一個項目複製多份部署多臺服務器~)- 阻礙技術創新:
對於單體應用來說,技術是在開發之前經過慎重評估後選定的,
每個團隊成員都必須使用相同的開發語言、持久化存儲及消息系統。
微服務
2014 ,martin fowler馬丁·福勒
提出的:微服務架構風格
常聽的:分佈式微服務
優點:
一個應用拆分爲一組小型服務
每一個服務: 運行在自己的進程內,也就是可獨立部署和升級,擁有自己獨立的數據庫。通過HTTP的方式進行互通;
• 優點
• 服務圍繞業務功能拆分
• 可以由全自動部署機制獨立部署
• 微服務能夠被小團隊單獨開發,這個小團隊是2到5人的開發人員組成。
• 微服務是松耦合的,是有功能意義的服務,無論是在開發階段或部署階段都是獨立的。
• 去中心化,服務自治。服務可以使用不同的語言、不同的存儲技術;只要實現功能即可~
•微服務只是業務邏輯的代碼,不會和HTML,CSS 或其他界面組件混合。
•每個微服務都有自己的存儲能力,可以有自己的數據庫。也可以有統一數據庫。
上圖:微服務分佈式架構,每一個點表示一個功能, 使用時只需要調用需要的功能模塊組合即可!
缺點:
- 運維要求高: 更多的服務意味着要投入更多的運維。
- 分佈式固有的複雜性:
使用微服務構建的是分佈式系統。對於一個分佈式系統,系統容錯、網絡延遲、
分佈式事務等都會帶來巨大的問題。- 接口調整成本高:
微服務之間通過接口進行通信。
如果修改某一個微服務的API,可能所有用到這個接口的微服務都需要進行調整。
遠程調用、服務發現、負載均衡、服務容錯、配置管理、服務監控、鏈路追蹤、日誌管理、任務調度……
相關概念
Provider和Consumer
分佈式微服務架構中,把一個應用差分爲多個 功能模塊; 每個功能模塊專注做自己的事情…
當需要實現某一功能時候, 只需要對多個需要的 功能模塊直接相互調用即可…
那麼每個模塊即是 Provider也是Consumer
(提供者和調用者)…
RPC和Restful
什麼叫RPC
- RPC【Remote Procedure Call】是指
遠程過程調用
是一種進程間通信方式,他是一種技術的思想,而不是規範。
它允許程序調用另一個地址空間(通常是共享網絡的另一臺機器上)的過程或函數,
而不用程序員顯式編碼這個遠程調用的細節。
即程序員無論是調用本地的還是遠程的函數,本質上編寫的調用代碼基本相同。即網絡通信
什麼是REST
- REST是一種
架構風格
,指的是一組架構約束條件和原則。 - 滿足這些約束條件和原則的應用程序或設計就是 RESTful。
- REST規範把所有內容都視爲資源,網絡上一切皆資源。
- REST並沒有創造新的技術,組件或服務,只是使用Web的現有特徵和能力。
- 可以完全通過HTTP協議實現,使用 HTTP 協議處理數據通信。
- REST架構對資源的操作包括獲取、創建、修改和刪除資源的操作
正好對應HTTP協議提供的GET、POST、PUT和DELETE方法。 - 這個之前學MVC時候學習過…
分佈式
一個應用拆分爲多個不同的功能模塊,做不同的事情
!
集羣
一臺服務器,承受不住某個工作,爲了減輕服務器壓力,做集羣 負載均價…多個設備做同一見事情!
選擇SpringCloud作爲微服務
選型依據
- 整體解決方案和框架成熟度
- 社區熱度
- 可維護性
- 學習曲線
當前各大IT公司用的微服務架構有哪些?
- 阿里Dubbo/HSF
- 京東JSF
- 新浪微博Motan
- 噹噹網DubboX
各微服務框架對比
分佈式基礎理論
什麼是分佈式系統?
《分佈式系統原理與範型》定義:
“分佈式系統是若干獨立計算機的集合,這些計算機對於用戶來說就像單個相關係統”
分佈式系統(distributed system)是建立在網絡之上的軟件系統。
發展演變
單一應用架構——垂直應用架構——分佈式服務架構——流動計算架構
單一應用架構
當網站流量很小時,只需一個應用,將所有功能都部署在一起,
以減少部署節點和成本。此時,用於簡化增刪改查工作量的數據訪問框架(ORM)是關鍵。
適用於小型網站,小型管理系統,將所有功能都部署到一個功能裏,簡單易用。
缺點:
性能擴展比較難 協同開發問題 不利於升級維護...
垂直應用架構
當訪問量逐漸增大,單一應用增加機器帶來的加速度越來越小,將應用拆成互不相干的幾個應用
以提升效率。此時,用於加速前端頁面開發的Web框架(MVC)是關鍵。
通過切分業務來實現各個模塊獨立部署:
降低了維護和部署的難度,團隊各司其職更易管理,性能擴展也更方便,更有針對性。
缺點: 公用模塊無法重複利用,開發性的浪費
分佈式服務架構
當垂直應用越來越多,應用之間交互不可避免,將核心業務抽取出來,
作爲獨立的服務,逐漸形成穩定的服務中心,使前端應用能更快速的響應多變的市場需求。
此時,用於提高業務複用及整合的分佈式服務框架(RPC)
是關鍵。
流動計算架構
當服務越來越多,容量的評估,小服務資源的浪費等問題逐漸顯現,
此時需增加一個調度中心基於訪問壓力實時管理集羣容量,提高集羣利用率。
提高機器利用率的資源調度 和 治理中心(SOA)[ Service Oriented Architecture]
是關鍵。
springClond入門 應用開發
SpringBoot和SpringCloud的區別
- SpringBoot專注於快速方便的開發單個個體微服務。
- SpringCloud是關注全局的微服務協調整理治理框架
它將SpringBoot開發的一個個單體微服務整合並管理起來:爲各個微服務之間提供
配置管理、服務發現、斷路器、路由、微代理、事件總線、全局鎖、決策競選、分佈式會話等等集成服務… - SpringBoot可以離開SpringCloud獨立使用開發項目,但是SpringCloud離不開SpringBoot,屬於
依賴的關係
- SpringBoot專注於快速、方便的開發單個微服務個體
- SpringCloud關注全局的服務治理框架。
搭建springcloud工程 分佈式服務架構
創建一個普通的Maven項目
爲了方便開發使用 Maven高級應用...
開發項目:
當然你也可以不用Maven來測試,多起幾個項目工程…
刪掉主工程的src (反之也用不上
主工程的pom.xml
中加入公共依賴
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>SpringCloudBJ</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<!-- Maven父工程包含管理的子工程... -->
<modules>
<module>common_api</module>
<module>common_orderService</module>
<module>common_userService</module>
</modules>
<!-- SpringBoot父依賴 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.6.RELEASE</version>
</parent>
<!-- 統一設置Maven項目編碼 jdk環境 -->
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!-- spring-boot的web依賴 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- spring-boot的應用日誌依賴 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</dependency>
<!-- spring-boot的單元測試依賴 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- lombok的依賴組件,別忘了要下載Idea lombok的插件哦~ -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.4</version>
<scope>provided</scope>
</dependency>
</dependencies>
<!-- 指定SpringCloud配置必要!! -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Greenwich.RELEASE</version> <!-- 版本... -->
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<!-- maven的默認下載資源.. -->
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
</project>
關於SpringCloud版本:Greenwich
SpringCloud版本更新非常快!A B C D E F G H目前最高已經到H了
我湊!!
2021年初
創建Maven子工程common_api實體模塊
主要存放項目開發所需要的實體類…
這裏只有一個實體類…沒有什麼太複雜的操作
Order.Java
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.RequiredArgsConstructor;
@Data
@AllArgsConstructor
@RequiredArgsConstructor
//創建一個實體類: 並根據lombok 及其註解生產對應的 構造函數,toString(); get/set...
public class Order {
private Integer id;
private String title;
private Double price;
private Integer uid;
}
pom.xml
不用任何添加或改動…看一下我其它Maven子工程如果調用;
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>SpringCloudBJ</artifactId>
<groupId>org.example</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>common_api</artifactId>
</project>
創建Maven子工程common_orderService訂單模塊
編寫訂單模塊相對於的代碼…
pom.xml
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>SpringCloudBJ</artifactId>
<groupId>org.example</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>common_orderService</artifactId>
<!-- 關鍵!! -->
<dependencies>
<!-- common_orderService工程引入common_api -->
<dependency>
<groupId>org.example</groupId>
<version>1.0-SNAPSHOT</version>
<artifactId>common_api</artifactId>
</dependency>
</dependencies>
</project>
OrderService.Java
import com.wsm.entity.Order;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
@Service
public class OrderService {
//模擬假訂單集合...
private static List<Order> orders = new ArrayList<>();
//類加載時候默認獲取一些數據..模擬假訂單..
static {
orders.add(new Order(1, "訂單11", 10.0, 1));
orders.add(new Order(2, "訂單21", 10.0, 2));
orders.add(new Order(3, "訂單31", 10.0, 1));
orders.add(new Order(4, "訂單41", 10.0, 2));
}
//根據輸入用戶id獲取當然用訂單集合..
public List<Order> findOrderByUser(Integer uid) {
List<Order> myorders = new ArrayList<>();
//遍歷集合從中獲取 uid一致的數據存放在集合中返回...
for (Order order : orders) {
if (order.getUid() == uid) {
myorders.add(order);
}
}
return myorders;
}
}
OrderController.Java
import com.wsm.entity.Order;
import com.wsm.service.OrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
public class OrderController {
@Autowired
private OrderService os;
//REST風格進行請求..
@GetMapping("/findOrderByUser/{uid}") //參數是以 /請求名/{參數1}/{參數2} 進行訪問的...
public List<Order> findOrderByUser(@PathVariable Integer uid){
//REST風格參數需要使用 @PathVariable獲取!!
return os.findOrderByUser(uid);
}
}
SpringBoot的主工程類:MyOrderServer.Java
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class MyOrderServer {
public static void main(String[] args) {
SpringApplication.run(MyOrderServer.class, args);
}
}
SpringBoot application.yml
配置文件
server:
port: 6001 #設置端口6001 當有多個微服務時候注意端口號可別衝突了..
spring:
application:
name: order-server #設置當然微服務名,後面的 註冊/調用服務,都是根據這個來的;
創建Maven子工程common_userService 用戶模塊
編寫用戶模塊相對於的代碼…
pom.xml
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>SpringCloudBJ</artifactId>
<groupId>org.example</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>common_userService</artifactId>
<dependencies>
<!-- common_userService工程引入common_api -->
<dependency>
<groupId>org.example</groupId>
<version>1.0-SNAPSHOT</version>
<artifactId>common_api</artifactId>
</dependency>
</dependencies>
</project>
UserService.Java
@Service
@Slf4j //加載lo4g使用...
public class UserService {
@Autowired
private RestTemplate restTemplate;
//通過restTemplate進行網絡通信,返回..其它遠程模塊的數據(雖然現在都是本地的不過就是模擬了..)
public List<Order> currentUserOrder(Integer uid) {
log.info("用戶服務調用訂單服務");
//硬編碼的調用!! 這裏的請求都寫死的...這好嗎?這不好...後面修改;
String myurl = "http://localhost:6001/findOrderByUser/" + uid;
log.info(myurl
);
List<Order> list = restTemplate.getForObject(myurl, List.class);
return list;
}
}
UserController.Java
//編程控制層,接受請求響應結果
@RestController
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/showUserOrder")
public List<Order> showUserOrder(Integer uid){
return userService.currentUserOrder(uid); //調用Service層
//Service又是通過網絡調用 訂單模塊來響應的結果,因此在此基礎上要缺點訂單模塊是運行中的...
}
}
SpringBoot的主工程類:MyUserServer.java
@SpringBootApplication
public class MyUserServer {
public static void main(String[] args) {
SpringApplication.run(MyUserServer.class, args);
}
@Bean
//實例化 RestTemplate 方便Service
//可別忘了@SpringBootApplication複合註解底層可以有@SpringBootConfiguration 它也是一個Spring的配置類!
public RestTemplate createRestTemplate() {
return new RestTemplate();
}
}
SpringBoot application.yml
配置文件
server:
port: 6002 #設置端口6002 當有多個微服務時候注意端口號可別衝突了..
spring:
application:
name: user-server #設置當然微服務名,後面的 註冊/調用服務,都是根據這個來的;
服務調用
前文已經編寫了三個基礎的微服務,在用戶下單時需要調用商品微服務獲取商品數據。
商品微服務提供了供人調用的HTTP接口
- 所以可以再下定單的時候使用http請求的相關工具類完成,
如常見的HttpClient,OkHttp,當然也可以使用Spring提供的RestTemplate
RestTemplate介紹
Spring框架提供的RestTemplate類可用於在應用中調用rest服務
它簡化了與http服務的通信方式,統一了RESTful的標準,封裝了http鏈接
- 我們只需要傳入url及返回值類型即可。相較於之前常用的HttpClient,
- RestTemplate是一種更優雅的調用RESTful服務的方式。
- RestTemplate類的設計原則與許多其他Spring 模板類(例如JdbcTemplate、JmsTemplate)相同
爲執行復雜任務提供了一種具有默認行爲的簡化方法。 - RestTemplate默認依賴JDK提供http連接的能力(HttpURLConnection)
如果有需要的話也可以通過setRequestFactory方法替換爲例如
Apache HttpComponents、Netty或OkHttp等其它HTTP library。 - 考慮到RestTemplate類是爲調用REST服務而設計的,因此它的主要方法與REST的基礎緊密相連就不足爲奇了
後者是HTTP協議的方法:HEAD、GET、POST、PUT、DELETE和OPTIONS。
RestTemplate類具有headForHeaders()、getForObject()、postForObject()、put()和delete()等方法。
硬編碼存在的問題
至此已經可以通過RestTemplate調用商品微服務的RESTFul API接口。
但是我們把提供者的網絡地址(ip,端口)等硬編碼到了代碼中,這種做法存在許多問題:
- 應用場景有侷限
- 無法動態調整
- …
那麼應該怎麼解決呢,就需要通過:註冊中心
動態的對服務註冊和服務發現
總結
以上就是一個典型的分佈式模塊架構
多模塊業務之間的相互調用 但↓↓↓↓
因爲是用戶模塊—引用—訂單模塊
訂單是提供者provide
用戶是調用者Consumer
- 而如果訂單模塊服務未開啓的情況下,會影響用戶模塊的使用!
注意!
- 而對應大量的模塊之間的調用, 隨着項目業務擴大…模塊之間的引用也會越來越複雜!!
- 而對於 A模塊服務停止 B模塊服務受影響…如果加劇呢 C模塊 D模塊…
B依賴A C依賴B D依賴C 而這時候A沒了會之間的造成服務的崩塌!!
爲了解決這種問題, 註冊中心
就出現了
服務註冊Eureka基礎
註冊中心可以說是微服務架構中的 ”通訊錄“,它記錄了服務和服務地址 映射關係在分佈式架構中
服務會註冊到這裏,當服務需要調用其它服務時,就這裏找到服務的地址,進行調用。
註冊中心的主要作用
服務註冊中心是微服務架構非常重要的一個組件,在微服務架構裏主要起到了協調者的一個作用。
註冊中心一般包含如下幾個功能:
- 服務發現:
提供者/調用者需要註冊聲明在註冊中心中才可以相互使用.
服務註冊/反註冊:保存服務提供者和服務調用者的信息
服務訂閱/取消訂閱:服務調用者訂閱服務提供者的信息,最好有實時推送的功能
服務路由(可選):具有篩選整合服務提供者的能力。 - 服務配置:
代碼上, 服務提供者/調度者需要配置註冊中心
配置訂閱:服務提供者和服務調用者訂閱微服務相關的配置
配置下發:主動將配置推送給服務提供者和服務調用者 - 服務健康檢測
服務要定時的向註冊中心提供心跳♥
告訴註冊中心我還在能幹活
當然註冊中心一般都有自我保護機制…
檢測服務提供者的健康情況
常見的註冊中心
- **Zookeeper **
zookeeper它是一個分佈式服務框架,是Apache Hadoop 的一個子項目
它主要是用來解決分佈式應用中經常遇到的一些數據管理問題,
如:統一命名服務、狀態同步服務、集羣管理、分佈式應用配置項的管理等。
簡單來說zookeeper=文件系統+監聽通知機制。 - Eureka
Eureka是在Java語言上,基於Restful Api開發的服務註冊與發現組件,Springcloud Netflflix中的重要組件 - Consul
Consul是由HashiCorp基於Go語言開發的支持多數據中心分佈式高可用的服務發佈和註冊服務軟件
採用Raft算法保證服務的一致性,且支持健康檢查 - Nacos
Nacos是一個更易於構建雲原生應用的動態服務發現、配置管理和服務管理平臺。
簡單來說 Nacos 就是註冊中心 + 配置中心的組合,提供簡單易用的特性集
幫助我們解決微服務開發必會涉及到的服務註冊與發現,服務配置,服務管理等問題。
**Nacos 還是 Spring Cloud Alibaba 組件之一,負責服務註冊與發現。 **
Eureka的基本架構
Spring Cloud 封裝了 Netflix 公司開發的 Eureka
Eureka 採用了 C-S 的設計架構。Eureka Server 作爲服務註冊功能的服務器,它是服務註冊中心。
- 使用 Eureka 的客戶端連接到 Eureka Server並維持心跳連接。
- 這樣系統的維護人員就可以通過 Eureka Server 來監控系統中各個微服務是否正常運行。
- Eureka包含兩個組件:
Eureka Server
和Eureka Client
- Eureka Server提供服務註冊
服務
各個節點啓動後,會在EurekaServer中進行註冊,
這樣EurekaServer中的服務註冊表中將會存儲所有可用服務節點的信息,
服務節點的信息可以在界面中直觀的看到 - EurekaClient是一個Java客戶端,用於簡化Eureka Server的交互
客戶端同時也具備一個內置的、使用輪詢(round-robin)負載算法的負載均衡器。
在應用啓動後,將會向Eureka Server發送心跳(默認週期爲30秒)。
如果Eureka Server在多個心跳週期內沒有接收到某個節點的心跳,EurekaServer將會從服務註冊表中把這個服務節點移除(默認90秒)
三大角色
- Eureka Server 提供服務註冊和發現
- Service Provider服務提供方將自身服務註冊到Eureka,從而使服務消費方能夠找到
- Service Consumer 服務消費方從Eureka獲取註冊服務列表,從而能夠消費服務
使用時先啓動註冊中心——Provider提供者——Consumer調用者
重構SpringCloud工程 流動計算架構
基於上面的SpringCloud的分佈式服務架構
開發
創建Maven子工程eureka-server 註冊中心
pom.xml
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>SpringCloudBJ</artifactId>
<groupId>org.example</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>eureka-server</artifactId>
<!-- Eureka-server服務依賴,必須! -->
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
</dependencies>
</project>
application.yml
server:
port: 7001 #設置註冊中心的 端口;
spring:
application:
name: eureka-server #註冊中心應用名稱;
#配置註冊中心....
eureka:
client:
service-url:
defaultZone: http://localhost:7001/eureka/ #註冊中心對外暴漏的註冊地址...
#要不要去註冊中心獲取其他服務的地址,默認爲true (目前只有一個註冊中心而且,當前就是註冊中心..)
fetch-registry: false
#是否將允許自己注入註冊中心,默認爲true (目前只有一個註冊中心而且,當前就是註冊中心..自己註冊自己?)
register-with-eureka: false #如果一個應用中有兩個註冊中心可以開啓,達到集羣註冊中心的目的...
主程序類MyEurekaServer.Java
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
@EnableEurekaServer //註解主程序開啓 Eureka服務
public class MyEurekaServer {
public static void main(String[] args) {
SpringApplication.run(MyEurekaServer.class, args);
}
}
@EnableEurekaServer
啓動註冊中心的服務, 表示當前項目作爲SpringCloud中的註冊中心
現在啓動程序就可以訪問當前的註冊中心了…
修改上面SpringBoot微服務 註冊到註冊中心中去!
common_orderService/userService註冊到註冊中心去:
加載註冊服務依賴
pom.xml
<!--- 註冊服務的依賴.. -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
主程序中加入 @EnableEurekaClient 注入註冊中心
以訂單的主程序爲例子, 其它也都這麼做
MyOrderServer.Java
@SpringBootApplication
@EnableEurekaClient
public class MyOrderServer {
public static void main(String[] args) {
SpringApplication.run(MyOrderServer.class, args);
}
}
@EnableEurekaClient 啓動註冊中心客戶端
表示當前主程序註冊到註冊中心去…
@EnableDiscoveryClient與@EnableEurekaClient區別
@EnableDiscoveryClient,一種爲@EnableEurekaClient,用法上基本一致。
- @EnableEurekaClient是針對於 Eureka註冊中心專門的啓動註冊
註解
- @EnableDiscoveryClient在包含了@EnableEurekaClient
它是對於所以註冊中心的一個統一開啓註解…
SpringBoot .yml文件的Eureka的配置
配置文件配置註冊中心 Eureka
(以業務order的爲例子)
application.yml
server:
port: 6001 #設置端口6001 當有多個微服務時候注意端口號可別衝突了..
spring:
application:
name: order-server #設置當然微服務名,後面的 註冊/調用服務,都是根據這個來的;
eureka:
client:
service-url:
defaultZone: http://localhost:7001/eureka/ #指定服務註冊的註冊中心;
instance:
prefer-ip-address: true #在Eureka上使用ip號..
instance-id: ${
spring.cloud.client.ip-address}:${
server.port} #在Eureka上顯示ip號..
最後別忘了把 common_userService中硬編碼解決了
UserService.Java
import com.wsm.entity.Order;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient; //這個DiscoveryClient別搞錯
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import java.util.List;
@Service
@Slf4j //加載lo4g使用...
public class UserService {
@Autowired
private RestTemplate restTemplate;
//通過restTemplate進行網絡通信,返回..其它遠程模塊的數據(雖然現在都是本地的不過就是模擬了..)
@Autowired //實現動態調用...
private DiscoveryClient discoveryClient;
public List<Order> currentUserOrder(Integer uid) {
//獲取註冊中心上的微服模塊實例 根據服務名;
//返回一個集合: 有可能這個服務在多個註冊中心上存在,`負載均衡~` 所以是一個集合;
List<ServiceInstance> instances = discoveryClient.getInstances("order-server");
ServiceInstance serviceInstance = instances.get(0); //而本次只有一個...
log.info("用戶服務調用訂單服務");
//動態調用服務 服務的host 服務端口號 這個就是服務controller請求 給其參數uid
String myurl = "http://" + serviceInstance.getHost() + ":" + serviceInstance.getPort() + "/findOrderByUser/" + uid;
log.info(myurl);
List<Order> list = restTemplate.getForObject(myurl, List.class);
return list;
}
}
動態的從註冊中心Eureka上獲取ip
查看這裏的 ip 192.168.1.1
- windows+r
- cmd
- 輸入ipconfig
- 如果是在同一個網段下, 可以實現不同電腦通過同一個註冊中心進行使用…
但我這個不上無線局域網配置器...
Eureka的服務剔除問題
在服務客戶端Client 配置的~
默認 30秒心跳💓 90秒續約時間…
.yml
eureka:
client:
service-url:
defaultZone: http://localhost:7001/eureka/ #指定服務註冊的註冊中心;
instance:
prefer-ip-address: true #在Eureka上顯示ip號..
instance-id: ${
spring.cloud.client.ip-address}:${
server.port} #在Eureka上顯示ip號..
lease-renewal-interval-in-seconds: 5 #客戶端向註冊中心發送心跳時間
lease-expiration-duration-in-seconds: 10 #如果沒有發送心跳的延遲續約時間...
如果客戶端的服務因爲某些原因關閉了。Eureka會根據心跳檢測到你沒了而移除你的服務…
- 客戶端定時向
註冊中心
發送心跳如果超過時間沒有發送 默認30秒 - 會有一個延遲等待時間. 默認90秒
兩分鐘~
如果還沒有啓動Eureka會把服務剔除… - 但, 因爲
Eureka自我保護機制
服務並不會真的 移除…而是會給你一個時間如果還沒有回來~則報錯!
Eureka自我保護機制
一般不會關閉自我保護機制,因爲如果服務又好了又可以立刻註冊會來使用...
在服務端即 註冊中心
關閉保護機制。。。
註冊中心的.yml
#配置註冊中心....
eureka:
client:
service-url:
defaultZone: http://localhost:7001/eureka/ #註冊中心對外暴漏的註冊地址...
#要不要去註冊中心獲取其他服務的地址,默認爲true (目前只有一個註冊中心而且,當前就是註冊中心..)
fetch-registry: false
#是否將允許自己注入註冊中心,默認爲true (目前只有一個註冊中心而且,當前就是註冊中心..自己註冊自己?)
register-with-eureka: false #如果一個應用中有兩個註冊中心可以開啓,達到集羣註冊中心的目的...
server:
enable-self-preservation: false #默認是ture 開啓的
eviction-interval-timer-in-ms: 4000 #默認是0 從不剔除!
保護機制只要關閉就會報錯!
而且只要服務失效就會移除…
nice 終於寫完了,建議三聯!!