前言
SpringCloud并不是一個第三方框架的名稱, 而是一整套微服務(wù)框架的統(tǒng)稱, 使用這套框架可以快速搭建出高可用的微服務(wù)環(huán)境, 因為功能眾多拼缝,所以又被稱SpringCloud全家桶, 由于篇幅較長所以文章采用了目錄引導(dǎo), 第二章是微服務(wù)的基礎(chǔ), 第三章是功能模塊擴展, 如網(wǎng)關(guān), 服務(wù)保護, 分布式配置中心, nginx, 下面就跟著我們的文章, 一起來看吧.
目錄
- 一.什么是微服務(wù)
- 二.快速開始
- 三.功能集成(網(wǎng)關(guān), 服務(wù)保護, 負載均衡, 分布式配置中心)
- 四.打包
- 五.微服務(wù)發(fā)布利器 -- Docker
- 六.Demo
一.什么是微服務(wù)
就是把一整個后臺項目拆分成多個模塊, 每一個模塊稱作一個服務(wù), 每個服務(wù)都可以獨立運行, 這樣做的好處是其中有一個服務(wù)掛掉后, 另外的服務(wù)不受影響, 這些服務(wù)使用接口相互通信, 減少了依賴和耦合.
-- 摘自白貓語錄
二.快速開始
整個項目是由maven
進行管理的, 依賴包就是我們開發(fā)時需要用到的第三方j(luò)ar包, 也就是框架, 這里為什么什么也不選? 我說一下, 因為我們要做的是微服務(wù), 所以框架結(jié)構(gòu)為一個基座
+多個子模塊
, 我們上面建立的就是基座
, 你可以把它當(dāng)成一個工作空間
用途是管理子模塊.
1.Eureka注冊中心
首先要新建我們SpringCloud項目的核心eureka注冊中心
, 為什么說它是項目的核心呢, 我在簡介中說過了, 微服務(wù)就是把一整個后臺應(yīng)用拆分成小的功能模塊, 那么這些模塊之間如何進行通信呢?
沒錯就是注冊中心, 那么我們接下來就開始搭建一個注冊中心吧!
首先新建一個Module
子項目, 也就是一個微服務(wù)模塊.
到這里我們注冊中心模塊就建立好了, 之后我們來簡單配置一下.
首先開啟eureka
服務(wù)
之后找到配置文件
配置一下application.yml
, 如果你的是application.properties
, 請修改后綴為yml
, 這兩個配置文件都可以配置工程, 相比之下yml
更直觀一些, 所以本教程使用yml
進行配置
之后我們進行配置
server:
# 配置服務(wù)端口
port: 8081
eureka:
client:
service-url:
# 配置eureka服務(wù)器地址
defaultZone: http://127.0.0.1:8081/eureka
#是否需要將自己注冊到注冊中心(注冊中心集群需要設(shè)置為true)
register-with-eureka: false
#是否需要搜索服務(wù)信息 因為自己是注冊中心所以為false
fetch-registry: false
注意縮進, 因為yml
使用縮進來區(qū)分不同字段的.
然后我們來運行項目吧!
在這里選擇ServiceEurekaApplication
, 然后點擊綠色的運行即可.
看到上面的日志就證明成功了.
然后我們來訪問一下注冊中心吧.
網(wǎng)頁可以正常運行后 我們的注冊中心就配置完畢了
2.創(chuàng)建微服務(wù)
只有注冊中心是沒有用的, 我們需要找一個地方來寫接口, 所以接下來我們就創(chuàng)建兩個服務(wù).
接下來勾選一些功能模塊
同理配置service-b
, 新建完成之后是這個樣子, 同理創(chuàng)建service-b
之后我們配置服務(wù)的入口文件
然后配置一下application.yml
首先是service-a
server:
# 服務(wù)端口號
port: 8082
spring:
application:
# 服務(wù)名稱 - 服務(wù)之間使用名稱進行通訊
name: service-objcat-a
eureka:
client:
service-url:
# 填寫注冊中心服務(wù)器地址
defaultZone: http://localhost:8081/eureka
# 是否需要將自己注冊到注冊中心
register-with-eureka: true
# 是否需要搜索服務(wù)信息
fetch-registry: true
instance:
# 使用ip地址注冊到注冊中心
prefer-ip-address: true
# 注冊中心列表中顯示的狀態(tài)參數(shù)
instance-id: ${spring.cloud.client.ip-address}:${server.port}
之后是service-b
server:
# 服務(wù)端口號
port: 8083
spring:
application:
# 服務(wù)名稱 - 服務(wù)之間使用名稱進行通訊
name: service-objcat-b
eureka:
client:
service-url:
# 填寫注冊中心服務(wù)器地址
defaultZone: http://localhost:8081/eureka
# 是否需要將自己注冊到注冊中心
register-with-eureka: true
# 是否需要搜索服務(wù)信息
fetch-registry: true
instance:
# 使用ip地址注冊到注冊中心
prefer-ip-address: true
# 注冊中心列表中顯示的狀態(tài)參數(shù)
instance-id: ${spring.cloud.client.ip-address}:${server.port}
之后我們來運行一下剛配置好服務(wù)吧
首先看編譯器的左下角, 有一個小方塊
, 鼠標(biāo)驮壮幔靠在上面會顯示菜單.
那我們接下來開始寫個簡單的接口
@RestController
public class TestController {
@RequestMapping("/hello")
public String hello() {
return "hello world";
}
}
重啟服務(wù), 訪問下面地址
瀏覽器上出現(xiàn)hello world
說明成功了
有人會問了 到這里并沒有使用到任何注冊中心的功能啊?
不要著急 接下來我們就是用一用注冊中心
我們現(xiàn)在有一個需求 使用服務(wù)b調(diào)用服務(wù)a的接口
這時我們就需要用到eurka(注冊中心)
和feign
客戶端了
首先我們在service-b中創(chuàng)建interface
@FeignClient("SERVICE-OBJCAT-A")
public interface ServiceAFeignClient {
@RequestMapping("/hello")
public String hello();
}
應(yīng)用名可以在eureka中找到
http://localhost:8081
之后我們來寫接口 在服務(wù)b中添加個控制器
@RestController
public class TestController {
@Autowired
private ServerAFeignClient serverAFeignClient;
@RequestMapping("/call")
public String call() {
String result = serverAFeignClient.hello();
return "b to a 訪問結(jié)果 ----- " + result;
}
}
之后我們發(fā)現(xiàn)報錯了 不要慌張設(shè)置一下即可
最后在應(yīng)用入口加上注解,就能實現(xiàn)服務(wù)之間的調(diào)用了.
重新運行服務(wù)b 在網(wǎng)站上訪問試試吧
到這里服務(wù)之間的相互訪問也可以完成了 到這里springcloud最基本的環(huán)境搭建就完成了 快寫幾個微服務(wù)玩玩吧
內(nèi)容擴展
我們來看一個神奇的現(xiàn)象 我把service-a接口中寫一個延時函數(shù) 我們看一下效果
之后我們重新運行service-a
我們會發(fā)現(xiàn)報如下錯誤
意思是讀取超時了 這是為什么呢
原因就是feign的默認請求超時時間是1秒 而我們延時1.5秒后返回了數(shù)據(jù) 所以這個請求失敗了 那么我們要如何解決這個問題呢?
很簡單 我們在配置文件中配置feign的超時時間即可
server:
#服務(wù)端口號
port: 8083
spring:
application:
#服務(wù)名稱 - 服務(wù)之間使用名稱進行通訊
name: service-objcat-b
eureka:
client:
service-url:
#填寫注冊中心服務(wù)器地址
defaultZone: http://localhost:8081/eureka
#是否需要將自己注冊到注冊中心
register-with-eureka: true
#是否需要搜索服務(wù)信息
fetch-registry: true
ribbon:
#建立連接超時時間
ConnectTimeout: 5000
#讀取資源超時間
ReadTimeout: 5000
關(guān)鍵是下面這三行
ribbon:
#建立連接超時時間
ConnectTimeout: 5000
#讀取資源超時間
ReadTimeout: 5000
這里說一下 ribbon
如果你是搞IT的 那么你一定聽說過一個叫負載均衡
的東西 而負載均衡呢 又分為兩種
1.本地負載均衡 一般使用ribbon
2.服務(wù)器端負載均衡 一般使用nginx
顧名思義所謂負載均衡
就是讓用戶訪問可以平均到集群服務(wù)上去 避免單個服務(wù)訪問量過大而增加服務(wù)器負擔(dān)
所謂集群 就是相同服務(wù)在不同服務(wù)器上運行(相同服務(wù)器也可 但同一個服務(wù)器端口一定不同) 實現(xiàn)同樣服務(wù)的效果
說到這里 你可能還是不太懂 沒關(guān)系 先看下面的例子 我們來重現(xiàn)一下ribbon
的負載均衡功能
我們現(xiàn)在就在本地開啟兩個service-a
首先修改一下代碼 讓服務(wù)打印出當(dāng)前端口號
對服務(wù)a做了上圖中的修改
1.獲取服務(wù)器端口號
2.拼接端口號返回給客戶端
3.注釋掉了延時函數(shù)提高效率
好 那我們來啟動兩個service-a 這個要進行設(shè)置一下 因為idea默認情況下是單例運行的 我們先要給服務(wù)改成不是單例的狀態(tài) 這樣就能跑起來兩個同樣名稱但端口不同的服務(wù)了
到了這一步 我們來跑起來兩個service-a吧
運行之后我們會發(fā)現(xiàn)有兩個a服務(wù) 一個是8082 一個是8092
這個就成為集群 同一個服務(wù)開啟了兩個端口 獨立運行 我們打開eureka看一下 服務(wù)都順利運行了
有兩個a服務(wù) 一個b服務(wù)
接口下來我們用b服務(wù)來訪問以下a服務(wù) 調(diào)用我們以前就寫好的方法 call
訪問的同一個地址 但是端口會在8082和8092之間來回切換 這就是所謂的本地負載均衡 那么這個機制是怎么實現(xiàn)的呢 其實很簡單 就是輪詢機制 計算公式就是 總請求次數(shù) % 服務(wù)器總數(shù)
取模后就調(diào)用相對應(yīng)索引的服務(wù) 就可以實現(xiàn)本地均衡負載了 這就是ribbon的基本原理
三.功能集成
1.網(wǎng)關(guān)
[JavaEE] SpringCloud集成Zuul網(wǎng)關(guān)
http://www.reibang.com/p/6ef9ca1efa4b
2.服務(wù)保護
[JavaEE] SpringCloud集成Hystrix服務(wù)保護
http://www.reibang.com/p/cce702d44b7d
3.負載均衡
[JavaEE] 狒狒都能懂的Nginx教程 for Mac
http://www.reibang.com/p/c21606bb4044
4.分布式配置中心
[JavaEE] SpringCloud集成Apollo分布式配置中心
http://www.reibang.com/p/5606483c7fbf
[JavaEE] SpringCloud集成SpringCloudConfig分布式配置中心
http://www.reibang.com/p/f6c0793e8458
四.打包
[JavaEE] SpringCloud項目打包
http://www.reibang.com/p/935868c9141e
五.微服務(wù)發(fā)布利器 -- Docker
[Docker] 入門教程
http://www.reibang.com/p/7b3737df847d
六.Demo
https://github.com/objcat/test-spring-cloud-demo.git
finall enjoy it.
by objcat 2018.11.14
更新日志:
- 2018年11月20日14:24:58
新增負載均衡原理
新增網(wǎng)關(guān)配置教程 - 2018年12月14日15:38:58
重構(gòu)文章, 完善部分細節(jié) - 2018年12月21日15:25:46
完善Demo, 新增Zuul網(wǎng)關(guān)和分布式配置中心Config - 2018年12月25日11:35:33
完善目錄和部分詞語修正