第一個springboot程式,微服務的瞭解
1:微服務是瞭解
1:基本介紹
微服務最早由Martin Fowler與James Lewis於2014年共同提出,微服務架構風格是一種使用一套小服務來開發單個應用的方式途徑,每個服務執行在自己的程序中,並使用輕量級機制通訊,通常是HTTP API,這些服務基於業務能力構建,並能夠通過自動化部署機制來獨立部署,這些服務使用不同的程式語言實現,以及不同資料儲存技術,並保持最低限度的集中式管理。
而所謂服務,一定要區別於系統,服務一個或者一組相對較小且獨立的功能單元,是使用者可以感知最小功能集。
單體架構在規模比較小的情況下工作情況良好,但是隨著系統規模的擴大,它暴露出來的問題也越來越多,主要有以下幾點:
1.複雜性逐漸變高
比如有的專案有幾十萬行程式碼,各個模組之間區別比較模糊,邏輯比較混亂,程式碼越多複雜性越高,越難解決遇到的問題。
2.技術債務逐漸上升
公司的人員流動是再正常不過的事情,有的員工在離職之前,疏於程式碼質量的自我管束,導致留下來很多坑,由於單體專案程式碼量龐大的驚人,留下的坑很難被發覺,這就給新來的員工帶來很大的煩惱,人員流動越大所留下的坑越多,也就是所謂的技術債務越來越多。
3.部署速度逐漸變慢
這個就很好理解了,單體架構模組非常多,程式碼量非常龐大,導致部署專案所花費的時間越來越多,曾經有的專案啟動就要一二十分鐘,這是多麼恐怖的事情啊,啟動幾次專案一天的時間就過去了,留給開發者開發的時間就非常少了。
4.阻礙技術創新
比如以前的某個專案使用struts2寫的,由於各個模組之間有著千絲萬縷的聯絡,程式碼量大,邏輯不夠清楚,如果現在想用spring mvc來重構這個專案將是非常困難的,付出的成本將非常大,所以更多的時候公司不得不硬著頭皮繼續使用老的struts架構,這就阻礙了技術的創新。
5.無法按需伸縮
比如說電影模組是CPU密集型的模組,而訂單模組是IO密集型的模組,假如我們要提升訂單模組的效能,比如加大記憶體、增加硬碟,但是由於所有的模組都在一個架構下,因此我們在擴充套件訂單模組的效能時不得不考慮其它模組的因素,因為我們不能因為擴充套件某個模組的效能而損害其它模組的效能,從而無法按需進行伸縮。
2:優缺點
特點
易於開發和維護
由於微服務單個模組就相當於一個專案,開發這個模組我們就只需關心這個模組的邏輯即可,程式碼量和邏輯複雜度都會降低,從而易於開發和維護。
啟動較快
這是相對單個微服務來講的,相比於啟動單體架構的整個專案,啟動某個模組的服務速度明顯是要快很多的。
區域性修改容易部署
在開發中發現了一個問題,如果是單體架構的話,我們就需要重新發布並啟動整個專案,非常耗時間,但是微服務則不同,哪個模組出現了bug我們只需要解決那個模組的bug就可以了,解決完bug之後,我們只需要重啟這個模組的服務即可,部署相對簡單,不必重啟整個專案從而大大節約時間。
技術棧不受限
比如訂單微服務和電影微服務原來都是用java寫的,現在我們想把電影微服務改成nodeJs技術,這是完全可以的,而且由於所關注的只是電影的邏輯而已,因此技術更換的成本也就會少很多。
按需伸縮
我們上面說了單體架構在想擴充套件某個模組的效能時不得不考慮到其它模組的效能會不會受影響,對於我們微服務來講,完全不是問題,電影模組通過什麼方式來提升效能不必考慮其它模組的情況。
缺點
運維要求較高
對於單體架構來講,我們只需要維護好這一個專案就可以了,但是對於微服務架構來講,由於專案是由多個微服務構成的,每個模組出現問題都會造成整個專案執行出現異常,想要知道是哪個模組造成的問題往往是不容易的,因為我們無法一步一步通過debug的方式來跟蹤,這就對運維人員提出了很高的要求。
介面調整成本高
比如,使用者微服務是要被訂單微服務和電影微服務所呼叫的,一旦使用者微服務的介面發生大的變動,那麼所有依賴它的微服務都要做相應的調整,由於微服務可能非常多,那麼調整介面所造成的成本將會明顯提高。
重複勞動
對於單體架構來講,如果某段業務被多個模組所共同使用,我們便可以抽象成一個工具類,被所有模組直接呼叫,但是微服務卻無法這樣做,因為這個微服務的工具類是不能被其它微服務所直接呼叫的,從而我們便不得不在每個微服務上都建這麼一個工具類,從而導致程式碼的重複。
2:技術列表
經典微服務架構,ali微服務 , dubbo微服務(遠端呼叫)
服務開發 Springboot、Spring、SpringMVC 、mybatis,mybatis-plus
服務註冊與發現 Eureka、Consul、Zookeeper等 nacos
服務呼叫 REST、RPC、gRPC
服務熔斷器 Hystrix
負載均衡 Ribbon、Nginx等
服務呼叫(客戶端呼叫服務發簡單工具) Feign等
openFeign
訊息佇列 RabbitMQ、ActiveMQ等
服務配置中心管理 SpringCloudConfig、Chef等
服務路由(API閘道器) Zuul等
服務部署 Docker、OpenStack等 k8s
事件訊息匯流排 SpringCloud Bus
資料快取redis
3:環境要求
–jdk1.8:Spring Boot 推薦jdk1.7及以上;java version "1.8.0_112"
–maven3.x:maven 3.3以上版本;
–IntelliJIDEA2017以上:IntelliJ IDEA 2017.2.2 x64、STS
–SpringBoot 2.2.2.RELEASE 以上, 建議使用2.3
給maven 的settings.xml配置檔案的profifiles標籤新增:
<profile> <id>jdk‐1.8</id> <activation> <activeByDefault>true</activeByDefault> <jdk>1.8</jdk> </activation> <properties> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> <maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion> </properties> </profile>
4:springboot程式
1:第一個springboot程式helloworld
需求:瀏覽器傳送一個hello請求,返回伺服器返回一個helloworld
1:嚮導建立專案
使用Spring Initializer快速建立Spring Boot專案
注意:選擇需要自己的模組,嚮導會聯網建立Spring Boot專案;
Web
2:編寫後臺程式
現在的後臺程式其實就是springmvc的程式,新增對應的註解
3:啟動主程式測試
Springboot專案建立好之後,會自動生成一個主程式,主程式的名字為projectNameApplication,主程式上有一個固定的註解@SpringBootApplication
啟動主程式之後就相當於將專案釋出了,通過瀏覽器訪問對應的後臺程式。
注意:所有的後臺程式必須位於主程式的子包中,否則無法進行管理
2:目錄介紹
resources資料夾中目錄結構
static:儲存所有的靜態資源; js css images;
templates:儲存所有的模板頁面;(Spring Boot預設jar包使用嵌入式的Tomcat,預設不支援JSP頁 面);可以使用模板引擎(freemarker、thymeleaf);
application.properties:Spring Boot應用的配置檔案;可以修改一些預設設定;
3:helloWorld探究
1:POM檔案
所有的springboot專案都自動的繼承於一個父專案,該專案對依賴的版本做了統一的管理;
Spring Boot的版本仲裁中心; 以後我們匯入依賴預設是不需要寫版本;(沒有在dependencies裡面管理的依賴自然需要宣告版本號)
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.x.x.RELEASE</version>
<relativePath/>
</parent>
繼承 spring-boot-starter-parent 來作為父專案, spring-boot-starter-parent的父專案又是Spring Boot Dependencies,
已經定義好了很多包的依賴,可以統一專案的依賴,避免後續的版本衝突。
在dependencies裡的部分配置可以不用填寫version資訊,這些version資訊會從spring-boot-dependencies裡得到繼承。
2:啟動類
spring-boot-starter:spring-boot場景啟動器;幫我們匯入了web模組正常執行所依賴的元件
Spring Boot將所有的功能場景都抽取出來,做成一個個的starters(啟動器),只需要在專案裡面引入這些starter 相關場景的所有依賴都會匯入進來。
要用什麼功能就匯入什麼場景的啟動器
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
3:主程式
@SpringBootApplication: Spring Boot應用標註在某個類上說明這個類是SpringBoot的主配置類,
SpringBoot 就應該執行這個類的main方法來啟動SpringBoot應用;
@SpringBootConfiguration:Spring Boot的配置類; 標註在某個類上,表示這是一個Spring Boot的配置類;
@Configuration:配置類上來標註這個註解; 配置類 ----- 配置檔案;配置類也是容器中的一個元件;@Component
@EnableAutoConfiguration:開啟自動配置功能;以前我們需要配置的東西,Spring Boot幫我們自動配置;
會給容器中匯入非常多的自動配置類(xxxAutoConfiguration);就是給容器中匯入這個場景需要的所有元件, 並配置好這些元件;
Spring Boot在啟動的時候從類路徑下的META-INF/spring.factories中獲取EnableAutoConfiguration指定的值,將這些值作為自動配置類匯入到容器中,自動配置類就生效,幫我們進行自動配置工作;以前我們需要自己配置的東 西,自動配置類都幫我們;
如何自定義一個配置類?
在一個類上加入@Configuration 註解,表明這就是一個配置類。在類中的方法上使用@Bean 進行註解,並返回某個類的一個例項,
表明這個方法是需要被Spring進行管理的bean。@Bean 如果不指定名稱的話,預設使用方法的名稱,也就是小寫的名稱。
<bean id=”方法名” class = “xxx”>
@Bean
任何一個標註了@Bean的方法,其返回值將作為一個bean元件定義註冊到Spring的IoC容器,方法名將預設成該bean定義的id。
如何測試IOC中的bean呢?
Main方法中的主啟動類其實有一個返回值,通過getBean的方法可以獲取容器中的bean。
在springboot中@Component註解仍然可以使用。
5:配置檔案
SpringBoot使用一個全域性的配置檔案,配置檔名是固定的; 配置檔案的作用:修改SpringBoot自動配置的預設值;SpringBoot在底層都給我們自動配置好
•application.properties
•application.yml
YAML(YAML Ain't Markup Language)
YAML A Markup Language:是一個標記語言
YAML isn't Markup Language:不是一個標記語言;
標記語言: 以前的配置檔案;大多都使用的是 xxxx.xml檔案;
YAML:以資料為中心,比json、xml等更適合做配置檔案;
YAML:配置例子
server:
port: 8081
Xml:
<server>
<port>8081</port>
</server>
Properties:
server.port=8090
1:yml/ yaml基本語法
k:(空格)v :表示一對鍵值對(空格必須有);
以空格的縮排來控制層級關係;只要是左對齊的一列資料,都是同一個層級的
server:
port: 8081
servlet:
context-path: /first
2:值的型別
1:簡單字面量型別
k: v:字面直接來寫; 字串預設不用加上單引號或者雙引號;
"":雙引號;不會轉義字串裡面的特殊字元;特殊字元會作為本身想表示的意思
name: "zhangsan \n lisi":輸出;zhangsan 換行 lisi
'':單引號;會轉義特殊字元,特殊字元最終只是一個普通的字串資料
name: ‘zhangsan \n lisi’:輸出;zhangsan \n lisi
注意:
1:將配置檔案中的內容和bean物件進行對映,需要在實體類上新增 @ConfigurationProperties(prefix = "配置檔案中的字首"),它預設是從全域性的配置檔案中取值
2:必須要將javabean新增至容器中需要使用 @Component 註解
2、陣列、集合
用- 值表示陣列中的一個元素
Friends
- xiaoming
- xiaoli
行內寫法
Friends: [xiaoming,xiaoli]
注意:
1:如果想將配置檔案中的資料注入到javabean中,需要在實體類上新增 @ConfigurationProperties(prefix = "配置檔案中的字首"),它預設是從全域性的配置檔案中取值
2:必須要將javabean新增至容器中需要使用 @Component 註解
3:新增@ConfigurationProperties註解後,idea上面爆紅的話不是配置問題,spring boot Configuration Annotation Proessor not found in classpath,
是缺少了依賴,需要在中新增配置檔案處理器的配置,配置了處理器之後就不會在報紅了,而且配置的時候會有提示
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency>
4:上面的做法是將配置檔案中的內容和bean物件進行對映,如果只有少量的屬性需要賦值的話,可以直接在屬性上加@Value("${key.value}")的註解進行取值或者直接賦值,
但是他不支援複雜的資料進行賦值,比如物件,集合等。一般只有簡單的取值會使用。採用完全對映的時候不需要使用@value這個註解。
5:上面的做法都是從全域性的配置檔案中讀取一些值,如果全部寫在全域性的配置檔案中的話,那麼會顯得很是臃腫,springboot還可以從指定的配置檔案中讀取相關的值。
可以使用@PropertySource(value = {"classpath:xxx.properties"})來指定具體的檔案,注意這個註解要和@ConfigurationProperties(prefix = "配置檔案中的字首")一起使用
注意引號的位置。
3:配置類
Springboot給容器中新增元件的方式可以使用傳統的新增spring配置檔案的方式或者簡單的註解方式,也可以寫一個配置類。Springboot意在給配置檔案做減肥,
所以官方建議我們需要新增元件的話可以使用配置類的方式。配置類中方法上新增@Bean即可,他會將方法的返回值新增到容器中。通過main方法中呼叫方法的返回值可以在容器中獲取這個bean.
注意:配置類上一定要加一個@Configuration註解,標註這個類是一個配置類
瞭解下:
@Configuration public class MyAppConfig { @Bean public TestService getService(){ return new TestService(); } }
4:多環境配置profile
1:多profile
我們在主配置檔案編寫的時候,檔名可以是 application-{profile}.properties/yml
如:application-dev.properties, application-test.properties,application-prod.properties
如果不去指導使用哪一個配置檔案的話,則預設使用application.properties的配置;
如果需要制定的話,則可以使用 spring.profiles.active=dev 來進行指定啟用
注意:激活了某個環境的配置檔案之後,只有和主配置中的相關配置相沖突的時候才會優先選擇被啟用檔案內容
如果主配置檔案中的內容和被啟用檔案的內容沒有衝突的話,依然會被載入
2: yml多文件快
如果配置檔案使用yml方式的話,yml支援多文件快的配置方式
使用 --- 進行分割,每一個快可以使用spring.profiles: dev 來給每一塊起個名字
然後使用spring.profiles.active: test 來進行啟用某一塊的配置
3:啟用指定的profile
如果使用properties進行多檔案配置方式的話,則預設使用application.properties的配置,
如果需要指定某個檔案生效的話,則可以使用 spring.profiles.active=dev 來進行啟用。
如果使用yml作為配置檔案的話,可以使用yml的多文件塊的方式進行多環境配置,
在塊檔案中可以使用spring.profiles: name 來指定塊檔案的名字
如果需要使用某一塊配置生效的話,則可以使用spring.profiles.active: name 來進行啟用
5:配置檔案位置
springboot 啟動會掃描以下位置的application.properties或者application.yml檔案作為Spring boot的預設配置檔案
–file:./config/ 專案下的config目錄下的配置檔案,優先順序最高
–file:./ 專案下的配置檔案
–classpath:/config/ resources下的config目錄下的配置檔案
–classpath:/ resources下的配置檔案
優先順序由高到底,高優先順序的配置會覆蓋低優先順序的配置; SpringBoot會從這四個位置全部載入主配置檔案;相沖突的會覆蓋,互補配置;與css一樣的原理
6:自動配置原理
精髓:
1)、SpringBoot啟動會載入大量的自動配置類,META-INF/spring.factories
2)、查詢我們需要的功能有沒有SpringBoot預設寫好的自動配置類;
3)、我們再來看這個自動配置類中到底配置了哪些元件;(只要我們要用的元件有,我們就不需要再來配置了)
4)、給容器中自動配置類新增元件的時候,會從properties類中獲取某些屬性。我們就可以在配置檔案中指定這些屬性的值;
配置的時候一般是@ConditionalOnProperty(prefix = "XXX")的字首加具體的屬性值,
如果沒有屬性的話則說明只有一個可以配置的,直接使用字首即可。
注意:
xxxxAutoConfifigurartion:自動配置類;給容器中新增元件配置資訊。
細節:註解的簡單瞭解:
@Conditional是一個衍生的判斷註解,必須是@Conditional指定的條件成立,才給容器中新增元件,配置配裡面的所有內容才生效;
自動配置類必須在一定的條件下才能生效; 我們怎麼知道哪些自動配置類生效?
我們可以在配置檔案中啟用 debug=true屬性;來讓控制檯列印自動配置報告,這樣我們就可以很方便的知道哪些自動配置類生效;