1. 程式人生 > >Dubbo之telnet實現

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() 
            
           

相關推薦

Dubbotelnet實現

我們可以通過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

自定義testdubbo註解的實現

       本文是作者在使用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

dubbodubbo協議使用

dubbo普通接口及實現類public interface DemoService{ String sayHello(String msg);}public class DemoServiceImpl implements DemoService{ public String sayHello(S

dubbormi協議使用

dubbo rmi普通接口與實現類public interface DemoService { String sayHello(String msg);}public class DemoServiceImpl implements DemoService { @Override public Stri

每天一個liunx命令3awk實現文本文件的抓取

logs -h 名稱 name $0 rep ray 表達式 指定 =============================================================================grep -h -s -E ‘HUAWEI_9000

Hadoop MapreduceWordCount實現

註意 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 /*定義