转载自:https://blog.csdn.net/u010853261/article/details/62043709 https://blog.csdn.net/u010412719/article/details/78107741
Reactor线程模型
Reactor线程模型有三种
单线程模型
多线程模型
主从Reactor线程模型
关于这三种线程模型的原型,可以参看:https://blog.csdn.net/u010853261/article/details/55805216
NioEventLoopGroup与Reactor线程模型的对应
前面介绍了Reactor线程模型的原型实现,那么NIOEventLoopGroup是怎么与Reactor关联在一起的呢?其实NIOEventLoopGroup就是一个线程池实现,通过设置不同的NIOEventLoopGroup方式就可以对应三种不同的Reactor线程模型。 这里我只给出服务端的配置,对于客户端都是一样的。 单线程模型
EventLoopGroup bossGroup = new NioEventLoopGroup(1 );
ServerBootstrap b = new ServerBootstrap();
b.group (bossGroup)
.channel(NioServerSocketChannel.class );
上面实例化了一个NIOEventLoopGroup,构造参数是1表示是单线程的线程池。然后接着调用 b.group(bossGroup)
设置了服务器端的 EventLoopGroup. 当传入一个 group 时, 那么 bossGroup 和 workerGroup 就是同一个 NioEventLoopGroup 了. 这时候呢, 因为 bossGroup 和 workerGroup 就是同一个 NioEventLoopGroup, 并且这个 NioEventLoopGroup 只有一个线程, 这样就会导致 Netty 中的 acceptor 和后续的所有客户端连接的 IO 操作都是在一个线程中处理的. 那么对应到 Reactor 的线程模型中, 我们这样设置 NioEventLoopGroup 时, 就相当于 Reactor 单线程模型.
多线程模型
EventLoopGroup bossGroup = new NioEventLoopGroup(1 );
EventLoopGroup workerGroup = new NioEventLoopGroup();
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class);
//...
bossGroup 中只有一个线程, 在workerGroup线程池中没有指定线程数量,所以默认是 CPU 核心数乘2, 因此对应的到 Reactor 线程模型中, 这样设置的 NioEventLoopGroup 其实就是 Reactor 多线程模型.
主从Reactor线程模型
EventLoopGroup bossGroup = new NioEventLoopGroup(4 );
EventLoopGroup workerGroup = new NioEventLoopGroup();
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class);
//...
Netty 的服务器端的 acceptor 阶段, 没有使用到多线程, 因此上面的主从多线程模型 在 Netty 的服务器端是不存在的. 服务器端的 ServerSocketChannel 只绑定到了 bossGroup 中的一个线程, 因此在调用 Java NIO 的 Selector.select 处理客户端的连接请求时, 实际上是在一个线程中的, 所以对只有一个服务的应用来说, bossGroup 设置多个线程是没有什么作用的, 反而还会造成资源浪费。
Netty的线程模型
Netty的线程模型并不是一成不变的,它实际取决于用户的启动参数配置。Netty的多线程编程最佳实践如下: 1)创建两个NioEventLoopGroup,用于逻辑隔离NIO Acceptor和NIO I/O线程。 2)尽量不要在ChannelHandler中启动用户线程(解码后用于将POJO消息派发到后端业务线程的除外)。 3)解码要放在NIO线程调用的解码Handler中进行,不要切换到用户线程中完成消息的解码。 4)如果业务逻辑操作非常简单,没有复杂的业务逻辑计算,没有可能会导致线程被阻塞的磁盘操作、数据库操作、网路操作等,可以直接在NIO线程上完成业务逻辑编排,不需要切换到用户线程。 5)如果业务逻辑处理复杂,不要在NIO线程上完成,建议将解码后的POJO消息封装成Task,派发到业务线程池中由业务线程执行,以保证NIO线程尽快被释放,处理其他的I/O操作。
NioEventLoopGroup
Netty内部都是通过线程在处理各种数据,EventLoopGroup就是用来管理调度他们的,注册Channel,管理他们的生命周期,下面就来看看EventLoopGroup是怎样工作的(基于4.1.11.Final源码)。
public class NioEventLoopGroup extends MultithreadEventLoopGroup {
/**
* Create a new instance using the default number of threads, the default {@link ThreadFactory} and
* the {@link SelectorProvider} which is returned by {@link SelectorProvider#provider()}.
*/
public NioEventLoopGroup () {
this (0 );
}
/**
* Create a new instance using the specified number of threads, {@link ThreadFactory} and the
* {@link SelectorProvider} which is returned by {@link SelectorProvider#provider()}.
*/
public NioEventLoopGroup (int nThreads) {
this (nThreads, (Executor) null );
}
/**
* Create a new instance using the specified number of threads, the given {@link ThreadFactory} and the
* {@link SelectorProvider} which is returned by {@link SelectorProvider#provider()}.
*/
public NioEventLoopGroup (int nThreads, ThreadFactory threadFactory) {
this (nThreads, threadFactory, SelectorProvider.provider());
}
public NioEventLoopGroup (int nThreads, Executor executor) {
this (nThreads, executor, SelectorProvider.provider());
}
public NioEventLoopGroup (int nThreads, ThreadFactory threadFactory,
final SelectorProvider selectorProvider, final SelectStrategyFactory selectStrategyFactory) {
super (nThreads, threadFactory, selectorProvider, selectStrategyFactory, RejectedExecutionHandlers.reject());
}
NioEventLoopGroup会调用其父类MultithreadEventLoopGroup的构造函数:
/**
* @see MultithreadEventExecutorGroup#MultithreadEventExecutorGroup(int, Executor, Object...)
*/
protected MultithreadEventLoopGroup (int nThreads, Executor executor, Object... args) {
super (nThreads == 0 ? DEFAULT_EVENT_LOOP_THREADS : nThreads, executor, args);
}
这里,内部线程数DEFAULT_EVENT_LOOP_THREADS
的大小是: DEFAULT_EVENT_LOOP_THREADS = Math.max(1, SystemPropertyUtil.getInt( "io.netty.eventLoopThreads", NettyRuntime.availableProcessors() * 2));
MultithreadEventLoopGroup的父类是MultithreadEventExecutorGroup:
protected MultithreadEventExecutorGroup (int nThreads, Executor executor,
EventExecutorChooserFactory chooserFactory, Object... args) {
if (nThreads <= 0 ) {
throw new IllegalArgumentException(String.format("nThreads: %d (expected: > 0)" , nThreads));
}
if (executor == null ) {
executor = new ThreadPerTaskExecutor(newDefaultThreadFactory());
}
children = new EventExecutor[nThreads];
for (int i = 0 ; i < nThreads; i ++) {
boolean success = false ;
try {
children[i] = newChild(executor, args);
success = true ;
} catch (Exception e) {
throw new IllegalStateException("failed to create a child event loop" , e);
} finally {
}
}
chooser = chooserFactory.newChooser(children);
final FutureListener terminationListener = new FutureListener() {
@Override
public void operationComplete (Future future) throws Exception {
if (terminatedChildren.incrementAndGet() == children.length) {
terminationFuture.setSuccess(null );
}
}
};
for (EventExecutor e: children) {
e.terminationFuture().addListener(terminationListener);
}
Set childrenSet = new LinkedHashSet(children.length);
Collections.addAll(childrenSet, children);
readonlyChildren = Collections.unmodifiableSet(childrenSet);
}
children 是EventExecutor数组对象,其大小是 nThreads, 这样就构成了一个线程池,里面存放的是通过NioEventLoopGroup的newChild方法生成的NioEventLoop对象:
@Override
protected EventLoop newChild (Executor executor, Object... args) throws Exception {
return new NioEventLoop(this , executor, (SelectorProvider) args[0 ],
((SelectStrategyFactory) args[1 ]).newSelectStrategy(), (RejectedExecutionHandler) args[2 ]);
}
注意到这里,children中所有的线程公用executor
,SelectorProvider
,SelectStrategyFactory
以及RejectedExecutionHandler
。SelectorProvider是通过SelectorProvider.provider()
获取的,而这个方法返回的是一个单例SelectorProvider。至此,Group和内部的Loop对象以及Executor就创建完毕。
NioEventLoop
NioEventLoop继承于SingleThreadEventLoop, 而SingleThreadEventLoop又继承于SingleThreadEventExecutor,SingleThreadEventExecutor继承于AbstractScheduledEventExecutor。 SingleThreadEventExecutor是Netty中对本地线程的抽象, 它内部有一个Thread thread属性, 存储了一个本地Java线程。因此可以认为, 一个NioEventLoop其实和一个特定的线程绑定, 并且在其生命周期内, 绑定的线程都不会再改变。 在AbstractScheduledEventExecutor中,Netty 实现了NioEventLoop的schedule功能, 即可以通过调用一个NioEventLoop 实例的schedule方法来运行一些定时任务. 而在SingleThreadEventLoop中, 又实现了任务队列的功能, 通过它, 可以调用一个NioEventLoop实例的execute方法来向任务队列中添加一个 task,并由 NioEventLoop 进行调度执行。 通常来说, NioEventLoop 肩负着两种任务, 第一个是作为IO线程, 执行与 Channel 相关的IO操作, 包括调用 select 等待就绪的IO事件、读写数据与数据的处理等; 而第二个任务是作为任务队列, 执行taskQueue中的任务, 例如用户调用eventLoop.schedule提交的定时任务也是这个线程执行的。 下面是它的具体的继承关系图: 它实现了EventLoop接口、EventExecutorGroup接口和ScheduledExecutorService接口,正是因为这种设计,导致NioEventLoop和其父类功能实现非常复杂。 作为NIO框架的Reactor线程,NioEventLoop需要处理网络I/O读写事件,因此它必须聚合一个Selector对象。在NioEventLoop构造时将创建并打开一个新的Selector。Netty对Selector的selectedKeys进行了优化,用户可以通过io.netty.noKeySetOptimization
开关决定是否启用该优化项。默认不打开selectedKeys优化功能。
对于NioEventLoop的实例化,基本就是在NioEventLoopGroup.newChild()
中调用的:
@Override
protected EventLoop newChild (Executor executor, Object... args) throws Exception {
return new NioEventLoop(this , executor, (SelectorProvider) args[0 ],
((SelectStrategyFactory) args[1 ]).newSelectStrategy(), (RejectedExecutionHandler) args[2 ]);
}
NioEventLoop(NioEventLoopGroup parent , Executor executor, SelectorProvider selectorProvider,
SelectStrategy strategy, RejectedExecutionHandler rejectedExecutionHandler) {
super(parent , executor, false , DEFAULT_MAX_PENDING_TASKS, rejectedExecutionHandler);
if (selectorProvider == null ) {
throw new NullPointerException("selectorProvider" );
}
if (strategy == null ) {
throw new NullPointerException("selectStrategy" );
}
provider = selectorProvider;
final SelectorTuple selectorTuple = openSelector();
selector = selectorTuple.selector;
unwrappedSelector = selectorTuple.unwrappedSelector;
selectStrategy = strategy;
}
来看NioEventLoop的run:
protected void run () {
/** 死循环:NioEventLoop 事件循环的核心就是这里! */
for (;;) {
try {
switch (selectStrategy.calculateStrategy(selectNowSupplier, hasTasks())) {
case SelectStrategy.CONTINUE:
continue ;
case SelectStrategy.SELECT:
select(wakenUp.getAndSet(false ));
if (wakenUp.get()) {
selector.wakeup();
}
default :
}
cancelledKeys = 0 ;
needsToSelectAgain = false ;
final int ioRatio = this .ioRatio;
if (ioRatio == 100 ) {
try {
processSelectedKeys();
} finally {
runAllTasks();
}
} else {
final long ioStartTime = System.nanoTime();
try {
processSelectedKeys();
} finally {
final long ioTime = System.nanoTime() - ioStartTime;
runAllTasks(ioTime * (100 - ioRatio) / ioRatio);
}
}
} catch (Throwable t) {
handleLoopException(t);
}
}
}
上面函数中的一个死循环 for(;;)
就是NioEventLoop事件循环执行机制。下面对上面过程进行详解,分两步:IO事件轮询、IO事件的处理。 1.IO事件轮询 首先, 在run()
方法中, 第一步是调用hasTasks()
方法来判断当前任务队列中是否有任务:
protected boolean hasTasks () {
assert inEventLoop();
return !taskQueue.isEmpty();
}
这个方法很简单, 仅仅是检查了一下 taskQueue 是否为空。至于 taskQueue 是什么呢, 其实它就是存放一系列的需要由此 EventLoop 所执行的任务列表。 1)当 taskQueue 不为空时, hasTasks() 就会返回TRUE,那么selectStrategy.calculateStrategy()
的实现里面就会执行selectSupplier.get()
而get()
方法里面会调用 selectNow();
:
void selectNow() throws IOException {
try {
selector.selectNow();
} finally {
if (wakenUp.get ()) {
selector.wakeup();
}
}
}
这个 selector 字段正是 Java NIO 中的多路复用器 Selector(比如KQueueSelectorImpl实例)。selector.selectNow()
立即返回当前就绪的IO事件的个数,如果存在IO事件,那么在switch 语句中就会直接执行 default,直接跳出switch语句,如果不存在,就是返回0,对应于continue,忽略此次循环。 2)当taskQueue为空时,selectStrategy.calculateStrategy()
就会返回SelectStrategy.SELECT
,对于switch case语句就是执行select()
函数,阻塞等待IO事件就绪。 selector.select()
是选择一些I/O操作已经准备好的管道。每个管道对应着一个key。这个方法是一个阻塞的选择操作。当至少有一个通道被选择时才返回。当这个方法被执行时,当前线程是允许被中断的。selector.selectNow()
与selector.select()
的区别在于,是非阻塞的,即当前操作即使没有通道准备好也是立即返回,只是返回的是0,不会阻塞当前线程.
2.IO事件处理 在 NioEventLoop.run()
方法中, 第一步是通过 select/selectNow 调用查询当前是否有就绪的 IO 事件. 那么当有 IO 事件就绪时, 第二步自然就是处理这些 IO 事件啦.首先让我们来看一下 NioEventLoop.run 中循环的剩余部分(核心部分):
final int ioRatio = this .ioRatio;
if (ioRatio == 100 ) {
processSelectedKeys();
runAllTasks();
} else {
final long ioStartTime = System.nanoTime();
processSelectedKeys();
final long ioTime = System.nanoTime() - ioStartTime;
runAllTasks(ioTime * (100 - ioRatio) / ioRatio);
}
上面列出的代码中, 有两个关键的调用, 第一个是 processSelectedKeys()
调用, 根据字面意思, 我们可以猜出这个方法肯定是查询就绪的 IO 事件, 然后处理它; 第二个调用是 runAllTasks()
, 这个方法我们也可以一眼就看出来它的功能就是运行 taskQueue 中的任务. ioRatio表示的是此线程分配给 IO 操作所占的时间比(即运行 processSelectedKeys 耗时在整个循环中所占用的时间). 例如 ioRatio 默认是 50, 则表示 IO 操作和执行 task 的所占用的线程执行时间比是 1 : 1. 当知道了 IO 操作耗时和它所占用的时间比, 那么执行 task 的时间就可以很方便的计算出来了。 当ioRatio为100时, Netty 就不考虑 IO 耗时的占比, 而是分别调用 processSelectedKeys()、runAllTasks(); 而当 ioRatio 不为 100时, 则执行到 else 分支, 在这个分支中, 首先记录下 processSelectedKeys() 所执行的时间(即 IO 操作的耗时), 然后根据公式, 计算出执行 task 所占用的时间, 然后以此为参数, 调用 runAllTasks().
你可能感兴趣的:(#,【Netty4】)
netty4源码阅读与分析---netty线程模型
红尘之一骑
java NIO netty源码阅读与分析
本文主要说下我自己对netty线程模型的理解,以及这样的线程模型的好处。通俗的来讲,netty的线程模型描述的就是老板和员工的故事。老板(通常情况下是一个老板)负责接活,与客户沟通,协调(netty的accept),谈成后(通道建立),他需要从员工中选出一位员工来负责处理后续具体的事宜(worker线程,这里我们有16位员工,编号1-16),员工做事时按照任务的先后顺序进行处理,这样可以避免错乱,
IO模型及Netty线程模型
一指禅心
IO/Netty netty 网络
Netty简介1.简介版本:Netty4.XNetty是基于NIO的异步网络通信框架能快速的搭建高性能易扩展的网络应用程序(服务器/客户端)2.特征设计适用于各种传输类型的统一API-阻塞和非阻塞套接字基于灵活且可扩展的事件模型,可将关注点明确分离高度可定制的线程模型-单线程,一个或多个线程池真正的无连接数据报套接字支持(从3.1开始)性能更高的吞吐量,更低的延迟减少资源消耗减少不必要的内存复制安
docker elasticsearch8启动失败
沙漠炫神
docker 运维 elasticsearch elk
dockerelasticsearch8.12.0启动后提示这个,并且始终无法访问localhost:9200receivedplaintexthttptrafficonanhttpschannel,closingconnectionNetty4HttpChannel解决方案:重新创建elasticsearch容器,加上-expack.security.enabled=false满血复活
19.kubernetes上部署Redis主从并实现读写分离
CodingDemo
Kubernetes入门实战 kubernetes redis 容器
介绍部署Redis主从首先需要确定Redis的master节点和slave节点,由于Kubernetes上的Pod默认是没有固定IP的,这里使用HeadlessServices结合StatefulSet,为每个Redis服务的Pod分配一个固定的DNS记录,就可以达到明确主从节点的目的camellia-redis-proxy是一款高性能的redis代理,使用netty4开发,主要特性如下:支持代理
Netty导读
天罚神
netty4 java nio
Netty导读一、一些资讯01Netty4、5版本02NettyNio03常见的使用场景二、阅读建议01Java多线程编程02项目实践03源码阅读策略一、一些资讯01Netty4、5版本现在稳定推荐使用的主流版本还是Netty4,Netty5中使用了ForkJoinPool,增加了代码的复杂度,但是对性能的改善却不明显,所以这个版本不推荐使用,官网也没有提供下载链接。Netty是一个高性能、异步事
「高并发通信框架Netty4 源码解读(二)」NIO的前世今生及核心概念
源码之路
Netty底层使用的是JavaNIO,是JDK自带的,NIO三个核心概念包括Buffer、Channel和Selector,我们解NIO的前世今生。0.前言计算机毫无用处,除了答案什么也没有。——毕加索本专题介绍了Java平台上的高级输入/输出,具体点说,就是使用Java2标准版(J2SE)软件开发包(SDK)1.4及以后版本进行的输入/输出。J2SE1.4版代号Merlin,包含可观的I/O新特
Dubbo源码解析第一期:如何使用Netty4构建RPC
飞向札幌的班机
dubbo dubbo rpc 网络协议
一、背景早期学习和使用Dubbo的时候(那时候Dubbo还没成为Apache顶级项目),写过一些源码解读,但随着Dubbo发生了翻天覆地的变化,那些文章早已过时,所以现在计划针对最新的ApacheDubbo源码来进行“阅读理解”,希望和大家一起再探Dubbo的实现。由于能力有限,如果文章有错误的地方,欢迎大家留言指正。本期的主题是Dubbo如何使用Netty4构建RPC来通讯。二、Server端视
「高并发通信框架Netty4 源码解读(六)」NIO通道之Socket通道
源码之路
socket网络通信太重要了。也是本专题的重中之重,所以小编单独写一篇文章来介绍Socket通道。Socket通道有与文件通道不同的特征。新的socket通道类可以运行非阻塞模式并且是可选择的。这两个性能可以激活程序(如网络服务器和中间件组件)巨大的可伸缩性和灵活性。本节中我们会看到,再也没有为每个socket连接使用一个线程的必要了,也避免了管理大量线程所需的上下文交换总开销。借助新的NIO类,
Elasticsearch启动后访问9200失败
诸葛苍穹
GIS开发 elasticsearch 大数据
receivedplaintexthttptrafficonanhttpschannel,closingconnectionNetty4HttpChannelreceivedplaintexthttptrafficonanhttpschannel,closingconnectionNetty4HttpChannel{localAddress=/[0:0:0:0:0:0:0:1]:9200,remo
java 从零开始手写 RPC (04) -序列化
老马啸西风2020
序列化java从零开始手写RPC(01)基于socket实现java从零开始手写RPC(02)-netty4实现客户端和服务端java从零开始手写RPC(03)如何实现客户端调用服务端?前面几节我们实现了最基础的客户端调用服务端,这一节来学习一下通讯中的对象序列化。fastjson为什么需要序列化netty底层都是基于ByteBuf进行通讯的。前面我们通过编码器/解码器专门为计算的入参/出参进行处
Netty源码分析----NioEventLoop之任务队列
_六道木
(*文章基于Netty4.1.22版本)这篇文章主要分析一下NioEventLoop中任务队列相关的代码源码分析taskQueueexecute方法调用的时候或者执行完startThread方法,会调用addTask添加任务protectedvoidaddTask(Runnabletask){if(!offerTask(task)){reject(task);}}finalbooleanoffer
netty4.x学习四http服务器的搭建
昨日已逝去
通过学习了解到netty可以像tomcat一样搭建一个httpServer服务器,这里简单的实现一下。首先,我们介绍一下httpRequest认识Http请求在动手写Netty框架之前,我们先要了解http请求的组成,如下图:image.pngHTTPRequest第一部分是包含的头信息HttpContent里面包含的是数据,可以后续有多个HttpContent部分LastHttpContent标
netty4服务器发送消息,netty 服务器端主动发消息给客户端
枯叶蚊
netty4服务器发送消息
netty服务器端主动发消息给客户端内容精选换一换客户在云容器引擎上搭建服务为手机应用订阅信息。首先客户端会向部署在CCE集群上的服务端(redis)发起请求,成功订阅信息服务。后继服务端侧会定时推送订阅的消息给客户端。服务端部署后,第一次订阅信息通信正常,但是10分钟内没有数据通信,客户端就接收不到订阅信息了。客户端第一次向服务端建立通信链接的时候(订阅),会主动开放对服务端的通信权限设备接入到
Netty 源码分析 —— NIO 基础(五)之零拷贝与其它源码解读
小安的大情调
我准备战斗到最后,不是因为我勇敢,是我想见证一切。--双雪涛《猎人》[TOC]Thinking一个技术,为什么要用它,解决了那些问题?如果不用会怎么样,有没有其它的解决方法?对比其它的解决方案,为什么最终选择了这种,都有何利弊?你觉得项目中还有那些地方可以用到,如果用了会带来那些问题?这些问题你又如何去解决的呢?本文基于Netty4.1.45.Final-SNAPSHOT1、NIO堆外内存与零拷贝
java 从零开始手写 RPC (06) reflect 反射实现通用调用之客户端
老马啸西风2020
通用调用java从零开始手写RPC(01)基于socket实现java从零开始手写RPC(02)-netty4实现客户端和服务端java从零开始手写RPC(03)如何实现客户端调用服务端?java从零开始手写RPC(04)-序列化上一篇我们介绍了,如何实现基于反射的通用服务端。这一节我们来一起学习下如何实现通用客户端。因为内容较多,所以拆分为2个部分。基本思路所有的方法调用,基于反射进行相关处理实
java netty实现tcp协议_Netty实现网络通信
何为自律
java netty实现tcp协议
Netty是一个JavaNIO客户端服务器框架,使用它可以快速简单地开发网络应用程序,比如服务器和客户端的协议。Netty大大简化了网络程序的开发过程比如TCP和UDP的socket服务的开发。更多关于Netty的知识,可以参阅《Netty4.x用户指南》(https://github.com/waylau/netty-4-user-guide)下面,就基于Netty快速实现一个聊天小程序。准备J
Netty内存模型-PoolChunk
薛定谔的猫Plus
1概述从netty4开始,netty加入了内存池管理,采用内存池管理比普通的newByteBuf性能提高了数十倍。首先介绍PoolChunk2原理PoolChunk主要负责内存块的分配与回收,首先来看看两个重要的术语。page:可以分配的最小的内存块单位。chunk:一堆page的集合。image上图中是一个默认大小的chunk,由2048个page组成了一个chunk,一个page的大小为819
netty4.x使用小记
九号自行车司机
HelloWorld引入netty包io.nettynetty-all4.1.33.Final实现handlerimportio.netty.buffer.ByteBuf;importio.netty.channel.ChannelHandlerContext;importio.netty.channel.ChannelInboundHandlerAdapter;/***Handlesaserve
Netty4-Netty入门-模型理论
最好束手就擒
Java java 开发语言 netty
Netty官网说明Netty是由JBOSS提供的一个Java开源框架。Netty提供异步的、基于事件驱动的网络应用程序框架,用以快速开发高性能、高可靠性的网络IO程序Netty可以帮助你快速、简单的开发出一个网络应用,相当于简化和流程化了NIO的开发过程Netty是目前最流行的NIO框架,Netty在互联网领域、大数据分布式计算领域、游戏行业、通信行业等获得了广泛的应用,知名的Elasticsea
springboot整合grpc
向大阳在此
java protobuf spring boot grpc
springboot整合grpc一、简介二、proto3三、SpringBoot整合Grpc)一、简介GRPC是google开源的一个高性能、跨语言的RPC框架,基于HTTP2协议,基于protobuf3.x,基于Netty4.x+。对于开发者而言:1)需要使用protobuf定义接口,即.proto文件2)然后使用compile工具生成特定语言的执行代码,比如JAVA、C/C++、Python等
Spring boot 整合grpc 运用
何xiao树
spring boot qt 后端
文章目录GRPC基础概念:ProtocolBuffers:proto基础语法:调用类型:Springboot整合grpc项目结构:整合代码:父pomproto模块服务端:客户端:实际调用:原生集成GRPC基础概念:GRPC是google开源的一个高性能、跨语言的RPC框架,基于HTTP2协议,基于protobuf3.x,基于Netty4.x.ProtocolBuffers:一个跨语言、跨平台的具有
【手撸RPC框架】SpringBoot+Netty4实现RPC框架
最怕的其实是孤单
【手撸RPC框架】SpringBoot+Netty4实现RPC框架线程模型Netty高性能架构设计简单了解React线程模型,参考文章【五分钟快速理解Reactor模型】举例说明:Reactor的三种线程模型线程模型1:传统阻塞I/O服务模型模型特点:采用阻塞IO模式获取输入的数据每个链接都需要独立的线程完成数据的输入,业务处理、数据返回。问题分析:当并发数很大,就会创建大量的线程,占用很大系统资
基础知识之什么是I/O
燕然一勒
操作系统 操作系统 linux unix I/O
本文内容来之书籍《Netty4核心原理与手写RPC框架实战》1.什么是I/O我们都知道在UNIX世界里一切皆文件,而文件是什么呢?文件就是一串二进制流而已,其实不管是Socket,还是FIFO(FirstInputFirstOutput,先进先出队列))、管道、终端。对计算机来说,一切都是文件,一切都是流。在信息交换的过程中,计算机都是对这些流进行数据的收发操作,简称为I/O操作(Inputand
「高并发通信框架Netty4 源码解读(七)」NIO通道之Selector选择器
源码之路
选择器提供选择执行已经就绪的任务的能力,这使得多元I/O成为可能。就绪选择和多元执行使得单线程能够有效率地同时管理多个I/O通道(channels)。C/C++代码的工具箱中,许多年前就已经有select()和poll()这两个POSIX(可移植性操作系统接口)系统调用可供使用了。许过操作系统也提供相似的功能,但对Java程序员来说,就绪选择功能直到JDK1.4才成为可行的方案。对于主要的工作经验
Netty自带的心跳机制——IdleStateHandler
钱多多_qdd
netty
一、前言Netty提供了对心跳机制的天然支持,心跳可以检测远程端是否存活,或者活跃。今天我们就一起初识一下Netty4的心跳机制。Netty4.0提供了一个类,名为IdleStateHandler,这个类可以对三种类型的心跳检测。二、项目中的应用上述是项目中应用到的心跳机制关键代码,主要步骤:在pipeline中添加IdleStateHandler;在IdleStateHandler后面再添加Id
java智慧停车系统源码
IT课程分享
java 开发语言
java智慧停车系统源码技术架构:后端开发语言java,采用最新springcloudalibaba版本开发,框架oauth2+springboot2.6(可升级到3.0)+doubble3.2,使用nacos,seata,sentinel,,数据库mysql/mongodb/redis/可追加oceanbase和tidb超大型数据库,即时通讯底层框架netty4,安卓和ios均为原生开发,后台管
java写jvm_用Java实现JVM第一章《命令行工具》
半木zxy
java写jvm
小傅哥|https://bugstack.cn沉淀、分享、成长,专注于原创专题案例,以最易学习编程的方式分享知识,让自己和他人都能有所收获。目前已完成的专题有;Netty4.x实战专题案例、用Java实现JVM、基于JavaAgent的全链路监控、手写RPC框架、架构设计专题案例、源码分析等。你用剑、我用刀,好的代码都很烧,望你不吝出招!一、背景描述为了更好的学习jvm阅读过《Java虚拟机规范》
教你用 Netty 实现一个简单的 RPC!
zl1zl2zl3
netty RPC Netty rpc
众所周知,dubbo底层使用了Netty作为网络通讯框架,而Netty的高性能我们之前也分析过源码,对他也算还是比较了解了。今天我们就自己用Netty实现一个简单的RPC框架。1需求模仿dubbo,消费者和提供者约定接口和协议,消费者远程调用提供者,提供者返回一个字符串,消费者打印提供者返回的数据。底层网络通信使用Netty4.1.16。2设计创建一个接口,定义抽象方法。用于消费者和提供者之间的约
java websocket netty_用SpringBoot集成Netty开发一个基于WebSocket的聊天室
王知遇
java websocket netty
前言基于SpringBoot,借助Netty控制长链接,使用WebSocket协议做一个实时的聊天室。项目效果项目统一登录路径:http://localhost:8080/chat/netty用户名随机生成,离线调用异步方法,数据写操作,登录显示历史聊天消息GitHub项目名:InChat项目地址:https://github.com/UncleCatMy...项目介绍:基于Netty4与Spri
java 从零开始手写 RPC (01) 基于 websocket 实现
老马啸西风2020
RPC解决的问题RPC主要是为了解决的两个问题:解决分布式系统中,服务之间的调用问题。远程调用时,要能够像本地调用一样方便,让调用者感知不到远程调用的逻辑。这一节我们来学习下如何基于websocket实现最简单的rpc调用,后续会实现基于netty4的版本。开源地址:https://github.com/houbb/rpc完整流程在这里插入图片描述其中左边的Client,对应的就是前面的Servi
Java实现的基于模板的网页结构化信息精准抽取组件:HtmlExtractor
yangshangchuan
信息抽取 HtmlExtractor 精准抽取 信息采集
HtmlExtractor是一个Java实现的基于模板的网页结构化信息精准抽取组件,本身并不包含爬虫功能,但可被爬虫或其他程序调用以便更精准地对网页结构化信息进行抽取。
HtmlExtractor是为大规模分布式环境设计的,采用主从架构,主节点负责维护抽取规则,从节点向主节点请求抽取规则,当抽取规则发生变化,主节点主动通知从节点,从而能实现抽取规则变化之后的实时动态生效。
如
java编程思想 -- 多态
百合不是茶
java 多态详解
一: 向上转型和向下转型
面向对象中的转型只会发生在有继承关系的子类和父类中(接口的实现也包括在这里)。父类:人 子类:男人向上转型: Person p = new Man() ; //向上转型不需要强制类型转化向下转型: Man man =
[自动数据处理]稳扎稳打,逐步形成自有ADP系统体系
comsci
dp
对于国内的IT行业来讲,虽然我们已经有了"两弹一星",在局部领域形成了自己独有的技术特征,并初步摆脱了国外的控制...但是前面的路还很长....
首先是我们的自动数据处理系统还无法处理很多高级工程...中等规模的拓扑分析系统也没有完成,更加复杂的
storm 自定义 日志文件
商人shang
storm cluster logback
Storm中的日志级级别默认为INFO,并且,日志文件是根据worker号来进行区分的,这样,同一个log文件中的信息不一定是一个业务的,这样就会有以下两个需求出现:
1. 想要进行一些调试信息的输出
2. 调试信息或者业务日志信息想要输出到一些固定的文件中
不要怕,不要烦恼,其实Storm已经提供了这样的支持,可以通过自定义logback 下的 cluster.xml 来输
Extjs3 SpringMVC使用 @RequestBody 标签问题记录
21jhf
springMVC使用 @RequestBody(required = false) UserVO userInfo
传递json对象数据,往往会出现http 415,400,500等错误,总结一下需要使用ajax提交json数据才行,ajax提交使用proxy,参数为jsonData,不能为params;另外,需要设置Content-type属性为json,代码如下:
(由于使用了父类aaa
一些排错方法
文强chu
方法
1、java.lang.IllegalStateException: Class invariant violation
at org.apache.log4j.LogManager.getLoggerRepository(LogManager.java:199)at org.apache.log4j.LogManager.getLogger(LogManager.java:228)
at o
Swing中文件恢复我觉得很难
小桔子
swing
我那个草了!老大怎么回事,怎么做项目评估的?只会说相信你可以做的,试一下,有的是时间!
用java开发一个图文处理工具,类似word,任意位置插入、拖动、删除图片以及文本等。文本框、流程图等,数据保存数据库,其余可保存pdf格式。ok,姐姐千辛万苦,
php 文件操作
aichenglong
PHP 读取文件 写入文件
1 写入文件
@$fp=fopen("$DOCUMENT_ROOT/order.txt", "ab");
if(!$fp){
echo "open file error" ;
exit;
}
$outputstring="date:"." \t tire:".$tire."
MySQL的btree索引和hash索引的区别
AILIKES
数据结构 mysql 算法
Hash 索引结构的特殊性,其 检索效率非常高,索引的检索可以一次定位,不像B-Tree 索引需要从根节点到枝节点,最后才能访问到页节点这样多次的IO访问,所以 Hash 索引的查询效率要远高于 B-Tree 索引。
可能很多人又有疑问了,既然 Hash 索引的效率要比 B-Tree 高很多,为什么大家不都用 Hash 索引而还要使用 B-Tree 索引呢
JAVA的抽象--- 接口 --实现
百合不是茶
抽象 接口 实现接口
//抽象 类 ,方法
//定义一个公共抽象的类 ,并在类中定义一个抽象的方法体
抽象的定义使用abstract
abstract class A 定义一个抽象类 例如:
//定义一个基类
public abstract class A{
//抽象类不能用来实例化,只能用来继承
//
JS变量作用域实例
bijian1013
作用域
<script>
var scope='hello';
function a(){
console.log(scope); //undefined
var scope='world';
console.log(scope); //world
console.log(b);
TDD实践(二)
bijian1013
java TDD
实践题目:分解质因数
Step1:
单元测试:
package com.bijian.study.factor.test;
import java.util.Arrays;
import junit.framework.Assert;
import org.junit.Before;
import org.junit.Test;
import com.bijian.
[MongoDB学习笔记一]MongoDB主从复制
bit1129
mongodb
MongoDB称为分布式数据库,主要原因是1.基于副本集的数据备份, 2.基于切片的数据扩容。副本集解决数据的读写性能问题,切片解决了MongoDB的数据扩容问题。
事实上,MongoDB提供了主从复制和副本复制两种备份方式,在MongoDB的主从复制和副本复制集群环境中,只有一台作为主服务器,另外一台或者多台服务器作为从服务器。 本文介绍MongoDB的主从复制模式,需要指明
【HBase五】Java API操作HBase
bit1129
hbase
import java.io.IOException;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.HColumnDescriptor;
import org.apache.ha
python调用zabbix api接口实时展示数据
ronin47
zabbix api接口来进行展示。经过思考之后,计划获取如下内容: 1、 获得认证密钥 2、 获取zabbix所有的主机组 3、 获取单个组下的所有主机 4、 获取某个主机下的所有监控项
jsp取得绝对路径
byalias
绝对路径
在JavaWeb开发中,常使用绝对路径的方式来引入JavaScript和CSS文件,这样可以避免因为目录变动导致引入文件找不到的情况,常用的做法如下:
一、使用${pageContext.request.contextPath}
代码” ${pageContext.request.contextPath}”的作用是取出部署的应用程序名,这样不管如何部署,所用路径都是正确的。
Java定时任务调度:用ExecutorService取代Timer
bylijinnan
java
《Java并发编程实战》一书提到的用ExecutorService取代Java Timer有几个理由,我认为其中最重要的理由是:
如果TimerTask抛出未检查的异常,Timer将会产生无法预料的行为。Timer线程并不捕获异常,所以 TimerTask抛出的未检查的异常会终止timer线程。这种情况下,Timer也不会再重新恢复线程的执行了;它错误的认为整个Timer都被取消了。此时,已经被
SQL 优化原则
chicony
sql
一、问题的提出
在应用系统开发初期,由于开发数据库数据比较少,对于查询SQL语句,复杂视图的的编写等体会不出SQL语句各种写法的性能优劣,但是如果将应用系统提交实际应用后,随着数据库中数据的增加,系统的响应速度就成为目前系统需要解决的最主要的问题之一。系统优化中一个很重要的方面就是SQL语句的优化。对于海量数据,劣质SQL语句和优质SQL语句之间的速度差别可以达到上百倍,可见对于一个系统
java 线程弹球小游戏
CrazyMizzz
java 游戏
最近java学到线程,于是做了一个线程弹球的小游戏,不过还没完善
这里是提纲
1.线程弹球游戏实现
1.实现界面需要使用哪些API类
JFrame
JPanel
JButton
FlowLayout
Graphics2D
Thread
Color
ActionListener
ActionEvent
MouseListener
Mouse
hadoop jps出现process information unavailable提示解决办法
daizj
hadoop jps
hadoop jps出现process information unavailable提示解决办法
jps时出现如下信息:
3019 -- process information unavailable3053 -- process information unavailable2985 -- process information unavailable2917 --
PHP图片水印缩放类实现
dcj3sjt126com
PHP
<?php
class Image{
private $path;
function __construct($path='./'){
$this->path=rtrim($path,'/').'/';
}
//水印函数,参数:背景图,水印图,位置,前缀,TMD透明度
public function water($b,$l,$pos
IOS控件学习:UILabel常用属性与用法
dcj3sjt126com
ios UILabel
参考网站:
http://shijue.me/show_text/521c396a8ddf876566000007
http://www.tuicool.com/articles/zquENb
http://blog.csdn.net/a451493485/article/details/9454695
http://wiki.eoe.cn/page/iOS_pptl_artile_281
完全手动建立maven骨架
eksliang
java eclipse Web
建一个 JAVA 项目 :
mvn archetype:create
-DgroupId=com.demo
-DartifactId=App
[-Dversion=0.0.1-SNAPSHOT]
[-Dpackaging=jar]
建一个 web 项目 :
mvn archetype:create
-DgroupId=com.demo
-DartifactId=web-a
配置清单
gengzg
配置
1、修改grub启动的内核版本
vi /boot/grub/grub.conf
将default 0改为1
拷贝mt7601Usta.ko到/lib文件夹
拷贝RT2870STA.dat到 /etc/Wireless/RT2870STA/文件夹
拷贝wifiscan到bin文件夹,chmod 775 /bin/wifiscan
拷贝wifiget.sh到bin文件夹,chm
Windows端口被占用处理方法
huqiji
windows
以下文章主要以80端口号为例,如果想知道其他的端口号也可以使用该方法..........................1、在windows下如何查看80端口占用情况?是被哪个进程占用?如何终止等. 这里主要是用到windows下的DOS工具,点击"开始"--"运行",输入&
开源ckplayer 网页播放器, 跨平台(html5, mobile),flv, f4v, mp4, rtmp协议. webm, ogg, m3u8 !
天梯梦
mobile
CKplayer,其全称为超酷flv播放器,它是一款用于网页上播放视频的软件,支持的格式有:http协议上的flv,f4v,mp4格式,同时支持rtmp视频流格 式播放,此播放器的特点在于用户可以自己定义播放器的风格,诸如播放/暂停按钮,静音按钮,全屏按钮都是以外部图片接口形式调用,用户根据自己的需要制作 出播放器风格所需要使用的各个按钮图片然后替换掉原始风格里相应的图片就可以制作出自己的风格了,
简单工厂设计模式
hm4123660
java 工厂设计模式 简单工厂模式
简单工厂模式(Simple Factory Pattern)属于类的创新型模式,又叫静态工厂方法模式。是通过专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。简单工厂模式是工厂模式家族中最简单实用的模式,可以理解为是不同工厂模式的一个特殊实现。
maven笔记
zhb8015
maven
跳过测试阶段:
mvn package -DskipTests
临时性跳过测试代码的编译:
mvn package -Dmaven.test.skip=true
maven.test.skip同时控制maven-compiler-plugin和maven-surefire-plugin两个插件的行为,即跳过编译,又跳过测试。
指定测试类
mvn test
非mapreduce生成Hfile,然后导入hbase当中
Stark_Summer
map hbase reduce Hfile path实例
最近一个群友的boss让研究hbase,让hbase的入库速度达到5w+/s,这可愁死了,4台个人电脑组成的集群,多线程入库调了好久,速度也才1w左右,都没有达到理想的那种速度,然后就想到了这种方式,但是网上多是用mapreduce来实现入库,而现在的需求是实时入库,不生成文件了,所以就只能自己用代码实现了,但是网上查了很多资料都没有查到,最后在一个网友的指引下,看了源码,最后找到了生成Hfile
jsp web tomcat 编码问题
王新春
tomcat jsp pageEncode
今天配置jsp项目在tomcat上,windows上正常,而linux上显示乱码,最后定位原因为tomcat 的server.xml 文件的配置,添加 URIEncoding 属性:
<Connector port="8080" protocol="HTTP/1.1"
connectionTi