`
dragonsoar
  • 浏览: 203986 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

纯Java的高性能长连接RPC解决方案

阅读更多

 

简介:轻量封装Ibatis3

         因为本人在国内最大的电子商务公司工作期间,深感一个好的分表分库框架可以大大提高系统的承载能力及系统的灵活性,而一个不好的分表分库方案,则让系统在大数据量处理的时候非常郁闷。所以, 在根据笔者在从事电子商务开发的这几年中,对各个应用场景而开发的一个轻量封装Ibatis3的一个分表分库框架。

         笔者工作的这几年之中,总结并开发了如下几个框架: summercool(Web 框架,已经应用于某国内大型网络公司的等重要应用)、summercool-hsf(基于Netty实现的RPC框架,已经应用国内某移动互联网公司)、 summercool-ddl(基于Mybaits的分表分库框架,已经应用国内某移动互联网公司);相继缓存方案、和消息系统解决方案也会慢慢开源。 Summercool框架做为笔者的第一个开源框架

summercool-hsf:http://summercool-hsf.googlecode.com/svn/trunk

 

 

1. 什么是HSF框架

    HSF框架是一个高性能远程通信框架,底层基于Netty实现TCP通信,对上层进行封装,提供易于使用和高度可扩展能力。

 

 

名词解译:

    1)Channel:可以理解为一个通道,或者连接

    2)ChannelGroup:多个通道组合成为一个ChannelGroup

 

2.HSF工作流程

 

3.消息协议设计

    消息协议这里是指对消息编码和解码的规范的一种定义,HSF内置的消息协议采用如下结构:

 

 

 

    Length:以4个字节表示,是指ID + Content的长度。

    ID:以1个字节表示,1表示Content部分被压缩,0表示未被压缩。

    Content:真实的消息内容。

 

 

4.处理器

    Netty框架原生提供一个处理器链对事件进行处理,每个处理器均实现ChannelHandler接口,ChannelHandler是个空接口,拥有三个子接口:ChannelDownstreamHandler, ChannelUpstreamHandler和LifeCycleAwareChannelHandler。这里我们主要关注前两个接口,因为它们被用来处理读与写的消息。
    事件主要分为三种:ChannelEvent、MessageEvent和ExceptionEvent,一旦这些事件被触发,它们将从处理器链的一端到另一端,被逐个处理器处理,注意,整个过程是单线程场景。一般而言,ChannelEvent和ExceptionEvent事件都是从底层被触发,因此,它们会被ChannelUpstreamHandler处理。而MessageEvent则需要根据读与写方式的不同,分别从两个方向被ChannelUpstreamHandler和ChannelDownstreamHandler处理。
    HSF内置的编(解)码处理器、压缩(解压)处理器及序列化(反序列化)处理器等都是直接或间接实现ChannelHandler。

    ♦ ChannelDownstreamHandler

 

public interface ChannelDownstreamHandler extends ChannelHandler {
    /**
     * Handles the specified downstream event.
     *
     * @param ctx  the context object for this handler
     * @param e    the downstream event to process or intercept
     */
    void handleDownstream(ChannelHandlerContext ctx, ChannelEvent e) throws Exception;
}

 

    ♦ ChannelUpstreamHandler

 

public interface ChannelUpstreamHandler extends ChannelHandler {
    /**
     * Handles the specified upstream event.
     *
     * @param ctx  the context object for this handler
     * @param e    the upstream event to process or intercept
     */
    void handleUpstream(ChannelHandlerContext ctx, ChannelEvent e) throws Exception;
}

 

 

4.1.Encoding流程

     HSF内置的encoding过程由三个Handler组合完成,流程如下:

 

 

 

    1) SerializeDownstreamHandler

 

/**
 * @Title: SerializeDownstreamHandler.java
 * @Package com.gexin.hsf.netty.channelhandler.downstream
 * @Description: 序列化
 * @author 
 * @date 2011-9-16 下午4:45:59
 * @version V1.0
 */
public class SerializeDownstreamHandler implements ChannelDownstreamHandler {
    Logger logger = LoggerFactory.getLogger(getClass());
    private Serializer serializer = new KryoSerializer();
    public SerializeDownstreamHandler() {
    }
    public void handleDownstream(ChannelHandlerContext ctx, ChannelEvent e) throws Exception {
        if (!(e instanceof MessageEvent)) {
            ctx.sendDownstream(e);
            return;
        }
        MessageEvent event = (MessageEvent) e;
        Object originalMessage = event.getMessage();
        Object encodedMessage = originalMessage;
        if (!(originalMessage instanceof Heartbeat)) {
            encodedMessage = serializer.serialize(originalMessage);
        } else {
            encodedMessage = Heartbeat.BYTES;
        }
        if (originalMessage == encodedMessage) {
            ctx.sendDownstream(e);
        } else if (encodedMessage != null) {
            write(ctx, e.getFuture(), encodedMessage, event.getRemoteAddress());
        }
    }
    public void setSerializer(Serializer serializer) {
        this.serializer = serializer;
    }
}

      2)CompressionDownstreamHandler

 

 

/**
 * @Title: CompressionDownstreamHandler.java
 * @Package com.gexin.hsf.netty.channelhandler.downstream
 * @Description: 压缩处理器
 * @author 
 * @date 2011-9-16 下午4:45:59
 * @version V1.0
 */
public class CompressionDownstreamHandler implements ChannelDownstreamHandler {
    private CompressionStrategy compressionStrategy = new ThresholdCompressionStrategy();
    public void handleDownstream(ChannelHandlerContext ctx, ChannelEvent e) throws Exception {
        if (!(e instanceof MessageEvent)) {
            ctx.sendDownstream(e);
            return;
        }
        MessageEvent event = (MessageEvent) e;
        Object originalMessage = event.getMessage();
        if (originalMessage instanceof byte[]) {
            CompressionResult compressionResult = compressionStrategy.compress((byte[]) originalMessage);
            byte[] resBuffer = compressionResult.getBuffer();
            int length = resBuffer.length;
            byte[] bytes = new byte[length + 1];
            bytes[0] = compressionResult.isCompressed() ? (byte) 1 : (byte) 0;
            for (int i = 0; i < length; i++) {
                bytes[i + 1] = resBuffer[i];
            }
            DownstreamMessageEvent evt = new DownstreamMessageEvent(event.getChannel(), event.getFuture(), bytes,
                    event.getRemoteAddress());
            ctx.sendDownstream(evt);
        } else {
            ctx.sendDownstream(e);
        }
    }
    public void setCompressionStrategy(CompressionStrategy compressionStrategy) {
        this.compressionStrategy = compressionStrategy;
    }
}

       3)LengthBasedEncoder

 

 

/**
 * @ClassName: LengthBasedEncoder
 * @Description: 基于长度的编码器
 * @author 
 * @date 2011-9-29 下午1:43:41
 * 
 */
public class LengthBasedEncoder extends ObjectEncoder {
    Logger logger = LoggerFactory.getLogger(getClass());
    private final int estimatedLength;
    public LengthBasedEncoder() {
        this(512);
    }
    public LengthBasedEncoder(int estimatedLength) {
        if (estimatedLength < 0) {
            throw new IllegalArgumentException("estimatedLength: " + estimatedLength);
        }
        this.estimatedLength = estimatedLength;
    }
    @Override
    protected Object encode(ChannelHandlerContext ctx, Channel channel, Object msg) throws Exception {
        if (msg instanceof byte[]) {
            byte[] bytes = (byte[]) msg;
            ChannelBuffer ob = ChannelBuffers.dynamicBuffer(estimatedLength, channel.getConfig().getBufferFactory());
            ob.writeInt(bytes.length);
            ob.writeBytes(bytes);
            return ob;
        } else {
            throw new IllegalArgumentException("msg must be a byte[], but " + msg);
        }
    }
}

 

 

   4.2.Decoding流程

    decoding流程与encoding正好相反,流程如下:

 

    1)LengthBasedDecoder

    对于TCP通信而言,粘包是很正常的现象,因此decoder必须处理粘包问题。HsfFrameDecoder是一个支持粘包处理的decoder类抽象。

/**
 * @ClassName: LengthBasedDecoder
 * @Description: 基于长度的解码器
 * @author 
 * @date 2011-9-29 下午1:42:59
 * 
 */
public class LengthBasedDecoder extends HsfFrameDecoder {
    private Logger logger = LoggerFactory.getLogger(getClass());
    private int headerFieldLength = 4;
    public LengthBasedDecoder() {
        this(4);
    }
    public LengthBasedDecoder(int headerFieldLength) {
        this.headerFieldLength = headerFieldLength;
    }
    @Override
    protected Object decode(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) throws Exception {
        if (buffer.readableBytes() >= headerFieldLength) {
            buffer.markReaderIndex();
            int length = buffer.readInt();
            if (length < 0) {
                logger.error("msg length must >= 0. but length={}", length);
                return null;
            } else if (length == 0) {
                return Heartbeat.BYTES;
            } else if (buffer.readableBytes() >= length) {
                byte[] bytes = new byte[length];
                buffer.readBytes(bytes);
                return bytes;
            } else {
                buffer.resetReaderIndex();
            }
        }
        return null;
    }
}

     2)DecompressionUpstreamHandler

/**
 * @Title: DecompressionUpstreamHandler.java
 * @Package com.gexin.hsf.netty.channelhandler.downstream
 * @Description: 解压缩处理器
 * @author 
 * @date 2011-9-16 下午4:45:59
 * @version V1.0
 */
public class DecompressionUpstreamHandler extends SimpleChannelUpstreamHandler {
    private CompressionStrategy compressionStrategy = new ThresholdCompressionStrategy();
    @Override
    public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
        if (e.getMessage() instanceof byte[]) {
            byte[] bytes = (byte[]) e.getMessage();
            int length = bytes.length;
            if (length > 0) {
                byte[] buffer = new byte[length - 1];
                for (int i = 1; i < length; i++) {
                    buffer[i - 1] = bytes[i];
                }
                if (bytes[0] == 1) {
                    buffer = compressionStrategy.decompress(buffer);
                }
                UpstreamMessageEvent event = new UpstreamMessageEvent(e.getChannel(), buffer, e.getRemoteAddress());
                super.messageReceived(ctx, event);
            }
        } else {
            super.messageReceived(ctx, e);
        }
    }
    public void setCompressionStrategy(CompressionStrategy compressionStrategy) {
        this.compressionStrategy = compressionStrategy;
    }
}

     3)DeserializeUpstreamHandler

/**
 * @Title: DeserializeUpstreamHandler.java
 * @Package com.gexin.hsf.netty.channelhandler.downstream
 * @Description: 反序列化
 * @author 
 * @date 2011-9-16 下午4:45:59
 * @version V1.0
 */
public class DeserializeUpstreamHandler extends SimpleChannelUpstreamHandler {
    private Logger logger = LoggerFactory.getLogger(getClass());
    private Serializer serializer = new KryoSerializer();
    @Override
    public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
        if (e.getMessage() == null) {
            return;
        } else if (e.getMessage() instanceof byte[]) {
            byte[] bytes = (byte[]) e.getMessage();
            Object msg;
            if (bytes.length == 0) {
                msg = Heartbeat.getSingleton();
            } else {
                try {
                    msg = serializer.deserialize(bytes);
                } catch (Exception ex) {
                    throw ex;
                }
            }
            UpstreamMessageEvent event = new UpstreamMessageEvent(e.getChannel(), msg, e.getRemoteAddress());
            super.messageReceived(ctx, event);
        } else {
            super.messageReceived(ctx, e);
        }
    }
    public void setSerializer(Serializer serializer) {
        this.serializer = serializer;
    }
}

    4.3.处理器链的建立

    HSF使用如下的方式构建处理器链:

bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
            public ChannelPipeline getPipeline() throws Exception {
                ChannelPipeline pipeline = Channels.pipeline();
                // 注册各种自定义Handler
                for (String key : handlers.keySet()) {
                    pipeline.addLast(key, handlers.get(key));
                }
                // 注册链路空闲检测Handler
                Integer writeIdleTime = LangUtil.parseInt(options.get(HsfOptions.WRITE_IDLE_TIME));
                Integer readIdleTime = LangUtil.parseInt(options.get(HsfOptions.READ_IDLE_TIME));
                if (writeIdleTime == null) {
                    writeIdleTime = 10;
                }
                if (readIdleTime == null) {
                    // 默认为写空闲的3倍
                    readIdleTime = writeIdleTime * 3;
                }
                pipeline.addLast("timeout", new IdleStateHandler(idleTimer, readIdleTime, writeIdleTime, 0));
                pipeline.addLast("idleHandler", new StateCheckChannelHandler(HsfAcceptorImpl.this));
                // 注册事件分发Handler
                pipeline.addLast("dispatchHandler", new DispatchUpStreamHandler(eventDispatcher));
                return pipeline;
            }
        });

5.Dispatcher

    消息经过Handler链处理后,将被Dispatcher转发,并进入EventListener链处理。

    Dispatcher内置两个线程池:channelExecutor和msgExecutor。

    channelExecutor用于处理通道事件和异常事件,考虑到在通道事件可能需要同步调用远程服务,因此此线程池不设上线(因为同步调用将会阻塞当前线程)。

    msgExecutor用于处理消息事件,根据经验值,缺省最大线程数为150,该值可以通过Option参数修改。

6.EventListener

    EventListener有以下三种:

    1)ChannelEventListener

/**
 * @Title: ChannelEventListener.java
 * @Package com.gexin.hsf.netty.listener
 * @Description: 通道事件监听类
 * @author 
 * @date 2011-9-27 上午11:45:50
 * @version V1.0
 */
public interface ChannelEventListener extends EventListener {
    /**
     * Invoked when a {@link Channel} was closed and all its related resources were released.
     * 
     * @author
     * @param ctx
     * @param channel
     * @param e
     * @return EventBehavior Whether to continue the events deliver
     */
    public EventBehavior channelClosed(ChannelHandlerContext ctx, HsfChannel channel, ChannelStateEvent e);
    /**
     * Invoked when a {@link Channel} is open, bound to a local address, and connected to a remote address.
     * 
     * @author
     * @param ctx
     * @param channel
     * @param e
     * @return EventBehavior Whether to continue the events deliver
     */
    public EventBehavior channelConnected(ChannelHandlerContext ctx, HsfChannel channel, ChannelStateEvent e);
    /**
     * Invoked when a group is created.
     * 
     * @author
     * @param ctx
     * @param channel
     * @param groupName
     * @return EventBehavior Whether to continue the events deliver
     */
    public EventBehavior groupCreated(ChannelHandlerContext ctx, HsfChannel channel, String groupName);
    /**
     * Invoked when a group is removed.
     * 
     * @author
     * @param ctx
     * @param channel
     * @param groupName
     * @return EventBehavior Whether to continue the events deliver
     */
    public EventBehavior groupRemoved(ChannelHandlerContext ctx, HsfChannel channel, String groupName);
}

     2)MessageEventListener

/**
 * @Title: MessageListener.java
 * @Package com.gexin.hsf.netty.listener
 * @Description: 消息监听接口
 * @author
 * @date 2011-9-27 上午11:36:22
 * @version V1.0
 */
public interface MessageEventListener extends EventListener {
    /**
     * Invoked when a message object (e.g: {@link ChannelBuffer}) was received
     * from a remote peer.
     */
    public EventBehavior messageReceived(ChannelHandlerContext ctx, HsfChannel channel, MessageEvent e);
}

     3)ExceptionEventListener

/**
 * @Title: ExceptionEventListener.java
 * @Package com.gexin.hsf.netty.listener
 * @Description: 异常监听接口
 * @author
 * @date 2011-9-27 上午11:48:09
 * @version V1.0
 */
public interface ExceptionEventListener extends EventListener {
    /**
     * Invoked when an exception was raised by an I/O thread or a {@link ChannelHandler}.
     */
    public EventBehavior exceptionCaught(ChannelHandlerContext ctx, Channel channel, ExceptionEvent e);
}

     Hsf框架会预先在EventListener链末端注册ServiceMessageEventListener,该Listener负责调用被注册的Service,并将返回值或异常回传。

    7.Service

    1)RemoteServiceContract注解

    所有实现了拥有RemoteServiceContract注解的Java类都可以直接注册到HsfService,示例如下:

@RemoteServiceContract
public interface TestService {
    String test(String ctx);
}
 
public class TestServiceImpl implements TestService {
    @Override
    public String test(String ctx) {
        return String.valueOf("hello " + ctx);
    }
}

    2)ServiceEntry

    对于未添加RemoteServiceContract注解的接口,Hsf框架使用org.summercool.hsf.pojo.ServiceEntry类实现注册。

   

    3)注册Service

    服务提供方需要向Hsf注册Service方可被远程调用,示例如下:

    ♦ 注册Service

HsfAcceptor acceptor = new HsfAcceptorImpl();
// 注册Service
acceptor.registerService(new TestServiceImpl());
// 监听端口
acceptor.bind(8082);

     ♦ 远程调用Service

HsfConnector connector = new HsfConnectorImpl();
connector.connect(new InetSocketAddress("127.0.0.1",8082));
// 同步方式
TestService testService = ServiceProxyFactory.getRoundFactoryInstance(connector).wrapSyncProxy(TestService.class);
System.out.println(testService.test("HSF"));

    

    3)同步与异步

    4)原理

   7.Handshake

    当通道建立后,Client和Server会进行三次握手,以完成初始化

    初次握手步骤

    1)Client与Server建立连接成功

    2)Client向Server发送握手请求包(handshake request)

    3)Server接收到握手请求包后,生成group信息,然后触发groupCreated事件,接着向client发送握手反馈包(handshake ack)

    4)Client接收到握手反馈包后,生成group信息,然后触发groupCreated事件,接着向server发送握手完成包(handshake finish)

    非初次握手步骤

    1)Client与Server建立连接成功

    2)Client向Server发送握手请求包(handshake request)

    3)Server接收到握手请求包后,添加该连接到Group,接着向client发送握手反馈包(handshake ack)

    4)Client接收到握手反馈包后,添加该连接到Group,接着向server发送握手完成包(handshake finish)

    以上三次握手所发送的包都只包含本身的group信息,但Hsf对外提供了握手的扩展接口,应用可以使用该接口结合自身的业务,以完成连接建立后的初始化工作。

    Client握手扩展接口

   8.Heartbeat、超时及重连机制

    Heartbeat和超时机制依赖于Netty的读空闲和写空闲回调。

    当发生写空闲时,会向对方发送Heartbeat消息,写空闲时间可以通过参数HsfOptions.WRITE_IDLE_TIME设定,缺省为10秒。

    当发生读空闲时,即判定为超时,主动关闭连接,读空闲时间可以通过参数HsfOptions.READ_IDLE_TIME设定,缺省为60秒。

    对于断开的连接,Hsf会为其重连,重连频率通过HsfOptions.RECONNECT_INTERVAL参数设定,缺省为10000毫秒。

 

   9.Option参数

    Hsf支持以参数配置:

参数名 说明 缺省值
HsfOptions.TCP_NO_DELAY TCP参数,是否关闭延迟发送消息包 true
HsfOptions.KEEP_ALIVE TCP参数,是否保持连接 true
HsfOptions.REUSE_ADDRESS TCP参数,是否重用端口 false
HsfOptions.WRITE_IDLE_TIME 写空闲时间(秒) 10
HsfOptions.READ_IDLE_TIME 读空闲时间(秒) 60
HsfOptions.SYNC_INVOKE_TIMEOUT 同步调用超时时间(毫秒) 60000
HsfOptions.HANDSHAKE_TIMEOUT 握手超时时间(毫秒) 15000
HsfOptions.FLOW_LIMIT 流量限额 2000000
HsfOptions.TIMEOUT_WHEN_FLOW_EXCEEDED 申请流量超时时间(毫秒) 3000
HsfOptions.MAX_THREAD_NUM_OF_DISPATCHER 分发器的最大线程数 150
HsfOptions.CHANNEL_NUM_PER_GROUP 每个Group建立的通道数 Runtime.getRuntime().availableProcessors()
HsfOptions.RECONNECT_INTERVAL 重连频率(毫秒) 10000
HsfOptions.CONNECT_TIMEOUT 建立连接超时时间(毫秒) 30000
HsfOptions.HOLD_CALLBACK_MESSAGE 是否缓存Callback方式发送的消息,缓存后将会在发送失败时回调doException方法参数传入

false

    这些参数可以通过如下方式调整:

HsfConnector connector = new HsfConnectorImpl();
connector.setOption(HsfOptions.CHANNEL_NUM_PER_GROUP, 1);

10.Hsf的使用

    待续(大家可以先看代码中的test包)

 

 

 

 

  • 大小: 8.4 KB
  • 大小: 41.4 KB
  • 大小: 7.3 KB
  • 大小: 14.2 KB
  • 大小: 14 KB
  • 大小: 23.8 KB
分享到:
评论
24 楼 allen.lei 2015-10-20  
服务器端如果要向某个客户端发送消息是否是需要服务端通过一个Map保存所有连接上来的客户端SocketChannel,客户端的Id作为Map的key(这个服务端代码中有实现吗?另外如果用map保存的话50w并发是否会爆掉啊?)。每次服务器端如果要向某个客户端发送消息,只需根据ClientId取出对应的SocketChannel,往里面写入message即可?
23 楼 ayanami001 2015-10-19  
请问分布式事务是如何处理的
22 楼 nothing.whoami 2015-05-08  
您好!请问下HSF的代码是开源的吗?想拜读下,谢谢!
21 楼 jussyzou 2015-01-14  
您好,什么时候能迁移完毕呢?希望能下载学习,谢谢。邮箱:jussyzou@163.com
20 楼 dragonsoar 2014-09-02  
lkgforex 写道
你好,我现在也在研究这块,但是现在  http://summercool-hsf.googlecode.com/svn/trunk/ 下载不了代码了。所以请分享一份代码 ,谢谢。
我的邮箱是 lkgforex@163.com

暂时在迁到gitcafe上面,等迁号了会通知你的~
19 楼 dragonsoar 2014-09-02  
ahua186186 写道
thank you  我还没看代码,我想问下你这个可以加SSL吗,可以用来传文件吗。


加不了SSL
18 楼 ahua186186 2014-08-04  
thank you  我还没看代码,我想问下你这个可以加SSL吗,可以用来传文件吗。
17 楼 lkgforex 2014-08-02  
你好,我现在也在研究这块,但是现在  http://summercool-hsf.googlecode.com/svn/trunk/ 下载不了代码了。所以请分享一份代码 ,谢谢。
我的邮箱是 lkgforex@163.com
16 楼 dragonsoar 2014-04-29  
magicyang919 写道
能不能多点文档啊?比如概要设计和详细设计文档。

正在弄中~
15 楼 magicyang919 2014-04-26  
能不能多点文档啊?比如概要设计和详细设计文档。
14 楼 dragonsoar 2013-11-14  
andye 写道
看您的代码就是一种享受!呵呵。
还有您的缓存方案和消息系统框架什么时候开源?

andye 写道
您这个框架是基于点对点调用模式实现的,如果实现多对多的调用,如Dubbo框架,改动会不会比较大?

暂时不会开源,因为堆外大缓存在国内还没有好的解决方案,这个解决方案用处比较广,所以可能会做为我们这样创业公司一个非常好的卖点。
先谢谢各位的支持,呵~
13 楼 jd2bs 2013-10-30  
andye 写道
您这个框架是基于点对点调用模式实现的,如果实现多对多的调用,如Dubbo框架,改动会不会比较大?


怎么是点对点呢? 楼主下面已经说了,configServer包就是处理多点调用的;如果你认为configServer包太简陋,可以改用dubbo的zokeeper方式来管理多个服务提供者,以提供工业强度。不过原理都是一样的。
12 楼 andye 2013-10-28  
看您的代码就是一种享受!呵呵。
还有您的缓存方案和消息系统框架什么时候开源?

andye 写道
您这个框架是基于点对点调用模式实现的,如果实现多对多的调用,如Dubbo框架,改动会不会比较大?
11 楼 andye 2013-10-28  
您这个框架是基于点对点调用模式实现的,如果实现多对多的调用,如Dubbo框架,改动会不会比较大?
10 楼 dragonsoar 2013-06-28  
thinkfly123thinkfly 写道
请问一下,phone的测试包的client和server如何进行交互,client向server发送消息,server接受client的消息,并向client发送消息?

是的,这个只是写的一个思路测试包,不严格,只是能跑通而已
9 楼 thinkfly123thinkfly 2013-06-26  
请问一下,phone的测试包的client和server如何进行交互,client向server发送消息,server接受client的消息,并向client发送消息?
8 楼 dragonsoar 2013-05-15  
yangfuchao418 写道
稳定性和性能怎么样??假如客户端是其他语言调用也可以?

肯定可以了; 稳定性和性能还是不错的,某些大公司内部一直在用的~
7 楼 yangfuchao418 2013-05-06  
稳定性和性能怎么样??假如客户端是其他语言调用也可以?
6 楼 dragonsoar 2013-03-05  
hda 写道
楼主,谢谢分享。提点意见。
你这里提到的HSF似乎与网上其他介绍的tb-hsf方案不一样,
这里提到的似乎没有负载和集群方面的考虑吧?也就是server无法简单的通过增加机器来扩展性能。
对否?

是可以通过加机器来实现扩展性能的,里面有一个configserver包,里面的解决方案和tb的一样的~
5 楼 hda 2013-02-27  
楼主,谢谢分享。提点意见。
你这里提到的HSF似乎与网上其他介绍的tb-hsf方案不一样,
这里提到的似乎没有负载和集群方面的考虑吧?也就是server无法简单的通过增加机器来扩展性能。
对否?

相关推荐

    纯Java的高性能长连接RPC解决方案.docx

    技术分享:纯Java的高性能长连接RPC解决方案

    超P7级!JAVA百万并发高性能网关设计 企业级CI & CD平台实践+企业级架构容器云平

    课程全程高能,直击超一线JAVA架构师的最前沿高级架构技术,课程内容包括了RPC核心框架剖析,注册中心深入剖析,消息队列企业级应用及原理剖析,分布式架构整体概括,企业级百万并发高性能网关设计实践,分布式架构...

    Sofa-rpc:SOFARPC是高性能,高扩展性的生产级Java RPC框架

    SOFARPC是一种高性能,高可扩展性的生产级Java RPC框架。 在Ant Financial中,SOFARPC已经使用了十多年,并且已经发展了五代。 SOFARPC致力于简化应用程序之间的RPC调用,并为应用程序提供方便,无代码入侵,稳定且...

    一款分布式的java游戏服务器框架,具备高性能、可伸缩、分布式、多线程等特点,java 8 +gradle 4.0

    一款高性能、实时通信、多进程的游戏解决方案 适用于手游、h5游戏等各类高性能游戏服务器的开发 功能特点 基于Disruptor消息队列设计的无锁并发模式 分布式(多进程)架构,几行代码实现一个功能服务器的搭建 多线程...

    Java思维导图xmind文件+导出图片

    分布式架构下的RPC解决方案 Zookeeper 分布式系统的基石 从0开始搭建3个节点额度zookeeper集群 深入分析Zookeeper在disconf配置中心的应用 基于Zookeeper Watcher 核心机制深入源码分析 Zookeeper集群升级、...

    java开源包4

    JSTUN 是另外一个用来解决穿越 NAT 进行通讯的 Java 解决方案,是 STUN 协议的 Java实现。 在浏览器上运行Java程序 Doppio DoppioVM 是一个可在浏览器上直接运行 Java 项目的系统,无需任何插件支持。目前它包含一...

    JAVA上百实例源码以及开源项目

    百度云盘分享 ... Java实现的FTP连接与数据浏览程序,实现实例化可操作的窗口。  部分源代码摘录:  ftpClient = new FtpClient(); //实例化FtpClient对象  String serverAddr=jtfServer.getText();...

    JAVA上百实例源码以及开源项目源代码

     Java实现的FTP连接与数据浏览程序,实现实例化可操作的窗口。  部分源代码摘录:  ftpClient = new FtpClient(); //实例化FtpClient对象  String serverAddr=jtfServer.getText(); //得到服务器地址  ...

    java开源包11

    JSTUN 是另外一个用来解决穿越 NAT 进行通讯的 Java 解决方案,是 STUN 协议的 Java实现。 在浏览器上运行Java程序 Doppio DoppioVM 是一个可在浏览器上直接运行 Java 项目的系统,无需任何插件支持。目前它包含一...

    java开源包6

    JSTUN 是另外一个用来解决穿越 NAT 进行通讯的 Java 解决方案,是 STUN 协议的 Java实现。 在浏览器上运行Java程序 Doppio DoppioVM 是一个可在浏览器上直接运行 Java 项目的系统,无需任何插件支持。目前它包含一...

    java开源包9

    JSTUN 是另外一个用来解决穿越 NAT 进行通讯的 Java 解决方案,是 STUN 协议的 Java实现。 在浏览器上运行Java程序 Doppio DoppioVM 是一个可在浏览器上直接运行 Java 项目的系统,无需任何插件支持。目前它包含一...

    java开源包101

    JSTUN 是另外一个用来解决穿越 NAT 进行通讯的 Java 解决方案,是 STUN 协议的 Java实现。 在浏览器上运行Java程序 Doppio DoppioVM 是一个可在浏览器上直接运行 Java 项目的系统,无需任何插件支持。目前它包含一...

    java开源包5

    JSTUN 是另外一个用来解决穿越 NAT 进行通讯的 Java 解决方案,是 STUN 协议的 Java实现。 在浏览器上运行Java程序 Doppio DoppioVM 是一个可在浏览器上直接运行 Java 项目的系统,无需任何插件支持。目前它包含一...

    java开源包8

    JSTUN 是另外一个用来解决穿越 NAT 进行通讯的 Java 解决方案,是 STUN 协议的 Java实现。 在浏览器上运行Java程序 Doppio DoppioVM 是一个可在浏览器上直接运行 Java 项目的系统,无需任何插件支持。目前它包含一...

    java开源包10

    JSTUN 是另外一个用来解决穿越 NAT 进行通讯的 Java 解决方案,是 STUN 协议的 Java实现。 在浏览器上运行Java程序 Doppio DoppioVM 是一个可在浏览器上直接运行 Java 项目的系统,无需任何插件支持。目前它包含一...

    java开源包1

    JSTUN 是另外一个用来解决穿越 NAT 进行通讯的 Java 解决方案,是 STUN 协议的 Java实现。 在浏览器上运行Java程序 Doppio DoppioVM 是一个可在浏览器上直接运行 Java 项目的系统,无需任何插件支持。目前它包含一...

    java开源包3

    JSTUN 是另外一个用来解决穿越 NAT 进行通讯的 Java 解决方案,是 STUN 协议的 Java实现。 在浏览器上运行Java程序 Doppio DoppioVM 是一个可在浏览器上直接运行 Java 项目的系统,无需任何插件支持。目前它包含一...

    java版商城源码下载-dawdler-series:dawdler-series是超高性能:rocket:rpc的一个解决方案,其特点简单、高效(运行,启

    是rpc的一个解决方案,其特点简单、高效、安全。包含了容器,客户端,mvc,前后端一致的校验框架,数据库事务传播方式(同spring一致)等等常用研发组件等. 为什么要重复的发明轮子?请看下面的dawdler之美,dawdler...

    最新Java面试题视频网盘,Java面试题84集、java面试专属及面试必问课程

    │ │ 9.JAVA并发编程之多线程并发同步业务场景与解决方案.wmv │ │ │ ├─10.微服务架构之Spring Cloud Eureka 场景分析与实战 │ │ 10.微服务架构之Spring Cloud Eureka 场景分析与实战.wmv │ │ │ ├─11....

Global site tag (gtag.js) - Google Analytics