springcloud入门实例(四:Feign的使用)

        话不多说,直接进入正题。其实Feign出现的目的,应该就是简化Ribbon的配置(我自己的理解,不太确定),用一个FeignClient替代RestTemplate。由于我们有可能不止Dept这一个微服务,还可能有Emp、Company等等,所以最好把FeignClient都定义到microservicecloud-api里,这样就不会导致Dept里配一个FeignClient,Emp里配一个,Company里再配一个。

        首先修改microservicecloud-api里的pom.xml文件,添加Feign依赖:

    <dependency>
  		<groupId>org.springframework.cloud</groupId>
  		<artifactId>spring-cloud-starter-feign</artifactId>
  	</dependency>

        之后和上一讲里一样,定义负载均衡策略,一个OwnRelu.java类,一个ReluConfig.java配置类,分别如下:

package com.sunsy.springcloud.config;

import java.util.List;
import java.util.Random;

import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.AbstractLoadBalancerRule;
import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.Server;

public class OwnRelu extends AbstractLoadBalancerRule {
    Random rand;

    public OwnRelu() {
        rand = new Random();
    }
    
    private int repeatValue = 0;
    private int currentIndex = 0;

    /**
     * Randomly choose from all living servers
     */
    public Server choose(ILoadBalancer lb, Object key) {
        if (lb == null) {
            return null;
        }
        Server server = null;

        while (server == null) {
            if (Thread.interrupted()) {
                return null;
            }
            List<Server> upList = lb.getReachableServers();
            List<Server> allList = lb.getAllServers();

            int serverCount = allList.size();
            if (serverCount == 0) {
                /*
                 * No servers. End regardless of pass, because subsequent passes
                 * only get more restrictive.
                 */
                return null;
            }

            if(repeatValue<5 && currentIndex==0) {
            	server = upList.get(currentIndex);
            	repeatValue++;
            }else {
            	repeatValue=0;
            	currentIndex++;
            	if(currentIndex>=upList.size()) {
                	currentIndex=0;
                }
            	server = upList.get(currentIndex);
            }
            
            
            
            if (server == null) {
                /*
                 * The only time this should happen is if the server list were
                 * somehow trimmed. This is a transient condition. Retry after
                 * yielding.
                 */
                Thread.yield();
                continue;
            }
            

            if (server.isAlive()) {
                return (server);
            }

            // Shouldn't actually happen.. but must be transient or a bug.
            server = null;
            Thread.yield();
        }

        return server;

    }

	@Override
	public Server choose(Object key) {
		return choose(getLoadBalancer(), key);
	}

	@Override
	public void initWithNiwsConfig(IClientConfig clientConfig) {
	
	}
}
package com.sunsy.springcloud.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.netflix.loadbalancer.IRule;

@Configuration
public class ReluConfig {
	
	@Bean
	public IRule ownRule() {
		return new OwnRelu();
	}

}

        然后创建DeptClientSerivce接口,表明DeptClientSerivce调用get方法用的是MICROSERVICECLOUD-DEPT微服务的/dept/get/id接口,用的负载均衡策略是ReluConfig里定义的策略:

package com.sunsy.springcloud.service;

import java.util.List;

import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.sunsy.springcloud.config.ReluConfig;
import com.sunsy.springcloud.entity.Dept;

@FeignClient(value="MICROSERVICECLOUD-DEPT", configuration=ReluConfig.class)
public interface DeptClientService {

	@RequestMapping(value="/dept/get/{id}", method=RequestMethod.GET)
	public Dept get(@PathVariable("id") long id);
	
	@RequestMapping(value="/dept/list", method=RequestMethod.GET)
	public List<Dept> list();
	
	@RequestMapping(value="/dept/add", method=RequestMethod.POST)
	public boolean add(Dept dept);
	
}

        之后创建一个新的子工程microservicecloud-consumer-dept-feign,和api一样在pom.xml里添加Feign依赖。

        application.yml复制microservicecloud-consumer-dept的application.yml即可。

        主启动类如下,添加了FeignClients支持注解:

package com.sunsy.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.feign.EnableFeignClients;
import org.springframework.cloud.netflix.ribbon.RibbonClient;
import org.springframework.context.annotation.ComponentScan;


@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients(basePackages= {"com.sunsy.springcloud"})
//@ComponentScan("com.sunsy.springcloud")
public class SpringCloudConsumerFeignApp {

	public static void main(String[] args) {
		SpringApplication.run(SpringCloudConsumerFeignApp.class, args);
	}
	
}

        最后加个controller:

package com.sunsy.springcloud.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import com.sunsy.springcloud.entity.Dept;
import com.sunsy.springcloud.service.DeptClientService;

@RestController
public class DeptConsumerController {

	@Autowired
	private DeptClientService service;
	
	@RequestMapping(value="/consumer/dept/list")
	public List<Dept> list(){
		return service.list();
	}
	
}

        启动三个EurekaServer模块,两个Provider模块以及刚刚创建的consumer-feign模块,访问http://127.0.0.1/consumer/dept/list可以获得和上一讲一样的负载均衡效果。

        github地址如下:https://github.com/ssystc/springcloud-demo

猜你喜欢

转载自blog.csdn.net/u014627099/article/details/86290158