天天看點

Spring Cloud+eureka+feign實作微服務與負載均衡

本例中我們在spring boot cloud架構下用,eureka和feign搭建一個簡單的基于微服務的分布式系統。該為服務系統隻有四個子產品,即四個微服務:

兩個生産子產品ProviderModule和ProviderModule2,模拟服務提供方,比如訂單服務;

一個調用子產品InvokeModule,調用兩個生産子產品,模拟服務消費。

一個注冊服務子產品eurekaServerModule,用來提供微服務的注冊和發現。

系統服務注冊與發現用eureka,服務遠端調用feign,并且feign內建有負載均衡功能。具體實作步驟和代碼如下。

項目名稱是service-eureka-feign,下面有四個子產品(子項目,)結構如下圖所示

Spring Cloud+eureka+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>
    <groupId>org.springframework</groupId>
    <artifactId>service-eureka-feign</artifactId>
    <version>0.1.0</version>
    <packaging>pom</packaging> 

    <modules>
	    <module>InvokerModule</module>
    	<module>ProviderModule</module>
    	<module>ProviderModule2</module>
    	<module>eurekaServerModule</module>
    </modules>
</project>
           

(1)eurekaServerModule子產品 

 pom.xml中關鍵的依賴包

<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-openfeign</artifactId>
		</dependency>
           

 application.properties配置檔案

server.port=8761
spring.application.name=server
eureka.instance.hostname=localhost
eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false
eureka.client.service-url.defaultZone=http://localhost:8761/eureka/
           

 啟動類EurekaServerApplication 

package com.example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
import org.springframework.cloud.openfeign.EnableFeignClients;
@EnableEurekaServer
@SpringBootApplication
public class EurekaServerApplication {

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

(2)服務提供子產品ProviderModule

pom.xml

<groupId>my.com</groupId>
	     <artifactId>ProviderModule</artifactId>
	     <version>0.0.1-SNAPSHOT</version>
	    <name>ProviderModule</name>
	    <description>ProviderModule</description>
        <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-openfeign</artifactId>
		</dependency>
           

配置檔案 application.properties

server.port=9000
spring.application.name=provider
eureka.client.service-url.defaultZone=http://localhost:8761/eureka/
           

啟動類ProviderApp 

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
@EnableFeignClients
@EnableEurekaClient
@SpringBootApplication
public class ProviderApp {
	public static void main(String[] args) {
		SpringApplication.run(ProviderApp.class, args);
	}
}
           

服務提供類ProviderController ,用controller來模型提供的接口,服務提供方法是showProvider()

import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
class ProviderController {

	@RequestMapping("/list/provider")
	public String showProvider(@RequestParam String name) {
		System.out.println("from provider port 9000");
		return "hello "+name + " from provider ";
	}
	
	@RequestMapping("/list/test/{name}")
	public String showTest(@PathVariable String name) {
		return "hello 2 "+name;
	}
}
           

(3) 服務提供子產品ProviderModule2

該子產品與ProviderModule的java代碼非常相同,隻有配置檔案和pom.xml不一樣

pom.xml

<groupId>my.com</groupId>
	<artifactId>ProviderModule2</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>ProviderModule2</name>
	<description>ProviderModule2</description>
       <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-openfeign</artifactId>
		</dependency>
           

配置檔案 application.properties

server.port=9002
spring.application.name=provider #與第一個服務提供子產品一樣的名字,後面友善feign統一調用
eureka.client.service-url.defaultZone=http://localhost:8761/eureka/
           

服務提供類ProviderController,注意該方法與ProviderModule中的ProviderController方法非常相似,一般來說要提高類似的功能,比如訂購車票服務,隻是涉及通路的資源不一樣,比如通路不同的資料庫等。

@RestController
class ProviderController {

	@RequestMapping("/list/provider")
	public String showProvider(@RequestParam String name) {
		System.out.println("from provider2 port 9002");
		return "hello "+name + " from provider2 ";
	}
	
	@RequestMapping("/list/test/{name}")
	public String showTest(@PathVariable String name) {
		return "hello 2 "+name;
	}
}
           

 (4)服務消費者子產品InvokeModule

 pom.xml

<groupId>com.example</groupId>
	<artifactId>InvokeModule</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>InvokeModule</name>
	<description>InvokeModule</description>
     <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-openfeign</artifactId>
		</dependency>
           

配置檔案 application.properties 

server.port=8000
spring.application.name=invoker
eureka.client.service-url.defaultZone=http://localhost:8761/eureka/

           

啟動類InvokerAPP

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

遠端服務調用接口(feign調用),調用的注冊在eureka中的服務名稱為“PROVIDER” ,有同名的兩個服務提供者。

@FeignClient("PROVIDER") //開啟Feign用戶端,PROVIDER是兩個ProviderModule和ProviderModule2微服務的serviceId
public interface FeignService {
    //對應要調用的ProviderModule和ProviderModule2微服務控制層請求方法
    @RequestMapping("/list/provider")
    String getUser(@RequestParam String name);
}
           

使用遠端接口調用,用controller來模拟調用feign遠端調用接口 。用循環模拟調用了10次。

@RestController
public class InvokerController {
	@Autowired
	private FeignService feignService;

	@RequestMapping("/feign")
	public String testInvoke(@RequestParam String name) {

        String result = "";
        //調用10次使用者微服務
        for (int i = 1; i <= 10; i++) {
        	//調用定義Feign用戶端方法
            System.out.println(i);
            result = feignService.getUser("invoker "+name);		
        }
        return result;
	}
}
           

開始測試:

分别啟動eurekaServerModule,ProviderModule,ProviderModule2和InvokerModule四個微服務。在浏覽器輸入eureka伺服器位址:http://localhost:8761/,得到如下的結果。

Spring Cloud+eureka+feign實作微服務與負載均衡

上圖中eureka伺服器中有兩個同名的provider服務。 

在浏覽器中輸入調用位址http://localhost:8000/feign?name=張三,有如下的輸出

Spring Cloud+eureka+feign實作微服務與負載均衡

上圖輸出的是傳回到浏覽器的結果 

  ProviderModule子產品的控制台輸出

Spring Cloud+eureka+feign實作微服務與負載均衡

 ProviderModule2子產品的控制台輸出

Spring Cloud+eureka+feign實作微服務與負載均衡

在上面兩個圖中可以看出, InvokerModule用同一名稱PROVIDER總共調用了10次服務,這10次服務分别評價配置設定到了兩個微服務提供子產品,起到了負載均衡作用。

完整的項目代碼位址:連結:https://pan.baidu.com/s/1UzoktQkFieMQ4Tm-tydhkA 

提取碼:72sy

繼續閱讀