運維工程師淺談微服務springboot2.0的架構

現在微服務方興未艾,從面試一些JAVA開發到做項目到上線的落地,說得比較多的就是微服務,今天就談 一下關於現有的微服務框架springboot,從側面瞭解一下微服務器的構架與運行原理:

一、知識點了解:

gradle教程,可以進行單元測試,打包,遠程發佈一個工具:

https://www.w3cschool.cn/gradle/6qo51htq.html

springboot,獲取現有的框架結構:

https://start.spring.io/

maven國內加速源:

http://maven.aliyun.com/mvn/view

http://www.mvnjar.com/

二、springboot架構:

Eureka/Consul/Zookeeper:服務發現 ,服務註冊
Hystrix:斷路器,加載保護 
Zuul:智能路由,網關
Ribbon/Feign:客戶端負載均衡
Turbine&hystrix-dashboard:集羣監控 
Springcloud-config:配置中心,遠程獲取配置文件,支持熱加載

zipkin:全鏈路跟蹤

è¿éåå¾çæè¿°

三、搭建微服務

1、搭建eureka-server服務sc-eureka-server

eureka-server作爲服務發現的核心,第一個搭建,後面的服務都要註冊到eureka-server上,意思是告訴eureka-server自己的服務地址是啥。當然還可以用zookeeper或者springconsul。

  • 1.修改build.gradle文件

如果是maven項目請對應的修改pom.xml

//加入阿里的私服倉庫地址
maven { url "http://maven.aliyun.com/nexus/content/groups/public/" }

以下依賴可以從https://start.spring.io/選擇時,打包下載即可

//加入依賴  
compile('org.springframework.cloud:spring-cloud-starter-netflix-eureka-server')
//加入security,是因爲訪問eureka-server需要用戶名和密碼訪問,爲了安全
compile('org.springframework.boot:spring-boot-starter-security')

支持遠程發佈,gradle uploadArchives,以下爲發佈到本地:

 
- 2.修改 application.yml,建議用yml(位於src\main\resources)。

server:
  port: 8761
eureka:
  datacenter: trmap
  environment: product
  server:
      # 關閉自我保護
      enable-self-preservation: false
      # 清理服務器
      eviction-interval-timer-in-ms: 5000
  client:
    healthcheck:
      enabled: true
    service-url:
      defaultZone: http://root:booszy@localhost:8761/eureka/
    register-with-eureka: false
    fetch-registry: false
spring:
  security:
    basic:
      enabled: true
    user:
      name: root
      password: booszy

 

3.修改程序的主類,建議修改類名,要加如eureka的 @EnableEurekaServer 註解,然後運行main方法。

@EnableEurekaServer
@SpringBootApplication
public class Sb2scEurekaApplication {
    public static void main(String[] args) {
        SpringApplication.run(Sb2scEurekaApplication.class, args);
    }
}

 

http://localhost:8761/ 這個是eureka-server的頁面地址,密碼在yml配置文件中,到這裏,說明eureka-server搭建好了,簡單吧,這一步一定要成功,否則後面的就不能繼續進行下去了,後邊基本類似。

2、搭建config-server服務sc-config-server

springcloud-config-server是用來將遠程git倉庫的配置文件動態拉下來,這樣配置文件就可以動態的維護了。當然也可以選擇本地倉庫。

新建一個springboot項目,修改maven私服地址,並加入一下依賴。

1.修改build.gradle文件

2.修改application.yml文件

server:
  port: 8800
spring:
  security:
    basic:
      enabled: true
    user:
      name: root
      password: booszy
  application:
    name: sc-config-server
  cloud:
    config:
      server:
        git:
          uri: https://git.coding.net/yirenyishi/springcloud-config-profile
          searchPaths: '{application}'
eureka:
  client:
    service-url:
      defaultZone: http://root:booszy@localhost:8761/eureka/
  instance:
    prefer-ip-address: true
    instance-id: ${spring.application.name}:${spring.application.instance_id:${server.port}}
    appname: sc-config-server

3.修改啓動類

修改啓動類,要加入這三個註解,因爲要註冊到eureka-server上,所以需要@EnableDiscoveryClient這個註解

@EnableConfigServer
@EnableDiscoveryClient
@SpringBootApplication
public class Sb2scConfigApplication {
    public static void main(String[] args) {
        SpringApplication.run(Sb2scConfigApplication.class, args);
    }
}

後運行啓動springboot項目,等啓動成功後訪問eureka的頁面,會發現sc-config-server已經註冊到上面了,如果啓動報錯,請檢查錯誤信息。

 

3、搭建服務提供者服務sc-provider

編寫一個服務提供者,爲下邊的消費者提供服務,用到了spring-webflux(spring新出的非阻塞式框架)不是springmvc,當然你們公司用什麼你還是繼續用什麼。

注意 : 這裏除了application.xml,還需要一個bootstrap.yml, 因爲bootstrap.yml得加載順序是在application.xml前邊,服務註冊和config配置必須放到bootstrap.yml。

修改build.gradle文件

增加一個jcenter下會有junit的包

 

2.編寫配置文件bootstrap.yml

* 注意 : 這裏除了application.xml,還需要一個bootstrap.yml

application.xml我是放到遠程倉庫地址的,大家可以直接到我的遠程倉庫,根據項目名(sc-provider-config)查詢。配置文件的倉庫地址:點擊訪問

eureka:
  client:
    service-url:
      defaultZone: http://root:booszy@localhost:8761/eureka/
  instance:
    prefer-ip-address: true
    instance-id: ${spring.application.name}:${spring.application.instance_id:${server.port}}
    appname: sc-provider

spring:
  application:
    name: sc-provider
  cloud:
    config:
      discovery:
        enabled: true
        service-id: sc-config-server
      fail-fast: true
      username: root
      password: booszy
      profile: csdn

3.編寫代碼

編寫主類

@EnableDiscoveryClient
@SpringBootApplication
public class Sb2scProviderApplication {
    public static void main(String[] args) {
        SpringApplication.run(Sb2scProviderApplication.class, args);
    }
}

新建IndexController進行測試,這裏只是爲了測試,案例代碼使用的是webflux,如果想使用springmvc,修改jar包依賴即可。

@RestController
@RequestMapping("test")
public class IndexController {
    //返回一個實體
    @GetMapping("{msg}")
    public Mono<String> sayHelloWorld(@PathVariable("msg") String msg) {
        System.out.println("come on " + msg);
        return Mono.just("sc-provider receive : " +msg);
    }
    //返回一個列表
    @GetMapping("list")
    public Flux<Integer> list() {
        List<Integer> list = new ArrayList<>();
        list.add(8);
        list.add(22);
        list.add(75);
        list.add(93);
        Flux<Integer> userFlux = Flux.fromIterable(list);
        return userFlux;
    }
}

運行springboot項目,去eureka-server查看,有沒有註冊上。

 

我們的sc-provider已經註冊到eureka上了,訪問接口,成功。

 

4、搭建消費者服務sc-consumer

消費者要訪問服務提供者的服務,這裏用的是通過RestTemplate/feign請求resetful接口,使用ribbon做客戶端負載均衡,hystrix做錯誤處理,feign和ribbon二選一,案例中ribbon和feign都有,也可以都用。 
還是熟悉的配方,熟悉的味道,新建springboot項目,添加項目依賴。

1.修改build.gradle文件

compile('org.springframework.cloud:spring-cloud-starter-netflix-eureka-client')
compile('org.springframework.cloud:spring-cloud-starter-config')
compile('org.springframework.boot:spring-boot-starter-webflux')
compile('org.springframework.boot:spring-boot-starter-actuator')
compile('org.springframework.cloud:spring-cloud-starter-openfeign')
compile('org.springframework.cloud:spring-cloud-starter-netflix-hystrix')

2.修改bootstrap.yml文件

application.yml 在git倉庫,請前往git倉庫查看。

eureka:
  client:
    service-url:
      defaultZone: http://root:booszy@localhost:8761/eureka/
  instance:
    prefer-ip-address: true
    instance-id: ${spring.application.name}:${spring.application.instance_id:${server.port}}
    appname: sc-consumer

spring:
  application:
    name: sc-consumer
  cloud:
    config:
      discovery:
        enabled: true
        service-id: sc-config-server
      fail-fast: true
      username: root
      password: booszy
      profile: csdn
#新版配置,否則後面dashboard無法找到hystrix.stream
management:
  endpoints:
    web:
      exposure:
        include: '*'

3.編寫代碼

啓動類代碼

@RibbonClient 指定服務使用的負載均衡類型,name不指定服務則爲所有的服務打開負載均衡,也可以在用yml中進行配置。 
@EnableHystrix 是支持hystrix打開斷路器,在規定時間內失敗參數超過一定參數,就會打開斷路器,不會發起請求,而是直接進入到錯誤處理方法。

@EnableDiscoveryClient
@EnableFeignClients
@EnableCircuitBreaker
@EnableHystrix
@SpringBootApplication
public class Sb2scConsumerApplication {
    // ribbon需要配置,負載均衡
    @Autowired
    private RestTemplateBuilder builder;

    // ribbon需要配置,負載均衡
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        return builder.build();
    }
    public static void main(String[] args) {
        SpringApplication.run(Sb2scConsumerApplication.class, args);
    }
}

1.ribbon案例

ribbon不需要單獨依賴,新建 RibbonController 
ribbon一個坑,不能接受List類型,要使用數組接收。 
@HystrixCommand(fallbackMethod=”fallbackMethod”) 
如果請求失敗,會進入fallbackMethod這個方法,fallbackMethod這個方法要求參數和返回值與回調他的方法保持一致。

@RestController
public class RibbonController {

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private LoadBalancerClient loadBalancerClient;

    @GetMapping("/ribbon/{wd}")
    @HystrixCommand(fallbackMethod="fallbackMethod")
    public Mono<String> sayHelloWorld(@PathVariable("wd") String parm) {
        String res = this.restTemplate.getForObject("http://sc-provider/test/" + parm, String.class);
        return Mono.just(res);
    }

    public Mono<String> fallbackMethod(@PathVariable("wd") String parm) {
        return Mono.just("fallback");
    }

運行springboot項目,先看有沒有註冊到eureka-server上。 

註冊成功後,訪問接口,測試是否正確。

ribbon使用就是這麼簡單,ribbon是springboot自帶,所以不需要單獨添加依賴。

2.feign案例

在實際開發中,feign使用的還是挺多的,feign底層還是使用了ribbon。廢話不多說,直接上步驟,在服務消費者中使用feign訪問服務提供者。

1配置文件

ribbon:
  ReadTimeout:  30000
  ConnectTimeout:  15000
hystrix:
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 10000

feign的默認請求超時時間是1s,所以經常會出現超時的問題,這裏我設置的是10s,因爲我的數據庫服務器在美國,所以有時候請求會比較慢。ribbon的請求時間也要設置,因爲feign用的是ribbon。這裏貼的是application.yml文件中的一小段

2 編碼

1、主類註解

@EnableFeignClients 
@EnableCircuitBreaker 
@EnableHystrix

這三個都要,hystrix主要作用是斷路器,會進如fein的fallback中。 主類代碼在上面已經貼出來了

2、編寫feign接口,MFeignClient.class

name是指要請求的服務名稱。這裏請求的是服務提供者 
fallback 是指請求失敗,進入斷路器的類,和使用ribbon是一樣的。 
configuration 是feign的一些配置,例如編碼器等。

@FeignClient(name = "sc-provider",fallback = MFeignClientFallback.class, configuration = MFeignConfig.class)
public interface MFeignClient {
    // 這是被請求微服務的地址,也就是provider的地址
    @GetMapping(value = "/test/{msg}")
    String sayHelloWorld(@PathVariable("msg") String msg);

    @GetMapping(value = "/test/list")
    List<Integer> list();

    @GetMapping(value = "/test/list")
    Integer[] array();
}

3 MFeignConfig.class feign的配置

這裏配置了feign的打印日誌等級

@Configuration
public class MFeignConfig {
    @Bean
    Logger.Level feignLoggerLevel() {
        return Logger.Level.FULL;
    }
}

4 MFeignClientFallback.class ,斷路器回調方法

斷路器要實現上邊定義的MFeignClient接口,請求失敗,進入斷路器時,會回調這裏的方法。

@Component
public class MFeignClientFallback implements MFeignClient{
    @Override
    public String sayHelloWorld(String msg) {
        return "fallback";
    }

    @Override
    public List<Integer> list() {
        return new ArrayList<>();
    }

    @Override
    public Integer[] array() {
        return new Integer[0];
    }
}

5 在controller中使用feign

@RestController
public class FeignController {

    @Autowired
    private MFeignClient feignClient;

    @GetMapping("/feign/{wd}")
    public Mono<String> sayHelloWorld(@PathVariable("wd") String parm) {
        String result = feignClient.sayHelloWorld(parm);
        return Mono.just(result);
    }

    @GetMapping("/feign/list")
    public Flux<Integer> list() {
        List<Integer> list = feignClient.list();
        Flux<Integer> userFlux = Flux.fromIterable(list);
        return userFlux;
    }

    @GetMapping("/feign/array")
    public Flux<Integer> array() {
        Integer[] arrays = feignClient.array();
        Flux<Integer> userFlux = Flux.fromArray(arrays);
        return userFlux;
    }
}

5、用zuul做路由轉發和負載均衡

這些微服務都是隱藏在後端的,用戶是看不到,或者不是直接接觸,可以用nginx或者zuul進行路由轉發和負載均衡,zuul負載均衡默認用的是ribbon。

1.修改build.gradle文件

    compile('org.springframework.cloud:spring-cloud-starter-netflix-eureka-client')
    compile('org.springframework.cloud:spring-cloud-starter-config')
    compile('org.springframework.cloud:spring-cloud-starter-netflix-zuul')
    compile('org.springframework.boot:spring-boot-starter-actuator')

2.修改bootstrap.yml

還是原來的配方,application.yml在git倉庫

eureka:
  client:
    service-url:
      defaultZone: http://root:booszy@localhost:8761/eureka/
  instance:
    prefer-ip-address: true
    instance-id: ${spring.application.name}:${spring.application.instance_id:${server.port}}
    appname: sc-zuul

spring:
  application:
    name: sc-zuul
  cloud:
    config:
      discovery:
        enabled: true
        service-id: sc-config-server
      fail-fast: true
      username: root
      password: booszy
      profile: csdn

3.啓動類

@RefreshScope這個註解是當application.yml配置文件發生變化的時候,不需要手動的進行重啓,調用localhost:8400/refresh,就會加載新的配置文件,當然正在訪問的客戶並不影響還是使用舊的配置文件,因爲不是重啓,後來的用戶會使用新的配置文件。注意這塊的刷新要用post請求

@EnableDiscoveryClient
@SpringBootApplication
@EnableZuulProxy
@RefreshScope
public class Sb2scZuulApplication {
    public static void main(String[] args) {
        SpringApplication.run(Sb2scZuulApplication.class, args);
    }
}

啓動springboot項目,訪問eureka-server 

這時候,我們就要通過zuul訪問微服務了,而不是直接去訪問微服務。 
應該訪問地址http://localhost:8400/sc-consumer/feign/list,這塊你要換成你的zuul地址。

但是有些人就會說,這樣以後用戶請求會不會太長,比較反感,所以可以通過配置進行修改訪問地址。

zuul:
  routes:
    springcloud-consumer-config: /consumer/**
    springcloud-provider-config: /provider/**

在application.yml中加入這樣一段配置,其實就是nginx中的反向代理,使用一下簡短的可以代理這個微服務。這個時候我們就可以這樣去訪問了http://localhost:8400/consumer/feign/list,是不是簡短了很多 

6、用hystrix-turbine-dashboard 做集羣監控

項目在生產環境中,每個服務的訪問量都不通,有些服務的訪問量比較大,有時候有些服務掛了,不能繼續服務,需要重啓的時候,我們並不知道,所以這時候就需要使用hystrix-turbine-dashboard做一個監控,監控所有的微服務,可以看到這個接口實時訪問量,和健康狀況。 
新建一個springboot項目,老套路,加入如下依賴

1 添加依賴

compile('org.springframework.cloud:spring-cloud-starter-netflix-eureka-client')
compile('org.springframework.boot:spring-boot-starter-actuator')
compile('org.springframework.cloud:spring-cloud-starter-netflix-hystrix')
compile('org.springframework.cloud:spring-cloud-starter-netflix-hystrix-dashboard')
compile('org.springframework.cloud:spring-cloud-starter-netflix-turbine')

2 修改application.yml配置文件 
注意:是application.yml,這裏不需要bootstrap.yml

server:
  port: 8900
eureka:
  client:
    service-url:
      defaultZone: http://root:booszy@localhost:8761/eureka/
  instance:
    prefer-ip-address: true
    instance-id: ${spring.application.name}:${spring.application.instance_id:${server.port}}
    appname: sc-dashboard
turbine:
  aggregator:
    clusterConfig: default
  appConfig: sc-consumer
  clusterNameExpression: "'default'"
spring:
  application:
    name: sc-dashboard
#management:
#  endpoints:
#    web:
#      exposure:
#        include: '*'

appConfig 後面是要檢測的註冊在eureka上的服務名,必須要有

3 修改主類

@EnableTurbine ,@EnableHystrixDashboard 一個都不能少

@EnableDiscoveryClient
@SpringBootApplication
@EnableTurbine
@EnableHystrixDashboard
public class Sb2scDashboardApplication {
    public static void main(String[] args) {
        SpringApplication.run(Sb2scDashboardApplication.class, args);
    }
}

4 訪問測試

這塊的端口是8900,訪問地址http://localhost:8900/hystrix,看到的是下面的頁面。 

然後在那個網址的輸入框裏輸網址http://localhost:8900/turbine.stream,點擊monitor stream。剛打開的時候可能是空的,什麼也沒有,這並不表示你已經錯了。這時候你訪問消費者服務的接口,例如訪問http://localhost:8400/consumer/feign/list,多訪問幾次,然後看控制檯有沒有出現一個監控面板,沒有就等會刷新一次,如果一直不出現,應該是配置有問題。

7、使用sleuth+zipkin 實現鏈路追蹤服務

在使用微服務的時候,我們發現,有時候排錯不好排查,所以就給大家整個這個鏈路追蹤,很方便知道是哪一個服務調用哪一個服務出現了問題。因爲有些項目可能服務比較多。

1 添加依賴

新建一個springboot項目 
雖然其他服務調用zipkin不是從eureka上動態過去服務地址,而是硬編碼,但是這塊還是考慮吧zipkin註冊到eureka上。

如果提示log4j有衝突,要排除依賴

configurations {
    compile.exclude module: 'log4j'
    compile.exclude module: 'slf4j-log4j12'
    compile.exclude module: 'spring-boot-starter-logging'
}

2 修改application配置文件

server:
  port: 9411
spring:
  application:
    name: sc-sc-zipkin
  profiles:
    active: csdn
eureka:
  client:
    service-url:
      defaultZone: http://root:booszy@localhost:8761/eureka/
  instance:
    prefer-ip-address: true
    instance-id: ${spring.application.name}:${spring.application.instance_id:${server.port}}
    appname: sc-zipkin
management:
  metrics:
    web:
      server:
        auto-time-requests: false

3 主類註解添加

@EnableZipkinServer 主要是這個註解 
啓動服務後訪問http://localhost:9411,就可以打開zipkin的控制檯頁面,這時候應該是什麼都沒有

@EnableDiscoveryClient
@SpringBootApplication
@EnableZipkinServer
public class Sb2scZipkinApplication {
    public static void main(String[] args) {
        SpringApplication.run(Sb2scZipkinApplication.class, args);
    }
}

4 其他服務中調用

這裏我們在消費者服務和提供者服務裏都加入如下依賴

compile('org.springframework.cloud:spring-cloud-starter-sleuth')
compile('org.springframework.cloud:spring-cloud-starter-zipkin')

然後修改配置文件,bootstrap.yml、 
這塊zipkin的地址是硬編碼的,目前還沒發現怎麼從服務註冊中心eureka上動態獲取,以後有解決方案,會更新帖子 
sleuth這個是配置提取率,可以配置也可以不配置

spring:
  zipkin:
    base-url: http://localhost:9411
  sleuth:
    sampler:
      percentage: 1.0

啓動服務,然後訪問消費者服務的接口,這時候訪問zipkin的控制檯http://localhost:9411

點擊依賴分析,可以看到調用服務鏈,因爲這塊只涉及到兩個服務,所以只有兩個,在實際生產環境中,這塊可能有很多,到時候看起來就特別直觀了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章