絕無此例娘香!用實(shí)例演示如何使用Spring搭建微服務(wù)框架,覺悟

一個(gè)使用Spring, Spring Boot 和 Spring Cloud設(shè)置微服務(wù)系統(tǒng)的簡單示例办龄。

微服務(wù)允許從許多協(xié)作組件構(gòu)建大型系統(tǒng)烘绽。它在流程級別執(zhí)行Spring在組件級別執(zhí)行的操作:松散耦合的流程而不是松散耦合的組件。

絕無此例俐填!用實(shí)例演示如何使用Spring搭建微服務(wù)框架安接,覺悟

例如,設(shè)想一個(gè)在線商店英融,為用戶帳戶盏檐、產(chǎn)品目錄訂單處理和購物車提供單獨(dú)的微服務(wù):

不可避免地,要構(gòu)建這樣一個(gè)系統(tǒng)驶悟,必須設(shè)置和配置許多移動(dòng)部件胡野。如何讓它們協(xié)同工作并不明顯——你需要很好地熟悉Spring Boot,因?yàn)镾pring Cloud充分利用了它痕鳍,需要幾個(gè)Netflix或其他OSS項(xiàng)目硫豆,當(dāng)然,還有一些Spring配置“魔力”!

絕無此例熊响!用實(shí)例演示如何使用Spring搭建微服務(wù)框架恭应,覺悟

在本文中,我旨在通過逐步構(gòu)建最簡單的系統(tǒng)來闡明事物是如何工作的耘眨。因此昼榛,我將只實(shí)現(xiàn)大系統(tǒng)的一小部分—用戶帳戶服務(wù)。

Web應(yīng)用程序?qū)⑹褂胷estful api向帳戶服務(wù)microservice發(fā)出請求剔难。我們還需要添加一個(gè)發(fā)現(xiàn)服務(wù)胆屿,以便其他進(jìn)程能夠找到彼此。

此應(yīng)用程序的代碼如下:http://github.com/paulc4/microservices-demo

對其工作原理的描述非常詳細(xì)偶宫。不耐煩的讀者可能更喜歡簡單地看代碼非迹。注意,它在一個(gè)項(xiàng)目中包含三個(gè)微服務(wù)纯趋。

好吧憎兽,我們開始吧…

服務(wù)注冊

當(dāng)多個(gè)進(jìn)程協(xié)同工作時(shí),它們需要找到彼此吵冒。如果您曾經(jīng)使用過Java的RMI機(jī)制纯命,您可能還記得它依賴于一個(gè)中央注冊表,這樣RMI進(jìn)程就可以找到彼此痹栖。微服務(wù)也有同樣的要求亿汞。

Netflix的開發(fā)人員在構(gòu)建系統(tǒng)時(shí)遇到了這個(gè)問題,他們創(chuàng)建了一個(gè)名為Eureka的注冊服務(wù)器(希臘語為“我找到了”)揪阿。對我們來說幸運(yùn)的是疗我,他們使他們的發(fā)現(xiàn)服務(wù)器開源,而且Spring已經(jīng)并入Spring Cloud南捂,這使得運(yùn)行Eureka服務(wù)器更加容易吴裤。下面是完整的discovery server應(yīng)用程序:

@SpringBootApplication
@EnableEurekaServer
public class ServiceRegistrationServer {

  public static void main(String[] args) {
    // Tell Boot to look for registration-server.yml
    System.setProperty("spring.config.name", "registration-server");
    SpringApplication.run(ServiceRegistrationServer.class, args);
  }
}

就這么簡單!

SpringCloud構(gòu)建在SpringBoot上溺健,并使用父級和啟動(dòng)POM麦牺。POM的重要部分包括:

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.1.RELEASE</version>
    </parent>

    <dependencies>
        <dependency>
            <!-- Setup Spring Boot -->
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <!-- Setup Spring MVC & REST, use Embedded Tomcat -->
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <!-- Spring Cloud starter -->
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter</artifactId>
        </dependency>

        <dependency>
            <!-- Eureka for service registration -->
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka-server</artifactId>
        </dependency>
    </dependencies>

   <!-- Spring Cloud 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>

這個(gè)POM已經(jīng)改變,因?yàn)槲易畛鯇懙奈恼率褂胹pringboot作為其父代矿瘦,而不是springcloud枕面。Spring云依賴關(guān)系是通過依賴關(guān)系管理部分提供的。

github代碼中還包含一個(gè)示例gradle構(gòu)建文件缚去。

默認(rèn)情況下潮秘,Spring引導(dǎo)應(yīng)用程序?qū)ふ覒?yīng)用程序?qū)傩曰蛘遖pplication.yml配置文件。通過設(shè)置spring.config.name屬性易结,我們可以告訴SpringBoot查找不同的文件—如果您在同一個(gè)項(xiàng)目中有多個(gè)SpringBoot應(yīng)用程序枕荞,這很有用—我很快就會這么做柜候。

此應(yīng)用程序?qū)ふ襯egistration-server.properties或registration-server.yml. 以下是注冊的相關(guān)registration-server.yml:

# Configure this Discovery Server
eureka:
  instance:
    hostname: localhost
  client:  # Not a client, don't register with yourself (unless running
           # multiple discovery servers for redundancy)
    registerWithEureka: false
    fetchRegistry: false

server:
  port: 1111   # HTTP (Tomcat) port

默認(rèn)情況下,Eureka在端口8761上運(yùn)行躏精,但這里我們將使用端口1111渣刷。另外,通過在進(jìn)程中包含注冊碼矗烛,我可能是一個(gè)服務(wù)器或客戶機(jī)辅柴。配置指定我不是客戶機(jī),并停止服務(wù)器進(jìn)程嘗試向自身注冊瞭吃。

現(xiàn)在嘗試運(yùn)行RegistrationServer(請參閱下面的運(yùn)行應(yīng)用程序的幫助)碌嘀。您可以在此處打開Eureka儀表板:http://localhost:1111,顯示應(yīng)用程序的部分將為空歪架。

從現(xiàn)在起股冗,我們將提到發(fā)現(xiàn)服務(wù)器,因?yàn)樗赡苁荅ureka或Consul和蚪。

Spring Cloud還支持Consul作為Eureka的替代品止状。您可以使用腳本啟動(dòng)consur代理(它的注冊服務(wù)器),然后客戶機(jī)使用它來查找他們的微服務(wù)攒霹。

創(chuàng)建微服務(wù):帳戶服務(wù)

微服務(wù)是處理定義良好的需求的獨(dú)立流程怯疤。

[圖片上傳失敗...(image-659c2-1614603159869)]

在使用Spring配置應(yīng)用程序時(shí),我們強(qiáng)調(diào)松耦合和緊密內(nèi)聚剔蹋,這不是新概念(Larry Constantine在20世紀(jì)60年代末首次定義了這些概念)旅薄,但現(xiàn)在我們將它們應(yīng)用于交互組件(Springbeans),而不是交互過程泣崩。

在這個(gè)例子中,我有一個(gè)簡單的帳戶管理微服務(wù)洛口,它使用Spring數(shù)據(jù)實(shí)現(xiàn)jpaccount repository矫付,Spring REST提供一個(gè)RESTful接口來訪問帳戶信息。在大多數(shù)方面第焰,這是一個(gè)簡單的Spring Boot application买优。

它的特殊之處在于它在啟動(dòng)時(shí)向發(fā)現(xiàn)服務(wù)器注冊。以下是Spring Boot啟動(dòng)類:

@EnableAutoConfiguration
@EnableDiscoveryClient
@Import(AccountsWebApplication.class)
public class AccountsServer {

    @Autowired
    AccountRepository accountRepository;

    public static void main(String[] args) {
        // Will configure using accounts-server.yml
        System.setProperty("spring.config.name", "accounts-server");

        SpringApplication.run(AccountsServer.class, args);
    }
}

注釋完成了以下工作:

  1. @EnableAutoConfiguration 將其定義為Spring引導(dǎo)應(yīng)用程序挺举。

  2. @EnableDiscoveryClient 這將啟用服務(wù)注冊和發(fā)現(xiàn)杀赢。在本例中,此進(jìn)程使用其應(yīng)用程序名稱(見下文)向discovery server服務(wù)注冊自己湘纵。

  3. @Import(AccountsWebApplication.class)-這個(gè)Java配置類設(shè)置其他所有內(nèi)容(請參閱下面的詳細(xì)信息)脂崔。

使這成為一項(xiàng)微服務(wù)的是通過@EnableDiscoveryClient向發(fā)現(xiàn)服務(wù)器注冊,其YML配置完成了設(shè)置:

# Spring properties
spring:
  application:
     name: accounts-service

# Discovery Server Access
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:1111/eureka/

# HTTP Server
server:
  port: 2222   # HTTP (Tomcat) port

請注意梧喷,此文件

1. 將應(yīng)用程序名稱設(shè)置為accounts-service砌左。此服務(wù)使用此名稱注冊脖咐,也可以使用此名稱訪問-請參閱下面的。

2. 指定要偵聽的自定義端口(2222)汇歹。我所有的進(jìn)程都在使用Tomcat屁擅,它們不能都監(jiān)聽端口8080。

3. Eureka服務(wù)進(jìn)程的URL-來自上一節(jié)产弹。

現(xiàn)在運(yùn)行AccountsService應(yīng)用程序并讓它完成初始化派歌。刷新儀表板http://localhost:1111并且您應(yīng)該看到“應(yīng)用程序”下列出的ACCOUNTS-SERVICE。注冊最多需要30秒(默認(rèn)情況下)痰哨,所以請耐心檢查RegistrationService的日志輸出

絕無此例硝皂!用實(shí)例演示如何使用Spring搭建微服務(wù)框架,覺悟

欲了解更多詳情作谭,請點(diǎn)擊此處:http://localhost:1111/eureka/apps/您應(yīng)該看到如下內(nèi)容:

<applications>
    <versions__delta>1</versions__delta>
    <apps__hashcode>UP_1_</apps__hashcode>
    <application>
        <name>ACCOUNTS-SERVICE</name>
        <instance>
            <hostName>autgchapmp1m1.corp.emc.com</hostName>
            <app>ACCOUNTS-SERVICE</app>
            <ipAddr>172.16.84.1</ipAddr><status>UP</status>
            <overriddenstatus>UNKNOWN</overriddenstatus>
            <port enabled="true">3344</port>
            <securePort enabled="false">443</securePort>
            ...
        </instance>
    </application>
</applications>

警告:不要嘗試使用Eclipse/STS的內(nèi)部web查看器顯示XML輸出稽物,因?yàn)樗荒苓@樣做。改用你最喜歡的網(wǎng)絡(luò)瀏覽器折欠。

或者轉(zhuǎn)到http://localhost:1111/eureka/apps/ACCOUNTS-SERVICE贝或,只需查看AccountsService的詳細(xì)信息-如果未注冊,您將獲得404锐秦。

配置選項(xiàng)

注冊時(shí)間:注冊最多需要30秒咪奖,因?yàn)檫@是默認(rèn)的客戶端刷新時(shí)間。您可以通過設(shè)置eureka.instance.leaseRenewalIntervalInSeconds=秒屬性設(shè)置為較小的數(shù)字(在演示應(yīng)用程序中酱床,我已將其設(shè)置為5)羊赵。在生產(chǎn)中不建議這樣做。

eureka:
  instance:
    leaseRenewalIntervalInSeconds: 5         # DO NOT DO THIS IN PRODUCTION

注冊Id:進(jìn)程(微服務(wù))使用唯一的Id向發(fā)現(xiàn)服務(wù)注冊扇谣。如果另一個(gè)進(jìn)程使用相同的Id注冊昧捷,它將被視為重新啟動(dòng)(例如某種故障轉(zhuǎn)移或恢復(fù)),第一個(gè)進(jìn)程注冊將被丟棄罐寨。這為我們提供了所需的容錯(cuò)系統(tǒng)靡挥。

為了運(yùn)行同一進(jìn)程的多個(gè)實(shí)例(為了負(fù)載平衡和恢復(fù)能力),它們需要用一個(gè)唯一的id注冊鸯绿。

在Angel release train下跋破,客戶機(jī)用于向發(fā)現(xiàn)服務(wù)器注冊的實(shí)例id是從客戶機(jī)的服務(wù)名稱(與Spring應(yīng)用程序名稱相同)以及客戶機(jī)的主機(jī)名稱派生而來的。因此瓶蝴,在同一主機(jī)上運(yùn)行的相同進(jìn)程將具有相同的id毒返,因此只有一個(gè)進(jìn)程可以注冊。

幸運(yùn)的是舷手,您可以通過客戶端的Eureka元數(shù)據(jù)映射手動(dòng)設(shè)置id屬性拧簸,如下所示:

eureka:
  instance:
    metadataMap:
      instanceId: ${spring.application.name}:${spring.application.instance_id:${server.port}}

自從Brixton發(fā)布train以來,這是默認(rèn)的聚霜。那它做什么呢狡恬?

我們正在將instanceId設(shè)置為application-name:instance_id珠叔,但如果未定義instance_id,則將改用application-name::server-port弟劲。請注意spring.application.instance_id僅在使用CloudFoundry時(shí)設(shè)置祷安,但它方便地為同一應(yīng)用程序的每個(gè)實(shí)例提供唯一的id號。在其他地方運(yùn)行時(shí)兔乞,我們可以使用服務(wù)器端口執(zhí)行類似的操作(因?yàn)橥慌_機(jī)器上的不同實(shí)例必須偵聽不同的端口)汇鞭。你經(jīng)常看到的另一個(gè)例子是{spring.application.name}:{spring.application.instance_id:${random.value}}但我個(gè)人發(fā)現(xiàn)庸追,使用端口號可以很容易地識別每個(gè)實(shí)例—隨機(jī)值只是長字符串霍骄,沒有任何意義。

注意:語法{x:{y}}是{x} != null ?{x} : ${y}淡溯。

自從Brixton發(fā)布以來读整,它還有一個(gè)專門的屬性:

eureka:
  instance:
    instanceId: ${spring.application.name}:${spring.application.instance_id:${random.value}}

訪問微服務(wù):Web服務(wù)

為了使用RESTful服務(wù),Spring提供了RestTemplate類咱娶。這允許您向RESTful服務(wù)器發(fā)送HTTP請求米间,并以多種格式獲取數(shù)據(jù),例如JSON和XML膘侮。

可以使用哪種格式取決于類路徑上是否存在marshaling類—例如屈糊,JAXB總是被檢測到,因?yàn)樗荍ava的標(biāo)準(zhǔn)部分琼了。如果類路徑中存在Jackson jar逻锐,則支持JSON。

微服務(wù)(discovery)客戶機(jī)可以使用restemplate雕薪,Spring會自動(dòng)將其配置為支持微服務(wù)(稍后會有更多)昧诱。

注意:Accounts微服務(wù)提供了一個(gè)基于HTTP的RESTful接口,但是可以使用任何合適的協(xié)議蹦哼。使用AMQPJMS的消息傳遞是一個(gè)明顯的替代方案(在這種情況下鳄哭,不再需要發(fā)現(xiàn)服務(wù)器—相反,進(jìn)程需要知道要與之交談的隊(duì)列的名稱纲熏,可以考慮為此使用Spring云配置服務(wù)器)。

以上就是有關(guān)使用Spring搭建微服務(wù)框架的學(xué)習(xí)筆記锄俄,希望可以對大家的學(xué)習(xí)有幫助局劲,喜歡的小伙伴可以幫忙轉(zhuǎn)發(fā)+關(guān)注,感謝大家奶赠!LZ后期會不定時(shí)更新干貨的S闾睢!毅戈!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末苹丸,一起剝皮案震驚了整個(gè)濱河市愤惰,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌赘理,老刑警劉巖宦言,帶你破解...
    沈念sama閱讀 206,214評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異商模,居然都是意外死亡奠旺,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評論 2 382
  • 文/潘曉璐 我一進(jìn)店門施流,熙熙樓的掌柜王于貴愁眉苦臉地迎上來响疚,“玉大人,你說我怎么就攤上這事瞪醋》拊危” “怎么了?”我有些...
    開封第一講書人閱讀 152,543評論 0 341
  • 文/不壞的土叔 我叫張陵银受,是天一觀的道長践盼。 經(jīng)常有香客問我,道長蚓土,這世上最難降的妖魔是什么宏侍? 我笑而不...
    開封第一講書人閱讀 55,221評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮蜀漆,結(jié)果婚禮上谅河,老公的妹妹穿的比我還像新娘。我一直安慰自己确丢,他們只是感情好绷耍,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,224評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著鲜侥,像睡著了一般褂始。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上描函,一...
    開封第一講書人閱讀 49,007評論 1 284
  • 那天崎苗,我揣著相機(jī)與錄音,去河邊找鬼舀寓。 笑死胆数,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的互墓。 我是一名探鬼主播必尼,決...
    沈念sama閱讀 38,313評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了判莉?” 一聲冷哼從身側(cè)響起豆挽,我...
    開封第一講書人閱讀 36,956評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎券盅,沒想到半個(gè)月后帮哈,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,441評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡渗饮,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,925評論 2 323
  • 正文 我和宋清朗相戀三年但汞,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片互站。...
    茶點(diǎn)故事閱讀 38,018評論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡私蕾,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出胡桃,到底是詐尸還是另有隱情踩叭,我是刑警寧澤,帶...
    沈念sama閱讀 33,685評論 4 322
  • 正文 年R本政府宣布翠胰,位于F島的核電站容贝,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏之景。R本人自食惡果不足惜斤富,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,234評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望锻狗。 院中可真熱鬧满力,春花似錦、人聲如沸轻纪。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽刻帚。三九已至潦嘶,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間崇众,已是汗流浹背掂僵。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留顷歌,地道東北人看峻。 一個(gè)月前我還...
    沈念sama閱讀 45,467評論 2 352
  • 正文 我出身青樓,卻偏偏與公主長得像衙吩,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子溪窒,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,762評論 2 345

推薦閱讀更多精彩內(nèi)容