自己设计一个的轻量级的RPC框架--服务手动降级

前言

前面几篇博客将的是搭建了一个轻量级的RPC的基础功能。最近也在学习Spring cloud,发现除了一些基础的功能还包含例如服务的断路、配置中心、网关等功能、负载均衡(先实现了一个简单的轮询)。所以接下来自己的目标就是完成这些功能的简易本。

服务的降级

什么是服务降级?当服务器压力剧增的情况下,根据实际业务情况及流量,对一些服务进行简单的处理(例如直接返回服务下线等),从而释放服务器资源以保证核心交易正常运作或高效运作。

服务的手动降级思路

1.zookeeper的叶子节点需要保存该服务的状态 例如正常状态是为true,降级状态为false。
2.需要一个前端页面展示所有的服务并可以进行修改其状态。
3.修改状态完毕之后需要通过zookeeper的watch的机制来通知所有的消费者服务状态发生变化
4.消费者需要定义当调用当服务降级之后的方法
通过以上思路就能完成一个简单的服务降级

zookeeper的改造

创建节点

将节点默认为true

zk.createNodeForTemporary("/RPCSERVER/"+entry.getKey()+"/"+hostAddress+":"+rpc.getPort(),"true");

watch

新增一个watch事件 用来通知服务降级
注意:这里要通过getDataByWatch();这个方法来再次注册watch。同理初始化服务的时候也要用这个注册watch

// 这个方法 == getDataByWatch()  当调用setData方法时候 会触发EventType.NodeDataChanged事件
this.zookeeper.getData(path, true, null)
else if(EventType.NodeDataChanged == eventType){//某节点的数据发生改变 节点注册
			System.out.println(path);
			String paths[] = path.split("/");
			Map<String,Map<String,String>> Map = ZkServer.serviceMap.get(paths[3]);
			Map<String, String> childMap;
			try {
				childMap = Map.get(new String(getData("/"+paths[2]+"/"+paths[3])));
				Iterator<Map.Entry<String, String>> it = childMap.entrySet().iterator();
				while (it.hasNext()) {
					Map.Entry<String, String> entry = it.next();
					if(paths[4].equals(entry.getKey())){
						System.out.println(entry.getValue());
						String isTrue = new String(getDataByWatch("/"+paths[2]+"/"+paths[3]+"/"+paths[4]));
						System.out.println(isTrue);
						if(isTrue.equals("false")){
							entry.setValue("false");
							System.out.println("/"+paths[2]+"/"+paths[3]+"/"+paths[4]+"下线");
						}else{
							entry.setValue("true");
							System.out.println("/"+paths[2]+"/"+paths[3]+"/"+paths[4]+"上线");
						}
					}
				}
			} catch (KeeperException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

修改状态

@RequestMapping("updateStatus")
	@ResponseBody
	public Map updateStatus(String serverName,String ip,String status){
		try {
			Boolean isTrue;
			if(status.equals("false")){
				isTrue = ZkServer.zk.setData("/RPCSERVER"+"/"+serverName+"/"+ip, "true");
			}else{
				isTrue = ZkServer.zk.setData("/RPCSERVER"+"/"+serverName+"/"+ip, "false");
			}
			if(isTrue){
				return toSuccessJson("成功");
			}else{
				return toSuccessJson("失败");
			}
		} catch (Exception e) {
			return toSuccessJson("失败");
		}
		
	}

失败调用实现

注解改造

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
public @interface RPCURL {
	String className();
	String methodName();
	//新增 
	String failClassName() default "";
}

增加一个接口

public interface FailBack {
	
	public String failBack();

}

修改调用代理类

			if(isTrue.equals("true")){
            	 String str[] = ipAndHost.split(":");
            	 request.setClassName(className);
            	 request.setMethodName(url.methodName());
            	 request.setParameters(args);
            	 requestLockMap.put(request.getRequestID(),request);
            	 RPCRequestNet.connect(str[0], Integer.parseInt(str[1])).send(request);
            	 requestLockMap.remove(request.getRequestID());
            	 return request.getResult();
             }else{
            	 FailBack failBack = (FailBack) ZkServer.serverContext.getBean(url.failClassName());
            	 return failBack.failBack();
             }

消费端实现该接口

@RPCClient
public interface clientWorld {
	@RPCURL(className="serverWorld2",methodName="message", failClassName = "fail") 
	public String message(String world);

}

@Service
public class Fail implements FailBack{

	@Override
	public String failBack() {
		return "管理员跑路了";
	}

}

前端页面

自己设计一个的轻量级的RPC框架--服务手动降级

效果

正常情况
自己设计一个的轻量级的RPC框架--服务手动降级
点击降级之后
自己设计一个的轻量级的RPC框架--服务手动降级
这样就完成了一个简单的服务手动降级