package hx.apigate.util;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import hx.apigate.circuitBreaker.CBManager;
import hx.apigate.databridge.CircleBreakException;
import org.apache.ignite.IgniteSemaphore;
import org.apache.ignite.binary.BinaryObjectException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import hx.apigate.databridge.NodeInfo;
import hx.apigate.databridge.SemphareException;
import hx.apigate.databridge.xmlBean.Route;
import hx.apigate.databridge.xmlBean.RouteAll;
import hx.apigate.databridge.xmlBean.RouteNode;
import hx.apigate.socket.handlers.GatewayServerHandler;
import io.netty.handler.codec.http.HttpMethod;
/**
* <p>Description: 路由选择工具类</p>
* <p>Copyright: Copyright (c) 2019</p>
* <p>Company: www.uiotcp.com</p>
* @author yangcheng
* @date 2019年10月29日
* @version 1.0
*/
public class RouteSelectUtil {
private static Logger logger = LoggerFactory.getLogger(RouteSelectUtil.class);
public static String HTTP = "http";
public static String DUBBO = "dubbo";
public static String CIRCLE = "circle";
public static String WEIGHT = "weight";
public static String pathSeparator = "/";
/**
* 根据url以及轮寻策略 选择路由的Node
* @param httpMethod
* @param sourceUrl 路径名称
* @return
* @throws Exception
*/
public static Object[] selectOneNode(String sourceUrl, HttpMethod httpMethod) throws SemphareException, CircleBreakException {
//获取与当前url匹配的route url
String sourceUrlTemp = sourceUrl.contains("?") ? sourceUrl.split("\\?")[0] : sourceUrl;
String pattern = getMatchedPattern(sourceUrlTemp,httpMethod);
if(pattern == null) {
return null;
}
Object[] ret =new Object[2];
ret[0] = pattern;
NodeInfo info = getRouteByPattern(sourceUrl,sourceUrlTemp,pattern);
if(info != null) {
ret[1] = info;
}
return ret;
}
/**
* 通过uri获取路由(不是节点node)
* @param patternUri
* @return
*/
public static IgniteSemaphore selectRouteByUri(String patternUri,String version){
//获取与当前url匹配的route url
Map<String, RouteAll> map = IgniteUtil.getAPIRouteCache().get("ALL_ROUTE");
RouteAll routeAll = map.get(patternUri);
int len = routeAll.getRoutes().size();
for(int i = 0 ; i < len ; i ++) {
if(version.equals(routeAll.getRoutes().get(i).getVersion())) {
return routeAll.getRoutes().get(i).getTps();
}
}
return null;
}
/**
* 根据获取到的url的pattern 获取规约类型并返回路由信息
* @param sourceUrl 请求的url(全路径,包含get请求的参数)
* @param sourceUrlTemp 将get请求的url中的参数截取掉,剩下简单的路径<br>
* @param pattern 网关配置的url模版 包含请求方式
* @return
*/
public static NodeInfo getRouteByPattern(String sourceUrl,String sourceUrlTemp,String pattern) throws SemphareException,CircleBreakException{
//根据负载策略选择微服务routeNode
RouteAll routeAll = getRouteAll4lvs(pattern) ;//IgniteUtil.getAPIRouteCache().get("ALL_ROUTE").get(pattern);
Route route = routeAll.nextRoute();
//获取路由信号量
if(!route.getTps().removed() && route.getTps().tryAcquire()) {
if(HTTP.equals(route.getProtocal())) {
int routeNum = route.getRouteNodes().size();
for(int i = 0 ; i < routeNum ; i ++) {
if(RouteSelectUtil.WEIGHT.equals(route.getStratege()) || route.getStratege() == null){
RouteNode node = route.nextNodeByWeight();
if(!route.getTps().removed() && node.getTps().tryAcquire()) {
String circleBreakKey = new StringBuilder(route.getMatchUrl()).append(route.getVersion())
.append(node.getIp()).append(node.getPort()).toString();
CBManager manager = null;
if(!IgniteUtil.getCircleBreakCache().containsKey(circleBreakKey)) {
manager = new CBManager(circleBreakKey,node.getIntTps() < 2 ? 1 : (node.getIntTps() > 100 ? 50 : node.getIntTps() >> 1),
node.getIntTps() < 5? 1 : (node.getIntTps() > 100 ? 20 : node.getIntTps() >> 2), 1000);
IgniteUtil.getCircleBreakCache().putIfAbsentAsync(circleBreakKey, manager);
}else {
manager = IgniteUtil.getCircleBreakCache().get(circleBreakKey);
}
try {
manager.getState().preMethodExecute();
} catch (CircleBreakException e) {
node.getTps().release();
route.getTps().release();
throw e;
}
return new NodeInfo(route.getVersion(),route.getProtocal(), node,sourceUrl,route.isNeedAuth(),circleBreakKey);
}
}else{
if(routeNum > 0){
int nextIndex = route.getIndex().addAndGet(1) % routeNum;
route.getIndex().set(nextIndex);
RouteNode node = route.getRouteNodes().get(nextIndex);
System.out.println(sourceUrl+"的node信号量为"+node.getTps().availablePermits() + "; host = " + node.getIp() +":"+ node.getPort());
if(!route.getTps().removed() && node.getTps().tryAcquire()) {
String circleBreakKey = new StringBuilder(route.getMatchUrl()).append(route.getVersion())
.append(node.getIp()).append(node.getPort()).toString();
CBManager manager = null;
if(!IgniteUtil.getCircleBreakCache().containsKey(circleBreakKey)) {
manager = new CBManager(circleBreakKey,node.getIntTps() < 2 ? 1 : (node.getIntTps() > 100 ? 50 : node.getIntTps() >> 1),
node.getIntTps() < 5? 1 : (node.getIntTps() > 100 ? 20 : node.getIntTps() >> 2), 1000);
IgniteUtil.getCircleBreakCache().putIfAbsentAsync(circleBreakKey, manager);
}else {
manager = IgniteUtil.getCircleBreakCache().get(circleBreakKey);
}
try {
manager.getState().preMethodExecute();
} catch (CircleBreakException e) {
node.getTps().release();
route.getTps().release();
throw e;
}
return new NodeInfo(route.getVersion(),route.getProtocal(), node,sourceUrl,route.isNeedAuth(),circleBreakKey);
}
}
}
}
}else if(DUBBO.equals(route.getProtocal())) {
String[] urls = sourceUrlTemp.substring(1).split("\\/");
int size = route.getRouteNodes().size();
if(size>1) {
for(int i = 0 ; i < size ; i ++) {
int nextIndex = route.getIndex().addAndGet(1) % size;
route.getIndex().set(nextIndex);
RouteNode node = route.getRouteNodes().get(nextIndex);
if(
![avatar](https://profile-avatar.csdnimg.cn/de50ac10e30e41b89db28203f97239be_qq_41701956.jpg!1)
Java程序员-张凯
- 粉丝: 1w+
- 资源: 7654
最新资源
- FFT傅里叶变换驱动的QPSK基带信号频偏估计与补偿算法的FPGA实现及验证方案,基于FFT傅里叶变换的QPSK基带信号频偏估计与补偿算法的FPGA实现:从调制到补偿的完整流程及软件版本与操作指南,N
- LBM方法在三维两相流计算中的应用:灵活调整相饱和度曲线、粘度比及接触角的研究,基于LBM方法的三维两相流体计算模型:可调参数及相饱和度曲线的输出解析,LBM方法三维两相计算 相饱和度曲线可输出,粘
- 基于comsol技术的磁可调双带高效吸收器,COMSOL磁可调双带吸收器技术解析与应用探讨,comsol磁可调双带吸收器 ,comsol;磁可调;双带;吸收器,COMSOL磁可调双带高效吸收器
- Simulink下的永磁同步电机FOC矢量控制模型与源代码仿真:集成SVPWM、DPWM等功能与死区补偿及过调制技术,Simulink下的永磁同步电机FOC矢量控制模型与代码实践:集成SVPWM、DP
- 风能储能协同运行模型:永磁风机与储能系统深度融合的电网接入策略及控制技术研究,《风能储能协同运行模型:永磁风机发电机与储能系统的高效并网策略研究及参数选择参考资料》,风力发电+储能并网协同运行模型含
- 基于C++的视觉框架:全方位视觉算法与操作界面源码包,助力二次开发,基于C++的智能视觉算法框架:源码全开放,包含可视化操作界面与多种视觉算法工具,基于c++的视觉框架,不仅提供了可视化操作界面源码
- Abaqus焊接仿真培训资料大全:热源模型、子程序及多焊缝焊接模拟实战教程,Abaqus焊接仿真全面解析:从热源模型到协同软件应用,多场景案例分析,abaqus焊接仿真培训资料,含热源模型,子程序 焊
- Comsol结合达西与PDE模拟地下水流:孔隙率增大与非均质性的导水路径及速度场、压力场分析,“Comsol达西与PDE结合揭示地下水流作用下孔隙率变化与导水路径可视化研究”,Comsol达西与pde
- MATLAB环境下基于随机游走拉普拉斯算子谱聚类算法的快速实现与可视化分析,基于MATLAB R2018A的随机游走拉普拉斯算子快速谱聚类算法与可视化分析,MATLAB环境下基于随机游走拉普拉斯算子的
- CocosCreatorHowToUse-cocos资源
- 基于蒙特卡洛模拟和Copula函数的风光典型场景生成及多类型电动汽车优化调度研究,基于蒙特卡洛模拟和Copula函数的风光典型场景生成及多类型电动汽车优化调度研究,考虑风光消纳的自适应电动汽车优化调度
- PSCAD仿真研究:220kv三相空载输电线路的合空线与切空线过电压分析及抑制策略探究,PSCAD仿真研究:三相空载输电线路的合闸过电压及其抑制策略分析,pscad仿真 采用pscad搭建220kv三
- 蓝桥杯之软件测试-蓝桥杯资源
- scratch-scratch资源
- 兼容霍尔有感与无感无霍尔的无刷电机驱动方案:基于8051内核STC8H1k的PCB设计与Keil驱动开发,兼容霍尔有感与无感无霍尔的无刷电机驱动方案:基于8051内核STC8H1k的资料整合包,无刷电
- go-fastdfs-golang资源
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
![feedback](https://img-home.csdnimg.cn/images/20220527035711.png)
![feedback](https://img-home.csdnimg.cn/images/20220527035711.png)
![feedback-tip](https://img-home.csdnimg.cn/images/20220527035111.png)