Netflix之第一个Ribbon程序(六)

Ribbon简介

Ribbon是一个在云服务中久经沙场的客户端IPC库,它提供以下的一些特性:

  1. 负载均衡
  2. 故障容错
  3. 在异步和动态的模型中支持多协议通讯(HTTP、TCP、UDP)
  4. 缓存与批处理

引入Ribbon依赖,可以去Ribbon的maven仓库获取,下面是一个maven引入示例:

<dependency>
    <groupId>com.netflix.ribbon</groupId>
    <artifactId>ribbon</artifactId>
    <version>2.2.2</version>
</dependency>

Ribbon所包含的模块

  1. ribbon:在其他Ribbon模块和Hystrix上集成负载均衡、容错、缓存/批处理的api
  2. ribbon-loadbalancer:可以独立或与其他模块一起使用的负载均衡器的api
  3. ribbon-eureka:使用Eureka客户端为云提供动态服务器列表的api
  4. ribbon-transport:使用带有负载均衡功能的RxNetty支持HTTP、TCP和UDP协议的传输客户端
  5. ribbon-httpclient:构建在Apache HttpClient之上,与负载均衡器集成的REST客户端
  6. ribbon-example:提供了一些示例
  7. ribbon-core:客户端配置api和其他共享api

我们将会使用蓝色字体标记的几个模块用作演示。

负载均衡器组件

Ribbon提供的基本功能

  1. 向通信客户端提供公共DNS名称或单个服务器的IP
  2. 根据特定的逻辑选择服务器

Ribbon提供的高级功能

  1. 通过将客户端划分为区域(如数据中心的机架),在相同区域中减少服务器延迟,从而在客户端和服务器之间建立关联
  2. 保持服务器的统计信息,避免出现高延迟或频繁故障的服务器
  3. 保持区域的统计信息,避免可能出现停机的区域

负载均衡器的三大子模块

  1. Rule:确定从列表返回哪个服务的逻辑组件
  2. Ping:在后台运行的组件以确保服务的活跃度
  3. ServerList:这可以是静态的或动态的。如果它是动态的(由DynamicServerListLoadBalancer使用),后台线程将在特定的时间间隔刷新和过滤列表

创建Ribbon程序


如架构图所示,Ribbon充当负载均衡器的作用,能够让我们的服务消费者调用到自己想使用的服务,服务消费者不用关心中间具体的操作,只需要将要调用的服务信息告诉负载均衡器,Ribbon就会从相应的服务集群中选择一个可以使用的服务器,供服务消费者调用。

我们创建两个简单maven项目,ribbon-server和ribbon-client,ribbon-server充当服务端,提供服务,并启动两个不同的服务实例(端口不同),ribbon-client充当客户端,发起服务调用。为了方便项目的搭建,我们这里使用Spring Boot(如果不清楚Spring Boot的同学,可以查看Spring Boot的简单使用(二),做一个大致了解)来快速开始,访问Spring Boot官网,获取最新的依赖,我这里使用的最新稳定版本是2.0.1,加入到我们ribbon-server项目的pom.xml中:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <version>2.0.1.RELEASE</version>
</dependency>

在ribbon-server下新建com.init.springCloud包,创建启动类ServerApp,用控制台输入不同的端口来启动不同的项目,代码如下:

package com.init.springCloud;

import java.util.Scanner;

import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;

@SpringBootApplication
public class ServerApp {

	public static void main(String[] args) {
		@SuppressWarnings("resource")
		Scanner scan = new Scanner(System.in);
		String port = scan.nextLine();
		new SpringApplicationBuilder(ServerApp.class).properties("server.port=" + port).run(args);
	}

}

再创建一个控制器类ServerController来返回当前服务的信息,这里我们让服务返回一个Person类的信息,两个类的代码如下:

package com.init.springCloud;

import lombok.Data;
//这里使用了lombok,不使用这个的同学可以去掉下面这个注解,然后手动添加getter、setter方法
@Data
public class Person {

	private Integer id;			//主键ID
	private String name;		//姓名
	private String info;		//信息,根据URL地址查看服务的来源
	
}
package com.init.springCloud;

import javax.servlet.http.HttpServletRequest;

import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ServerController {

	@RequestMapping(value = "/search/{id}", method = RequestMethod.GET, 
			produces = MediaType.APPLICATION_JSON_VALUE)
	@ResponseBody
	public Person searchPerson(@PathVariable Integer id,HttpServletRequest request){
		Person person = new Person();
		person.setId(id);
		person.setName("Spirit");
		person.setInfo(request.getRequestURL().toString());
		return person;
	}
	
}

运行ServerApp类的main()方法,输入8082,启动第一个server服务;再次启动main()方法,输入8083,启动第二个server服务。

然后为ribbon-client项目引入Ribbon的依赖,进入Ribbon依赖仓库,引入Ribbon的核心包ribbon-core和http请求包ribbon-httpclient,版本的话,我这里引入的是最新稳定版本2.2.5

<dependency>
    <groupId>com.netflix.ribbon</groupId>
    <artifactId>ribbon-core</artifactId>
    <version>2.2.5</version>
</dependency>
<dependency>
    <groupId>com.netflix.ribbon</groupId>
    <artifactId>ribbon-httpclient</artifactId>
    <version>2.2.5</version>
</dependency>

然后同样在ribbon-client项目下创建com.init.springCloud包,新建RibbonTest类,参照Ribbon的GitHub文档,创建负载请求,代码如下:

package com.init.springCloud;

import com.netflix.client.ClientException;
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.niws.client.http.RestClient;

public class RibbonTest {

	public static void main(String[] args) {
		
		//设置要请求的服务器
		ConfigurationManager.getConfigInstance().setProperty(
	      		"sample-client.ribbon.listOfServers", 
	      		"localhost:8082,localhost:8083");
		//设置REST请求客户端
		RestClient client = (RestClient) ClientFactory.getNamedClient("sample-client");
		//创建请求实例
		HttpRequest request = HttpRequest.newBuilder().uri("/search/1").build();
		//连续发送10次请求到服务器
		for(int i=0; i<10; i++){
			try {
				HttpResponse response = client.executeWithLoadBalancer(request);
				String result = response.getEntity(String.class);
				System.out.println("请求结果:"+result);
			} catch (ClientException e) {
				e.printStackTrace();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		
	}
	
}

笔者这里在引用Netflix提供的Ribbon快速开始文档的时候,出了些问题,由于文档比较久了,示例并不能直接使用,所以做了一些修改,同时,ribbon-httpclient是基于Apache的Http请求的,Ribbon弃用了这个方法,转而使用自己的内部http方法,时间关系,我在查阅文档的时候并没有找到这个替代的方法,就放弃了,如果有解决了这个问题的小伙伴,可以分享给我。

运行RibbonTest类的main()方法,我们可以看到测试类的方法是轮询请求了两个服务:


轮流去请求两个服务,是因为调用了Ribbon的Rule规则里面的RoundRobinRule,这是Ribbon的默认请求规则。Ribbon更加详细的信息后续再更。

源码点击这里

Spring Cloud系列:

Spring Cloud介绍与环境搭建(一)

Spring Boot的简单使用(二)

Spring Cloud服务管理框架Eureka简单示例(三)

Spring Cloud服务管理框架Eureka项目集群(四)

猜你喜欢

转载自blog.csdn.net/mrspirit/article/details/80182508