/*
* Copyright 2009-2016 Weibo, Inc.
*
* 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.weibo.api.motan.protocol.rpc;
import java.util.HashMap;
import java.util.Map;
import com.weibo.api.motan.common.URLParamType;
import com.weibo.api.motan.core.extension.ExtensionLoader;
import com.weibo.api.motan.core.extension.SpiMeta;
import com.weibo.api.motan.exception.MotanServiceException;
import com.weibo.api.motan.protocol.AbstractProtocol;
import com.weibo.api.motan.rpc.AbstractExporter;
import com.weibo.api.motan.rpc.AbstractReferer;
import com.weibo.api.motan.rpc.Exporter;
import com.weibo.api.motan.rpc.Future;
import com.weibo.api.motan.rpc.FutureListener;
import com.weibo.api.motan.rpc.Provider;
import com.weibo.api.motan.rpc.Referer;
import com.weibo.api.motan.rpc.Request;
import com.weibo.api.motan.rpc.Response;
import com.weibo.api.motan.rpc.URL;
import com.weibo.api.motan.transport.Client;
import com.weibo.api.motan.transport.EndpointFactory;
import com.weibo.api.motan.transport.ProviderMessageRouter;
import com.weibo.api.motan.transport.ProviderProtectedMessageRouter;
import com.weibo.api.motan.transport.Server;
import com.weibo.api.motan.transport.TransportException;
import com.weibo.api.motan.util.LoggerUtil;
import com.weibo.api.motan.util.MotanFrameworkUtil;
/**
* @author maijunsheng
* @version 创建时间:2013-5-22
*/
@SpiMeta(name = "motan")
public class DefaultRpcProtocol extends AbstractProtocol {
// 多个service可能在相同端口进行服务暴露,因此来自同个端口的请求需要进行路由以找到相应的服务,同时不在该端口暴露的服务不应该被找到
private Map<String, ProviderMessageRouter> ipPort2RequestRouter = new HashMap<String, ProviderMessageRouter>();
@Override
protected <T> Exporter<T> createExporter(Provider<T> provider, URL url) {
return new DefaultRpcExporter<T>(provider, url);
}
@Override
protected <T> Referer<T> createReferer(Class<T> clz, URL url, URL serviceUrl) {
return new DefaultRpcReferer<T>(clz, url, serviceUrl);
}
/**
* rpc provider
*
* @param <T>
* @author maijunsheng
*/
class DefaultRpcExporter<T> extends AbstractExporter<T> {
private Server server;
private EndpointFactory endpointFactory;
public DefaultRpcExporter(Provider<T> provider, URL url) {
super(provider, url);
ProviderMessageRouter requestRouter = initRequestRouter(url);
endpointFactory =
ExtensionLoader.getExtensionLoader(EndpointFactory.class).getExtension(
url.getParameter(URLParamType.endpointFactory.getName(), URLParamType.endpointFactory.getValue()));
server = endpointFactory.createServer(url, requestRouter);
}
@SuppressWarnings("unchecked")
@Override
public void unexport() {
String protocolKey = MotanFrameworkUtil.getProtocolKey(url);
String ipPort = url.getServerPortStr();
Exporter<T> exporter = (Exporter<T>) exporterMap.remove(protocolKey);
if (exporter != null) {
exporter.destroy();
}
synchronized (ipPort2RequestRouter) {
ProviderMessageRouter requestRouter = ipPort2RequestRouter.get(ipPort);
if (requestRouter != null) {
requestRouter.removeProvider(provider);
}
}
LoggerUtil.info("DefaultRpcExporter unexport Success: url={}", url);
}
@Override
protected boolean doInit() {
boolean result = server.open();
return result;
}
@Override
public boolean isAvailable() {
return server.isAvailable();
}
@Override
public void destroy() {
endpointFactory.safeReleaseResource(server, url);
LoggerUtil.info("DefaultRpcExporter destory Success: url={}", url);
}
private ProviderMessageRouter initRequestRouter(URL url) {
ProviderMessageRouter requestRouter = null;
String ipPort = url.getServerPortStr();
synchronized (ipPort2RequestRouter) {
requestRouter = ipPort2RequestRouter.get(ipPort);
if (requestRouter == null) {
requestRouter = new ProviderProtectedMessageRouter(provider);
ipPort2RequestRouter.put(ipPort, requestRouter);
} else {
requestRouter.addProvider(provider);
}
}
return requestRouter;
}
}
/**
* rpc referer
*
* @param <T>
* @author maijunsheng
*/
class DefaultRpcReferer<T> extends AbstractReferer<T> {
private Client client;
private EndpointFactory endpointFactory;
public DefaultRpcReferer(Class<T> clz, URL url, URL serviceUrl) {
super(clz, url, serviceUrl);
endpointFactory =
ExtensionLoader.getExtensionLoader(EndpointFactory.class).getExtension(
url.getParameter(URLParamType.endpointFactory.getName(), URLParamType.endpointFactory.getValue()));
client = endpointFactory.createClient(url);
}
@Override
protected Response doCall(Request request) {
try {
// 为了能够实现跨group请求,需要使用server端的group。
request.setAttachment(URLParamType.group.getName(), serviceUrl.getGroup());
return client.request(request);
} catch (TransportException exception) {
throw new MotanServiceException("DefaultRpcReferer call Error: url=" + url.getUri(), exception);
}
}
@Override
protected void decrActiveCount(Request request, Response response) {
if (response == null || !(response instanceof Future)) {
activeRefererCount.decrementAndGet();
return;
}
Future future = (Future) response;
future.addListener(new FutureListener() {
@Override
public void operationComplete(Future future) throws Exception {
activeRefererCount.decrementAndGet();
}
});
}
@Override
protected boolean doInit() {
boolean result = client.open();
return result;
}
@Override
public boolean isAvailable() {
return client.isAvailable();
}
@Override
public void destroy() {
endpointFactory.safeReleaseResource(client, url);
LoggerUtil.info("DefaultRpcReferer destory client: url={}" + url);
}
}
}