1. Feign介绍

Feign是一个rest客户端框架,能够访问远程web service,在之前的列子中,我们在invoke-service中调用provide-service时,使用了spring自带的resttemplate来访问服务。而Feign会使我们的访问更加简单,使用它的注解我们将会很方便的访问web service。下面就让我们开始学习吧。

2.改造provide-service1,使它变成多个实例注册到Eureka。

修改provideServer醒目的application.yml文件,使用profiles来配置两份配置参数:

spring:
  profiles: p1
  application:
    name: provider-server1
server:
  port: 8091
eureka:
  instance:
    hostname: localhost
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/
---
spring:
  profiles: p2
  application:
    name: provider-server2
server:
  port: 8092
eureka:
  instance:
    hostname: localhost
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/

修改启动类:

package com.demo;

import java.util.Scanner;

import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;

@SpringBootApplication
@EnableEurekaClient
public class App {
   public static void main(String[] args) {
       //控制台输入p1,p2
     Scanner scan = new Scanner(System.in);
     String profiles = scan.nextLine();
     new SpringApplicationBuilder(App.class).profiles(profiles).run(args);
}
}

运行启动类在ide控制台输入p1启动provider-server1,然后再次运行启动类,输入p2启动provider-server2。
然后访问之前的Eureka,访问http://localhost:8761/,发现已经有两个服务provider-server1,provider-server2。

3.改造invokerService,使用Feign来调用上面的两个服务。

添加Feign的依赖:

<dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Edgware.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-feign</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-config</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-ribbon</artifactId>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.2.3</version>
            <scope>compile</scope>
        </dependency>
    </dependencies>

修改启动端口,应为之前的8092已经被上面的服务占用了,你也可以使用其他端口:

spring:
  application:
    name: invoker-server1
server:
  port: 8093
eureka:
  instance:
    hostname: localhost
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/

新建Feign客户端调用接口CallClient:

package com.demo;

import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;

@FeignClient("provider-server1")  //申明调用服务
public interface CallClient {
    @GetMapping("/api/hello")
    String hello();
}

修改启动类,添加注解@EnableFeignClients

package com.demo;

import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.feign.EnableFeignClients;

@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class App {
  
    public static void main(String[] args) {
        new SpringApplicationBuilder(App.class).run(args);
    }
}

修改CallService:

package com.demo;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@Configuration
public class CallService {
    @Autowired
    private CallClient ccl;

    @GetMapping("/call")
    public String call(){
        return ccl.hello();
    }
}

启动应用,访问http://localhost:8761/,发现3个服务都启动,然后访问http://localhost:8093/call,正常显示:hello world。刚才我们只是访问了provider-server1,现在我们要改造一下,让Feign实现负载均衡。

在provideServer,application.yml中将两个服务的名称都改为:provider-server。
修改RestApi:

package com.demo;

import javax.servlet.http.HttpServletRequest;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

@RestController
public class RestApi {
    
    @GetMapping("/api/hello")
    public String Hello(){
        ServletRequestAttributes requestAttr =  (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = requestAttr.getRequest();
        System.out.println("请求了:"+request.getRequestURL());
        return "hello world";
    }
}

然后重新启动服务提供者:provideServer。

修改invokerService,CallClient,让其调用provider-server:

package com.demo;

import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;

@FeignClient("provider-server")  //申明调用服务
public interface CallClient {
    @GetMapping("/api/hello")
    String hello();
}

重新启动应用,然后访问http://localhost:8093/call,控制台会轮流显示:
请求了:http://localhost:8091/api/hello
请求了:http://localhost:8092/api/hello
这样feign就帮我们做好了负载均衡,美滋滋。


Mike晓
95 声望18 粉丝