/* * Copyright (C) 2019 Baidu, Inc. All Rights Reserved. */ package com.baidu.brpc.client.channel; import com.baidu.brpc.RpcMethodInfo; import com.baidu.brpc.client.CommunicationOptions; import com.baidu.brpc.client.FastFutureStore; import com.baidu.brpc.client.MethodUtils; import com.baidu.brpc.client.RpcFuture; import com.baidu.brpc.exceptions.RpcException; import com.baidu.brpc.protocol.Protocol; import com.baidu.brpc.protocol.RpcRequest; import com.baidu.brpc.protocol.push.SPHead; import com.baidu.brpc.protocol.push.ServerPushProtocol; import com.baidu.brpc.server.push.RegisterService; import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBuf; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelFutureListener; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.builder.EqualsBuilder; import org.apache.commons.lang3.builder.HashCodeBuilder; import java.net.InetSocketAddress; import java.util.Queue; @Slf4j public abstract class AbstractBrpcChannel implements BrpcChannel { protected ServiceInstance serviceInstance; protected CommunicationOptions communicationOptions; protected Bootstrap bootstrap; protected BootstrapManager bootstrapManager = BootstrapManager.getInstance(); public AbstractBrpcChannel(ServiceInstance serviceInstance, CommunicationOptions communicationOptions) { this.serviceInstance = serviceInstance; this.communicationOptions = communicationOptions; this.bootstrap = bootstrapManager.getOrCreateBootstrap( serviceInstance.getServiceName(), communicationOptions); } @Override public void updateChannel(Channel channel) { } // server push 模式下, 把client的clientName发送到server去 public void sendClientNameToServer(ChannelFuture channelFuture) { RpcRequest r = new RpcRequest(); r.setChannel(channelFuture.channel()); r.setReadTimeoutMillis(10 * 1000); r.setWriteTimeoutMillis(10 * 1000); SPHead spHead = ((ServerPushProtocol) communicationOptions.getProtocol()).createSPHead(); spHead.setType(SPHead.TYPE_REGISTER_REQUEST); // 注册类型 r.setSpHead(spHead); String serviceName = RegisterService.class.getName(); String methodName = "registerClient"; r.setServiceName(serviceName); r.setMethodName(methodName); RpcMethodInfo rpcMethodInfo = MethodUtils.getRpcMethodInfo(RegisterService.class, methodName); r.setRpcMethodInfo(rpcMethodInfo); r.setArgs(new Object[] {communicationOptions.getClientName()}); // generate correlationId RpcFuture registerRpcFuture = new RpcFuture(); long correlationId = FastFutureStore.getInstance(0).put(registerRpcFuture); registerRpcFuture.setCorrelationId(correlationId); // rpcFuture.setChannelInfo(channelInfo); r.setCorrelationId(correlationId); ByteBuf byteBuf; try { log.debug("send sendClientNameToServer, name:{}, correlationId:{}", communicationOptions.getClientName(), r.getCorrelationId()); byteBuf = communicationOptions.getProtocol().encodeRequest(r); } catch (Exception e) { log.error("send report packet to server, encode packet failed, msg:", e); throw new RpcException(RpcException.SERIALIZATION_EXCEPTION, "rpc encode failed:", e); } channelFuture.channel().writeAndFlush(byteBuf); } @Override public Channel connect() { final String ip = serviceInstance.getIp(); final int port = serviceInstance.getPort(); final ChannelFuture future = bootstrap.connect(new InetSocketAddress(ip, port)); future.addListener(new ChannelFutureListener() { @Override public void operationComplete(ChannelFuture channelFuture) throws Exception { if (channelFuture.isSuccess()) { log.debug("future callback, connect to {}:{} success, channel={}", ip, port, channelFuture.channel()); // 发送clientName包到server if (communicationOptions.getProtocol() instanceof ServerPushProtocol) { sendClientNameToServer(future); } } else { log.debug("future callback, connect to {}:{} failed due to {}", ip, port, channelFuture.cause().getMessage()); } } }); future.syncUninterruptibly(); if (future.isSuccess()) { return future.channel(); } else { // throw exception when connect failed to the connection pool acquirer log.error("connect to {}:{} failed, msg={}", ip, port, future.cause().getMessage()); throw new RpcException(future.cause()); } } @Override public ServiceInstance getServiceInstance() { return serviceInstance; } @Override public long getFailedNum() { return 0; } @Override public void incFailedNum() { } @Override public Queue<Integer> getLatencyWindow() { return null; } @Override public void updateLatency(int latency) { } @Override public void updateLatencyWithReadTimeOut() { } @Override public Protocol getProtocol() { return communicationOptions.getProtocol(); } @Override public int hashCode() { return new HashCodeBuilder() .append(serviceInstance.getIp()) .append(serviceInstance.getPort()) .toHashCode(); } @Override public boolean equals(Object object) { boolean flag = false; if (object != null && BrpcChannel.class.isAssignableFrom(object.getClass())) { BrpcChannel rhs = (BrpcChannel) object; flag = new EqualsBuilder() .append(serviceInstance.getIp(), rhs.getServiceInstance().getIp()) .append(serviceInstance.getPort(), rhs.getServiceInstance().getPort()) .isEquals(); } return flag; } @Override public void close() { } }