服务调用有两种方式:

  A.使用RestTemplate 进行服务调用 查看

  B.使用Feign 进行声明式服务调用

上一次写了使用RestTemplate的方式,这次使用Feign的方式实现

服务注册发现中心使用nacos

启动nacos

spring boot 版本 2.2.1.RELEASE

1.服务端

provider

(1)添加依赖

    <properties>
        <java.version>1.8</java.version>
        <nacos.version>2.1.1.RELEASE</nacos.version>
        <spring-cloud.version>Greenwich.SR3</spring-cloud.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
            <version>${nacos.version}</version>
        </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>

(2)修改配置

server.port=8010

spring.application.name=service-provider

spring.cloud.nacos.discovery.enabled=true
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
spring.cloud.nacos.discovery.service=${spring.application.name}

management.endpoints.web.exposure.include=*
management.endpoint.health.show-details=always

(3)测试方法

package com.xyz.provider.controller;

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

@RestController
public class demoController {
    @RequestMapping("/hello")
    public String Hello(){
        return "hello,provider";
    }

}

provider1

修改端口为8011

修改测试方法

package com.xyz.provider1.controller;

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

@RestController
public class demoController {
    @RequestMapping("/hello")
    public String Hello(){
        return "hello,another provider";
    }
    
}

启动provider和provider1

2.客户端

customer

(1)添加依赖

   <properties>
        <java.version>1.8</java.version>
        <nacos.version>2.1.1.RELEASE</nacos.version>
        <spring-cloud.version>Greenwich.SR4</spring-cloud.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
            <version>${nacos.version}</version>
        </dependency>
        <dependency>
            <groupId>io.github.openfeign</groupId>
            <artifactId>feign-okhttp</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</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>

(2)配置

server.port=8015
spring.application.name=service-comsumer
management.endpoints.web.exposure.include=*
management.endpoint.health.show-details=always
spring.cloud.nacos.discovery.enabled=true
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
spring.cloud.nacos.discovery.service=${spring.application.name}

(3)修改启动类

添加注解 @EnableFeignClients,开启扫描Spring Cloud Feign客户端的功能

package com.xyz.comsumer;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@EnableFeignClients @SpringBootApplication
public class ComsumerApplication { public static void main(String[] args) { SpringApplication.run(ComsumerApplication.class, args); } }

(4)添加Feign接口

创建RemoteHelloService接口,来定义OpenFeign要调用的远程服务接口

通过@FeginClient注解指定被调用方的服务名

通过fallback属性指定RemoteHelloServiceFallbackFactory类,来进行远程调用的熔断和降级处理。

provider是要调用的服务名

说明:

  添加跟调用目标方法一样的方法声明,必须跟目标方法的定义一致

RemoteHelloService

package com.xyz.comsumer.feign;

import com.xyz.comsumer.feign.factory.RemoteHelloServiceFallbackFactory;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;

@FeignClient(contextId = "remotehelloService", value = "service-provider", fallbackFactory = RemoteHelloServiceFallbackFactory.class)
public interface RemoteHelloService {

    @GetMapping("/hello")
    String hello();

}

RemoteHelloServiceFallbackImpl 

package com.xyz.comsumer.feign.fallback;

import com.xyz.comsumer.feign.RemoteHelloService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

@Component
public class RemoteHelloServiceFallbackImpl implements RemoteHelloService {
    private final Logger logger = LoggerFactory.getLogger(RemoteHelloServiceFallbackImpl.class);
    private Throwable cause;

    @Override
    public String hello() {
        logger.error("feign 查询信息失败:{}", cause);
        return null;
    }

    public Throwable getCause() {
        return cause;
    }

    public void setCause(Throwable cause) {
        this.cause = cause;
    }

}

RemoteHelloServiceFallbackFactory

package com.xyz.comsumer.feign.factory;

import com.xyz.comsumer.feign.RemoteHelloService;
import com.xyz.comsumer.feign.fallback.RemoteHelloServiceFallbackImpl;
import feign.hystrix.FallbackFactory;
import org.springframework.stereotype.Component;

@Component
public class RemoteHelloServiceFallbackFactory implements FallbackFactory<RemoteHelloService> {

    @Override
    public RemoteHelloService create(Throwable throwable) {
        RemoteHelloServiceFallbackImpl remoteFallback = new RemoteHelloServiceFallbackImpl();
        remoteFallback.setCause(throwable);
        return remoteFallback;
    }
}

要使用Feign的fallback机制,需要开启Feign的Hystrix的功能

增加配置

feign.hystrix.enabled=true

(4)服务调用

注入刚才声明的ProviderService,就可以像本地方法一样进行调用了

package com.xyz.comsumer.controller;

import com.xyz.comsumer.feign.RemoteHelloService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class FeignController {
    @Autowired
    RemoteHelloService remoteHelloService;
    @RequestMapping("feignTest")
    public String feignTest(){
        return remoteHelloService.hello();
    }
}

启动customer

访问http://localhost:8015/call

交替返回结果

  hello,provider 或 hello,another provider