第二篇:服务消费者Feign

一  Feign简介

Feign是一个声明式的伪Http客户端,它使得写Http客户端变得更简单。使用Feign,只需要创建一个接口并注解。它具有可插拔的注解特性,可使用Feign 注解和JAX-RS注解。Feign支持可插拔的编码器和解码器。Feign默认集成了Ribbon,并和Eureka结合,默认实现了负载均衡的效果。

简而言之:

  • Feign 采用的是基于接口的注解
  • Feign 整合了ribbon,具有负载均衡的能力
  • 整合了Hystrix,具有熔断的能力

二  准备工作

继续用上一节的工程, 启动eureka-server,端口为8060;

三  创建两个feign的服务callcenter-user和callcenter-freeswitch

新建一个spring-boot Module ,取名为callcenter-user,在它的pom文件引入Feign的起步依赖spring-cloud-starter-feign、Eureka的起步依赖spring-cloud-starter-netflix-eureka-client、Web的起步依赖spring-boot-starter-web,代码如下:

<?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>

    <groupId>com.hmzj</groupId>
    <artifactId>callcenter-user</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>callcenter-user</name>
    <description>Demo project for Spring Boot</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.3.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <spring-cloud.version>Finchley.RELEASE</spring-cloud.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-config</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
        </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-openfeign</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </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>


</project>

 

在工程的配置文件application.yml文件,指定程序名为callcenter-user,端口号为8050,服务注册地址为http://127.0.0.1:8060/eureka/ ,代码如下:

server:
  port: 8051
spring:
  application:
    name: callcenter-user
eureka:
  instance:
    prefer-ip-address: true
    instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}
    # 心跳检测检测与续约时间
    # 测试时将值设置设置小些,保证服务关闭后注册中心能及时踢出服务
    lease-renewal-interval-in-seconds: 1 # lease-renewal-interval-in-seconds 每间隔1s,向服务端发送一次心跳,证明自己依然”存活“
    lease-expiration-duration-in-seconds: 2 #lease-expiration-duration-in-seconds  告诉服务端,如果我2s之内没有给你发心跳,就代表我“死”了,将我踢出掉。
  client:
    serviceUrl:
      defaultZone: http://userName:password@127.0.0.1:8060/eureka/ #服务注册时的账号和密码

 

 

在程序的启动类CallcenterUserApplication,加上@EnableFeignClients注解开启Feign的功能:

@EnableFeignClients
@EnableDiscoveryClient //也可以使用@EnableEurekaClient 
@SpringBootApplication
public class CallcenterUserApplication { public static void main(String[] args) { SpringApplication.run(CallcenterUserApplication.class, args); } }

 

新建一个spring-boot Module ,取名为callcenter-freeswitch,在它的pom文件引入Feign的起步依赖spring-cloud-starter-feign、Eureka的起步依赖spring-cloud-starter-netflix-eureka-client、Web的起步依赖spring-boot-starter-web,代码如下:

<?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>

<groupId>com.hmzj</groupId>
<artifactId>callcenter-freeswitch</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>

<name>callcenter-freeswitch</name>
<description>Demo project for Spring Boot</description>

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<spring-cloud.version>Finchley.RELEASE</spring-cloud.version>
</properties>

<dependencies>
<dependency>
<groupId>com.hmzj</groupId>
<artifactId>callcenter-utils</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</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-openfeign</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</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>


</project>

 

在工程的配置文件application.yml文件,指定程序名为callcenter-freeswitch,端口号为8052,服务注册地址为http://127.0.0.1:8060/eureka/ ,代码如下:

server:
  port: 8052
spring:
  application:
    name: callcenter-freeswitch
eureka:
  instance:
    prefer-ip-address: true
    instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}
    # 心跳检测检测与续约时间
    # 测试时将值设置设置小些,保证服务关闭后注册中心能及时踢出服务
    lease-renewal-interval-in-seconds: 1 # lease-renewal-interval-in-seconds 每间隔1s,向服务端发送一次心跳,证明自己依然”存活“
    lease-expiration-duration-in-seconds: 2 #lease-expiration-duration-in-seconds  告诉服务端,如果我2s之内没有给你发心跳,就代表我“死”了,将我踢出掉。
  client:
    serviceUrl:
      defaultZone: http://userName:password@127.0.0.1:8060/eureka/ #服务注册时的账号和密码

 

 

在程序的启动类CallcenterFreeswitchApplication,加上@EnableFeignClients注解开启Feign的功能:

@EnableFeignClients
@EnableDiscoveryClient //也可以使用@EnableEurekaClient 
@SpringBootApplication
public class CallcenterFreeswitchApplication{
public static void main(String[] args) {
SpringApplication.run(CallcenterFreeswitchApplication.class, args);
}
 }

 

四 微服务之间的调用示例

 

在callcenter-user根目录下创建package 叫controller 创建TestController:

package com.hmzj.callcenteruser.controller;

import com.hmzj.callcenteruser.entry.User;
import com.hmzj.callcenteruser.service.FreeswitchService;
import com.hmzj.callcenteruser.service.UserService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author Yangqi.Pang
 * @version V0.0.1
 */
@RestController
@RefreshScope
@RequestMapping("test")
public class TestConteoller {

        private FreeswitchService freeswitchService;
        private UserService userService;

        public TestConteoller(FreeswitchService freeswitchService, UserService userService) {
                this.freeswitchService = freeswitchService;
                this.userService = userService;
        }

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


        @GetMapping("sayHello/{userName}")
        public String sayHello(@PathVariable String userName){
            return "hello "+userName+"I'm come from user my port :"+port;
        }

        @GetMapping("saveUser")
        public void saveUser(User user){
               userService.saveUser(user);
        }

        @GetMapping("freeswitchSayHi/{userName}")
        public String freeswitchSayHi(@PathVariable String userName){
                return freeswitchService.sayHi(userName);
        }
}

 

 

 


在callcenter-user根目录下创建package 叫service创建FreeswitchService:

package com.hmzj.callcenteruser.service;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

/**
 * @author Yangqi.Pang
 * @version V0.0.1
 */
@FeignClient(value = "callcenter-freeswitch")
@Service
public interface FreeswitchService {

    @GetMapping("/test/sayHi/{userName}")
    String sayHi(@PathVariable(value = "userName") String userName);
}

 

此处的@FeignClient注解里的value值就是调用的服务名称

 

在callcenter-freeswitch根目录下创建package 叫controller 创建TestController:

package com.hmzj.callcenterfreeswitch.controller;

import com.hmzj.callcenterfreeswitch.entry.User;
import com.hmzj.callcenterfreeswitch.service.FreeSwitchService;
import com.hmzj.callcenterfreeswitch.service.UserService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author Yangqi.Pang
 * @version V0.0.1
 */
@RestController
@RequestMapping("test")
public class TestController {

    private UserService userService;

    private FreeSwitchService freeSwitchService;

    public TestController(UserService userService, FreeSwitchService freeSwitchService) {
        this.userService = userService;
        this.freeSwitchService = freeSwitchService;
    }



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

    @GetMapping("sayHi/{userName}")
    public String sayHi(@PathVariable String userName){
        return "hi "+userName+"I'm come from freeswitch my port :"+port;
    }

    @GetMapping("saveUser")
    public void saveUser(User user){
        freeSwitchService.saveUser(user);
    }

    @GetMapping("userSayHello/{userName}")
    public String userSayHello(@PathVariable String userName){
        return userService.sayHello(userName);
    }
}

启动服务callcenter-user:

启动服务callcenter-freeswitch:

访问 http://localhost:8051/test/sayHello/pyq 浏览器会显示

  hello pyqI'm come from user my port :8051   

  这个是调用8051端口 的服务  还没有跨服务调用

接下来访问 http://localhost:8051/test/freeswitchSayHi/pyq 浏览器会显示

  hi pyqI'm come from freeswitch my port :8052   

  这个是调用8052端口的服务  跨服务调用

 

 

五   检测Feign的负载均衡

再次启动服务callcenter-freeswitch端口号为8053:

 

 

 idea中可以启动多个示例的方式

 

 

 

 

 

 

 访问http://localhost:8051/test/freeswitchSayHi/pyq 浏览器会显示

 

    

    端口号交替出现

 

posted @ 2018-07-30 15:29  左手程序,右手诗  阅读(552)  评论(0编辑  收藏  举报