spring cloud微服務項目搭建
===================================
示例版本:
1.spring boot 2.0版本
2.開發工具 IntellJ IDEA
===================================
一些特別注意的點:
1.創建spring boot項目
2.在父級項目下創建子級module【這一點曾經糾結了我好久】
3.父子級項目之間建立關系
4.eureka集群的創建
5.打包子級module必須保證父級項目已經打包了
6.target下所有的東西都是可以刪除的
7.命令啟動分布式中的集群服務
8.
===================================
搭建一個spring cloud項目的完整流程
1.idea上創建一個新的spring boot項目,名字就叫spring cloud
這一步 有 就點擊新窗口 沒有就算了
【如果使用的是maven的話】注意,新創建了新的項目以后,idea的關於maven倉庫地址的設置,需要重新設置一下
等待jar包下載完成,當前步驟下,整個項目結構如下:就是單個的spring boot項目
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>com.swapping</groupId> <artifactId>springcloud</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>springcloud</name> <description>Demo project for Spring Cloud</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.3.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <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> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
注意,有些idea自己的配置文件和項目沒有多大關系的,可以選擇忽略不顯示這些文件,忽略文件的操作:https://www.cnblogs.com/sxdcgaq8080/p/9007883.html
注意,把雜七雜八的文件隱藏后,干凈的項目顯示如下
因為現在要創建的是spring cloud項目,所以在當前的pom.xml文件中添加依賴如下:【完全復制,替換原pom.xml文件內容即可】【注意項目jar包版本問題】【注意最后打包 時候 jar要改成pom】

<?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>com.swapping</groupId> <artifactId>springcloud</artifactId> <version>0.0.1-SNAPSHOT</version> <!-- 注意 最后打包 最外層的pom 需要更改為 pom而不是jar <packaging>jar</packaging> --> <packaging>pom</packaging> <name>springcloud</name> <description>Demo project for Spring Cloud</description> <modules> <module>springcloud-ms-eureka</module> </modules> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.3.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> <spring-cloud.version>2.0.0.RELEASE</spring-cloud.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!--最外層 主項目 添加spring cloud依賴 https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter</artifactId> <version>${spring-cloud.version}</version> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Finchley.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
2.創建本項目的子module,也就是創建一個項目的子模塊
好了,現在進行第二步,在剛剛創建的項目上右鍵 創建子項目模塊【Eureka 服務注冊中心】
好,現在咱們看一下目前的項目結構
建立父子項目之間的聯系
OK,可以看出來。現在子級module已經成功創建了,但是 並不是說這個eureka子級項目在springcloud父級項目下,就是父子級了,必須得聲明一下,他們的父子級關系,
第一步》》》這個就需要在外層的父項目中的pom.xml文件中進行聲明:
這個地方聲明的子級項目的名字 對應的是自己項目的pom.xml文件中子級項目自己的名字
<modules> <module>springcloud-ms-eureka</module> </modules>
對應的是自己項目pom.xml文件中的名字
第二步》》》在子級的pom.xml文件中進行聲明
子級pom.xml文件中添加如下:
<parent> <groupId>com.swapping</groupId> <artifactId>springcloud</artifactId> <version>0.0.1-SNAPSHOT</version> </parent>
對應父級pom.xml中的
這樣聲明了以后,父子級項目的關系就建立起來了!!
父子級項目的處理咱們說道這里。
下面就看本微服務eureka的配置步驟:
第一步:
完善eureka微服務的完整的pom.xml文【注意spring boot2.0版本 eureka的jar包名字已經改變】

<?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>com.swapping</groupId> <artifactId>springcloud-ms-eureka</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>springcloud-ms-eureka</name> <description>eureka for project </description> <parent> <groupId>com.swapping</groupId> <artifactId>springcloud</artifactId> <version>0.0.1-SNAPSHOT</version> </parent> <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> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency> </dependencies> </project>
第二步:
在eureka微服務的啟動類中添加注解@EnableEurekaServer
第三步:
完善eureka的配置文件properties文件【或者yml文件】
在完善之前,可以先去hosts文件做一個簡單的小配置,有利於后續的一些展示
hosts文件位置如下:
在hosts文件中添加:
127.0.0.1 swapping1
127.0.0.1 swapping2
127.0.0.1 swapping3
OK,現在完善配置文件

#聲明本服務在注冊中心展示的名字、也是在網關訪問時定位服務的名字 spring.application.name=spring-cloud-ms-eureka #在windows下的hosts文件中增加了 127.0.0.1 swapping1 eureka.instance.hostname=swapping1 server.port=8000 #是否將自己作為服務注冊到注冊中心,默認為true,false不能將自己注冊到自己, #如果有多個服務注冊中心的微服務的話,可以將這個設置為true,表示可以將注冊中心1注冊到注冊中心2中 eureka.client.register-with-eureka=false #表示是否從eureka注冊中心中獲取注冊信息,默認為true eureka.client.fetch-registry=false #注冊中心的交互地址,設置多個地址可以用,分隔 查詢服務和注冊服務都需要依賴這個地址 #關於設置注冊中心這么關鍵的服務,如果是單點話,遇到故障就是毀滅性的。 #在一個分布式系統中,服務注冊中心是最重要的基礎部分,理應隨時處於可以提供服務的狀態。為了維持其可用性,使用集群是很好的解決方案 #所以 在一個分布式系統中,設置最少兩個服務注冊中心是最基本的 eureka.client.serviceUrl.defaultZone=http://${eureka.instance.hostname}:${server.port}/eureka/
第四步》》》好了 最后啟動服務,右鍵 啟動 啟動類或者在Run Dasboard右鍵啟動
或者
如果因為jar包版本出錯,解決方案:https://www.cnblogs.com/sxdcgaq8080/p/9314666.html
啟動以后,按照剛剛eureka配置文件中配置的端口訪問頁面,或者在Run Dashboard中點擊對應端口直接就在瀏覽器啟動也可以
此刻顯示 注冊中心 中並沒有服務注冊
3.創建集群的Eureka【開發搭建分布式,可以跳過本步】【部署時候使用本步驟,開發時候使用第二步驟的單點服務注冊中心 即可在滿足本地使用】
既然咱們已經創建了單個的注冊服務中心,那么如同上面所說,為了保證服務的高可用,那最起碼應該啟動兩個服務注冊,這里我們就開始在本機上啟動多個服務注冊中心,類似於創建集群。
還記得上面配置eureka的時候,配置了:
eureka.client.register-with-eureka=false
就是配置單點eureka的時候,禁止自己向自己注冊。
現在配置多個服務注冊中心集群,就可以相互注冊到對方,即可實現高可用的部署,所以這個參數就可以設置為true了。
第一步》修改剛剛erueka的配置文件
這個文件名稱的修改原理,請查看:spring boot多資源環境
第二步》分別完善三個配置文件
application-swapping1.properties

#聲明本服務在注冊中心展示的名字、也是在網關訪問時定位服務的名字 spring.application.name=spring-cloud-ms-eureka spring.profiles = swapping1 #在windows下的hosts文件中增加了 127.0.0.1 swapping1 eureka.instance.hostname=swapping1 server.port=8000 #是否將自己作為服務注冊到注冊中心,默認為true,false不能將自己注冊到自己, #如果有多個服務注冊中心的微服務的話,可以將這個設置為true,表示可以將注冊中心1注冊到注冊中心2中 #eureka.client.register-with-eureka=false #表示是否從eureka注冊中心中獲取注冊信息,默認為true #eureka.client.fetch-registry=false #注冊中心的交互地址,設置多個地址可以用,分隔 查詢服務和注冊服務都需要依賴這個地址 #關於設置注冊中心這么關鍵的服務,如果是單點話,遇到故障就是毀滅性的。 #在一個分布式系統中,服務注冊中心是最重要的基礎部分,理應隨時處於可以提供服務的狀態。為了維持其可用性,使用集群是很好的解決方案 #所以 在一個分布式系統中,設置最少兩個服務注冊中心是最基本的 eureka.client.serviceUrl.defaultZone=http://swapping2:8001/eureka/,http://swapping3:8002/eureka/
application-swapping2.properties

#聲明本服務在注冊中心展示的名字、也是在網關訪問時定位服務的名字 spring.application.name=spring-cloud-ms-eureka spring.profiles = swapping2 eureka.instance.hostname=swapping2 server.port=8001 eureka.client.serviceUrl.defaultZone=http://swapping1:8000/eureka/,http://swapping3:8002/eureka/
application-swapping3.properties

#聲明本服務在注冊中心展示的名字、也是在網關訪問時定位服務的名字 spring.application.name=spring-cloud-ms-eureka spring.profiles = swapping3 eureka.instance.hostname=swapping3 server.port=8002 eureka.client.serviceUrl.defaultZone=http://swapping1:8000/eureka/,http://swapping2:8001/eureka/
第三步》分別打包最外層父級項目和內層的微服務
此時可以看到咱們的Run Dashboard中啟動類已經找不到匹配的配置文件了。所以在平時開發的話,即可在本地采用上面的單點注冊中心即可完成開發需求。
OK,這里需要注意一點,就是在打包任意ms微服務之前,必須保證,父級項目也就是最外層的項目已經打包成功了,因為所有子級的module都引用了父級的jar包依賴,如果父級項目未打包,那么子級module打包是不會成功的!!!
好的,首先打包父級項目或者最外層依賴的項目,然后依次打包進來
打包時候出現問題,可以參考這個地址:https://www.cnblogs.com/sxdcgaq8080/p/9314865.html
OK,外層的父級項目打包成功后,輪到了內層的eureka,咱們要建集群的微服務進行打包
第四步》利用三個不同的配置文件,啟動不同端口的服務注冊中心,創建集群
第三步打包成功的jar包,可以在本服務的target中找到【注意,target下所有東西都可以刪除掉,因為target下所有文件都是編譯以后的結果】
OK,開始分別啟動這三個服務注冊中心了
需要先在idea命令窗口走到咱們打包的jar包存放的位置:
在idea上的命令窗口鍵入命令:
java -jar springcloud-ms-eureka-0.0.1-SNAPSHOT.jar --spring.profiles.active=swapping1
然后分別以swapping2和swapping3啟動服務注冊中心【這個時候,就體會到了修改hosts文件的妙處了吧!!!】
java -jar springcloud-ms-eureka-0.0.1-SNAPSHOT.jar --spring.profiles.active=swapping2
java -jar springcloud-ms-eureka-0.0.1-SNAPSHOT.jar --spring.profiles.active=swapping3
注意下面 並沒有 進入target目錄中,僅作為開啟新頁簽的展示操作 ,如果要啟動成功,需要cd到target目錄下進行操作
如果啟動報錯,可以參考:https://www.cnblogs.com/sxdcgaq8080/p/9315197.html
OK,正常啟動完第一個服務。應該是會報錯連接失敗,因為它要注冊的地址服務2和服務3都還沒有正式啟動,直到三個服務都成功啟動了,才會都正常了。
后面的服務啟動成功。前面的服務會注冊的到的!!!!
然后分別打開頁面查看
OK 到這里 eureka集群 就成功搭建完成了!!!
========================================
4. 創建分布式系統中的服務提供者和服務消費者,並提供Feign進行服務調用
上面兩步中,把spring cloud創建分布式系統的核心步驟,創建單個Eureka服務注冊中心 以及 注冊中心集群。
【ms---代表微服務的意思】【DB---代表數據庫】
既然是分布式系統,當然是有做這個系統核心業務的一個一個的ms微服務。而這一個一個的ms微服務都是根據不同的業務功能進行划分模塊的。
舉個簡單的例子:
場景:在一個商城系統中,一個會員,購買一個商品,然后相應的這個會員也會獲取一定的積分【關於微服務的抽離以及數據庫需不需要獨立設計,完全取決於實際場景】
1.商品--ms-goods有關商品的,可以抽離出來成一個ms微服務,連接一個獨立的DB--goods
2.會員--ms-member有關會員的,可以抽離出來 一個單獨的ms微服務,連接一個獨立的DB--member
3.積分--ms-integral 有關積分的,可以單獨抽離成一個ms微服務,連接一個獨立的DB--integral或者integral作為一張表,存在於DB--member數據庫中
關於場景:在這個簡單的場景中,會涉及到幾個操作
1.購買操作從member會員服務發起
2.商品服務提供購買商品的接口,接口功能就是購買商品的這個服務,對應的goods數據庫中,商品數量減1
3.積分服務同樣需要提供一個更改積分的接口,接口功能就是會員對應的購物積分有所增加,比如增加商品等價的積分
好,看了上面這個簡單的例子,其中涉及到的一些問題和一些要說的東西就顯現出來了。【黑粗標記就是重點】
1.首先理解一個概念,就是現在關於商品的操作【操作就簡單的理解成CRUD增刪改查】都在商品服務里面,關於會員的操作都在會員服務里面。
2.所以,如果想要在會員做了購買商品的動作后,想要在會員服務中調用商品服務中的購買服務,就涉及到了跨微服務調用的情況
3.這樣就引申出了服務提供者和服務消費者這樣的概念,而在上面的這種情況中,商品服務就是服務提供者,會員服務就是服務調用者
4.而服務消費者想要調用到服務提供者提供的功能服務,則需要商品服務除了在服務內部提供 購買商品 的接口外,還需要提供接口對應的Feign,這樣會員服務才能調用到商品服務內部的接口功能。
5.會員購買,商品減1,積分增加,這整個的流程如果中間哪一步失敗,怎么辦?肯定要保證這整個的流程要么全部成功,要么全部失敗,這就是事務的原子性,這里也就涉及到了分布式事務的概念,而分布式事務也是分布式系統中的難點!【分布式事務最后再說】
結尾
10.分布式事務
分布式事務實現的思想:
分布式事務=本地事務【原子事務】+異步【消息通知】