首页 文章 精选 留言 我的

精选列表

搜索[Unicode通信],共10003篇文章
优秀的个人博客,低调大师

源码分析Dubbo网络通信篇NettyServer、HeaderExchangeServer

本文主要分析一下NettyServer,HeaderExchangeServer实现细节。 1、NettyServer NettyServer整个类图如下: 首先从全貌上大概看一下NettyServer对象所持有的属性: AbstractPeer private final ChannelHandler handler 事件处理Handler。 private volatile URL url 该协议的第一个服务提供者的URL, Server只需要用到 URL中的参数,与具体某一个服务没什么关系。 AbstractEndpoint private Codec2 codec 编码解码器。 private int timeout 超时时间 private int connectTimeout 连接超时时间 AbstractServer private InetSocketAddress localAddress :url host:port地址。 private InetSocketAddress bindAddress:如果是多网卡,并且指定了 bind.ip、bind.port,如果为空,与localAddress相同。 private int accepts : AbstractServer#accepts未使用到。 private int idleTimeout = 600; AbstractServer#accepts未使用到。 NettyServer private Map< String, Channel> channels:< ip:port, channel> 所有通道。 private ServerBootstrap bootstrap : netty 服务端启动器。 private io.netty.channel.Channel channel:服务端监听通道。 private EventLoopGroup bossGroup;Netty boss线程组(负责连接事件) private EventLoopGroup workerGroup : nety work线程组(负责IO事件) 1.1 NettyServer 构造方法 public NettyServer(URL url, ChannelHandler handler) throws RemotingException { super(url, ChannelHandlers.wrap(handler, ExecutorUtil.setThreadName(url, SERVER_THREAD_POOL_NAME))); } 直接调用父类的public AbstractServer(URL url, ChannelHandler handler)方法,从前面的文章中得知, ChannelHandlers.wrap方法会对ChannelHandler handler进行封装,主要是加入事件分发模式(Dispatch)。 1.1.1 AbstractServer构造方法 public AbstractServer(URL url, ChannelHandler handler) throws RemotingException { super(url, handler); // @1 localAddress = getUrl().toInetSocketAddress(); // @2 String bindIp = getUrl().getParameter(Constants.BIND_IP_KEY, getUrl().getHost()); int bindPort = getUrl().getParameter(Constants.BIND_PORT_KEY, getUrl().getPort()); if (url.getParameter(Constants.ANYHOST_KEY, false) || NetUtils.isInvalidLocalHost(bindIp)) { bindIp = NetUtils.ANYHOST; } bindAddress = new InetSocketAddress(bindIp, bindPort); // @3 this.accepts = url.getParameter(Constants.ACCEPTS_KEY, Constants.DEFAULT_ACCEPTS); this.idleTimeout = url.getParameter(Constants.IDLE_TIMEOUT_KEY, Constants.DEFAULT_IDLE_TIMEOUT); // @4 try { doOpen(); // @5 if (logger.isInfoEnabled()) { logger.info("Start " + getClass().getSimpleName() + " bind " + getBindAddress() + ", export " + getLocalAddress()); } } catch (Throwable t) { throw new RemotingException(url.toInetSocketAddress(), null, "Failed to bind " + getClass().getSimpleName() + " on " + getLocalAddress() + ", cause: " + t.getMessage(), t); } //fixme replace this with better method DataStore dataStore = ExtensionLoader.getExtensionLoader(DataStore.class).getDefaultExtension(); executor = (ExecutorService) dataStore.get(Constants.EXECUTOR_SERVICE_COMPONENT_KEY, Integer.toString(url.getPort())); } 代码@1:调用父类的构造方法,主要初始化AbstractPeer(channelHandler、url)和AbstractEndpoint(codec2、timeout、idleTimeout ) 代码@2:根据URL中的host与端口,创建localAddress。 代码@3:如果配置了< dubbo:parameter key = "bind.ip" value = ""/> 与 < dubbo:parameter key = "bind.port" />,则用该IP与端口创建bindAddress,通常用于多网卡,如果未配置,bindAddress与 localAddress绑定的IP与端口一样。 代码@4:初始化accepts与idleTimeout ,这两个参数未被其他地方使用。 代码@5,调用doOpen方法,正式在相应端口建立网络监听。 1.2、源码分析NettyServer#doOpen protected void doOpen() throws Throwable { NettyHelper.setNettyLoggerFactory(); bootstrap = new ServerBootstrap(); // @1 bossGroup = new NioEventLoopGroup(1, new DefaultThreadFactory("NettyServerBoss", true)); // @2 workerGroup = new NioEventLoopGroup(getUrl().getPositiveParameter(Constants.IO_THREADS_KEY, Constants.DEFAULT_IO_THREADS), new DefaultThreadFactory("NettyServerWorker", true)); // @3 final NettyServerHandler nettyServerHandler = new NettyServerHandler(getUrl(), this); // @4 channels = nettyServerHandler.getChannels(); bootstrap.group(bossGroup, workerGroup) // @5 .channel(NioServerSocketChannel.class) .childOption(ChannelOption.TCP_NODELAY, Boolean.TRUE) .childOption(ChannelOption.SO_REUSEADDR, Boolean.TRUE) .childOption(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT) .childHandler(new ChannelInitializer<niosocketchannel>() { @Override protected void initChannel(NioSocketChannel ch) throws Exception { NettyCodecAdapter adapter = new NettyCodecAdapter(getCodec(), getUrl(), NettyServer.this); ch.pipeline()//.addLast("logging",new LoggingHandler(LogLevel.INFO))//for debug .addLast("decoder", adapter.getDecoder()) .addLast("encoder", adapter.getEncoder()) .addLast("handler", nettyServerHandler); } }); // bind ChannelFuture channelFuture = bootstrap.bind(getBindAddress()); // @6 channelFuture.syncUninterruptibly(); channel = channelFuture.channel(); } 代码@1:创建Netty服务端启动帮助类ServerBootstrap. 代码@2:创建服务端Boss线程,线程名:.NettyServerBoss,主要负责客户端的连接事件,主从多Reactor线程模型中的主线程(连接事件)。 代码@3:创建服务端Work线程组,线程名:NettyServerWorker-序号,线程个数取自参数:iothreads,默认为(CPU核数+1)与32取小值,顾名思义,IO线程数,主要处理读写事件,编码、解码都在IO线程中完成。 代码@4:创建用户Handler,这里是NettyServerHandler。 代码@5:Netty启动的常规写法,关注如下内容: addLast("decoder", adapter.getDecoder()) : 添加解码器 addLast("encoder", adapter.getEncoder()) :添加编码器 addLast("handler", nettyServerHandler) :添加业务Handler。 这里简单介绍一下流程: 客户端建立与服务端连接,此时Boss线程的连接事件触发,建立TCP连接,并向IO线程注册该通道(Channel0)的读事件。 当客户端向服务端发送请求消息后,IO线程中的读事件触发,会首先调用adapter.getDecoder() 根据对应的请求协议(例如dubbo)从二进制流中解码出一个完整的请求对象,然后传入到业务handler,例如nettyServerHandler,执行相应的事件方法,例如recive方法。 当服务端向Channel写入响应结果时,首先编码器会按照协议编码成二进制流,供客户端解码。 如果对Netty想深入学习的话,请移步到作者的《源码分析Netty系列》 2、HeaderExchangeServer 根据 Dubbo 服务端初始化流程,我们可知,Dubbo 为了封装各种不同的网络实现客户端(netty、mina)等,引入了 Exchangers 层,存在 ExchangeServer,其实现 Server 并内部持有具体的 Server 实现端,例如 NettyServer。 接下来,我们重点来关注一下 HeaderExchangeServer. 核心属性如下: ScheduledExecutorService scheduled:心跳线程数,线程名称前缀,dubbo-remoting-server-heartbeat-thread-序号 private final Server server:具体的Server实现类,例如NettyServer。 private ScheduledFuture< ?> heartbeatTimer:心跳调度Future,可以通过future取消心跳等动作。 private int heartbeat:心跳间隔时间 private int heartbeatTimeout:心跳超时时间,至少为heartbeat的两倍 2.1 构造函数 public HeaderExchangeServer(Server server) { if (server == null) { throw new IllegalArgumentException("server == null"); } this.server = server; this.heartbeat = server.getUrl().getParameter(Constants.HEARTBEAT_KEY, 0); this.heartbeatTimeout = server.getUrl().getParameter(Constants.HEARTBEAT_TIMEOUT_KEY, heartbeat * 3); if (heartbeatTimeout &lt; heartbeat * 2) { throw new IllegalStateException("heartbeatTimeout &lt; heartbeatInterval * 2"); } startHeartbeatTimer(); } 说明,主要是通过heartbeat参数设置心跳间隔,如果不配置,则不启动心跳检测。从上面看来HeaderExchangeServer内部持有Server,并封装了心跳的功能,在这里就不细细分析了。 >作者介绍:丁威,《RocketMQ技术内幕》作者,RocketMQ 社区优秀布道师、CSDN2019博客之星TOP10,维护公众号:中间件兴趣圈目前已陆续发表源码分析Java集合、Java 并发包(JUC)、Netty、Mycat、Dubbo、RocketMQ、Mybatis等源码专栏。可以点击链接加入中间件知识星球 ,一起探讨高并发、分布式服务架构,交流源码。 </niosocketchannel>

优秀的个人博客,低调大师

ALink协议是最简单的通信协议

物联网全栈教程-从云端到设备(六) 关注零妖的微信公众号,获取第一手物联网的技术干货:LINGYAOIOT 一 物联网项目在开发初期,需要云端和设备端两个工种的工程师一起谈谈实现的技术细节。有一个叫作ALink协议的语言,成功解决了两个物种之间交流困难的世纪难题! ALink协议是针对物联网开发领域设计的一种数据交换规范。设备端按照这个简单的规范把数据组织一下发送给云端,云端工程师也懂这个简单的规范,可以直接拿这个数据进行处理。同时还解决了调试困难的痛点:云端工程师使用一个叫做MQTT客户端的电脑工具,就可以发送符合ALink协议的测试数据调试云端产品的代码;设备端工程师就可以在给单片机写代码的时候直接组织一个符合ALink协议的测试数据,从而不用依赖云端下发。 二 物联网将物理世界的万物接入网络并通过整合各类服务实现智能化。“物”(T

优秀的个人博客,低调大师

Spring Cloud微服务实战(五)-应用通信

订单服务源码https://github.com/Wasabi1234/SpringCloud_OrderDemo 商品服务源码https://github.com/Wasabi1234/SpringCloud_ProductDemo 1 HTTP vs RPC 5-2 RestTemplate的三种使用方式 3 负载均衡器:Ribbion 4 追踪源码自定义负载均衡策略 command+option+B进入其实现类 再跟进到 LoadBalancerClient 中 RibbonLoadBalancerClient#choose() RibbonLoadBalancerClient#getServer(ILoadBalancer loadBalancer) ILoadBalancer RibbonLoadBalancerClient#getServer(ILoadBalancer loadBalancer) ILoadBalancer#getAllServers(),并进入 启动两个 Product 服务 product#1 product#2 再 debug 启动 Order 服务 三个服务成功注册 在此打断点,并 debug 运行 获取服务列表 再看看其负载均衡策略 可见默认即轮询 负载均衡请求 请求到2 请求到1 的确是轮询请求 通过启动日志也可看出具体使用的策略 为了检验是否为轮询,在此打断点 符合预期,确实为轮询 如果希望使用其他负载均衡规则该咋办呢,看官网文档 如希望用随机规则替代默认的轮询规则 配置全路径名 成功替换默认规则 5-5 Feign的使用Feign是一个声明式的Web服务客户端。这使得Web服务客户端的写入更加方便 要使用Feign创建一个界面并对其进行注释。它具有可插入注释支持,包括Feign注释和JAX-RS注释。Feign还支持可插拔编码器和解码器。Spring Cloud增加了对Spring MVC注释的支持,并使用Spring Web中默认使用的HttpMessageConverters。Spring Cloud集成Ribbon和Eureka以在使用Feign时提供负载均衡的http客户端。 如何加入Feign 要在您的项目中包含Feign,请使用组org.springframework.cloud和工件ID spring-cloud-starter-feign的启动器 在启动类添加注解@EnableFeignClients 可以在@EnableFeignClients属性defaultConfiguration中以与上述相似的方式指定默认配置。不同之处在于,此配置将适用于所有feigh客户端。 调用商品服务的目标接口 声明调用的服务接口方法 @FeignClient name属性为某所需调用的某个服务的接口 在@FeignClient注释中,String值(以上“存储”)是一个任意的客户端名称,用于创建Ribbon负载平衡器,还可以使用url属性(绝对值或只是主机名)指定URL。应用程序上下文中的bean的名称是该接口的完全限定名称。要指定自己的别名值,可以使用@FeignClient注释的qualifier值。 添加@FeignClient注解 5-6 获取商品列表(Feign) 5-7 扣库存(Feign) 5-8 整合接口打通下单流程(Feign) 5-9 项目改造成多模块 5-10 同步or异步 5-11 RabbitMQ的安装 5-12 微服务,Docker和DevOps

优秀的个人博客,低调大师

新手练练----也做即时通信系统(2)

继续完善功能,后面的路还很长。。。 今天还用这个小示例程序给别人讲了次课,发现自己的演讲天赋还是不错的,讲完后闻及感受,说我讲的听通俗易懂的,例子比喻也很不错,开心,呵呵。。。 clientMain.java out.println(this.clientCmd); this.serverMsg = in.readLine(); strTmp = this.serverMsg.split(spliter); if(strTmp[0].equals(new String("getbuddys"))) { this.creatBuddyList(strTmp); //用服务器传过来的好友数据建列表 } private void creatBuddyList(String[] buddys) { DefaultMutableTreeNode buddy = null; for(int i=1;i<buddys.length;i++) { buddy = new DefaultMutableTreeNode(buddys[i]); root.add(buddy); } } JPanel jPanel1 = new JPanel(); DefaultMutableTreeNode root = new DefaultMutableTreeNode("我的好友"); JTree buddyTree = new JTree(root); JScrollPane jScrollPane1 = new JScrollPane(buddyTree); SeverThread.java else if(msgTmp[0].equals(new String("getbuddys"))) {//获取好友列表 String clientID = msgTmp[1];//获取客户id号 String buddyName; com.vitamin.DataAccess.DBbase myDb = new DBbase(); this.sql = "select * from buddies where user = "+clientID; this.rs = myDb.executeQuery(this.sql); while(rs.next()) { buddyName = rs.getString("buddy"); this.serverMsg += buddyName; } this.out.println(this.serverMsg); } 运行结果: 6-22-2.GIF 本文转自Phinecos(洞庭散人)博客园博客,原文链接:http://www.cnblogs.com/phinecos/archive/2006/06/22/433350.html,如需转载请自行联系原作者

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

用户登录
用户注册