Spring Cloud使用總結

網易雲社群發表於2018-10-10

本文來自網易雲社群,轉載務必請註明出處。


Spring Cloud 是spring團隊推出的基於SpringBoot的分散式微服務框架,為開發者提供了在分散式系統(如配置管理、服務發現、斷路器、智慧路由、微代理、控制匯流排、一次性 Token、全域性鎖、決策競選、分散式會話和叢集狀態)操作的開發工具。

隨著部門內的產品,包括對外提供的一些服務越來越多,另外有一些基礎的功能需要抽象出來,團隊內部就開始對一些介面和業務進行服務化的改造,經過一些對比,初步採用的方案就是spring cloud。現對spring cloud的使用做一些簡單的總結。

基本配置

maven配置

專案本身都是基於maven的,首先可以利用maven的parent project的特性來管理spring cloud依賴的版本,spring cloud本身也提供了幾個starter project的maven依賴管理的基礎jar包。大致的配置如下:

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

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>ch.qos.logback</groupId>
                    <artifactId>logback-classic</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        ...    </dependencies>複製程式碼

服務註冊中心

dubbo的服務的註冊和發現可以依賴於zk或者redis來實現,spring cloud官方提供了自己的解決方案,使用eureka來做的,所以我們需要一個eureka server,實現起來很簡單,按照示例來即可:

  1. pom中新增

         <dependency>
             <groupId>org.springframework.cloud</groupId>
             <artifactId>spring-cloud-starter-eureka-server</artifactId>
         </dependency>複製程式碼
  2. 主程式如下

    @SpringBootApplication@EnableEurekaClientpublic class EurekaServer { public static void main(String[] args) {
         SpringApplication.run(EurekaServer.class, args);
     }
    }複製程式碼
  3. 在application.properties中新增監聽的埠號,如server.port=8761,然後啟動程式即可

註冊一個服務

  1. 在main函式所在程式中新增 @SpringBootApplication註解

  2. 在application.properties中新增上面註冊中心的地址,比如說, eureka.client.serviceUrl.defaultZone=http\://localhost\:8761/eureka/ 注意,生產環境這個註冊中心是需要多節點的

  3. 設定服務註冊的名稱,以及監聽的埠,也是在application.properties中的,如:

spring.application.name=spam-detect-service
server.port=8082複製程式碼
  1. 在controller上新增 @RestController及方法的@RequestMapping註解

啟動main函式,我們的服務就啟動並註冊到eureka server上了

發現並呼叫服務

  1. 在主程式的入口新增註解

@SpringBootApplication@EnableEurekaClient複製程式碼
  1. 新增一個RestTemplate例項(在主程式中新增即可),宣告為bean,方便別的服務進行autowired注入,用來進行HTTP呼叫

@LoadBalanced@BeanRestTemplate restTemplate() {    return new RestTemplate();
}複製程式碼
  1. 配置application.properties,主要是配置註冊中心的地址 eureka.client.serviceUrl.defaultZone=http\://localhost\:8761/eureka/

  2. 在程式的程式碼中使用restTemplate根據服務名稱訪問服務

@AutowiredRestTemplate restTemplate;static final String SERVICE_NAME = "spam-detect-service";public MMResult spamDetect(String type, String image) {    try {
        ....
        MMResult r = restTemplate.postForObject("http://" + SERVICE_NAME
                + "/xxxx", request, MMResult.class);        return r;
    } catch (Throwable t) {
        ....
    }
}複製程式碼

服務註冊/發現

Spring Cloud的一個重要貢獻者是Netflix,它提供了構建一個分散式rpc系統的關鍵的一些核心模組,在spring cloud 中,我們可以通過幾個簡單的註釋,就能構造一個分散式系統。系統中提供的模式包括服務發現(Eureka),斷路器(Hystrix),智慧路由(Zuul)和客戶端負載平衡等。

服務發現

Spring Cloud預設使用netflix貢獻的eureka來作為服務註冊和發現的。 服務發現預設採用EurekaClient,使用方式是:

@Autowiredprivate EurekaClient discoveryClient;複製程式碼

可能是覺得EurekaClient不太好用,spring同時提供了替代的方式,就是基於Feign和上面提到的RestTemplate,在例項上新增@RestTemplate註解即可。

服務註冊

在應用程式的main函式上新增如下註解即可

@SpringBootApplication@EnableEurekaServer複製程式碼

Ribbon

Spring Cloud採用ribbon來實現負載均衡loadbalance,使用restTemplate的時候新增@LoadBalance註解即可。服務的失敗重試retry、超時配置等,可以在application.properties中做一下配置即可

ribbon.ConnectTimeout=500ribbon.ReadTimeout=5000ribbon.MaxAutoRetries=1ribbon.MaxAutoRetriesNextServer=1ribbon.OkToRetryOnAllOperations=true複製程式碼

ribbon還可以不使用服務名稱的方式進行呼叫,可以把服務配置為固定的實體地址列表進行訪問,為服務名稱

.ribbon.listOfServers= 127.0.0.1:1234,127.0.0.1:1235

斷路器(Circuit Breaker)

當服務不可用的時候,或者需要進行併發訪問控制的時候使用的,spring cloud採用Hystrix來實現,在業務方法上加上@HystrixCommand 註解

服務不可用事預設回覆

配置@HystrixCommand的fallback屬性,如@HystrixCommand(fallbackMethod = "systemError"),注意systemError方法需要與業務方法的引數是一致的

併發訪問控制

配置@HystrixCommand的properties屬性

commandProperties = { @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "5000") }, threadPoolProperties = {
            @HystrixProperty(name = "coreSize", value = "5"),
            @HystrixProperty(name = "maxQueueSize", value = "10") }複製程式碼

服務路由zuul

zuul是基於jvm的路由轉發和負載均衡,有點類似於nginx,但是是基於jvm的,我們java程式設計師可以很方便的在上面做一些事情,它通常是放在入口,可以做一些轉發、安全校驗等統一的事情。它既可以轉發到本地的服務,也可以轉發到網際網路上其它url(使用ribbon的固定實體地址方式)。

配置轉發

在application.properties中配置

zuul.routes.<users>.path = /myusers/**
zuul.routes.<users>.serviceId = users複製程式碼

在程式碼中定義轉發

@Beanpublic PatternServiceRouteMapper serviceRouteMapper() {    return new PatternServiceRouteMapper(        "(?<name>^.+)-(?<version>v.+$)",        "${version}/${name}");
}複製程式碼

其它

可以配置zuul.host.maxTotalConnections 和 zuul.host.maxPerRouteConnections 可以控制路由的併發量

其它常用配置項

ip prefer and ignore

SpringCloud註冊服務的時候使用的是InetUtils的findFirstNonLoopbackAddress()方法,有時候我們的伺服器被發現的地址,偏偏不是機房內的互通ip,導致服務註冊上了,呼叫的時候訪問不通,這時候我們就需要設定忽略這個ip了,在配置檔案中 spring.cloud.inetutils.ignoredInterfaces=eth0

跨域

不討論跨域的必要性,如果需要用到跨域請求,需要做以下配置

  1. 在程式碼中設定 response.addHeader("Access-Control-Allow-Origin", "*");

  2. 新增option處理類

    @RestControllerpublic class OptionBean { @RequestMapping(method = RequestMethod.OPTIONS, value = "/**") public ResponseEntity manageOptions(HttpServletResponse response) {
         response.addHeader("Access-Control-Allow-Origin", "*");
         response.setHeader("Allow", "HEAD,GET,PUT,OPTIONS");     return new ResponseEntity(HttpStatus.OK);
     }
    }複製程式碼

    3.設定 spring.mvc.dispatch-options-request=true

tomcat的一些配置

如需要設定post size,upload file dize 等

@Bean  
    public MultipartConfigElement multipartConfigElement() {  
        MultipartConfigFactory factory = new MultipartConfigFactory();  
        factory.setMaxFileSize("20MB");  
        factory.setMaxRequestSize("20MB");  
        return factory.createMultipartConfig();  
    }    @Bean
    public TomcatEmbeddedServletContainerFactory tomcatEmbeddedServletContainerFactory() {
        TomcatEmbeddedServletContainerFactory tomcatFactory = new TomcatEmbeddedServletContainerFactory();

        tomcatFactory.addConnectorCustomizers(new TomcatConnectorCustomizer() {            @Override
            public void customize(Connector connector) {                // tomcat default nio connector
                Http11NioProtocol handler = (Http11NioProtocol) connector
                        .getProtocolHandler();                // acceptCount is backlog, default value is 100, you can change
                // which you want value in here
                handler.setBacklog(100);
                handler.setMaxThreads(1000);
                connector.setMaxPostSize(-1);
            }
        });        return tomcatFactory;
    }複製程式碼

服務存活檢查

eureka.client.healthcheck.enabled=true

Spring Cloud其它功能及後續關注

  • 配置中心,原生時基於git,感覺不太好用,所以暫時沒有更多關注

  • 與zookeeper、netty等的互動。目前主要是基於http的,對於實時性要求比較高的場合,可以研究一下


本文來自網易雲社群 ,經作者王洪偉授權釋出。

網易雲免費體驗館,0成本體驗20+款雲產品!

更多網易研發、產品、運營經驗分享請訪問網易雲社群


相關文章:
【推薦】 react技術棧實踐(2)
【推薦】 使用QUIC


相關文章