Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.baidu.brpc.client.CommunicationClient Maven / Gradle / Ivy
/*
* Copyright (c) 2019 Baidu, Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.baidu.brpc.client;
import com.baidu.brpc.ChannelInfo;
import com.baidu.brpc.client.channel.BrpcChannel;
import com.baidu.brpc.client.channel.BrpcChannelFactory;
import com.baidu.brpc.client.channel.ChannelType;
import com.baidu.brpc.client.channel.ServiceInstance;
import com.baidu.brpc.exceptions.RpcException;
import com.baidu.brpc.interceptor.ClientInvokeInterceptor;
import com.baidu.brpc.interceptor.ClientTraceInterceptor;
import com.baidu.brpc.interceptor.Interceptor;
import com.baidu.brpc.protocol.Request;
import com.baidu.brpc.protocol.Response;
import com.baidu.brpc.thread.TimerInstance;
import com.baidu.brpc.utils.CollectionUtils;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.util.Timeout;
import io.netty.util.Timer;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import java.nio.channels.ClosedChannelException;
import java.util.ArrayList;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* Created by huwenwei on 2019/12/06.
*/
@SuppressWarnings("unchecked")
@Getter
@Slf4j
public class CommunicationClient {
protected ServiceInstance serviceInstance;
protected CommunicationOptions communicationOptions;
protected BrpcChannel brpcChannel;
protected List interceptors = new ArrayList();
private AtomicBoolean stop = new AtomicBoolean(false);
public CommunicationClient(
ServiceInstance serviceInstance,
CommunicationOptions communicationOptions,
List interceptors) {
this.serviceInstance = serviceInstance;
this.communicationOptions = communicationOptions.clone();
this.brpcChannel = BrpcChannelFactory.createChannel(serviceInstance, this.communicationOptions);
if (CollectionUtils.isNotEmpty(interceptors)) {
this.interceptors.addAll(interceptors);
}
this.interceptors.add(new ClientTraceInterceptor());
this.interceptors.add(new ClientInvokeInterceptor(this));
}
public void execute(Request request, Response response) throws RpcException {
request.setCommunicationClient(this);
Channel channel = selectChannel();
request.setChannel(channel);
ChannelInfo channelInfo = ChannelInfo.getClientChannelInfo(channel);
RpcFuture rpcFuture = RpcFuture.createRpcFuture(request);
if (request.getCallback() != null) {
rpcFuture.setInterceptors(interceptors);
}
channelInfo.setCorrelationId(rpcFuture.getCorrelationId());
rpcFuture.setChannelInfo(channelInfo);
rpcFuture.setChannelType(communicationOptions.getChannelType());
request.setRpcFuture(rpcFuture);
request.setCorrelationId(rpcFuture.getCorrelationId());
try {
request.setSendBuf(communicationOptions.getProtocol().encodeRequest(request));
} catch (Throwable t) {
throw new RpcException(RpcException.SERIALIZATION_EXCEPTION, t.getMessage(), t);
}
// register timeout timer
Timer timeoutTimer = TimerInstance.getInstance();
RpcTimeoutTimer timeoutTask = new RpcTimeoutTimer(
channelInfo, request.getCorrelationId(), communicationOptions.getProtocol());
Timeout timeout = timeoutTimer.newTimeout(timeoutTask, request.getReadTimeoutMillis(), TimeUnit.MILLISECONDS);
request.getRpcFuture().setTimeout(timeout);
try {
// netty will release the send buffer after sent.
// we retain here, so it can be used when rpc retry.
request.retain();
ChannelFuture sendFuture = request.getChannel().writeAndFlush(request.getSendBuf());
sendFuture.awaitUninterruptibly(request.getWriteTimeoutMillis());
if (!sendFuture.isSuccess()) {
if (!(sendFuture.cause() instanceof ClosedChannelException)) {
log.warn("send request failed, channelActive={}, ex=",
request.getChannel().isActive(), sendFuture.cause());
}
String errMsg = String.format("send request failed, channelActive=%b",
request.getChannel().isActive());
throw new RpcException(RpcException.NETWORK_EXCEPTION, errMsg);
}
} catch (Exception ex) {
channelInfo.handleRequestFail(communicationOptions.getChannelType(), request.getCorrelationId());
timeout.cancel();
log.debug("send request failed:", ex);
if (ex instanceof RpcException) {
throw (RpcException) ex;
} else {
throw new RpcException(RpcException.NETWORK_EXCEPTION, "send request failed", ex);
}
}
// return channel
channelInfo.handleRequestSuccess(communicationOptions.getChannelType());
// receive
if (rpcFuture.isAsync()) {
response.setRpcFuture(rpcFuture);
} else {
response.setResult(rpcFuture.get(request.getReadTimeoutMillis(), TimeUnit.MILLISECONDS));
response.setCorrelationId(rpcFuture.getCorrelationId());
}
}
public void executeChain(Request request, Response response) throws RpcException {
execute(request, response);
}
public Channel selectChannel() {
Channel channel;
try {
channel = brpcChannel.getChannel();
} catch (NoSuchElementException full) {
int maxConnections = brpcChannel.getCurrentMaxConnection() * 2;
brpcChannel.updateMaxConnection(maxConnections);
String errMsg = String.format("channel pool is exhausted, and double maxTotalConnection,server=%s:%d",
brpcChannel.getServiceInstance().getIp(), brpcChannel.getServiceInstance().getPort());
log.debug(errMsg);
throw new RpcException(RpcException.NETWORK_EXCEPTION, errMsg, full);
} catch (IllegalStateException illegalState) {
String errMsg = String.format("channel pool is closed, server=%s:%d",
brpcChannel.getServiceInstance().getIp(), brpcChannel.getServiceInstance().getPort());
log.debug(errMsg);
throw new RpcException(RpcException.UNKNOWN_EXCEPTION, errMsg, illegalState);
} catch (Exception connectedFailed) {
String errMsg;
if (communicationOptions.getChannelType() == ChannelType.POOLED_CONNECTION) {
errMsg = String.format("channel pool make new object failed, "
+ "active=%d,idle=%d,server=%s:%d, ex=%s",
brpcChannel.getActiveConnectionNum(),
brpcChannel.getIdleConnectionNum(),
brpcChannel.getServiceInstance().getIp(),
brpcChannel.getServiceInstance().getPort(),
connectedFailed.getMessage());
} else {
errMsg = String.format("get channel failed, ex=%s", connectedFailed.getMessage());
}
log.debug(errMsg);
throw new RpcException(RpcException.UNKNOWN_EXCEPTION, errMsg, connectedFailed);
}
if (channel == null) {
String errMsg = "channel is null, retry another channel";
log.debug(errMsg);
throw new RpcException(RpcException.UNKNOWN_EXCEPTION, errMsg);
}
if (!channel.isActive()) {
brpcChannel.incFailedNum();
// 如果连接不是有效的,从连接池中剔除。
brpcChannel.removeChannel(channel);
String errMsg = "channel is non active, retry another channel";
throw new RpcException(RpcException.NETWORK_EXCEPTION, errMsg);
}
return channel;
}
public void stop() {
if (stop.compareAndSet(false, true)) {
if (brpcChannel != null) {
brpcChannel.close();
}
}
}
@Override
public boolean equals(Object object) {
boolean flag = false;
if (object != null && CommunicationClient.class.isAssignableFrom(object.getClass())) {
CommunicationClient rhs = (CommunicationClient) object;
flag = new EqualsBuilder()
.append(serviceInstance, rhs.serviceInstance)
.isEquals();
}
return flag;
}
@Override
public int hashCode() {
return new HashCodeBuilder()
.append(serviceInstance)
.toHashCode();
}
@Override
public String toString() {
return serviceInstance.toString();
}
}