天天看點

springcloud的服務提供者的叢集搭建和消費者使用Ribbon和Feign前言後記

目錄

  • 前言
    • 1、搭建一個服務叢集并起了個應用名字(三合一)
    • 2、消費者調用使用Ribbon負載均衡器
    • 3、消費者的Feign優化,解決Ribbon輪詢問題
  • 後記

前言

本章的标題可能有點長,總的來說在上章的知識中我們學了如何搭建一個注冊中心叢集,

springcloud的服務提供者的叢集搭建和消費者使用Ribbon和Feign前言後記

本次内容:如何搭建服務提供者叢集和通過調用ribbon來負載均衡的調用這個叢集

springcloud的服務提供者的叢集搭建和消費者使用Ribbon和Feign前言後記

1、搭建一個服務叢集并起了個應用名字(三合一)

伺服器名字為:microservice-student-provider

springcloud的服務提供者的叢集搭建和消費者使用Ribbon和Feign前言後記

pom.xml配置

在原先的基礎上并沒有做出很大的改變

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <!--保持使用版本的一緻1.0-SNAPSHOT-->
    <parent>
        <groupId>com.liwangwang</groupId>
        <artifactId>springcloud</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <artifactId>microservice-student-provider</artifactId>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <!--相當于全局的一個依賴關系,這個導入能確定整個項目使用的包版本一緻
            比如全局中的: spring-cloud-dependencies
                           spring-boot-dependencies
                           druid-spring-boot-starter

        -->
        <dependency>
            <groupId>com.liwangwang</groupId>
            <artifactId>microservice-common</artifactId>
        </dependency>
        <!--處理web請求-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--test測試的包-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!--使用的資料庫關系映射架構是jpa-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <!--使用的是mysql資料庫-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <!--使用tomcat-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
        </dependency>
        <!--druid資料源-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
        </dependency>
        <!--  修改後立即生效,熱部署  -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>springloaded</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
        </dependency>
        <!--需要引入公共子產品的實體類等(在導入的時候出現)-->
        <dependency>
            <groupId>com.liwangwang</groupId>
            <artifactId>microservice-common</artifactId>
            <version>1.0-SNAPSHOT</version>
            <scope>compile</scope>
        </dependency>
        <!--添加注冊中心Eureka相關配置,就是說這個是消費者-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-config</artifactId>
        </dependency>
        <!-- actuator監控引入,點選後的追責 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>



    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

           

application.yml檔案

與原先的檔案比多了

springcloud的服務提供者的叢集搭建和消費者使用Ribbon和Feign前言後記
---
server:
  port: 1001
  context-path: /
spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/context?useUnicode=true&characterEncoding=utf8
    username: root
    password: 123
  jpa:
    hibernate:
      ddl-auto: update
    show-sql: true
  application: # 設定應用的基本資訊(名稱
    name: microservice-student
  profiles: provider-1001

eureka:
  instance:
    hostname: localhost  #eureka消費者主機執行個體名稱
    appname: microservice-student  #消費者服務名
    instance-id: microservice-student:1001 #消費者執行個體名稱
    prefer-ip-address: true #是否顯示IP
  client:
    service-url:
      #設定與Eureka注冊中心互動的位址,是所有注冊中心
      defaultZone: http://eureka2001.javawwl.com:2001/eureka/,http://eureka2002.javawwl.com:2002/eureka/,http://eureka2003.javawwl.com:2003/eureka/   #把服務注冊到eureka注冊中心

info:
  groupId: com.liwangwang.springcloud
  artifactId: microservice-student-provider-1001
  version: 1.0-SNAPSHOT
  userName: http://www.javawwl.com
  phone: 123456

---
server:
  port: 1002
  context-path: /
spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/context?useUnicode=true&characterEncoding=utf8
    username: root
    password: 123
  jpa:
    hibernate:
      ddl-auto: update
    show-sql: true
  application: # 設定應用的基本資訊(名稱
    name: microservice-student
  profiles: provider-1002

eureka:
  instance:
    hostname: localhost  #eureka消費者主機執行個體名稱
    appname: microservice-student  #消費者服務名
    instance-id: microservice-student:1002 #消費者執行個體名稱
    prefer-ip-address: true #是否顯示IP
  client:
    service-url:
      #設定與Eureka注冊中心互動的位址,是所有注冊中心
      defaultZone: http://eureka2001.javawwl.com:2001/eureka/,http://eureka2002.javawwl.com:2002/eureka/,http://eureka2003.javawwl.com:2003/eureka/   #把服務注冊到eureka注冊中心

info:
  groupId: com.liwangwang.springcloud
  artifactId: microservice-student-provider-1002
  version: 1.0-SNAPSHOT
  userName: http://www.javawwl.com
  phone: 123456

---
server:
  port: 1003
  context-path: /
spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/context?useUnicode=true&characterEncoding=utf8
    username: root
    password: 123
  jpa:
    hibernate:
      ddl-auto: update
    show-sql: true
  application: # 設定應用的基本資訊(名稱
    name: microservice-student
  profiles:

eureka:
  instance:
    hostname: localhost  #eureka消費者主機執行個體名稱
    appname: microservice-student  #消費者服務名
    instance-id: microservice-student:1003 #消費者執行個體名稱
    prefer-ip-address: true #是否顯示IP
  client:
    service-url:
      #設定與Eureka注冊中心互動的位址,是所有注冊中心
      defaultZone: http://eureka2001.javawwl.com:2001/eureka/,http://eureka2002.javawwl.com:2002/eureka/,http://eureka2003.javawwl.com:2003/eureka/   #把服務注冊到eureka注冊中心

info:
  groupId: com.liwangwang.springcloud
  artifactId: microservice-student-provider-1003
  version: 1.0-SNAPSHOT
  userName: http://www.javawwl.com
  phone: 123456


           

controller層

處理消費者發過來的請求

package com.liwangwang.microservicestudentprovider.controller;

import com.liwangwang.microservicecommon.entity.Student;
import com.liwangwang.microservicestudentprovider.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/student")
public class StudentProviderController {

    @Value("${server.port}")
    private String port;


    @Autowired
    private StudentService studentService;
     
    @PostMapping(value="/save")
    public boolean save(Student student){
        try{
            studentService.save(student);  
            return true;
        }catch(Exception e){
            return false;
        }
    }
     
    @GetMapping(value="/list")
    public List<Student> list(){
        return studentService.list();
    }
     
    @GetMapping(value="/get/{id}")
    public Student get(@PathVariable("id") Integer id){
        return studentService.findById(id);
    }
     
    @GetMapping(value="/delete/{id}")
    public boolean delete(@PathVariable("id") Integer id){
        try{
            studentService.delete(id);
            return true;
        }catch(Exception e){
            return false;
        }
    }

    @RequestMapping("/ribbon")
    public String ribbon(){
        return "工号【"+port+"】正在為您服務";
    }

}

           

main方法

springcloud的服務提供者的叢集搭建和消費者使用Ribbon和Feign前言後記
package com.liwangwang.microservicestudentprovider;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;

@EntityScan("com.liwangwang.*.*")
@EnableEurekaClient
@SpringBootApplication
public class MicroserviceStudentProviderApplication {

    public static void main(String[] args) {
        SpringApplication.run(MicroserviceStudentProviderApplication.class, args);
    }

}

           

配置三個在上章已經教了如何使用

springcloud的服務提供者的叢集搭建和消費者使用Ribbon和Feign前言後記

2、消費者調用使用Ribbon負載均衡器

消費端的名字:microservice-student-consumer-80

pom.xml的對比,消費端和服務提供者的差別

springcloud的服務提供者的叢集搭建和消費者使用Ribbon和Feign前言後記

pom.xml

具體的細節在上面

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <!--保持使用版本的一緻1.0-SNAPSHOT-->
    <parent>
        <groupId>com.liwangwang</groupId>
        <artifactId>springcloud</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <artifactId>microservice-student-consumer-80</artifactId>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <!--相當于全局的一個依賴關系,這個導入能確定整個項目使用的包版本一緻
            比如全局中的: spring-cloud-dependencies
                           spring-boot-dependencies
                           druid-spring-boot-starter

        -->
        <dependency>
            <groupId>com.liwangwang</groupId>
            <artifactId>microservice-common</artifactId>
        </dependency>
        <!--處理web請求-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--test測試的包-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!--使用的資料庫關系映射架構是jpa-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <!--使用的是mysql資料庫-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <!--使用tomcat-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
        </dependency>
        <!--  修改後立即生效,熱部署  -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>springloaded</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
        </dependency>
        <!--需要引入公共子產品的實體類等(在導入的時候出現)-->
        <dependency>
            <groupId>com.liwangwang</groupId>
            <artifactId>microservice-common</artifactId>
            <version>1.0-SNAPSHOT</version>
            <scope>compile</scope>
        </dependency>
        <!--添加注冊中心Eureka相關配置,就是說這個是消費者-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-config</artifactId>
        </dependency>
        <!--使用了ribbon的包-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-ribbon</artifactId>
        </dependency>





    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

           

yml檔案

如上面所說加上了Eureka的一個消費者所該配置的

server:
  port: 80
  context-path: /
eureka:
  client:
    service-url:
      #設定與Eureka注冊中心互動的位址,查詢服務和注冊服務用到
      defaultZone: http://eureka2001.javawwl.com:2001/eureka/,http://eureka2002.javawwl.com:2002/eureka/,http://eureka2003.javawwl.com:2003/eureka/
    register-with-eureka: false     #false 由于該應用為消費者,是以設定為false,代表不向注冊中心注冊自己。
    fetch-registry: true     #true 由于消費者(消費者)就是尋找服務執行個體,它需要去檢索服務,是以設定為true



           

controller層:

改變不大,就改變了server_ip_port的字段,

記住一定要是上面的服務提供者搭建而成的一個名字,并且大寫

springcloud的服務提供者的叢集搭建和消費者使用Ribbon和Feign前言後記

config的改變:

springcloud的服務提供者的叢集搭建和消費者使用Ribbon和Feign前言後記

結果測試

springcloud的服務提供者的叢集搭建和消費者使用Ribbon和Feign前言後記

3、消費者的Feign優化,解決Ribbon輪詢問題

重新建立一個消費者: microservice-student-consumer-feign-80

此pom.xml,和yml檔案都不變。

springcloud的服務提供者的叢集搭建和消費者使用Ribbon和Feign前言後記

一、解決Ribbon輪詢問題

package com.liwangwang.microservicestudentconsumerfeign80.config;

import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RetryRule;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

@Configuration
public class SpringCloudConfig {

    @LoadBalanced  // 引入ribbon負載均衡
    @Bean
    public RestTemplate getRestTemplate() {
        return new RestTemplate();
    }

    /**
     * 自定義調用規則(服務提供者掉線後不再調用,解決輪詢問題)
     * @return
     */
    @Bean
    public IRule myRule(){
        return new RetryRule();
//        return new RandomRule();
    }
}

           

二、Feign的優化

controller改變成了這個,變成了從common項目裡擷取一個service,并注入裡面

StudentConsumerController

package com.liwangwang.microservicestudentconsumerfeign80.controller;

import com.liwangwang.microservicecommon.entity.Student;
import com.liwangwang.microservicecommon.service.StudentClientService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;

import java.util.List;

@RestController
@RequestMapping("/student")
public class StudentConsumerController {

    @Autowired
    private StudentClientService studentClientService;

    @Autowired
    private RestTemplate restTemplate;

    @PostMapping(value = "/save")
    private boolean save(Student student) {
        return studentClientService.save(student);
    }

    @GetMapping(value = "/list")
    public List<Student> list() {
        return studentClientService.list();
    }

    @GetMapping(value = "/get/{id}")
    public Student get(@PathVariable("id") Integer id) {
        return studentClientService.get(id);
    }

    @GetMapping(value = "/delete/{id}")
    public boolean delete(@PathVariable("id") Integer id) {
        try {
            studentClientService.delete(id);
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    @RequestMapping("/ribbon")
    public String ribbon(){
        return studentClientService.ribbon();
    }
}

           

main檔案

springcloud的服務提供者的叢集搭建和消費者使用Ribbon和Feign前言後記

common層的改變

springcloud的服務提供者的叢集搭建和消費者使用Ribbon和Feign前言後記

StudentClientService :這個就是要使用到注入的service 層

package com.liwangwang.microservicecommon.service;

import com.liwangwang.microservicecommon.entity.Student;
import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import java.util.List;

/**
 * Student Feign接口消費者
 * @author Administrator
 *
 */
@FeignClient(value="MICROSERVICE-STUDENT")
public interface StudentClientService {
 
    /**
     * 根據id查詢學生資訊
     * @param id
     * @return
     */
    @GetMapping(value="/student/get/{id}")
    public Student get(@PathVariable("id") Integer id);
     
    /**
     * 查詢學生資訊
     * @return
     */
    @GetMapping(value="/student/list")
    public List<Student> list();
     
    /**
     * 添加或者修改學生資訊
     * @param student
     * @return
     */
    @PostMapping(value="/student/save")
    public boolean save(Student student);
     
    /**
     * 根據id删除學生資訊
     * @return
     */
    @GetMapping(value="/student/delete/{id}")
    public boolean delete(@PathVariable("id") Integer id);

    @RequestMapping("/student/ribbon")
    public String ribbon();
}

           

測試

springcloud的服務提供者的叢集搭建和消費者使用Ribbon和Feign前言後記

後記

好吧,其實大部分的講解我都已圖解的方式寫了上去,額,導緻不能copy了,哎~

本章學習内容:

1、建立了一個服務叢集

在上章中我們搭建好了一個服務注冊中心的三合一叢集,那麼此次我們第一步要做的就是搭建一個服務叢集,注意大緻的配置檔案不變:

增加一個

application.name: microservice-student # 設定叢集名稱

profiles: provider-1001 # 設定此服務的唯一辨別

springcloud的服務提供者的叢集搭建和消費者使用Ribbon和Feign前言後記

2、使用到了Ribbon的負載均衡

這裡簡單聊一下負載均衡幹嘛的?

在我們以前是直接知道那個服務提供者的一個位址(ip+端口)的話就直接去通路就是了,可現如今我們的一個服務提供者變成了一個服務提供者叢集并且注冊到了Eureka的注冊中心上,那麼等我們的消費端使用注冊中心擷取服務位址(ip+端口)後發現有了三個服務提供者,其實這并不影響操作,你大可繼續像之前一樣知道之前的服務位址就可以通路了,可這就沒什麼變化了,是以為了提高性能我們使用了Ribbon的負載均衡,這樣是把原先固定的位址(ip+端口)變成了由Ribbon掌控的配置設定,比如說:輪詢,随機,這樣每一個服務提供者都會被通路到,并且就算當機宕的隻有一個服務提供者了,那一個服務提供者也能提供所有的服務。

額,實作負載均衡的重點:

消費者中導好:Ribbon依賴

消費者中 加上注解:@LoadBalanced

springcloud的服務提供者的叢集搭建和消費者使用Ribbon和Feign前言後記

3、使用了Feign來優化代碼

為什麼要優化?

我們是不是到時候會在每一個controller層裡都會寫一個類似(http://MICROSERVICE-STUDENT)

那麼如果我們有一天更改了名字,那麼是不是意味這所有的controller層都需要更改這個字元串。

還有寫成了service層的話,有些要調用的話也可以少寫一些代碼。

實作Feign的重點

消費者中導好:Feign依賴

消費者中在main類上加上注解:@EnableFeignClients(value = “com.liwangwang..”)

在common項目上的注解:@FeignClient(value=“MICROSERVICE-STUDENT”)

springcloud的服務提供者的叢集搭建和消費者使用Ribbon和Feign前言後記

繼續閱讀