This commit is contained in:
Redkale
2017-12-14 10:42:46 +08:00
parent 3e10ab8dff
commit 889f0ac381
4 changed files with 11 additions and 11 deletions

View File

@@ -98,7 +98,7 @@
</p>
<p>&nbsp;&nbsp;<b>Service</b></p>
<p>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="http://redkale.org" target="_blank">Redkale</a>所有API设计中最精简的当属RPC功能RPC没有直接调用的API其功能依附在Service。RPC或类似功能的框架在Java里一直是比较重量级的从古老的Corba、RMI到后来的EJB、WebService还有其他很多RPC开源框架都有着复杂的配置和大量API学习成本有些还需要区分客户端和服务端(如WebService)。 Service不仅只是个逻辑层的规范定义还集成了很强大的RPC和异步调用功能远程模式的Service就是RPC功能系统在依赖注入过程中创建Service时通过基本的IP配置自动识别是创建本地模式的Service还是远程模式的Service远程模式的Service使用的就是RPC但在代码层Service的调用本地模式与远程模式完全一样。更神奇的是带有异步回调函数AsyncHandler 或返回类型为CompletableFuture的Service方法同样能执行远程模式。这种RPC的简易性是其他框架都无可匹敌的。REST风格的Service在接口设计上尽量减少注解性的配置同时保留灵活性,减少HttpServlet的编写。<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="http://redkale.org" target="_blank">Redkale</a>所有API设计中最精简的当属RPC功能RPC没有直接调用的API其功能依附在Service。RPC或类似功能的框架在Java里一直是比较重量级的从古老的Corba、RMI到后来的EJB、WebService还有其他很多RPC开源框架都有着复杂的配置和大量API学习成本有些还需要区分客户端和服务端(如WebService)。 Service不仅只是个逻辑层的规范定义还集成了很强大的RPC和异步调用功能远程模式的Service就是RPC功能系统在依赖注入过程中创建Service时通过基本的IP配置自动识别是创建本地模式的Service还是远程模式的Service远程模式的Service使用的就是RPC但在代码层Service的调用本地模式与远程模式完全一样。更神奇的是带有异步回调函数CompletionHandler 或返回类型为CompletableFuture的Service方法同样能执行远程模式。这种RPC的简易性是其他框架都无可匹敌的。REST风格的Service在接口设计上尽量减少注解性的配置同时保留灵活性,减少HttpServlet的编写。<br>
</p>
<p>&nbsp;&nbsp;<b>Source</b></p>
<p>

View File

@@ -34,7 +34,7 @@
<tr><td style="text-align: left;">@RestService</td><td>标记Service需要REST化。</td></tr>
<tr><td style="text-align: left;">@RestMapping</td><td>标记请求的方法名,同一方法上可重复标记(需确保name值在Service中是唯一的)。<br><b>其标记的Service方法只能throws IOException或不抛异常</b></td></tr>
<tr><td style="text-align: left;">@RestConvert</td><td>标记请求的方法名上对返回值以JSON形式输出时进行字段的屏蔽或开启进行设置</b></td></tr>
<tr><td style="text-align: left;">@RestParam</td><td>获取常规参数值, 字段类型可以是 基础数据类型/Flipper/AsyncHandler/String/JavaBean<br>name='&#38;'&nbsp;&nbsp;&nbsp;&nbsp;表示当前用户(@HttpUserType)<br>name='#'&nbsp;&nbsp;&nbsp;&nbsp;表示截取uri最后一段<br>name='#xxx:'&nbsp;&nbsp;&nbsp;&nbsp;表示从uri中/pipes/xxx:v/截取xxx:的值</td></tr>
<tr><td style="text-align: left;">@RestParam</td><td>获取常规参数值, 字段类型可以是 基础数据类型/Flipper/CompletionHandler/String/JavaBean<br>name='&#38;'&nbsp;&nbsp;&nbsp;&nbsp;表示当前用户(@HttpUserType)<br>name='#'&nbsp;&nbsp;&nbsp;&nbsp;表示截取uri最后一段<br>name='#xxx:'&nbsp;&nbsp;&nbsp;&nbsp;表示从uri中/pipes/xxx:v/截取xxx:的值</td></tr>
<tr><td style="text-align: left;">@RestHeader</td><td>通过request.getHeader获取参数值, 字段类型只能是String</td></tr>
<tr><td style="text-align: left;">@RestCookie</td><td>通过request.getCookie获取Cookie值, 字段类型只能是String</td></tr>
<tr><td style="text-align: left;">@RestBody<td>通过request.getBody获取参数值, 字段类型只能是String/byte[]/JavaBean</td></tr>

View File

@@ -557,11 +557,11 @@
<span class="c1">//增加Cookie值</span>
<span class="kd">public</span> <span class="n">HttpResponse</span> <span class="nf">addCookie</span><span class="o">(</span><span class="n">Collection</span><span class="o">&lt;</span><span class="n">HttpCookie</span><span class="o">&gt;</span> <span class="n">cookies</span><span class="o">);</span>
<span class="c1">//创建AsyncHandler实例将非字符串对象以JSON格式输出字符串以文本输出</span>
<span class="kd">public</span> <span class="n">AsyncHandler</span> <span class="nf">createAsyncHandler</span><span class="o">();</span>
<span class="c1">//创建CompletionHandler实例将非字符串对象以JSON格式输出字符串以文本输出</span>
<span class="kd">public</span> <span class="n">CompletionHandler</span> <span class="nf">createAsyncHandler</span><span class="o">();</span>
<span class="c1">//传入的AsyncHandler子类必须是public且保证其子类可被继承且completed、failed可被重载且包含空参数的构造函数</span>
<span class="kd">public</span> <span class="o">&lt;</span><span class="n">H</span> <span class="kd">extends</span> <span class="n">AsyncHandler</span><span class="o">&gt;</span> <span class="n">H</span> <span class="nf">createAsyncHandler</span><span class="o">(</span><span class="n">Class</span><span class="o">&lt;</span><span class="n">H</span><span class="o">&gt;</span> <span class="n">handlerClass</span><span class="o">);</span>
<span class="c1">//传入的CompletionHandler子类必须是public且保证其子类可被继承且completed、failed可被重载且包含空参数的构造函数</span>
<span class="kd">public</span> <span class="o">&lt;</span><span class="n">H</span> <span class="kd">extends</span> <span class="n">CompletionHandler</span><span class="o">&gt;</span> <span class="n">H</span> <span class="nf">createAsyncHandler</span><span class="o">(</span><span class="n">Class</span><span class="o">&lt;</span><span class="n">H</span><span class="o">&gt;</span> <span class="n">handlerClass</span><span class="o">);</span>
<span class="c1">//设置状态码</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">setStatus</span><span class="o">(</span><span class="kt">int</span> <span class="n">status</span><span class="o">);</span>
@@ -595,10 +595,10 @@
<span class="kd">public</span> <span class="n">HttpResponse</span> <span class="nf">skipHeader</span><span class="o">();</span>
<span class="c1">//异步输出指定内容</span>
<span class="kd">public</span> <span class="o">&lt;</span><span class="n">A</span><span class="o">&gt;</span> <span class="kt">void</span> <span class="nf">sendBody</span><span class="o">(</span><span class="n">ByteBuffer</span> <span class="n">buffer</span><span class="o">,</span> <span class="n">A</span> <span class="n">attachment</span><span class="o">,</span> <span class="n">AsyncHandler</span><span class="o">&lt;</span><span class="n">Integer</span><span class="o">,</span> <span class="n">A</span><span class="o">&gt;</span> <span class="n">handler</span><span class="o">);</span>
<span class="kd">public</span> <span class="o">&lt;</span><span class="n">A</span><span class="o">&gt;</span> <span class="kt">void</span> <span class="nf">sendBody</span><span class="o">(</span><span class="n">ByteBuffer</span> <span class="n">buffer</span><span class="o">,</span> <span class="n">A</span> <span class="n">attachment</span><span class="o">,</span> <span class="n">CompletionHandler</span><span class="o">&lt;</span><span class="n">Integer</span><span class="o">,</span> <span class="n">A</span><span class="o">&gt;</span> <span class="n">handler</span><span class="o">);</span>
<span class="c1">//异步输出指定内容</span>
<span class="kd">public</span> <span class="o">&lt;</span><span class="n">A</span><span class="o">&gt;</span> <span class="kt">void</span> <span class="nf">sendBody</span><span class="o">(</span><span class="n">ByteBuffer</span><span class="o">[]</span> <span class="n">buffers</span><span class="o">,</span> <span class="n">A</span> <span class="n">attachment</span><span class="o">,</span> <span class="n">AsyncHandler</span><span class="o">&lt;</span><span class="n">Integer</span><span class="o">,</span> <span class="n">A</span><span class="o">&gt;</span> <span class="n">handler</span><span class="o">);</span>
<span class="kd">public</span> <span class="o">&lt;</span><span class="n">A</span><span class="o">&gt;</span> <span class="kt">void</span> <span class="nf">sendBody</span><span class="o">(</span><span class="n">ByteBuffer</span><span class="o">[]</span> <span class="n">buffers</span><span class="o">,</span> <span class="n">A</span> <span class="n">attachment</span><span class="o">,</span> <span class="n">CompletionHandler</span><span class="o">&lt;</span><span class="n">Integer</span><span class="o">,</span> <span class="n">A</span><span class="o">&gt;</span> <span class="n">handler</span><span class="o">);</span>
<span class="c1">//关闭HTTP连接如果是keep-alive则不强制关闭</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">finish</span><span class="o">();</span>

View File

@@ -608,14 +608,14 @@
<h3><a id="service_async" class="anchor" href="#" aria-hidden="true"></a>Service 异步调用</h3>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;远程模式不仅对@RpcCall注解进行处理而且对方法含有 <b>AsyncHandler</b> 的参数或返回类型为<b>CompletableFuture</b>也进行异步特殊处理。异步调用对远程模式非常有意义可以减少同步方式对当前线程的占用时间。也给Source组件的异步调用提供了基础。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;远程模式不仅对@RpcCall注解进行处理而且对方法含有 <b>CompletionHandler</b> 的参数或返回类型为<b>CompletableFuture</b>也进行异步特殊处理。异步调用对远程模式非常有意义可以减少同步方式对当前线程的占用时间。也给Source组件的异步调用提供了基础。</p>
<div class="highlight"><pre> <span class="nd">@Override</span>
<span class="kd">public</span> <span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span> <span class="kt">void</span> <span class="nf">updateAsync</span><span class="o">(</span><span class="kd">final</span> <span class="n">AsyncHandler</span><span class="o">&lt;</span><span class="n">Void</span><span class="o">,</span> <span class="n">T</span><span class="o">[]&gt;</span> <span class="n">handler</span><span class="o">,</span> <span class="nd">@RpcAttachment</span> <span class="kd">final</span> <span class="n">T</span><span class="o">...</span> <span class="n">values</span><span class="o">)</span> <span class="o">{</span>
<span class="kd">public</span> <span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span> <span class="kt">void</span> <span class="nf">updateAsync</span><span class="o">(</span><span class="kd">final</span> <span class="n">CompletionHandler</span><span class="o">&lt;</span><span class="n">Void</span><span class="o">,</span> <span class="n">T</span><span class="o">[]&gt;</span> <span class="n">handler</span><span class="o">,</span> <span class="nd">@RpcAttachment</span> <span class="kd">final</span> <span class="n">T</span><span class="o">...</span> <span class="n">values</span><span class="o">)</span> <span class="o">{</span>
<span class="n">source</span><span class="o">.</span><span class="na">update</span><span class="o">(</span><span class="n">values</span><span class="o">);</span>
<span class="k">if</span> <span class="o">(</span><span class="n">handler</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span> <span class="n">handler</span><span class="o">.</span><span class="na">completed</span><span class="o">(</span><span class="kc">null</span><span class="o">,</span> <span class="n">values</span><span class="o">);</span>
<span class="o">}</span></pre></div>
<p>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;如上图源码,异步接口(含<b>AsyncHandler</b>参数或返回类型为<b>CompletableFuture</b>)与同步接口执行流程相同。当Service为远程模式时调用异步接口时通信接口发到远程服务器时AsyncHandler参数的值传<b>null</b>,返回数据后再调用本地的AsyncHandler参数值执行。<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;如上图源码,异步接口(含<b>CompletionHandler</b>参数或返回类型为<b>CompletableFuture</b>)与同步接口执行流程相同。当Service为远程模式时调用异步接口时通信接口发到远程服务器时CompletionHandler参数的值传<b>null</b>,返回数据后再调用本地的CompletionHandler参数值执行。<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;异步调用方式是提高服务并发性的有效手段特别是在远程模式Service比较多的情况下效果更明显。以HTTP服务为例在Tomcat刚刚改版成NIO的时候网上随处可见都是大谈NIO性能比BIO多好认为BIO与NIO的不同是BIO往往会引入多线程每个连接一个单独的线程NIO则是使用单线程或者只使用少量的多线程每个连接共用一个线程。而事实上呢通常还是通过增加线程数来提高并发量。为什么NIO作用不大呢 因为一个HTTP动态请求耗时最多是业务逻辑层特别是操作数据库IO操作的耗时比重小得多只有在静态资源请求这种纯IO操作才能体现NIO、AIO(NIO.2)的优势。举例一个简单的数据查询请求采用BIO方式耗时为了方便比较将所耗时间扩大几倍如下: <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1、服务器TCP连接开始到进入HttpServlet耗时 10ms <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2、用户态判断和参数验证&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 耗时 10ms <br>