sbc(一)SpringBoot+SpringCloud初探

crossoverJie發表於2019-03-04

前言

有看過我之前的SSM系列的朋友應該有一點印象是非常深刻的。

那就是需要配置的配置檔案非常多,什麼Springmybatisredismq之類的配置檔案非常多,並且還存在各種版本,甚至有些版本還互不相容。其中有很多可能就是剛開始整合的時候需要配置,之後壓根就不會再動了。

鑑於此,Spring又推出了又一神器SpringBoot.

它可以讓我們更加快速的開發Spring應用,甚至做到了開箱即用。
由於在實際開發中我們使用SpringBoot+SpringCloud進行了一段時間的持續交付,並在生產環境得到了驗證,其中也有不少踩坑的地方,藉此機會和大家分享交流一下。

本篇我們首先會用利用SpringBoot構建出一個簡單的REST API.
接著會建立另一個SpringBoot專案,基於SpringCloud部署,並在兩個應用之間進行呼叫。

使用SpringBoot構建REST API

我們可以使用Spring官方提供的初始化工具幫我們生成一個基礎專案:start.spring.io/,如下圖所示:

sb2.jpg
sb2.jpg

填入相應資訊即可。由於只是要實現REST API所以這裡只需要引用web依賴即可。

將生成好的專案匯入IDE(我使用的是idea)中,目錄結構如下;

sb3.jpg
sb3.jpg

  • 其中的SbcUserApplication是整個應用的入口。
  • resource/application.properties這裡是存放整個應用的配置檔案。
  • 其中的statictemplates是存放靜態資源以及前端模板的地方,由於我們採用了前後端分離,所以這些目錄基本上用不上了。

通過執行SbcUserApplication類的main方法可以啟動SpringBoot專案。

接著在PostMan中進行呼叫,看到以下結果表明啟動成功了:

springBoot01.jpg
springBoot01.jpg

這樣一看是不是要比之前用Spring+SpringMVC來整合要方便快捷很多。

建立另一個SpringBoot專案

當我們的專案採用微服務構建之後自然就會被拆分成N多個獨立的應用。比如上文中的sbc-user用於使用者管理。這裡再建立一個sbc-order使用者生成訂單。

為了方便之後的程式碼複用,我將common包中的一些列舉值、工具類單獨提到sbc-common應用中了,這樣有其他應用要使用這些基礎類直接引入這個依賴即可。

<dependency>
    <groupId>com.crossoverJie</groupId>
    <artifactId>sbc-common</artifactId>
    <version>1.0.0-SNAPSHOT</version>
</dependency>複製程式碼

建立步驟和上文差不多,這裡就不再贅述了。
其中有一個order/getOrderNo的服務,呼叫結果如下:

springBoot02.jpg
springBoot02.jpg

之後會利用SpringCloud來將兩個服務關聯起來,並可以互相呼叫。

使用SpringCloud進行分散式呼叫

搭建eureka註冊中心

既然是要搭建微服務那自然少不了註冊中心了,之前講的dubbo採用的是zookeeper作為註冊中心,SpringCloud則採用的是Netflix Eureka來做服務的註冊與發現。

新建一個專案sbc-service,目錄結構如下:

springBoot03.jpg
springBoot03.jpg

核心的pom.xml

<dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-eureka-server</artifactId>
    </dependency>
    <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-classic</artifactId>
        <version>1.2.1</version>
    </dependency>

</dependencies>

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>Brixton.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>複製程式碼

非常easy,只需要引入eureka的依賴即可。
然後在入口類加入一個註解@EnableEurekaServer,即可將該專案作為服務註冊中心:

package com.crossoverJie.service;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

@EnableEurekaServer
@SpringBootApplication
public class EurekaApplication {
    private final static Logger logger = LoggerFactory.getLogger(EurekaApplication.class);
    public static void main(String[] args) {

        SpringApplication.run(EurekaApplication.class, args);
        logger.info("SpringBoot Start Success");
    }

}複製程式碼

接著修改配置檔案application.properties:

server.port=8888

# 不向註冊中心註冊自己
eureka.client.register-with-eureka=false

# 不需要檢索服務
eureka.client.fetch-registry=false

eureka.client.serviceUrl.defaultZone=http://localhost:${server.port}/eureka/複製程式碼

配置一下埠以及註冊中心的地址即可。
然後按照正常啟動springBoot專案一樣啟動即可。

在位址列輸入http://localhost:8888看到一下介面:

springBoot04.jpg
springBoot04.jpg

當然現在在註冊中心還看不到任何一個應用,下面需要將上文的sbc-user,sbc-order註冊進來。

向註冊中心註冊服務提供者

只需要在application.properties配置檔案中加上註冊中心的配置:

eureka.client.serviceUrl.defaultZone=http://localhost:8888/eureka/複製程式碼

並在sbc-order的主類中加入@EnableDiscoveryClient註解即可完成註冊服務。

啟動註冊中心以及應用,在註冊中心看到一下介面則成功註冊:

springBoot05.jpg
springBoot05.jpg

消費註冊中心的服務

服務是註冊上去了,自然是需要消費了,這裡就簡單模擬了在呼叫http://localhost:8080/user/getUser這個介面的時候getUser介面會去呼叫ordergetOrder服務。

這裡會用到另一個依賴:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-ribbon</artifactId>
</dependency>複製程式碼

他可以幫我們做到客戶端負載,具體使用如下:

  • 加入ribbon依賴。
  • 在主類中開啟@LoadBalanced客戶端負載。
  • 建立restTemplate類的例項
@Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }複製程式碼
  • 使用restTemplate呼叫遠端服務:

     @Autowired
    private RestTemplate restTemplate;

     @RequestMapping(value = "/getUser",method = RequestMethod.POST)
    public UserRes getUser(@RequestBody UserReq userReq){
        OrderNoReq req = new OrderNoReq() ;
        req.setReqNo("1213");
        //呼叫遠端服務
        ResponseEntity<Object> res = restTemplate.postForEntity("http://sbc-order/order/getOrderNo", req, Object.class);
        logger.info("res="+JSON.toJSONString(res));

        logger.debug("入參="+ JSON.toJSONString(userReq));
        UserRes userRes = new UserRes() ;
        userRes.setUserId(123);
        userRes.setUserName("張三");

        userRes.setReqNo(userReq.getReqNo());
        userRes.setCode(StatusEnum.SUCCESS.getCode());
        userRes.setMessage("成功");

        return userRes ;

    }複製程式碼

由於我的遠端介面是post,所以使用了postForEntity()方法,如果是get就換成getForEntity()即可。

注意這裡是使用應用名sbc-order(配置於sbc-order的application.properties中)來進行呼叫的,並不是一個IP地址。

啟動註冊中心、兩個應用。
PostMan呼叫getUser介面時控制檯列印:

2017-06-27 00:18:04.534  INFO 63252 --- [nio-8080-exec-3] c.c.sbcuser.controller.UserController    : res={"body":{"code":"4000","message":"appID不能為空","reqNo":"1213"},"headers":{"X-Application-Context":["sbc-order:8181"],"Content-Type":["application/xml;charset=UTF-8"],"Transfer-Encoding":["chunked"],"Date":["Mon, 26 Jun 2017 16:18:04 GMT"]},"statusCode":"OK","statusCodeValue":200}複製程式碼

由於並沒有傳遞appId所以order服務返回了一個錯誤,也正說明是遠端呼叫到了該服務。

總結

ps:這裡只是簡單使用了ribbon來進行服務呼叫,但在實際的開發中還是比較少的使用這種方式來呼叫遠端服務,而是使用Feign進行宣告式呼叫,可以簡化客戶端程式碼,具體使用方式請持續關注。

本次算是springBoot+springCloud的入門,還有很多東西沒有講到,之後我將會根據實際使用的一些經驗繼續分享SpringCloud這個新興框架。

專案地址:github.com/crossoverJi…

個人部落格地址:crossoverjie.top

weixinchat.jpg
weixinchat.jpg