dubbo远程方法调用的基本原理

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了dubbo远程方法调用的基本原理相关的知识,希望对你有一定的参考价值。

1 dubbo是远程服务调用rpc框架

2 dubbo缺省协议采用单一长连接和NIO通讯

1client端生成一个唯一的id,封装方法调用信息obj(接口名,方法名,参数,处理结果的回调对象),在全局的ConcurrentHashMap中保存put(id,obj), 将id和obj发送到server端,当前线程使用callback的get()方法试图获取远程返回的结果,在get()内部,则使用synchronized获取回调对象callback的锁, 先检测是否已经获取到结果,如果没有,然后调用callback的wait()方法,释放callback上的锁,让当前线程处于等待状态。

2server端接收到请求并处理后,返回给client端处理结果,client从中取到ID,再从前面的ConcurrentHashMap里面get(ID),从而找到callback,将方法调用结果设置到callback对象里 ,使用synchronized获取回调对象callback的锁(因为前面调用过wait(),那个线程已释放callback的锁了),再notifyAll(),唤醒前面处于等待状态的线程继续执行

 

 

 

 

参考:https://blog.csdn.net/paul_wei2008/article/details/19355681

 

在实际项目有类似的需求,不过没有用锁机制,线程等待,直接使用sleep方法了

package com.moreas.r1;

public interface Event {
	public void handlerEvent(Object params);
}

  

 

package com.moreas.r1;

import java.util.HashMap;
import java.util.Map;

public class RemoteService implements Event {

	private int monitor_result = 0;

	public Object remoteLocate(String deviceID) {

		Map<String, Object> returnMap = new HashMap<>();
		returnMap.put("code", 1);

		@SuppressWarnings("unchecked")
		Map<String, Object> deviceMap = (Map<String, Object>) ServerManager.application.get(deviceID);

		// 生成指令
		String msgID = Utils.createMsgID();
		OrderEntity order = new OrderEntity();
		order.setMsgID(msgID);
		order.setCmd("Monitor");
		order.setDeviceID(deviceID);

		deviceMap.put("MsgId", msgID);
		ServerManager.application.put(deviceID, deviceMap);

		// 将自己添加到回调的map中
		LocateService.addHandlerEvent(deviceID + "_Monitor", this);

		// 使用socket将指令order发送出去

		// 等待
		try {

			int cnt = 0;
			while ((monitor_result == 0) && cnt < 280) {
				Thread.sleep(100);
				cnt++;
			}

		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		if (monitor_result != 0) { // 通过handlerEvent方法将处理结果设置到monitor_result中
			returnMap.put("code", 2);
		} else {
			System.out.println("请求超时了");
			returnMap.put("code", 2);
		}

		LocateService.removeHandlerEvent(deviceID + "_Monitor");
		return returnMap;

	}

	@Override
	public void handlerEvent(Object params) {
		Map map = (Map) params;
		if (((String) map.get("result")).equals(123)) {
			monitor_result = 11;
		}
	}

}

  

package com.moreas.r1;

import java.util.HashMap;

public class LocateService extends CallBack {

	@SuppressWarnings({ "rawtypes", "unchecked" })
	public void handlerUploadLctDataByApp(OrderEntity receiveOrder, String deviceID) {
		// 通过receiveOrder取得参数,调用本地方法获取结果result
		int resultData = 1;

		if (resultData == 1) {

			Event event = getEvent(deviceID + "_Monitor");
			if (event != null) {
				HashMap map = new HashMap<>();
				map.put("locResult", "123");
				event.handlerEvent(map);
			}
		}
	}

}

  

package com.moreas.r1;

import java.util.HashMap;
import java.util.Map;

public class CallBack {

	private static Map<String, Event> eventList = new HashMap<>();

	public static void addHandlerEvent(String key, Event eventClass) {

		if (eventList.containsKey(key)) {
			return;
		}

		synchronized (eventList) {
			eventList.put(key, eventClass);
		}
	}

	public static void removeHandlerEvent(String key) {

		if (!eventList.containsKey(key)) {
			return;
		}

		synchronized (eventList) {
			eventList.remove(key);
		}
	}

	public static void clearHandlerEvent() {

		synchronized (eventList) {
			eventList.clear();
		}
	}

	public static boolean containsKey(String key) {

		return eventList.containsKey(key);
	}

	public static Event getEvent(String key) {

		if (!containsKey(key))
			return null;

		return eventList.get(key);
	}

}

  

package com.moreas.r1;

import java.util.Map;

public class ReceiveData {
	
	

	//order是接受到的指令,接受到指令后,进行处理
	@SuppressWarnings({ "unused", "unchecked" })
	private void handler(OrderEntity order) {
		
		if(order.getCmd().equals("Monitor")){
			//获取application中的MsgId
			String deviceID = order.getDeviceID();
			Map<String, Object> deviceMap = (Map<String, Object>)ServerManager.application.get(deviceID);
			String msgID = (String)deviceMap.get("MsgId");
			//order中的MsgId
			if(msgID.equals(order.getMsgID())) {
				
				new LocateService().handlerUploadLctDataByApp(order, deviceID);
				
				deviceMap.remove("MsgId");
				ServerManager.application.put(deviceID,deviceMap);
			}
			
		}
		
		
	}
}

  

package com.moreas.r1;

public class OrderEntity {

	private String msgID; // 消息ID

	private String cmd;

	private String deviceID;

	public String getDeviceID() {
		return deviceID;
	}

	public void setDeviceID(String deviceID) {
		this.deviceID = deviceID;
	}

	public String getCmd() {
		return cmd;
	}

	public void setCmd(String cmd) {
		this.cmd = cmd;
	}

	public String getMsgID() {
		return msgID;
	}

	public void setMsgID(String msgID) {
		this.msgID = msgID;
	}

	public String getMsg() {
		return "123";
	};
}

  

package com.moreas.r1;

import java.util.HashMap;
import java.util.Map;

public class ServerManager {

	private static final String flag = "ServerManger";

	public static Map<String, Object> application = new HashMap<String, Object>();

}

  

package com.moreas.r1;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Random;

public class Utils {

	public static String createMsgID() {

		Random random = new Random();
		int nonce = random.nextInt(1000);
		String nonceStr = "" + nonce;
		if (nonce < 100) {
			nonceStr = "0" + nonceStr;
			if (nonce < 10) {
				nonceStr = "0" + nonceStr;
			}
		}

		SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");
		String currTime = df.format(new Date());

		return currTime + "-" + nonceStr;
	}
}

  

 

 

以上是关于dubbo远程方法调用的基本原理的主要内容,如果未能解决你的问题,请参考以下文章

Dubbo基本原理机制

alibaba远程调用框架dubbo原理

Dubbo-

dubbo基础学习总结

dubbo学习远程调用原理

Dubbo底层原理,java分布式框架,源码分析