寫在前面
使用spring cloud搭建微服務框架,是我最近最主要的工作之一,一開始我使用bubbo加zookeeper制作了一個基於dubbo的微服務框架,然后被架構師否了,架構師曰:此物過時。隨即,我上一套spring cloud,與公司大環境框架一致,也廢了不少功夫,現在在這里分享基礎結構給各位博友,如有不對的地方,歡迎大家直接評論區慫我。嘿嘿。
后續的代碼已傳至我的github,大家可以下載查看。
微服務
首先我們要了解什么是微服務,以及微服務的作用,我們才能夠順利的搭建一個微服務架構。
博主先用一句話總結什么是微服務。
微服務就是對某個應用系統的每個API進行有效的拆分,然后通過某種連接方式,用以提供給其他應用系統調用的API的服務,在調用過程中實現和解決了一系列問題的綜合就是微服務架構
顧名思義,微服務得從兩個方面去理解,什么是"微"、什么是"服務"。
微
簡單的講就是體積小,隨處運行,開發簡單。傳統的spring mvc框架配置繁雜,項目依賴雜亂,常常令開發和維護頭疼不已。
服務
所謂服務,一定要區別於系統,服務一個或者一組相對較小且獨立的功能單元,是用戶可以感知最小功能集。
微服務最早由Martin Fowler與James Lewis於2014年共同提出,微服務架構風格是一種使用一套小服務來開發單個應用的方式途徑,每個服務運行在自己的進程中,並使用輕量級機制通信,通常是HTTP API,這些服務基於業務能力構建,並能夠通過自動化部署機制來獨立部署,這些服務使用不同的編程語言實現,以及不同數據存儲技術,並保持最低限度的集中式管理。
應用的拆分
有程序員A,B,C,他們現在都需要開發一套訂單管理系統。
程序員A采用單系統架構,業務代碼做mvc拆分,前端部分使用php做渲染層。
程序員B采用多應用架構,將產品、訂單、物流、工單、客服等做應用級拆分,然后使用REST API或者tcp直接交互,每個應用都是一個mvc系統,獨立開發。
程序員C采用微服務,將產品、訂單、物流、工單、客服等做應用級拆分,再使用微服務框架將他們打散拆分成一個個的服務,例如訂單列表查詢服務、產品列表查詢服務、產品詳情查詢服務等。使用一個個服務組成應用系統然后整合為訂單管理系統
毫無疑問,程序員A的架構方式只能夠在訂單量小,吃了上頓沒下頓的公司應用了。
而程序員B的架構類似大部分電商平台前期的架構邏輯,這套架構適應能力不錯,但是隨着系統的不斷擴大,維護變的極為復雜,版本的更替,應用之間的API調用隨着各種各樣的需求復雜多變。
隨着B架構的演變,誕生了程序員C的架構模式,微服務。微服務的理解就是將類似 訂單列表查詢服務、產品列表查詢服務、產品詳情查詢服務進行細分,微分。使我們的代碼能夠通過統一的網關進行整合,能夠讓整個公司的系統開發力量徹底整合起來,並且微服務中的服務治理、熔斷、負載均衡等等功能加強了對整個系統的治理能力。
目前應對中大型站點的后台架構,微服務是最適合的一套模式。同時spring boot的出現讓微服務的開發變得更簡單,理解更容易,例如dubbo的開發方式其實比較簡單、易懂,spring cloud更是深度整合spring boot的能力,借用網友的一張對比圖:

圖出處:https://blog.csdn.net/zhouyanqingbfq/article/details/79407285
另外有很多關於微服務的知識理念,博主整理了一些:
https://blog.csdn.net/fly_zhyu/article/details/76408158
https://www.cnblogs.com/wintersun/p/6219259.html
spring boot
Spring Boot不是一門新技術,所以不用緊張。從本質上來說,Spring Boot就是Spring,它做了那些沒有它你也會去做的Spring Bean配置。它使用“習慣優於配置”(項目中存在大量的配置,此外還內置了一個習慣性的配置,讓你無需手動進行配置)的理念讓你的項目快速運行起來。使用Spring Boot很容易創建一個獨立運行(運行jar,內嵌Servlet容器)、准生產級別的基於Spring框架的項目,使用Spring Boot你可以不用或者只需要很少的Spring配置。
這一部分博主不再追述,提供一些資料大家看看就好,能點進這篇博文的人這里默認你會一些的吧。
【轉】Spring Boot干貨系列:(一)優雅的入門篇
spring cloud
Spring Cloud provides tools for developers to quickly build some of the common patterns in distributed systems (e.g. configuration management, service discovery, circuit breakers, intelligent routing, micro-proxy, control bus, one-time tokens, global locks, leadership election, distributed sessions, cluster state). Coordination of distributed systems leads to boiler plate patterns, and using Spring Cloud developers can quickly stand up services and applications that implement those patterns. They will work well in any distributed environment, including the developer's own laptop, bare metal data centres, and managed platforms such as Cloud Foundry.
spring cloud 提供一些工具迅速構建一些常用模式的分布式系統(例如 配置管理,服務發現,斷路器,路由,微代理,控制總線,token,全局鎖,分布式sessions,cluster state),使用Spring Cloud開發人員可以快速站出實現這些模式的服務和應用程序。 他們可以在任何分布式環境中運行良好,包括開發人員自己的筆記本電腦,裸機數據中心和托管平台,如Cloud Foundry。
來自spring cloud 官網的第一句介紹,spring cloud提供了一系列的工具去構建一套分布式系統,這些工具共同組成了一個微服務架構系統,注冊中心、網關、provider、consumer、Rest、分布式鎖、分布式session等等功能。
spring cloud的學習資料整理:
http://www.ityouknow.com/springcloud/2016/12/30/springcloud-collect.html
https://blog.csdn.net/forezp/article/details/70148833
注冊中心
eureka注冊中心的搭建 博主使用IDEA搭建
1首先創建一個空的maven項目

填入參數:


finish就ok
finish后刪除目錄下src文件夾
2.然后在cloud中新建module,右鍵根目錄,選擇new》module

新建一個spring boot項目,並添加上eureka依賴



注意content root的地址,在cloudDemo目錄下的erueka
點擊finish,就生成了一個springboot項目,等待maven初始化完畢,此時的項目結構,和eureka的pom文件如下:

啟動eureka注冊中心的方式很簡單,在springboot的啟動類上加上注解
@EnableEurekaServer

然后配置我們的spring boot啟動:
將resource下面的 application.properties文件改為application.yml文件並添加如下配置:
server: port: 8801 eureka: instance: hostname: localhost client: registerWithEureka: false fetchRegistry: false serviceUrl: defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/

然后啟動項目訪問localhost:8801,看到這個界面,Eureka注冊中心就已經啟動成功,接下來我們可以編寫一個提供者,一個消費者。

spring cloud的消費者也可以是提供者,二者只有邏輯上的區別,它是鏈式的存在。在spring boot中有兩種消費方式:
1.rest+ribbon
2.Feign
接下來我們編寫消費者
rest+ribbon消費
首先保持Eureka的啟動不變,然后在cloudDemo下新建一個module 叫做ribbon,它也是spring boot結構:



注意我們要添加三個依賴,如上圖紅框依次選擇即可。

一樣,要注意content root的目錄。
創建完成后,編寫springboot的啟動類,首先加上 @ComponentScan 注解,然后添加 @EnableDiscoveryClient 注冊服務,然后注入RestTemplate對象,
@LoadBalanced 表示開啟負載均衡
完整的代碼如下:

@SpringBootApplication @EnableDiscoveryClient //注冊服務 @ComponentScan public class RibbonApplication { public static void main(String[] args) { SpringApplication.run(RibbonApplication.class, args); }
@Bean @Autowired @LoadBalanced RestTemplate restTemplate(){ return new RestTemplate(); } }
然后我們創建一個測試用的service文件:


代碼如下:
@Service public class HelloService { public String sayHello(){ return "helloWorld"; // 提供一個hello World } }
然后我們再編寫一個controller,提供一個hello的controller:

完整代碼如下:
@RestController public class HelloController { @Autowired private HelloService helloService; @GetMapping("/hello") public String sayHello(String name){ return helloService.sayHello() + " " + name; } }
然后我們再配置application.yml , 一樣的 將配置文件改為yml格式,然后輸入配置:
eureka: client: serviceUrl: defaultZone: http://localhost:8801/eureka/ server: port: 8802 spring: application: name: ribbon-provider
之后啟動服務,啟動后訪問 localhost:8802/hello?name=zhangtaifeng :

測試完成,這個服務我們用他做服務提供者(provider),然后我們再重新建一個module,可以叫做 ribbon-consumer,整體配置一致,我們只需要修改service和controller部分(注意package):

然后修改配置文件為:
eureka: client: serviceUrl: defaultZone: http://localhost:8801/eureka/ server: port: 8803 spring: application: name: ribbon-consumer
改了端口和應用名稱。
然后復制上面的spring boot入口文件代碼,復制service和controller文件,依然 注意包名和路徑,然后修改HelloService:

我們啟動應用看看:

RestTemplate成功調用了8802端口上的provider。
到了這里,相信大家對spring cloud調用服務有了一定的了解,cloud通過rest調用服務進行服務間的通信,每一個controller的方法對外提供對應的服務接口。相比較dubbo的rpc調用有一些不一樣的優勢,同時它的開發方式更簡單,配合zuul網關的使用能夠達到更好的效果。
Feign消費
feign消費是通過注解的方式進行的消費模式,它默認打開了負載均衡,還是在cloudDemo下創建一個module,名字叫feign:


注意引用的包。
創建完成,首先編寫入口文件,主要是加上
@EnableDiscoveryClient
@EnableFeignClients
這兩個注解,用於注冊和發現服務。

然后我們在目錄下新建一個service,controller,或者從前面的工程復制,另外需要新建一個rpc文件夾,然后在rpc下新建一個GetHello接口:

編寫訪問rpc的方法,使用feign調用更加簡便,添加@FeignClient注解即可,value的意思就是目標服務器,可以直接用yml中配置的application名稱,完整代碼如下:
@FeignClient(value = "ribbon-consumer") public interface GetHello { @RequestMapping(value = "/hello?name=feign",method = RequestMethod.GET) public String sayHello(); }
然后再改造下service代碼:

@Service public class HelloService { @Autowired private GetHello getHello; //注入rpc public String sayHello(){ return getHello.sayHello(); // 提供一個hello World } }
最后還是修改application.yml文件,配置大致相同,修改應用名和端口,代碼如下:
eureka: client: serviceUrl: defaultZone: http://localhost:8801/eureka/ server: port: 8804 spring: application: name: feign-consumer
然后我們啟動這個工程看看有什么效果,注意,這所有的步驟,前面的服務都沒有關閉噢:


啟動后效果如圖。
小結
代碼已傳至我的github,大家可以下載查看。
從這里看,spring cloud將我們的幾個應用串聯起來,各個服務之間互相通過restAPI調用,我覺得Feign要優於ribbon,另外Eureka注冊中心也可以換成zookeeper或者consul,我目前使用consul。
spring cloud東西非常多,慢慢看,大家一起進步,謝謝。
有什么問題大家評論區多多交流。
