dubbo原始碼解析(二十八)遠端呼叫——memcached協議
遠端呼叫——memcached協議
目標:介紹memcached協議的設計和實現,介紹dubbo-rpc-memcached的原始碼。
前言
dubbo實現memcached協議是基於Memcached,Memcached 是一個高效的 KV 快取伺服器,在dubbo中沒有涉及到關於memcached協議的服務暴露,只有服務引用,因為在訪問Memcached伺服器時,Memcached客戶端可以在伺服器上儲存也可以獲取。
原始碼分析
(一)MemcachedProtocol
該類繼承AbstractProtocol,是memcached協議實現的核心。
1.屬性
/** * 預設埠號 */ public static final int DEFAULT_PORT = 11211;
2.export
@Override public <T> Exporter<T> export(final Invoker<T> invoker) throws RpcException { // 不支援memcached服務暴露 throw new UnsupportedOperationException("Unsupported export memcached service. url: " + invoker.getUrl()); }
可以看到,服務暴露方法直接丟擲異常。
3.refer
@Override public <T> Invoker<T> refer(final Class<T> type, final URL url) throws RpcException { try { // 獲得地址 String address = url.getAddress(); // 獲得備用地址 String backup = url.getParameter(Constants.BACKUP_KEY); // 把備用地址拼接上 if (backup != null && backup.length() > 0) { address += "," + backup; } // 建立Memcached客戶端構造器 MemcachedClientBuilder builder = new XMemcachedClientBuilder(AddrUtil.getAddresses(address)); // 建立客戶端 final MemcachedClient memcachedClient = builder.build(); // 到期時間引數配置 final int expiry = url.getParameter("expiry", 0); // 獲得值命令 final String get = url.getParameter("get", "get"); // 新增值命令根據型別來取決是put還是set final String set = url.getParameter("set", Map.class.equals(type) ? "put" : "set"); // 刪除值命令 final String delete = url.getParameter("delete", Map.class.equals(type) ? "remove" : "delete"); return new AbstractInvoker<T>(type, url) { @Override protected Result doInvoke(Invocation invocation) throws Throwable { try { // 如果是獲取方法名的值 if (get.equals(invocation.getMethodName())) { // 如果引數長度不等於1,則丟擲異常 if (invocation.getArguments().length != 1) { throw new IllegalArgumentException("The memcached get method arguments mismatch, must only one arguments. interface: " + type.getName() + ", method: " + invocation.getMethodName() + ", url: " + url); } // 否則呼叫get方法來獲取 return new RpcResult(memcachedClient.get(String.valueOf(invocation.getArguments()[0]))); } else if (set.equals(invocation.getMethodName())) { // 如果引數長度不為2,則丟擲異常 if (invocation.getArguments().length != 2) { throw new IllegalArgumentException("The memcached set method arguments mismatch, must be two arguments. interface: " + type.getName() + ", method: " + invocation.getMethodName() + ", url: " + url); } // 無論任何現有值如何,都在快取中設定一個物件 memcachedClient.set(String.valueOf(invocation.getArguments()[0]), expiry, invocation.getArguments()[1]); return new RpcResult(); } else if (delete.equals(invocation.getMethodName())) { // 刪除操作只有一個引數,如果引數長度不等於1,則丟擲異常 if (invocation.getArguments().length != 1) { throw new IllegalArgumentException("The memcached delete method arguments mismatch, must only one arguments. interface: " + type.getName() + ", method: " + invocation.getMethodName() + ", url: " + url); } // 刪除某個值 memcachedClient.delete(String.valueOf(invocation.getArguments()[0])); return new RpcResult(); } else { // 不支援的操作 throw new UnsupportedOperationException("Unsupported method " + invocation.getMethodName() + " in memcached service."); } } catch (Throwable t) { RpcException re = new RpcException("Failed to invoke memcached service method. interface: " + type.getName() + ", method: " + invocation.getMethodName() + ", url: " + url + ", cause: " + t.getMessage(), t); if (t instanceof TimeoutException || t instanceof SocketTimeoutException) { re.setCode(RpcException.TIMEOUT_EXCEPTION); } else if (t instanceof MemcachedException || t instanceof IOException) { re.setCode(RpcException.NETWORK_EXCEPTION); } throw re; } } @Override public void destroy() { super.destroy(); try { // 關閉客戶端 memcachedClient.shutdown(); } catch (Throwable e) { logger.warn(e.getMessage(), e); } } }; } catch (Throwable t) { throw new RpcException("Failed to refer memcached service. interface: " + type.getName() + ", url: " + url + ", cause: " + t.getMessage(), t); } }
該方法是服務引用方法,基於MemcachedClient的get、set、delete方法來對應Memcached的get、set、delete命令進行對值的操作。
後記
該部分相關的原始碼解析地址:https://github.com/CrazyHZM/i...
該文章講解了遠端呼叫中關於memcached協議實現的部分,邏輯比較簡單。接下來我將開始對rpc模組關於redis協議部分進行講解。