我們本文,只介紹如何搭建一個微服務架構,其中微服務的理論知識見另一篇文章:
1、創建父工程(之后所有的服務,均在父工程下創建),引入在pom文件引入依賴

1 <?xml version="1.0" encoding="UTF-8"?> 2 <project xmlns="http://maven.apache.org/POM/4.0.0" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 5 <modelVersion>4.0.0</modelVersion> 6 7 <groupId>com.mk</groupId> 8 <artifactId>spring_cloud</artifactId> 9 <version>1.0-SNAPSHOT</version> 10 11 <modules> 12 <module>User-Service</module> 13 <module>consumer-user</module> 14 <module>Euraka-service</module> 15 <module>getAwayService</module> 16 <module>myConfig</module> 17 </modules> 18 <packaging>pom</packaging> 19 20 <properties> 21 <java.version>1.8</java.version> 22 <spring-cloud.version>Greenwich.SR1</spring-cloud.version> 23 <mapper.starter.version>2.1.5</mapper.starter.version> 24 <mysql.version>5.1.46</mysql.version> 25 </properties> 26 27 28 <parent> 29 <groupId>org.springframework.boot</groupId> 30 <artifactId>spring-boot-starter-parent</artifactId> 31 <version>2.1.2.RELEASE</version> 32 <relativePath/> 33 34 </parent> 35 36 <dependencyManagement> 37 <dependencies> 38 <!-- springCloud --> 39 <dependency> 40 <groupId>org.springframework.cloud</groupId> 41 <artifactId>spring-cloud-dependencies</artifactId> 42 <version>${spring-cloud.version}</version> 43 <type>pom</type> 44 <scope>import</scope> 45 </dependency> 46 <!-- 通用Mapper啟動器 --> 47 <dependency> 48 <groupId>tk.mybatis</groupId> 49 <artifactId>mapper-spring-boot-starter</artifactId> 50 <version>${mapper.starter.version}</version> 51 </dependency> 52 <!-- mysql驅動 --> 53 <dependency> 54 <groupId>mysql</groupId> 55 <artifactId>mysql-connector-java</artifactId> 56 <version>${mysql.version}</version> 57 </dependency> 58 59 60 </dependencies> 61 </dependencyManagement> 62 <dependencies> 63 <dependency> 64 <groupId>org.projectlombok</groupId> 65 <artifactId>lombok</artifactId> 66 </dependency> 67 </dependencies> 68 <build> 69 <plugins> 70 <plugin> 71 <groupId>org.springframework.boot</groupId> 72 <artifactId>spring-boot-maven-plugin</artifactId> 73 </plugin> 74 </plugins> 75 </build> 76 </project>
2、服務提供者:我們的服務是,根據id查詢一個user,所以就會引入一些數據庫相關的依賴

1 <?xml version="1.0" encoding="UTF-8"?> 2 <project xmlns="http://maven.apache.org/POM/4.0.0" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 5 <parent> 6 <artifactId>spring_cloud</artifactId> 7 <groupId>com.mk</groupId> 8 <version>1.0-SNAPSHOT</version> 9 </parent> 10 11 12 <modelVersion>4.0.0</modelVersion> 13 14 <artifactId>User-Service</artifactId> 15 16 <properties> 17 <maven.compiler.source>8</maven.compiler.source> 18 <maven.compiler.target>8</maven.compiler.target> 19 </properties> 20 21 <dependencies> 22 <dependency> 23 <groupId>org.springframework.boot</groupId> 24 <artifactId>spring-boot-starter-web</artifactId> 25 </dependency> 26 27 <dependency> 28 <groupId>org.springframework.boot</groupId> 29 <artifactId>spring-boot-starter-test</artifactId> 30 </dependency> 31 32 33 <!-- 通用Mapper啟動器 --> 34 <dependency> 35 <groupId>tk.mybatis</groupId> 36 <artifactId>mapper-spring-boot-starter</artifactId> 37 </dependency> 38 39 40 <!-- mysql驅動 --> 41 <dependency> 42 <groupId>mysql</groupId> 43 <artifactId>mysql-connector-java</artifactId> 44 </dependency> 45 46 <dependency> 47 <groupId>org.springframework.cloud</groupId> 48 <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> 49 </dependency> 50 51 <dependency> 52 <groupId>org.springframework.cloud</groupId> 53 <artifactId>spring-cloud-starter-config</artifactId> 54 </dependency> 55 </dependencies> 56 57 58 </project>
2.1:實體類:其中Data注解,減少代碼量
2.2:dao層:使用tkMybatis,所以就不需要我們自己寫單表的一些語句
2.3:service層:
2.4:controller層:
2.5:啟動類:
2.6:yml配置文件(配有注釋)
3.1:服務消費者:因為客戶端,不需要操作數據庫,所以只需要實體類和控制層就行。
3.2:pom依賴文件:

1 <?xml version="1.0" encoding="UTF-8"?> 2 <project xmlns="http://maven.apache.org/POM/4.0.0" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 5 <parent> 6 <artifactId>spring_cloud</artifactId> 7 <groupId>com.mk</groupId> 8 <version>1.0-SNAPSHOT</version> 9 </parent> 10 <modelVersion>4.0.0</modelVersion> 11 12 <artifactId>consumer-user</artifactId> 13 14 <properties> 15 <maven.compiler.source>8</maven.compiler.source> 16 <maven.compiler.target>8</maven.compiler.target> 17 </properties> 18 19 20 <dependencies> 21 <dependency> 22 <groupId>org.springframework.boot</groupId> 23 <artifactId>spring-boot-starter-web</artifactId> 24 </dependency> 25 26 27 <!--euraka客戶端--> 28 <dependency> 29 <groupId>org.springframework.cloud</groupId> 30 <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> 31 </dependency> 32 33 <!--熔斷器--> 34 <dependency> 35 <groupId>org.springframework.cloud</groupId> 36 <artifactId>spring-cloud-starter-netflix-hystrix</artifactId> 37 </dependency> 38 39 <!--feign代理--> 40 <dependency> 41 <groupId>org.springframework.cloud</groupId> 42 <artifactId>spring-cloud-starter-openfeign</artifactId> 43 </dependency> 44 </dependencies> 45 46 </project>
3.3:實體類:因為是客戶端,所以就不需要那些jpa注解

1 package com.mk.consumer.pojo; 2 3 import lombok.Data; 4 5 @Data 6 public class User { 7 private Long id; 8 private String userName; 9 private String password; 10 private String name; 11 private long age; 12 private long sex; 13 private java.sql.Date birthday; 14 private java.sql.Date created; 15 private java.sql.Date updated; 16 private String note; 17 18 }
3.4:controller層:(這里我們采用截圖,因為后面會對這里進行改造)
3.5:配置文件:
3.6:啟動類:

1 package com.mk.consumer; 2 3 import org.springframework.boot.SpringApplication; 4 import org.springframework.boot.autoconfigure.SpringBootApplication; 5 import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker; 6 import org.springframework.cloud.client.discovery.EnableDiscoveryClient; 7 import org.springframework.cloud.client.loadbalancer.LoadBalanced; 8 import org.springframework.cloud.openfeign.EnableFeignClients; 9 import org.springframework.context.annotation.Bean; 10 import org.springframework.web.client.RestTemplate; 11 12 @SpringBootApplication 13 @EnableDiscoveryClient 14 @EnableCircuitBreaker //開啟熔斷器 15 @EnableFeignClients //開啟feign組件功能 16 public class Application { 17 public static void main(String[] args) { 18 SpringApplication.run(Application.class, args); 19 } 20 21 22 /*spring提供的模板,對http進行封裝*/ 23 @Bean 24 @LoadBalanced //負載均衡 25 public RestTemplate restTemplate(){ 26 return new RestTemplate(); 27 } 28 }
4.1Eureka注冊中心;既然后我們客戶端和服務端都有了,那么我們還需要搭建自己的Eureka注冊中心,來發現服務,引入依賴

1 <?xml version="1.0" encoding="UTF-8"?> 2 <project xmlns="http://maven.apache.org/POM/4.0.0" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 5 <parent> 6 <artifactId>spring_cloud</artifactId> 7 <groupId>com.mk</groupId> 8 <version>1.0-SNAPSHOT</version> 9 </parent> 10 <modelVersion>4.0.0</modelVersion> 11 12 <artifactId>Euraka-service</artifactId> 13 14 <properties> 15 <maven.compiler.source>8</maven.compiler.source> 16 <maven.compiler.target>8</maven.compiler.target> 17 </properties> 18 19 <dependencies> 20 <dependency> 21 <groupId>org.springframework.cloud</groupId> 22 <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> 23 </dependency> 24 </dependencies> 25 26 27 28 </project>
4.2:配置文件:(配有注解)

1 #端口號 2 server: 3 port: 10010 4 5 #服務名,因為Eureka本身也是一個服務 6 spring: 7 application: 8 name: eureka 9 10 #服務注冊中心的位置 11 eureka: 12 client: 13 service-url: 14 defaultZone: http://127.0.0.1:10010/eureka 15 instance: 16 17 # 不注冊自己 18 register-with-eureka: false 19 # 不拉取服務 20 fetch-registry: false
4.3:啟動類:

1 package com.mk.eureka; 2 3 import org.springframework.boot.SpringApplication; 4 import org.springframework.boot.autoconfigure.SpringBootApplication; 5 import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; 6 7 @SpringBootApplication 8 @EnableEurekaServer 9 public class Application { 10 public static void main(String[] args) { 11 SpringApplication.run(Application.class, args); 12 } 13 }
以上我們的客戶端,服務端,注冊中心都配置完畢,那么我們啟動服務看看。
訪問Eureka注冊中心:注意端口號
訪問我們的服務:(傳入id為2),可以看到,返回一個json數據
以上就是,我們傳入正確的id,假如,我們傳入的id,在數據庫中,不存在怎么辦呢。經實踐發現,服務就會一直等待,那么我們后續的其他的請求就會阻塞,這樣我們后續用戶的請求也會阻塞。
5.Spring Cloud為我們提供了Hystrix組件:特地處理我們服務時間超時,然后我們可以回顯給用戶一些有好的提示。
5.1:添加hystrix依賴
5.2:在啟動類上添加開啟@EnableCircuitBreaker的注解
5.3.編寫我們的降級邏輯,也就是給用戶的提示
5.4.測試降級邏輯,為了確保一定能夠滿足服務降級的條件(1.該服務的線程池滿,2.服務超時(Hystrix的默認超時時長為1)),我們就不啟動服務端,那么客戶端的請求一定超時,就會觸發服務降級。下面是測試結果
從上面可以看出,我們的服務,雖然沒有得到應該的結果,但是我們的線程得到釋放,並不會影響其他的服務。這就是我們服務降級的一個流程。
那么上面服務降級的方式,我們每增加一個方法是不是,就需要我們在該方法上進行注入呢,還有另外一種,更加簡便的方式,就注解在類上,就不用每一個方法都去注入了
以上我們就搭建了一個簡易的微服務,但是還存在一些問題。比如我的3.4步驟中,可以看到我們的url被寫死,那么我們后期的需求改變或者說是拓展其他的功能,那么顯然是不方便的。
我們SpringCloud給我們提供了一個叫做feign的組件,是一種聲明式、模板化的HTTP客戶端。在Spring Cloud中使用Feign, 我們可以做到使用HTTP請求遠程服務時能與調用本地方法一樣的編碼體驗,開發者完全感知不到這是遠程方法,更感知不到這是個HTTP請求。下面,我們就對客戶端進行優化。
6.Feign聲明式服務,
6.1.pom文件依賴,添加如下
6.2我們添加日志配置類,方便我們對請求的參數,請求體進行查看。

package com.mk.consumer.logger; import feign.Logger; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class FeignLogger { @Bean public Logger.Level feignLoggerLevel(){ //日志級別是記錄所有(包括請求的行,請求體,) return Logger.Level.FULL; } }
6.3.下面我們添加我們的客戶端控制層的接口,
6.4.我們改造后的控制層,就變得優雅了許多,仿佛就是在調用我們的本地方法。
6.5.測試結果
從結果可以看出,我們同樣可以得到結果,這就是feign組件的作用,方便我們服務的調用,得到與調用本地方法一致的編碼體驗。
6.6.feign對hystrix的支持,feign中有對hystrix的支持,我們只需要定義一個類,實現我們6.3中的客戶端接口,然后再客戶端中通過注解,添加即可。下面是降級邏輯
6.7.下面我們看一下測試結果,觸發條件和之前的hystrix一樣
7. 以上就是,feign的使用。其實feign就是簡化我們內部的,服務與服務之間的調用,那么我們服務暴露給對外的api接口,應該怎樣解決呢?同樣Spring Cloud提供了Gateway網關組件。
我們外部的請求,首先就會通過網關的過濾,鑒權,然后才能請求我們內部的服務。下面我們就來配置我們的網關。
7.1,新建一個model,引入依賴
7.2.編寫啟動類
7.3,編寫配置文件,Gateway,重點就是配置文件
7.4下面我們,啟動服務,看看效果
8.上面就是Gateway的簡單應用,當然,網關還有一些添加前綴,去除前綴,過濾器的一些使用,大家可以自己去探索。大家肯定會發現,我們整個微服務搭建下來,配置文件超級多,而且以后開發,
所有的配置文件肯定也不是在一台電腦上,所以有的配置文件,就訪問不了,沒事,SpringCloud也為我們提供了SpringCloud config分布式配置中心。
8.1.既然要有git倉庫,那就自己准備一個,我就不粘貼步驟了,唯一需要注意的是這個配置文件的命名方式,就比如我的配置文件的名字是:“userService-dev.yml”,userService就代表服務名,-這是分隔符,dev就代表是開發環境。
然后就是將我們的userService的配置文案上傳到gitee的新建文件,(只截取了一部分)
8.2新建一個model,引入依賴
8.3編寫啟動類
8.4編寫配置文件
8.5下面我們就通過本地訪問git上的配置文件
這就是我們之前准備的在倉庫中的配置文件,這樣我們就可以通過配置中心進行訪問。
8.6.既然可以通過配置中心訪問,下面我們就對我們的服務端的配置文件(就是之前的UserService)進行修改,注意配置文件名改為bootstrap.yml,因為bootstrap.yml文件是Spring Boot的默認配置文件,而且其加載的時間相比於application.yml更早。 application.yml和bootstrap.yml雖然都是Spring Boot的默認配置文件,但是定位卻不相同。bootstrap.yml 可以理解成系統級別的一些參數配置,這些參數一般是不會變動的
8.7.我們重啟UserService服務。發現UserService仍然存在,說明能夠讀取到配置中心的文件。
9.既然,我們在git配置了配置文件,那么如果,我們在git上進行了修改,那么本地的配置文件會不會自己刷新呢,顯然是不會的。我們的Spring cloud也為我們提供了叫做:Spring cloud bus服務總線,專門用於同步git上配置文件的改變。下面我們進行測試。
9.1. 在8.2中增加如下依賴,
9.3:在8.3增加如下配置
9.4.在往服務提供者中增加如下依賴:
9.5.修改2.4的controller為:
9.6.測試,先正常訪問
9.7.控制台輸出的是:
9.8.我們修改name為mk
9.9.利用我們postman工具,發送我們在8.3中暴露的api,(注意我們需要提前安裝\otp_win64_23.0.exe和rabbitmq-server-3.8.5.exe),因為rabbitmq使用otp語言實現
9.10.我們再次訪問9.6的url,查看控制台的輸出變為我們剛剛更新的mk
就實現了我們配置中心改變,同步到本地的功能。
下面就是SpringCloud的完整體系架構圖
整個微服務搭建完畢,各個組件的功能總結見另外一篇文章:https://www.cnblogs.com/kunmin/p/15108090.html