天天看点

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

继续阅读