Dubbo之telnet實現
我們可以通過telnet來訪問道對應dubbo服務的資訊
比如
我們可以利用一些指令來訪問。
我們知道,預設情況下,dubbo使用netty做transport。
那麼dubbo是如何區分開正常業務請求和telnet請求呢?
首先來看一下netty的服務。
NettyServer在開啟是會註冊一些downStream和upStream的event
public class NettyServer extends AbstractServer implements Server { private static final Logger logger = LoggerFactory.getLogger(NettyServer.class); private Map<String, Channel> channels; // <ip:port, channel> private ServerBootstrap bootstrap; private org.jboss.netty.channel.Channel channel; public NettyServer(URL url, ChannelHandler handler) throws RemotingException{ super(url, ChannelHandlers.wrap(handler, ExecutorUtil.setThreadName(url, SERVER_THREAD_POOL_NAME))); } @Override protected void doOpen() throws Throwable { NettyHelper.setNettyLoggerFactory(); ExecutorService boss = Executors.newCachedThreadPool(new NamedThreadFactory("NettyServerBoss", true)); ExecutorService worker = Executors.newCachedThreadPool(new NamedThreadFactory("NettyServerWorker", true)); ChannelFactory channelFactory = new NioServerSocketChannelFactory(boss, worker, getUrl().getPositiveParameter(Constants.IO_THREADS_KEY, Constants.DEFAULT_IO_THREADS)); bootstrap = new ServerBootstrap(channelFactory); final NettyHandler nettyHandler = new NettyHandler(getUrl(), this); channels = nettyHandler.getChannels(); // https://issues.jboss.org/browse/NETTY-365 // https://issues.jboss.org/browse/NETTY-379 // final Timer timer = new HashedWheelTimer(new NamedThreadFactory("NettyIdleTimer", true)); bootstrap.setPipelineFactory(new ChannelPipelineFactory() { public ChannelPipeline getPipeline() { NettyCodecAdapter adapter = new NettyCodecAdapter(getCodec() ,getUrl(), NettyServer.this); ChannelPipeline pipeline = Channels.pipeline(); /*int idleTimeout = getIdleTimeout(); if (idleTimeout > 10000) { pipeline.addLast("timer", new IdleStateHandler(timer, idleTimeout / 1000, 0, 0)); }*/ pipeline.addLast("decoder", adapter.getDecoder()); pipeline.addLast("encoder", adapter.getEncoder()); pipeline.addLast("handler", nettyHandler); return pipeline; } }); // bind channel = bootstrap.bind(getBindAddress()); }
其中decoder和encoder對應加解碼,這邊也對應了之前呼叫異常時無法通過attachment傳遞資訊Dubbo自定義異常message過長解決
那麼這邊的nettyHandler最終通過層層包裝委託的機制其實到了真正執行的應該是
HeaderExchangeHandler
public void received(Channel channel, Object message) throws RemotingException { channel.setAttribute(KEY_READ_TIMESTAMP, System.currentTimeMillis()); ExchangeChannel exchangeChannel = HeaderExchangeChannel.getOrAddChannel(channel); try { if (message instanceof Request) { // handle request. Request request = (Request) message; if (request.isEvent()) { handlerEvent(channel, request); } else { if (request.isTwoWay()) { Response response = handleRequest(exchangeChannel, request); channel.send(response); } else { handler.received(exchangeChannel, request.getData()); } } } else if (message instanceof Response) { handleResponse(channel, (Response) message); } else if (message instanceof String) { if (isClientSide(channel)) { Exception e = new Exception("Dubbo client can not supported string message: " + message + " in channel: " + channel + ", url: " + channel.getUrl()); logger.error(e.getMessage(), e); } else { String echo = handler.telnet(channel, (String) message); if (echo != null && echo.length() > 0) { channel.send(echo); } } } else { handler.received(exchangeChannel, message); } } finally { HeaderExchangeChannel.removeChannelIfDisconnected(channel); } }
其中根據請求message的型別進行了區分,如果是request則進行正常的業務呼叫,如果是String則進行telnet的回覆。
這邊的handler型別是ExchangeHandlerAdapter及其對應的子類。
可以確認呼叫telnet時繼續根據spi的方法來查詢對應的實現
public String telnet(Channel channel, String message) throws RemotingException { String prompt = channel.getUrl().getParameterAndDecoded(Constants.PROMPT_KEY, Constants.DEFAULT_PROMPT); boolean noprompt = message.contains("--no-prompt"); message = message.replace("--no-prompt", ""); StringBuilder buf = new StringBuilder(); message = message.trim(); String command; if (message.length() > 0) { int i = message.indexOf(' '); if (i > 0) { command = message.substring(0, i).trim(); message = message.substring(i + 1).trim(); } else { command = message; message = ""; } } else { command = ""; } if (command.length() > 0) { if (extensionLoader.hasExtension(command)) { try { String result = extensionLoader.getExtension(command).telnet(channel, message); if (result == null) { return null; } buf.append(result); } catch (Throwable t) { buf.append(t.getMessage()); } } else { buf.append("Unsupported command: "); buf.append(command); } } if (buf.length() > 0) { buf.append("\r\n"); } if (prompt != null && prompt.length()相關推薦
Dubbo之telnet實現
我們可以通過telnet來訪問道對應dubbo服務的資訊比如我們可以利用一些指令來訪問。我們知道,預設情況下,dubbo使用netty做transport。那麼dubbo是如何區分開正常業務請求和telnet請求呢?首先來看一下netty的服務。NettyServer在開啟是會註冊一些downStream和u
dubbo之泛化實現
att num 客戶端 測試框架 say -s urn pan keyword 實現泛化調用 泛化接口調用方式主要用於客戶端沒有 API 接口及模型類元的情況,參數及返回值中的所有 POJO 均用 Map 表示,通常用於框架集成,比如:實現一個通用的服務測試框架,可通過
Dubbo內核實現之SPI簡單介紹
路徑 簡單 prot inter 策略模式 業務 services 具體實現 指定 Dubbo采用微內核+插件體系,使得設計優雅,擴展性強。那所謂的微內核+插件體系是如何實現的呢!即我們定義了服務接口標準,讓廠商去實現(如果不了解spi的請谷歌百度下), jdk通過Serv
自定義test之dubbo註解的實現
本文是作者在使用dubbo開發的時候,在使用Junit寫單元測試時,對於dubbo服務的消費者如果獲取呢,最常用就是在測試類上加註解 @ContextConfiguration("/sp
Dubbo系列之SPI實現機制(五)
private String createAdaptiveExtensionClassCode() { StringBuilder codeBuidler = new StringBuilder(); Method[] methods = type.getMethods(); boolean
JavaWeb網上圖書商城完整項目--day02-6.ajax校驗功能之頁面實現
ret code 需要 gis 提交 ima date else back 1 、現在我們要在regist.js中實現ajax的功能,使用用戶名到後臺查詢是否註冊,郵箱是否到後臺註冊,驗證碼是否正確的功能 我們來看regist.js的代碼 //該函數在html文檔加載完成
Django之路 - 實現登錄隨機驗證碼
短信祝福 python 中間件 程序 檢測 登錄驗證碼是每個網站登錄時的基本標配,網上也有很多相應的文章, 但是從生成驗證碼到 應用到自己的網站上的全步驟,並沒有看到很多, 為了節約大家的時間,我把整體步驟寫下來, 即拿即用哈 1. 生成隨機驗證碼 隨機驗證碼代碼 2. 如何應用到你的dj
dubbo之dubbo協議使用
dubbo普通接口及實現類public interface DemoService{ String sayHello(String msg);}public class DemoServiceImpl implements DemoService{ public String sayHello(S
dubbo之rmi協議使用
dubbo rmi普通接口與實現類public interface DemoService { String sayHello(String msg);}public class DemoServiceImpl implements DemoService { @Override public Stri
每天一個liunx命令3之awk實現文本文件的抓取
logs -h 名稱 name $0 rep ray 表達式 指定 =============================================================================grep -h -s -E ‘HUAWEI_9000
Hadoop Mapreduce之WordCount實現
註意 com split gin 繼承 [] leo ring exce 1.新建一個WCMapper繼承Mapper public class WCMapper extends Mapper<LongWritable, Text, Text, LongWritab
Nginx之 proxy_pass實現代理 小記
location proxy_pass 反向代理Nginx之 proxy_pass 小記1.環境介紹:Nginx :開啟80端口訪問Apache :開啟兩個虛擬主機分別是 端口88 、端口 89 2.配置文件:Apahce虛擬主機<VirtualHost *:89> DocumentRoot
建造者模式之C++實現
emp 產品 它的 聚合 begin tor typename 默認 學習交流 說明:本文僅供學習交流,轉載請標明出處。歡迎轉載! 建造者模式(Builder)也叫生成器模式,我們都知道。假設我們想完畢一個復雜產品的創建過程,我們必須分開創建。再組裝。比
大話數據結構之php實現單鏈表
線性表 單鏈表最近想起來兩件事1.大話數據結構和大話設計模式這兩本書很有意思,C語言有指針,所以實現起來容易理解,所以突然想到用PHP寫一下來熟悉一下數據結構的線性表,不過看的比較慢。一般兩三天才看完一部分,畢竟還要工作,老板還安裝攝像頭看著每天幹了啥。。。。。老板事業興隆,嘻嘻。線性表的概念不贅述,直接去看
hibernate查詢之Criteria實現分頁方法(GROOVY語法)
tracking b2b earch urn eat con div 查詢 mod public int searchTest(String name, Integer pageIndex, List<Test> resultList){ def
Spring系列之AOP實現的兩種方式
部分 靜態常量 cep value conf tar import enc ble AOP常用的實現方式有兩種,一種是采用聲明的方式來實現(基於XML),一種是采用註解的方式來實現(基於AspectJ)。 首先復習下AOP中一些比較重要的概念: Joinpoint(連接點)
算法(第四版)學習筆記之java實現可以動態調整數組大小的棧
length pub move sta gen font -c @override lifo 下壓(LIFO)棧:可以動態調整數組大小的實現 import java.util.Iterator; public class ResizingArrayStack&l
直接插入排序(高級版)之C++實現
include ostream 源代碼 cpp -s 臨時 ios 結束 中間變量 直接插入排序(高級版)之C++實現 一、源代碼:InsertSortHigh.cpp 1 /*直接插入排序思想: 2 假設待排序的記錄存放在數組R[1..n]中。初始時,R[1]自成
選擇排序之C++實現
運行 等於 排序 urn 結束 align 想是 mes 存儲 選擇排序之C++實現 一、源代碼:SelectSort.cpp 1 /* 2 選擇排序(從小到大)的基本思想是,首先,選出最小的數,放在第一個位置; 3 然後,選出第二小的數,放在第二個位置; 4 以
二分搜索之C++實現
[] .com 技術 ont 說明 tex ron ostream 一維數組 二分搜索之C++實現 一、源代碼:BinarySearch.cpp 1 #include<iostream> 2 using namespace std; 3 4 /*定義