springcloud负载均衡组件openfeign与ribbon单独使用

在springcloud中,openfeign是取代了feign作为负载均衡组件的,feign最早是netflix提供的,他是一个轻量级的支持RESTful的http服务调用框架,内置了ribbon,而ribbon可以提供负载均衡机制,因此feign可以作为一个负载均衡的远程服务调用框架使用。feign后来不升级了,被github的openfeign取代,openfeign在feign的基础上,又支持springmvc注解的功能。

我们说openfeign其实也可以通过ribbon实现负载均衡,但是他们都可以单独使用,不一定是在springcloud大基础下,下面给出一个实例,来说明ribbon和openfeign单独使用时,如何负载均衡,并且实现远程服务调用。

首先我们需要利用springboot构建一个RESTfull的应用,提供一个接口index(),返回一个字符串。然后我们利用不同的配置文件,开启两个实例。以便我们模拟负载均衡。应用的结构如下:

springboot主要内容WebApplication.java:

package com.xxx.webapp;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@SpringBootApplication
@RestController
public class WebApplication {
	@Value("${webapp.message}")
	private String message;
	
	@Value("${server.port}")
	private int port;
    public static void main( String[] args ){
    	SpringApplication.run(WebApplication.class, args);
    }
    
    @GetMapping("/index")
    public String index(){
    	return "{\"id\':101,\"name\":\"xxx\",\"message\":\""+message+"\",\"port\":\""+port+"\"}";
    }
}

application.yml

server:
  port: 8081
webapp:
  message: springboot

application-dev.yml

server:
  port: 8082
webapp:
  message: springboot2

这里就是我们准备要远程调用的服务。 

\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ 

我们新建一个maven工程,单独使用openfeign和ribbon,我们需要引入如下依赖:

<dependency>
  <groupId>com.netflix.ribbon</groupId>
  <artifactId>ribbon-loadbalancer</artifactId>
  <version>2.2.5</version>  
</dependency>
<dependency>
  <groupId>com.netflix.ribbon</groupId>
  <artifactId>ribbon-httpclient</artifactId>
  <version>2.2.5</version>
</dependency>
<dependency>
  <groupId>org.slf4j</groupId>
  <artifactId>slf4j-log4j12</artifactId>
  <version>1.7.25</version>
</dependency>

<dependency>
   <groupId>io.github.openfeign</groupId>
   <artifactId>feign-core</artifactId>
   <version>9.5.1</version>
</dependency>
<dependency>
   <groupId>io.github.openfeign</groupId>
   <artifactId>feign-jackson</artifactId>
   <version>9.5.1</version>
</dependency>
<dependency>
   <groupId>io.github.openfeign</groupId>
   <artifactId>feign-ribbon</artifactId>
   <version>9.5.1</version>
</dependency>

先来看看负载均衡算法:

package com.xxx.ribbon;
import java.util.ArrayList;
import java.util.List;
import com.netflix.loadbalancer.BaseLoadBalancer;
import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.Server;
public class BalancerApplication {
    public static void main( String[] args ){
    	ILoadBalancer balancer = new BaseLoadBalancer();
    	List<Server> servers = new ArrayList<Server>();
    	servers.add(new Server("localhost", 8081));
    	servers.add(new Server("localhost", 8082));
    	balancer.addServers(servers);
    	
    	for(int i=0;i<10;i++){
    		Server choosedServer = balancer.chooseServer(null);
    		System.out.println(choosedServer);
    	}
    }
}

这个测试程序和前面准备的两个springboot服务没有关系,只是说明ribbon的负载均衡,默认BaseLoadBalancer类的负载均衡算法是round robin(循环),这里有两个服务地址,按照预期,我们会看到打印结果应该是两个地址交替打印。

打印结果,符合我们的预期,我们可以看看BaseLoadBalancer的源代码,看看默认的负载均衡算法:

如果我们需要定制自己的规则,可以通过实现IRule接口,这里给出一个自定义的规则:所有http请求60%到8081,剩余的到8082, 按照思路,我们的代码可以这么来实现。

package com.xxx.ribbon;

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

import com.netflix.loadbalancer.BaseLoadBalancer;
import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.Server;

public class CustomerBalancerRule implements IRule {
	
	private ILoadBalancer balancer = new BaseLoadBalancer();

	@Override
	public Server choose(Object key) {
		List<Server> servers = balancer.getAllServers();
		Random random = new Random();
		final int number = random.nextInt(10);
		if(number<7){
			return servers.get(0);
		}
		return servers.get(1);
	}

	@Override
	public void setLoadBalancer(ILoadBalancer lb) {
		this.balancer = lb;
	}

	@Override
	public ILoadBalancer getLoadBalancer() {
		return this.balancer;
	}

}

我们通过实际的服务调用来看看,从调用结果上来检验这个负载策略。

package com.xxx.ribbon;
import com.netflix.client.ClientFactory;
import com.netflix.client.http.HttpRequest;
import com.netflix.client.http.HttpResponse;
import com.netflix.config.ConfigurationManager;
import com.netflix.loadbalancer.RoundRobinRule;
import com.netflix.niws.client.http.RestClient;
@SuppressWarnings("deprecation")
public class CustomerBalancerRuleApplication {

	public static void main(String[] args) throws Exception{
		
		ConfigurationManager.getConfigInstance().setProperty("providers.ribbon.listOfServers",
				"localhost:8081,localhost:8082");
		ConfigurationManager.getConfigInstance().setProperty("providers.ribbon.NFLoadBalancerRuleClassName",
				RoundRobinRule.class.getName());
		RestClient client = (RestClient) ClientFactory.getNamedClient("providers");
		HttpRequest request = HttpRequest.newBuilder().uri("/index").build();
		for(int i=0;i<10;i++){
			HttpResponse response = client.executeWithLoadBalancer(request);
			System.out.println("loop "+i+" run result -> "+response.getEntity(String.class));
		}
	}
}

我们通过配置providers.ribbon.listOfServers属性来指定providers服务的两个地址,然后通过 providers.ribbon

.NFLoadBalancerRuleClassName属性来指定我们的负载均衡策略。providers是自定义的服务名,关于ribbon的属性配置,都需要冠以这个前缀,后面我们通过providers会获取client,然后拼接我们的uri,就构成了具体的请求地址。

下面运行这个程序,我们查看打印信息:

打印结果是不固定的,因为我们的规则本来就是计算的是一个概率,因此这条请求最终会落到那台服务器上,只能说60%的可能会在8081上。这里打印的10次正好有6次确实是落在了8081上,也有可能是7次甚至8次都会落在8081上。我们注释掉代码中设置负载规则的部分,再次运行程序,又回到了默认的循环规则打印的结果:

 

以上示例,说明了ribbon单独作为一个远程调用服务框架,是具有负载均衡功能的。下面我们使用openfeign提供的api,并且使用ribbon作为client,来实现远程服务调用。

需要先定义一个接口UserService.java:

package com.xxx.openfeign;
import feign.RequestLine;
public interface UserService {
	@RequestLine("GET /index")
	String index();
}

这里,我们使用从配置文件读取配置的方法,准备一个配置文件providers.properties,文件名和我们对应的服务名providers对应:

providers.ribbon.MaxAutoRetries=1
providers.ribbon.MaxAutoRetriesNextServer=1
providers.ribbon.OkToRetryOnAllOperations=true
providers.ribbon.ServerListRefreshInterval=2000
providers.ribbon.ConnectTimeout=3000
providers.ribbon.ReadTimeout=3000
providers.ribbon.listOfServers=localhost:8081,localhost:8082
providers.ribbon.EnablePrimeConnections=true

最主要的配置是需要指定providers.ribbon.listOfServers属性。 

启动类:

package com.xxx.openfeign;
import java.io.IOException;
import com.netflix.config.ConfigurationManager;
import feign.Feign;
import feign.ribbon.RibbonClient;
public class FeignApplication {

	public static void main(String[] args) throws IOException {
		//加载配置文件
		ConfigurationManager.loadPropertiesFromResources("providers.properties");
		//UserService
		UserService userService = Feign.builder().client(RibbonClient.create())
				//.encoder(new JacksonEncoder())
				//.decoder(new JacksonDecoder())
				.target(UserService.class,"http://providers");
		for(int i=0;i<10;i++){
			String result = userService.index();
			System.out.println("loop "+i+",result -> "+result);
		}
	}

}

运行程序,打印信息如下:

打印结果与ribbon使用默认负载均衡规则的效果是一样的。 

openfeign和ribbon都可以单独使用,能够实现负载均衡的远程服务调用。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

luffy5459

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值