net.hasor.rsf.container.RsfBeanContainer Maven / Gradle / Ivy
The newest version!
/*
* Copyright 2008-2009 the original author or authors.
*
* 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 net.hasor.rsf.container;
import net.hasor.core.AppContext;
import net.hasor.core.BindInfo;
import net.hasor.core.EventContext;
import net.hasor.rsf.*;
import net.hasor.rsf.address.AddressPool;
import net.hasor.rsf.address.RouteTypeEnum;
import net.hasor.rsf.domain.ProtocolStatus;
import net.hasor.rsf.domain.RsfEvent;
import net.hasor.rsf.domain.RsfException;
import net.hasor.rsf.domain.RsfServiceType;
import net.hasor.utils.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.function.Supplier;
/**
*
* @version : 2015年12月6日
* @author 赵永春 ([email protected])
*/
public class RsfBeanContainer {
protected Logger logger = LoggerFactory.getLogger(getClass());
private final static Supplier[] EMPTY_FILTER = new Supplier[0];
private final ConcurrentMap> serviceMap = new ConcurrentHashMap<>();
private final ConcurrentMap> aliasNameMap = new ConcurrentHashMap<>();
private final List filterList = new ArrayList<>();
private final Object filterLock = new Object();
private final ConcurrentMap[]> filterCache = new ConcurrentHashMap<>();
private final AddressPool addressPool;
private AppContext appContext;
public RsfBeanContainer(AddressPool addressPool) {
this.addressPool = addressPool;
}
public AppContext getAppContext() {
return appContext;
}
/**
* 计算指定服务上配置的过滤器。{@link RsfFilter}按照配置方式分为共有和私有。
* 共有Filter的生效范围是所有Service,私有Filter的生效范围仅Service。
* 每一个Filter在配置的时候都需要指定ID,根据ID私有Filter可以覆盖共有Filter的配置。
* @param serviceID 服务ID
*/
public Supplier[] getFilterProviders(String serviceID) {
ServiceDefine> info = this.serviceMap.get(serviceID);
if (info == null) {
return EMPTY_FILTER;
}
Supplier[] result = filterCache.get(serviceID);
if (result == null) {
List cacheIds = new LinkedList<>();
Map cacheFilters = new HashMap<>();
//2.计算最终结果。
List publicList = this.filterList;
if (!publicList.isEmpty()) {
for (FilterDefine filter : publicList) {
String filterID = filter.filterID();
cacheFilters.put(filterID, filter);
cacheIds.add(filterID);
}
}
List snapshotsList = info.getFilterSnapshots();
if (snapshotsList != null && !snapshotsList.isEmpty()) {
for (FilterDefine filter : snapshotsList) {
String filterID = filter.filterID();
cacheFilters.put(filterID, filter);//保存或覆盖已有。
if (cacheIds.contains(filterID)) {
cacheIds.remove(filterID);//如果全局Filter已经定义了这个ID,那么从已有顺序中删除,在尾部追加私有Filter。
}
cacheIds.add(filterID);
}
}
//3.产出最终结果(过滤器链前端是public,后段是private)。
List> filterArrays = new ArrayList<>(cacheIds.size());
for (String filterID : cacheIds) {
FilterDefine define = cacheFilters.get(filterID);
filterArrays.add(define);
}
result = filterArrays.toArray(new Supplier[0]);
this.filterCache.put(serviceID, result);
}
return result;
}
/**
* 根据服务id获取服务对象。如果服务未定义或者服务未声明提供者,则返回null。
* @param rsfBindInfo 服务ID。
* @return 服务提供者
*/
public Supplier getProvider(RsfBindInfo rsfBindInfo) {
ServiceDefine> info = this.serviceMap.get(rsfBindInfo.getBindID());
if (info == null)
return null;
Supplier> target = info.getCustomerProvider();
if (target != null) {
return (Supplier) target;
}
return null;
}
/**
* 根据服务id获取服务元信息。
* @param serviceID 服务ID。
*/
public RsfBindInfo> getRsfBindInfo(String serviceID) {
ServiceDefine> info = this.serviceMap.get(serviceID);
if (info == null)
return null;
return info.getDomain();
}
/**
* 根据服务id获取服务元信息。
* @param aliasType 名字分类。
* @param aliasName 别名。
*/
public RsfBindInfo> getRsfBindInfo(String aliasType, String aliasName) {
ConcurrentMap aliasNameMaps = this.aliasNameMap.get(aliasType);
if (aliasNameMaps == null) {
return null;
}
String serviceID = aliasNameMaps.get(aliasName);
if (serviceID == null) {
return null;
}
return this.serviceMap.get(serviceID);
}
/**
* 根据类型获取服务元信息。如果类型上配置了{@link RsfService @RsfService}注解,则使用该注解的配置信息。
* 否则将使用RSF默认配置下的Group、Version。
* @param serviceType 服务类型。
*/
public RsfBindInfo getRsfBindInfo(Class serviceType) {
RsfSettings rsfSettings = this.addressPool.getRsfEnvironment().getSettings();
String serviceGroup = rsfSettings.getDefaultGroup();
String serviceName = serviceType.getName();
String serviceVersion = rsfSettings.getDefaultVersion();
//覆盖
RsfService serviceInfo = serviceType.getAnnotation(RsfService.class);
if (serviceInfo != null) {
if (!StringUtils.isBlank(serviceInfo.group())) {
serviceGroup = serviceInfo.group();
}
if (!StringUtils.isBlank(serviceInfo.name())) {
serviceName = serviceInfo.name();
}
if (!StringUtils.isBlank(serviceInfo.version())) {
serviceVersion = serviceInfo.version();
}
}
return (RsfBindInfo) getRsfBindInfo(serviceGroup, serviceName, serviceVersion);
}
/**
* 根据服务坐标获取服务元信息。
* @param group 组别
* @param name 服务名
* @param version 服务版本
*/
public RsfBindInfo> getRsfBindInfo(String group, String name, String version) {
String serviceID = "[" + group + "]" + name + "-" + version;//String.format("[%s]%s-%s", group, name, version);
return this.getRsfBindInfo(serviceID);
}
/**获取所有已经注册的服务名称。*/
public List getServiceIDs() {
return new ArrayList<>(this.serviceMap.keySet());
}
/**根据别名系统获取所有已经注册的服务名称。*/
public List getServiceIDs(String category) {
ConcurrentMap aliasNameMaps = this.aliasNameMap.get(category);
if (aliasNameMaps == null) {
return Collections.EMPTY_LIST;
}
return new ArrayList<>(aliasNameMaps.keySet());
}
/**获取环境对象。*/
public RsfEnvironment getEnvironment() {
return this.addressPool.getRsfEnvironment();
}
/* ----------------------------------------------------------------------------------------- */
/**创建{@link RsfApiBinder}。*/
public RsfPublisher createPublisher(final RsfBeanContainer container, final RsfContext rsfContext) {
return new ContextRsfBindBuilder() {
@Override
protected RsfBeanContainer getContainer() {
return container;
}
@Override
protected RsfContext getRsfContext() {
return rsfContext;
}
};
}
/**
* 添加一个全局服务过滤器。
* @param define 过滤器对象。
*/
public void publishFilter(FilterDefine define) {
String filterID = Objects.requireNonNull(define.filterID());
synchronized (this.filterLock) {
for (FilterDefine filter : this.filterList) {
if (filterID.equals(filter.filterID())) {
throw new IllegalStateException("repeate filterID :" + filterID);
}
}
this.filterList.add(define);
this.filterCache.clear();
}
}
/**
* 发布服务
* @param serviceDefine 服务定义。
*/
public synchronized boolean publishService(ServiceDefine serviceDefine) {
String serviceID = serviceDefine.getDomain().getBindID();
if (this.serviceMap.containsKey(serviceID)) {
String serviceType = this.serviceMap.get(serviceID).getDomain().getServiceType().name();
String logMessage = "a " + serviceType + " of the same name already exists , serviceID -> " + serviceID;
this.logger.error(logMessage);
throw new IllegalStateException(logMessage);
}
this.logger.info("service to public, id= {}", serviceID);
ServiceDefine> info = this.serviceMap.putIfAbsent(serviceID, serviceDefine);
//
EventContext eventContext = this.addressPool.getRsfEnvironment().getEventContext();
if (RsfServiceType.Provider == serviceDefine.getServiceType()) {
//服务提供者
if (serviceDefine.getCustomerProvider() == null) {
throw new RsfException(ProtocolStatus.Forbidden, "Provider Not set the implementation class.");
}
try {
eventContext.fireSyncEvent(RsfEvent.Rsf_ProviderService, serviceDefine);
} catch (Throwable e) {
logger.error(e.getMessage(), e);
}
} else {
//服务消费者
try {
eventContext.fireSyncEvent(RsfEvent.Rsf_ConsumerService, serviceDefine);
} catch (Throwable e) {
logger.error(e.getMessage(), e);
}
}
// .收录别名
Set aliasTypes = serviceDefine.getAliasTypes();
for (String aliasType : aliasTypes) {
ConcurrentMap aliasMap = this.aliasNameMap.get(aliasType);
if (aliasMap == null) {
aliasMap = new ConcurrentHashMap<>();
this.aliasNameMap.putIfAbsent(aliasType, aliasMap);
}
String aliasName = serviceDefine.getAliasName(aliasType);
if (StringUtils.isBlank(aliasName)) {
continue;
}
aliasMap.putIfAbsent(aliasName, serviceID);
}
//
// .追加地址
this.addressPool.appendStaticAddress(serviceID, serviceDefine.getAddressSet());
// .更新流控
String flowControl = serviceDefine.getFlowControl();
if (StringUtils.isNotBlank(flowControl)) {
this.addressPool.updateFlowControl(serviceID, flowControl);
}
// .更新路由
Map scriptMap = serviceDefine.getRouteScript();
if (scriptMap != null && !scriptMap.isEmpty()) {
for (Map.Entry routeEnt : scriptMap.entrySet()) {
this.addressPool.updateRoute(serviceID, routeEnt.getKey(), routeEnt.getValue());
}
}
//
return true;
}
/**
* 回收发布的服务
* @param serviceID 服务定义。
*/
public synchronized boolean recoverService(String serviceID) {
if (this.serviceMap.containsKey(serviceID)) {
//
// .发布删除消息( 1.Center解除注册、2.地址本回收)
EventContext eventContext = this.getEnvironment().getEventContext();
RsfBindInfo> rsfBindInfo = this.serviceMap.get(serviceID);
try {
eventContext.fireSyncEvent(RsfEvent.Rsf_DeleteService, rsfBindInfo);
} catch (Throwable e) {
logger.error(e.getMessage(), e);
}
//
// .回收服务
this.serviceMap.remove(serviceID);
//
for (Map.Entry> aliasEntry : this.aliasNameMap.entrySet()) {
ConcurrentMap aliasSet = aliasEntry.getValue();
ArrayList toRemove = new ArrayList<>();
for (Map.Entry entry : aliasSet.entrySet()) {
if (serviceID.equals(entry.getValue())) {
toRemove.add(entry.getKey());
}
}
//
for (String key : toRemove) {
aliasSet.remove(key);
}
}
//
return true;
}
return false;
}
//
/* ----------------------------------------------------------------------------------------- */
//
/**
* 发布的服务
* @param appContext 用于查找服务的容器上下文。
*/
public void lookUp(AppContext appContext) {
this.appContext = appContext;
List> filterList = appContext.findBindingRegister(FilterDefine.class);
for (BindInfo defile : filterList) {
FilterDefine fd = appContext.getInstance(defile);
if (fd != null) {
this.publishFilter(fd);
}
}
List> serviceList = appContext.findBindingRegister(ServiceDefine.class);
for (BindInfo defile : serviceList) {
ServiceDefine sd = appContext.getInstance(defile);
if (sd != null) {
this.publishService(sd);
}
}
//
this.logger.info("lookUp finish.");
}
}