1. 程式人生 > >Java後端愛上SpringCloud 第二節:內部負載均衡 Ribbon和Feign

Java後端愛上SpringCloud 第二節:內部負載均衡 Ribbon和Feign

Java後端愛上SpringCloud 第一節:內部負載均衡 Ribbon和Feign


PS:為什麼說是內部負載均衡?因為Ribbon和Feign都是在SpringClodu服務間的呼叫做的,之後會講到在外部請求做負載均衡。至於負載均衡是啥,大家可以自行搜尋一下,老規矩先貼一些連線,讓大家明確概念,在進行實現。
這裡先簡單的貼一下負載均衡的概念:

負載均衡:英文名稱為Load Balance, 建立在現有網路結構之上,它提供了一種廉價有效透明的方法擴充套件網路裝置和伺服器的頻寬、增加吞吐量、加強網路資料處理能力、提高網路的靈活性和可用性。其意思就是分攤到多個操作單元上進行執行,例如Web伺服器、FTP伺服器、企業關鍵應用伺服器和其它關鍵任務伺服器等,從而共同完成工作任務。

一些連結

Ribbon和Feign的區別和比較

Ribbon Feign
軟負載 軟負載
支援TCP,HTTP,UPU 支援HTTP
支援容錯 支援容錯
和RestTemplate結合起來實現負載均衡 簡單的HTTP生命呼叫

當前架構

之前有個工程起名為spring-first,太low了,我把它改名為My-Cloud-First雖然也很low。貼一下現在的架構圖:

在這裡插入圖片描述
下面開始實現正題。

建立My-Spring-Ribbon

建立一個My-Spring-Ribbon工程。
pom檔案如下:

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.1.1.RELEASE</version>
		<relativePath /> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.hyn</groupId>
	<artifactId>My-Spring-Ribbon</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>My-Spring-Ribbon</name>
	<description>Demo project for Spring Boot</description>

	<properties>
		<java.version>1.8</java.version>
		<spring-cloud.version>Greenwich.RC1</spring-cloud.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
		</dependency>
	</dependencies>

	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>org.springframework.cloud</groupId>
				<artifactId>spring-cloud-dependencies</artifactId>
				<version>${spring-cloud.version}</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>

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

	<repositories>
		<repository>
			<id>spring-milestones</id>
			<name>Spring Milestones</name>
			<url>https://repo.spring.io/milestone</url>
		</repository>
	</repositories>
</project>

註冊到Eureka上面:

spring:
  application:
    name: spring-boot-ribbo
server:
  port: 8765
# tag::configuration-eureka[]

management:
  endpoints:
    web:
      exposure:
        include: "*"  #<2>
  endpoint:
    health:
      show-details: ALWAYS
# end::configuration-eureka[]
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/ 

記得在啟動類上加上:@EnableEurekaClient
寫一個controller:RibbonControler

package com.hyn.cloud.ribbon.controler;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/ribbon")
public class RibbonControler {

    @RequestMapping(value = "/name",method=RequestMethod.GET)
    @ResponseBody
    public String ribbon(@RequestParam String name){
    	String respResult="I am ribbon,My name is "+name;
		return respResult;
    }
}

依次啟動Eureka,Admin,Ribbon,測試一下:http://127.0.0.1:8765/ribbon/name?name=hyn
在這裡插入圖片描述

建立My-Spring-Feign

建立一個My-Spring-Feign工程。
pom檔案如下:

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.1.1.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.hyn</groupId>
	<artifactId>My-Spring-Feign</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>My-Cloud-Feign</name>
	<description>Demo project for Spring Boot</description>

	<properties>
		<java.version>1.8</java.version>
		<spring-cloud.version>Greenwich.RC2</spring-cloud.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-openfeign</artifactId>
		</dependency>
        <dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
		</dependency>
	</dependencies>

	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>org.springframework.cloud</groupId>
				<artifactId>spring-cloud-dependencies</artifactId>
				<version>${spring-cloud.version}</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>

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

	<repositories>
		<repository>
			<id>spring-milestones</id>
			<name>Spring Milestones</name>
			<url>https://repo.spring.io/milestone</url>
		</repository>
	</repositories>

</project>

註冊到Eureka上面:

spring:
  application:
    name: spring-boot-feign
server:
  port: 8763
# tag::configuration-eureka[]

management:
  endpoints:
    web:
      exposure:
        include: "*"  #<2>
  endpoint:
    health:
      show-details: ALWAYS
# end::configuration-eureka[]
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/ 

記得在啟動類上加上:@EnableEurekaClient
寫一個controller:RibbonControler

package com.hyn.cloud.feign.controler;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/feign")
public class FeignControler {

    @RequestMapping(value = "/name",method=RequestMethod.GET)
    @ResponseBody
    public String feign(@RequestParam String name){
    	String respResult="I am feign,My name is "+name;
		return respResult;
    }
}

依次啟動Feign,測試一下:http://127.0.0.1:8763/feign/name?name=hyn

在這裡插入圖片描述

現在可以看到,在SpringBootAdmin上如下結構:
在這裡插入圖片描述

Ribbon呼叫

說明一下RestTemplate:

  • RestTemplate是Spring提供的用於訪問Rest服務的客戶端。
  • RestTemplate提供了多種便捷訪問遠端Http服務的方法,能夠大大提高客戶端的編寫效率。
  • 呼叫RestTemplate的預設建構函式,RestTemplate物件在底層通過使用java.net包下的實現建立HTTP 請求,可以通過使用ClientHttpRequestFactory指定不同的HTTP請求方式。
  • ClientHttpRequestFactory介面主要提供了兩種實現方式,一種是SimpleClientHttpRequestFactory,使用J2SE提供的方式(既java.net包提供的方式)建立底層的Http請求連線,還有一種方式是使用HttpComponentsClientHttpRequestFactory方式,底層使用HttpClient訪問遠端的Http服務,使用HttpClient可以配置連線池和證書等資訊。

啟動類修改:

package com.hyn.cloud.ribbon;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@SpringBootApplication
@EnableEurekaClient
@EnableDiscoveryClient
public class MyCloudRibbonApplication {

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

    /**
    * Spring提供的用於訪問Rest服務的客戶端
    * @return
    */
   @Bean
   @LoadBalanced
   RestTemplate restTemplate() {
       return new RestTemplate();
   }
}

controller 類修改

package com.hyn.cloud.ribbon.controler;


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@RestController
@RequestMapping("/ribbon")
public class RibbonControler {

   /**
    * 注入RestTemplate
    */
   @Autowired
   RestTemplate restTemplate;
   
   @RequestMapping(value = "/name",method=RequestMethod.GET)
   @ResponseBody
   public String ribbon(@RequestParam String name){
   	String respResult="I am ribbon,My name is "+name;
   	String url="http://SPRING-BOOT-FEIGN/feign/name?name=";
       return restTemplate.getForObject(url+respResult, String.class);
   }
}

在呼叫一下:
在這裡插入圖片描述
可以看到通過Ribbon去呼叫了Feign,雖然栗子舉的有些生硬。哈哈哈哈

Feign呼叫

啟動類修改:

package com.hyn.cloud.feign;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.openfeign.EnableFeignClients;

@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients //開啟spring cloud feign的支援
public class MyCloudFeignApplication {

   public static void main(String[] args) {
   	SpringApplication.