SpringCloud-Feign聲明式服務調用

在前面的文章中能夠發現當咱們經過RestTemplate調用其它服務的API時,所須要的參數須在請求的URL中進行拼接,若是參數少的話或許咱們還能夠忍受,一旦有多個參數的話,這時拼接請求字符串就會效率低下,而且顯得好傻。html

那麼有沒有更好的解決方案呢?答案是肯定的有,Netflix已經爲咱們提供了一個框架:Feign。java

Feign是一個聲明式的Web Service客戶端,它的目的就是讓Web Service調用更加簡單。Feign提供了HTTP請求的模板,經過編寫簡單的接口和插入註解,就能夠定義好HTTP請求的參數、格式、地址等信息。web

而Feign則會徹底代理HTTP請求,咱們只須要像調用方法同樣調用它就能夠完成服務請求及相關處理。Feign整合了Ribbon和Hystrix(關於Hystrix咱們後面再講),可讓咱們再也不須要顯式地使用這兩個組件。spring

總起來講,Feign具備以下特性:瀏覽器

  • 可插拔的註解支持,包括Feign註解和JAX-RS註解;
  • 支持可插拔的HTTP編碼器和解碼器;
  • 支持Hystrix和它的Fallback;
  • 支持Ribbon的負載均衡;
  • 支持HTTP請求和響應的壓縮。

這看起來有點像咱們springmvc模式的Controller層的RequestMapping映射。這種模式是咱們很是喜歡的。Feign是用@FeignClient來映射服務的。mvc

 

首先第一步,在原來的基礎上新建一個Feign模塊,接着引入相關依賴,引入Feign依賴,會自動引入Hystrix依賴的,以下:app

複製代碼
    <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
            <version>1.3.5.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-feign</artifactId>
            <version>1.4.0.RELEASE</version>
        </dependency>
複製代碼

 

application.yml配置以下:負載均衡

複製代碼
server:
  port: 8083
spring:
  application:
    name: feign-consumer
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8888/eureka/,http://localhost:8889/eureka/
複製代碼

 

 

接着在前面文章中的的的兩個provider1和provider2兩個模塊的服務新增幾個方法,以下代碼所示:框架

複製代碼
/**
 * Created by cong on 2018/5/8.
 */
@RestController
public class HelloController {

    @RequestMapping("/hello")
    public String hello(){
        System.out.println("訪問來1了......");
        return "hello1";
    }

    @RequestMapping("/hjcs")
    public List<String> laowangs(String ids){
        List<String> list = new ArrayList<>();
        list.add("laowang1");
        list.add("laowang2");
        list.add("laowang3");
        return list;
    }

    //新增的方法
    @RequestMapping(value = "/hellol", method= RequestMethod.GET)
    public String hello(@RequestParam String name) {
        return "Hello " + name;
    }

    @RequestMapping(value = "/hello2", method= RequestMethod.GET)
    public User hello(@RequestHeader String name, @RequestHeader Integer age) {
        return new User(name, age);
    }

    @RequestMapping(value = "/hello3", method = RequestMethod.POST)
    public String hello (@RequestBody User user) {
        return "Hello "+ user. getName () + ", " + user. getAge ();
    }

}
複製代碼

 

接着是上面代碼所需用到的User類,代碼以下:異步

複製代碼
/**
 * Created by cong 2017/12/2.
 */
public class User {

    private String name;
    private Integer age;

    //序列化傳輸的時候必需要有空構造方法,否則會出錯
    public User() {
    }
    public User(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }
}
複製代碼

 

接下來用Feign的@FeignClient(「服務名稱」)映射服務調用。代碼以下:

複製代碼
package hjc;

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

/**
 * Created by cong on 2018/5/17.
 */
//configuration = xxx.class  這個類配置Hystrix的一些精確屬性
//value=「你用到的服務名稱」
@FeignClient(value = "hello-service",fallback = FeignFallBack.class) public interface FeignService {   //服務中方法的映射路徑 @RequestMapping("/hello") String hello(); @RequestMapping(value = "/hellol", method= RequestMethod.GET) String hello(@RequestParam("name") String name) ; @RequestMapping(value = "/hello2", method= RequestMethod.GET) User hello(@RequestHeader("name") String name, @RequestHeader("age") Integer age); @RequestMapping(value = "/hello3", method= RequestMethod.POST) String hello(@RequestBody User user); }
複製代碼

 

接着在Controller層注入FeiService這個接口,進行遠程服務調用,代碼以下:

複製代碼
/**
 * Created by cong on 2018/5/17.
 */
@RestController
public class ConsumerController {

    @Autowired
    FeignService feignService;

    @RequestMapping("/consumer")
    public String helloConsumer(){
        return feignService.hello();
    }

    @RequestMapping("/consumer2")
    public String helloConsumer2(){
        String r1 = feignService.hello("hjc");
        String r2 = feignService.hello("hjc", 23).toString();
        String r3 = feignService.hello(new User("hjc", 23));
        return r1 + "-----" + r2 + "----" + r3;
    }

}
複製代碼

 

接着在Feign模塊的啓動類哪裏打上Eureka客戶端的註解@EnableDiscoveryClient  Feign客戶端的註解@EnableFeignClients,代碼以下:

複製代碼
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class FeignApplication {

    public static void main(String[] args) {
        SpringApplication.run(FeignApplication.class, args);
    }
}
複製代碼

 

接着啓動啓動類,瀏覽器上輸入localhost:8083/consumer  運行結果以下:

 

能夠看到負載均衡輪詢出現hello1,hello2。

 

接着繼續在瀏覽器上輸入localhost:8083/consumer2,運行結果以下:

 

 

接下來咱們進行Feign聲明式調用服務下的,服務降級的使用,那麼咱們就必須新建一個FeignFallBack類來繼承FeiService,代碼以下:

複製代碼
package hjc;

import org.springframework.stereotype.Component;

/**
 * Created by cong on 2018/5/17.
 */
@Component
public class FeignFallBack implements FeignService{
  //實現的方法是服務調用的降級方法 @Override public String hello() { return "error"; } @Override public String hello(String name) { return "error"; } @Override public User hello(String name, Integer age) { return new User(); } @Override public String hello(User user) { return "error"; } }
複製代碼

 接着咱們再把那兩個服務提供模塊provider1,provider2模塊進行中止,運行結果以下所示:

 

 能夠看到咱們這幾個調用,都進行了服務降級了。

 

那麼若是咱們想精確的控制一下Hystrix的參數也是能夠的,比方說跟Hystrix結合的參數,那麼能夠在FeignClient註解裏面配置一個Configuration=XXX類.class屬性,在哪一個類裏面精確的指定一下屬性。

或者在application.yml裏面配置,以下:

複製代碼
hystrix:
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutinMilliseconds: 5000

ribbon:
  connectTimeout: 500

#若是想對單獨的某個服務進行詳細配置,以下
hello-service:
  ribbon:
    connectTimeout: 500
複製代碼

 

這裏知足了咱們大部分場景的調用,可是有寫精細場景,仍是要用原生的Hystrix,跟咱們以前的Hystrix用法一下,不要走Feign客戶端調用就好了,以下:

複製代碼
/**
 * Created by cong on 2018/5/17.
 */
public class HjcCommand extends HystrixCommand {
    protected HjcCommand(HystrixCommandGroupKey group) {
        super(group);
    }

    @Override
    protected Object run() throws Exception {
        return null;
    }
}
複製代碼

 

那麼咱們若是想用原聲的HystrixCommand去搞一個異步請求怎麼辦?代碼以下:

首先再引入一個依賴,feign客戶端沒有默認引入進來,須要咱們本身引入:

    <dependency>
            <groupId>com.netflix.hystrix</groupId>
            <artifactId>hystrix-javanica</artifactId>
            <version>1.5.9</version>
        </dependency>

接着用HystrixCommand註解方式實現:

複製代碼
/**
 * Created by cong on 2018/5/17.
 */
@Service
public class HjcCommand {

    @Autowired
    private FeignService feignService;

    //同步方式
    @HystrixCommand
    public Future<String> getEmployeesAsync(){
        return new AsyncResult<String>() {
            @Override
            public String invoke() {
                return feignService.hello("hjc");
            }
        };
    }

    //用同步方式還不如直接用Feign客戶端
    @HystrixCommand
    public String getEmployeesAsync1(){
        return feignService.hello("laowang");
    }

}
複製代碼

這樣還不行,咱們還須要聲明一個切面,HystrixConfiguration,接着,將HystrixConfiguration加入到spring管理,代碼以下:

複製代碼
@Configuration
public class HystrixConfiguration {

    @Bean
    public HystrixCommandAspect hystrixAspect(){
        return  new HystrixCommandAspect();
    }

}
複製代碼

 

轉自https://www.cnblogs.com/huangjuncong/p/9053576.html

相關文章
相關標籤/搜索