微服务架构之均衡组件 Ribbon解析:进阶应用(完结)
使用Netty发送网络请求
Ribbon
除了可以和RestTemplate
,Feign
一起使用之外,还可以与Netty
进行集成,也就是说,Ribbon
使用负载均衡策略选择完服务器之后,然后再交给Netty
进行网络请求。
其实,上一篇文章的介绍的Ribbon
的LoadBalancerCommand
的submit
函数可以直接使用Netty
框架,也就是在ServerOperation
的call
函数中使用Netty
代替HttpURLConnection
来发送网络请求。但是,Ribbon
已经替使用者们封装好了与Netty
进行集成的相关实现。
RibbonTransport
封装了生成LoadBalancingHttpClient<ByteBuf, ByteBuf>
对象的各类工厂函数。使用LoadBalancingHttpClient<ByteBuf, ByteBuf>
的submit
发送网络请求,底层默认使用Netty
框架来进行网络请求。ByteBuf
是Netty
框架内的字符串缓存实例。
public class SimpleGet {
@edu.umd.cs.findbugs.annotations.SuppressWarnings
public static void main(String[] args) throws Exception {
LoadBalancingHttpClient<ByteBuf, ByteBuf> client = RibbonTransport.newHttpClient();
//HttpClientRequest.createGet接口可以直接生成对应的请求
HttpClientRequest<ByteBuf> request = HttpClientRequest.createGet("http://www.google.com/");
final CountDownLatch latch = new CountDownLatch(1);
//
client.submit(request)
.toBlocking()
.forEach(new Action1<HttpClientResponse<ByteBuf>>() {
@Override
public void call(HttpClientResponse<ByteBuf> t1) {
System.out.println("Status code: " + t1.getStatus());
t1.getContent().subscribe(new Action1<ByteBuf>() {
@Override
public void call(ByteBuf content) {
//可以直接对Netty的ByteBuf进行操作
System.out.println("Response content: " + content.toString(Charset.defaultCharset()));
latch.countDown();
}
});
}
});
latch.await(2, TimeUnit.SECONDS);
}
}
只读数据库的负载均衡实现
读者在学习了FeignLoadBalancer
的原理和Ribbon
的API之后,可以为任何需要负载均衡策略的项目添加Ribbon
的集成。
比如一个的数据库中间件项目,它支持多个读库的数据读取,它希望对多个的读库进行数据读取时可以支持一定的负载均衡策略。那么,读者就可以通过集成Ribbon
来实现读库之间的负载均衡。
首先,你需要定义DBServer
类来继承Ribbon
的Server
类,来存储只读数据库服务器的状态信息,比如说IP地址,数据库连接数,平均请求响应时间等。
然后再定义一个DBLoadBalancer
来继承BaseLoadBalancer
类,示例代码中直接使用WeightedResponseTimeRule
对DBServer
列表进行负载均衡的选择,然后使用自定义的DBPing
来检测数据库是否可用。
public DBLoadBalancer buildFixedDBServerListLoadBalancer(List<DBServer> servers) {
IRule rule = new WeightedResponseTimeRule();
IPing ping = new DBPing();
DBLoadBalancer lb = new DBLoadBalancer(config, rule, ping);
lb.setServersList(servers);
return lb;
}
而使用DBLoadBalancer
的过程也很简单,通过LoadBalancerCommand
的withLoadBalancer
来使用它,然后在submit
的回调函数中使用选出的数据库和SQL语句交给其他组件来执行SQL操作。
public class DBConnectionLoadBalancer {
private final ILoadBalancer loadBalancer;
private final RetryHandler retryHandler = new DefaultLoadBalancerRetryHandler(0, 1, true);
public DBConnectionLoadBalancer(List<DBServer> serverList) {
loadBalancer = LoadBalancerBuilder.newBuilder().buildFixedDBServerListLoadBalancer(serverList);
}
public String executeSQL(final String sql) throws Exception {
//使用LoadBalancerCommand来进行负载均衡,具体策略可以在Builder中进行设置。
return LoadBalancerCommand.<String>builder()
.withLoadBalancer(loadBalancer)
.build()
.submit(new ServerOperation<String>() {
@Override
public Observable<String> call(Server server) {
URL url;
try {
return Observable.just(DBManager.execute(server, sql));
} catch (Exception e) {
return Observable.error(e);
}
}
}).toBlocking().first();
}
}
ILoadBalancer
通过一定的负载策略从读数据库列表中选出一个数据库来让DBManager
执行SQL语句,通过这种方式,读者就可以实现读数据库的负载均衡机制。
- 点赞
- 收藏
- 关注作者
评论(0)