Files
redkale/service.html
wentch 7ff418c577
2016-01-18 09:34:08 +08:00

308 lines
44 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="en-us">
<head>
<meta charset="UTF-8">
<title>RedKale - Java 开源框架</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" type="text/css" href="stylesheets/normalize.css" media="screen">
<link rel="stylesheet" type="text/css" href="stylesheets/stylesheet.css" media="screen">
<link rel="stylesheet" type="text/css" href="stylesheets/github-light.css" media="screen">
<link rel="stylesheet" type="text/css" href="stylesheets/highlight.css" media="screen">
</head>
<body>
<section class="page-header">
<a href="index.html" class="project-name">RedKale</a>
<h2 class="project-tagline"></h2>
<a href="redkale.html" class="btn">RedKale 入门</a>
<a href="convert.html" class="btn">Convert 组件</a>
<a href="service.html" class="btn">Service 组件</a>
<a href="source.html" class="btn">Source 组件</a>
<a href="net.html" class="btn">Net 组件</a>
<a href="watch.html" class="btn">Watch 组件</a>
<a href="javadoc/index.html" target="_blank" class="btn">Javadoc API</a>
<a href="https://github.com/wentch/redkale" target="_blank" class="btn">Github 源码</a>
</section>
<section class="main-content">
<h3><a id="service_intro" class="anchor" href="#" aria-hidden="true"><span class="octicon octicon-link"></span></a>Service 组件介绍</h3>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Service 是RedKale最核心的组件依赖于Convert、SNCP协议、Resource依赖注入。Service主要处理业务逻辑和操作数据层是微服务架构中的单一原子服务。每一个Service实例分两种模式: <b>本地模式</b><b>远程模式</b>。其模式由 conf/application.xml 文件来配置。使用者在调用过程中通常不需要区分当前Service实例是哪种模式。<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 为了能确保本地模式与远程模式自由切换对Service的实现类有一定的约束: <br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1. Service实现类会被继承不能修饰为 <span style="color: #0000FF;">final</span> <br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2. 带@MultiRun注解的方法会被重载不能修饰为 <span style="color: #0000FF;">final</span> <br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; RedKale进程启动时扫描可加载的Service实现类根据配置文件配置的模式采用JDK 8内置的ASM技术动态生成相应的Service临时类进行实例化并注册到ResourceFactory同其他Service、Servlet依赖注入。
</p>
<h3><a id="service_local" class="anchor" href="#" aria-hidden="true"><span class="octicon octicon-link"></span></a>Service 本地模式</h3>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;以一个简单的UserService类范例来说明动态生成的两种模式临时类。UserService提供查询用户、注册、登陆、修改用户名功能:</br></p>
<div class="highlight"><pre><span class="kd">public</span> <span class="kd">class</span> <span class="nc">UserService</span> <span class="kd">implements</span> <span class="n">Service</span> <span class="o">{</span>
<span class="c1">//用户简单信息缓存</span>
<span class="kd">private</span> <span class="kd">final</span> <span class="n">Map</span><span class="o">&lt;</span><span class="n">Integer</span><span class="o">,</span> <span class="n">UserInfo</span><span class="o">&gt;</span> <span class="n">users</span> <span class="o">=</span> <span class="k">new</span> <span class="n">ConcurrentHashMap</span><span class="o">&lt;&gt;();</span>
<span class="c1">//存放手机号码与userid的对应关系</span>
<span class="kd">private</span> <span class="kd">final</span> <span class="n">Map</span><span class="o">&lt;</span><span class="n">Long</span><span class="o">,</span> <span class="n">Integer</span><span class="o">&gt;</span> <span class="n">mobileToUserids</span> <span class="o">=</span> <span class="k">new</span> <span class="n">ConcurrentHashMap</span><span class="o">&lt;&gt;();</span>
<span class="kd">public</span> <span class="kd">final</span> <span class="n">String</span> <span class="nf">testLocalNodeName</span><span class="o">()</span> <span class="o">{</span>
<span class="k">return</span> <span class="s">&quot;本地节点名&quot;</span><span class="o">;</span>
<span class="o">}</span>
<span class="c1">//查询用户信息</span>
<span class="kd">public</span> <span class="n">UserInfo</span> <span class="nf">findUserInfo</span><span class="o">(</span><span class="kt">int</span> <span class="n">userid</span><span class="o">)</span> <span class="o">{</span>
<span class="k">return</span> <span class="n">users</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="n">userid</span><span class="o">);</span>
<span class="o">}</span>
<span class="c1">//根据手机号码查询用户ID没有返回0</span>
<span class="kd">public</span> <span class="kt">int</span> <span class="nf">findUserid</span><span class="o">(</span><span class="kt">long</span> <span class="n">mobile</span><span class="o">)</span> <span class="o">{</span>
<span class="n">Integer</span> <span class="n">rs</span> <span class="o">=</span> <span class="n">mobileToUserids</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="n">mobile</span><span class="o">);</span>
<span class="k">return</span> <span class="n">rs</span> <span class="o">==</span> <span class="kc">null</span> <span class="o">?</span> <span class="mi">0</span> <span class="o">:</span> <span class="n">rs</span><span class="o">;</span>
<span class="o">}</span>
<span class="c1">//缓存用户信息</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">putUserInfo</span><span class="o">(</span><span class="n">UserInfo</span> <span class="n">user</span><span class="o">)</span> <span class="o">{</span>
<span class="n">users</span><span class="o">.</span><span class="na">put</span><span class="o">(</span><span class="n">user</span><span class="o">.</span><span class="na">getUserid</span><span class="o">(),</span> <span class="n">user</span><span class="o">);</span>
<span class="k">if</span> <span class="o">(</span><span class="n">user</span><span class="o">.</span><span class="na">getMobile</span><span class="o">()</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="o">)</span> <span class="n">mobileToUserids</span><span class="o">.</span><span class="na">put</span><span class="o">(</span><span class="n">user</span><span class="o">.</span><span class="na">getMobile</span><span class="o">(),</span> <span class="n">user</span><span class="o">.</span><span class="na">getUserid</span><span class="o">());</span>
<span class="o">}</span>
<span class="c1">//登录</span>
<span class="kd">public</span> <span class="n">RetResult</span><span class="o">&lt;</span><span class="n">UserInfo</span><span class="o">&gt;</span> <span class="nf">login</span><span class="o">(</span><span class="n">LoginBean</span> <span class="n">bean</span><span class="o">)</span> <span class="o">{</span>
<span class="c1">// 登陆逻辑</span>
<span class="k">return</span> <span class="k">new</span> <span class="n">RetResult</span><span class="o">&lt;&gt;(</span><span class="mi">100</span><span class="o">);</span>
<span class="o">}</span>
<span class="c1">//注册</span>
<span class="nd">@MultiRun</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">register</span><span class="o">(</span><span class="n">UserInfo</span> <span class="n">user</span><span class="o">)</span> <span class="o">{</span>
<span class="k">this</span><span class="o">.</span><span class="na">users</span><span class="o">.</span><span class="na">put</span><span class="o">(</span><span class="n">user</span><span class="o">.</span><span class="na">getUserid</span><span class="o">(),</span> <span class="n">user</span><span class="o">);</span>
<span class="o">}</span>
<span class="c1">//更新用户名</span>
<span class="nd">@MultiRun</span><span class="o">(</span><span class="n">diffrun</span> <span class="o">=</span> <span class="kc">false</span><span class="o">)</span>
<span class="kd">public</span> <span class="n">UserInfo</span> <span class="nf">updateUsername</span><span class="o">(</span><span class="kt">int</span> <span class="n">userid</span><span class="o">,</span> <span class="n">String</span> <span class="n">username</span><span class="o">)</span> <span class="o">{</span>
<span class="n">UserInfo</span> <span class="n">user</span> <span class="o">=</span> <span class="k">this</span><span class="o">.</span><span class="na">users</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="n">userid</span><span class="o">);</span>
<span class="k">if</span> <span class="o">(</span><span class="n">user</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span> <span class="n">user</span><span class="o">.</span><span class="na">setUsername</span><span class="o">(</span><span class="n">username</span><span class="o">);</span>
<span class="k">return</span> <span class="n">user</span><span class="o">;</span>
<span class="o">}</span>
<span class="o">}</span>
</pre></div>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;动态生成的本地模式UserService</p>
<div class="highlight"><pre><span class="nd">@Resource</span><span class="o">(</span><span class="n">name</span> <span class="o">=</span> <span class="s">""</span><span class="o">)</span>
<span class="nd">@SncpDyn</span><span class="o">(</span><span class="n">remote</span> <span class="o">=</span> <span class="kc">false</span><span class="o">)</span>
<span class="nd">@ResourceType</span><span class="o">({</span><span class="n">UserService</span><span class="o">.</span><span class="kd">class</span><span class="o">})</span>
<span class="kd">public</span> <span class="kd">final</span> <span class="kd">class</span> <span class="nc">_DynLocalUserService</span> <span class="kd">extends</span> <span class="n">UserService</span> <span class="o">{</span>
<span class="nd">@Resource</span>
<span class="kd">private</span> <span class="n">BsonConvert</span> <span class="n">_convert</span><span class="o">;</span>
<span class="kd">private</span> <span class="n">Transport</span> <span class="n">_sameGroupTransport</span><span class="o">;</span>
<span class="kd">private</span> <span class="n">Transport</span><span class="o">[]</span> <span class="n">_diffGroupTransports</span><span class="o">;</span>
<span class="kd">private</span> <span class="n">SncpClient</span> <span class="n">_client</span><span class="o">;</span>
<span class="kd">private</span> <span class="n">String</span> <span class="n">_selfstring</span><span class="o">;</span>
<span class="nd">@Override</span>
<span class="kd">public</span> <span class="n">String</span> <span class="nf">toString</span><span class="o">()</span> <span class="o">{</span>
<span class="k">return</span> <span class="n">_selfstring</span> <span class="o">==</span> <span class="kc">null</span> <span class="o">?</span> <span class="kd">super</span><span class="o">.</span><span class="na">toString</span><span class="o">()</span> <span class="o">:</span> <span class="n">_selfstring</span><span class="o">;</span>
<span class="o">}</span>
<span class="nd">@Override</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">register</span><span class="o">(</span><span class="n">UserInfo</span> <span class="n">user</span><span class="o">)</span> <span class="o">{</span>
<span class="kd">this</span><span class="o">.</span><span class="na">_register</span><span class="o">(</span><span class="kc">true</span><span class="o">,</span> <span class="kc">true</span><span class="o">,</span> <span class="kc">true</span><span class="o">,</span> <span class="n">user</span><span class="o">);</span>
<span class="o">}</span>
<span class="nd">@SncpDyn</span><span class="o">(</span><span class="n">remote</span> <span class="o">=</span> <span class="kc">false</span><span class="o">,</span> <span class="n">index</span> <span class="o">=</span> <span class="mi">0</span><span class="o">)</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">_register</span><span class="o">(</span><span class="kt">boolean</span> <span class="n">selfrunnable</span><span class="o">,</span> <span class="kt">boolean</span> <span class="n">samerunnable</span><span class="o">,</span> <span class="kt">boolean</span> <span class="n">diffrunnable</span><span class="o">,</span> <span class="n">UserInfo</span> <span class="n">user</span><span class="o">)</span> <span class="o">{</span>
<span class="k">if</span> <span class="o">(</span><span class="n">selfrunnable</span><span class="o">)</span> <span class="kd">super</span><span class="o">.</span><span class="na">register</span><span class="o">(</span><span class="n">user</span><span class="o">);</span>
<span class="k">if</span> <span class="o">(</span><span class="n">_client</span> <span class="o">==</span> <span class="kc">null</span><span class="o">)</span> <span class="k">return</span><span class="o">;</span>
<span class="k">if</span> <span class="o">(</span><span class="n">samerunnable</span><span class="o">)</span> <span class="n">_client</span><span class="o">.</span><span class="na">remoteSameGroup</span><span class="o">(</span><span class="n">_convert</span><span class="o">,</span> <span class="n">_sameGroupTransport</span><span class="o">,</span> <span class="mi">0</span><span class="o">,</span> <span class="kc">true</span><span class="o">,</span> <span class="kc">false</span><span class="o">,</span> <span class="kc">false</span><span class="o">,</span> <span class="n">user</span><span class="o">);</span>
<span class="k">if</span> <span class="o">(</span><span class="n">diffrunnable</span><span class="o">)</span> <span class="n">_client</span><span class="o">.</span><span class="na">remoteDiffGroup</span><span class="o">(</span><span class="n">_convert</span><span class="o">,</span> <span class="n">_diffGroupTransports</span><span class="o">,</span> <span class="mi">0</span><span class="o">,</span> <span class="kc">true</span><span class="o">,</span> <span class="kc">true</span><span class="o">,</span> <span class="kc">false</span><span class="o">,</span> <span class="n">user</span><span class="o">);</span>
<span class="o">}</span>
<span class="nd">@Override</span>
<span class="kd">public</span> <span class="n">UserInfo</span> <span class="nf">updateUsername</span><span class="o">(</span><span class="kt">int</span> <span class="n">userid</span><span class="o">,</span> <span class="n">String</span> <span class="n">username</span><span class="o">)</span> <span class="o">{</span>
<span class="k">return</span> <span class="kd">this</span><span class="o">.</span><span class="na">_updateUsername</span><span class="o">(</span><span class="kc">true</span><span class="o">,</span> <span class="kc">true</span><span class="o">,</span> <span class="kc">false</span><span class="o">,</span> <span class="n">userid</span><span class="o">,</span> <span class="n">username</span><span class="o">);</span>
<span class="o">}</span>
<span class="nd">@SncpDyn</span><span class="o">(</span><span class="n">remote</span> <span class="o">=</span> <span class="kc">false</span><span class="o">,</span> <span class="n">index</span> <span class="o">=</span> <span class="mi">1</span><span class="o">)</span>
<span class="kd">public</span> <span class="n">UserInfo</span> <span class="nf">_updateUsername</span><span class="o">(</span><span class="kt">boolean</span> <span class="n">selfrunnable</span><span class="o">,</span> <span class="kt">boolean</span> <span class="n">samerunnable</span><span class="o">,</span> <span class="kt">boolean</span> <span class="n">diffrunnable</span><span class="o">,</span> <span class="kt">int</span> <span class="n">userid</span><span class="o">,</span> <span class="n">String</span> <span class="n">username</span><span class="o">)</span> <span class="o">{</span>
<span class="n">UserInfo</span> <span class="n">rs</span> <span class="o">=</span> <span class="kd">super</span><span class="o">.</span><span class="na">updateUsername</span><span class="o">(</span><span class="n">userid</span><span class="o">,</span> <span class="n">username</span><span class="o">);</span>
<span class="k">if</span> <span class="o">(</span><span class="n">_client</span> <span class="o">==</span> <span class="kc">null</span><span class="o">)</span> <span class="k">return</span> <span class="kc">null</span><span class="o">;</span>
<span class="k">if</span> <span class="o">(</span><span class="n">samerunnable</span><span class="o">)</span> <span class="n">_client</span><span class="o">.</span><span class="na">remoteSameGroup</span><span class="o">(</span><span class="n">_convert</span><span class="o">,</span> <span class="n">_sameGroupTransport</span><span class="o">,</span> <span class="mi">1</span><span class="o">,</span> <span class="kc">true</span><span class="o">,</span> <span class="kc">false</span><span class="o">,</span> <span class="kc">false</span><span class="o">,</span> <span class="n">userid</span><span class="o">,</span> <span class="n">username</span><span class="o">);</span>
<span class="k">if</span> <span class="o">(</span><span class="n">diffrunnable</span><span class="o">)</span> <span class="n">_client</span><span class="o">.</span><span class="na">remoteDiffGroup</span><span class="o">(</span><span class="n">_convert</span><span class="o">,</span> <span class="n">_diffGroupTransports</span><span class="o">,</span> <span class="mi">1</span><span class="o">,</span> <span class="kc">true</span><span class="o">,</span> <span class="kc">true</span><span class="o">,</span> <span class="kc">false</span><span class="o">,</span> <span class="n">userid</span><span class="o">,</span> <span class="n">username</span><span class="o">);</span>
<span class="k">return</span> <span class="n">rs</span><span class="o">;</span>
<span class="o">}</span>
<span class="o">}</span>
</pre></div>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;由以上等价的代码可以看出来本地模式Service会重载被@MultiRun注解的方法。@MultiRun有以下几个参数: </p>
<div class="highlight"><pre><span class="kd">public</span> <span class="nd">@interface</span> <span class="n">MultiRun</span> <span class="o">{</span>
<span class="kt">boolean</span> <span class="nf">selfrun</span><span class="o">()</span> <span class="k">default</span> <span class="kc">true</span><span class="o">;</span> <span class="c1">//当前本地实例是否运行指定操作只有当指定操作的方法的返回值为void时该值才能为true否则忽略。</span>
<span class="kt">boolean</span> <span class="nf">samerun</span><span class="o">()</span> <span class="k">default</span> <span class="kc">true</span><span class="o">;</span> <span class="c1">//是否同组节点运行指定操作</span>
<span class="kt">boolean</span> <span class="nf">diffrun</span><span class="o">()</span> <span class="k">default</span> <span class="kc">true</span><span class="o">;</span> <span class="c1">//是否不同组节点运行指定操作</span>
<span class="kt">boolean</span> <span class="nf">async</span><span class="o">()</span> <span class="k">default</span> <span class="kc">true</span><span class="o">;</span> <span class="c1">//分布式运行是否采用异步模式</span>
<span class="o">}</span> </pre></div>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;在动态生成的远程模式UserService时会根据不同参数生成相应的方法。若一个Service类没有含@MultiRun注解的方法那么动态类只会重载toString方法。当UserService服务仅需要部署一个进程由于没有其他等同服务的进程因此在UserService实例化时_client会赋值为null。</p>
<div class="highlight"><pre><span class="nt">&lt;resources&gt;</span>
<span class="nt">&lt;group</span> <span class="na">name=</span><span class="s">&quot;GROUP-A&quot;</span><span class="nt">&gt;</span>
<span class="nt">&lt;node</span> <span class="na">addr=</span><span class="s">&quot;192.168.10.111&quot;</span> <span class="na">port=</span><span class="s">&quot;7070&quot;</span><span class="nt">/&gt;</span>
<span class="nt">&lt;node</span> <span class="na">addr=</span><span class="s">&quot;192.168.10.112&quot;</span> <span class="na">port=</span><span class="s">&quot;7070&quot;</span><span class="nt">/&gt;</span>
<span class="nt">&lt;node</span> <span class="na">addr=</span><span class="s">&quot;192.168.10.113&quot;</span> <span class="na">port=</span><span class="s">&quot;7070&quot;</span><span class="nt">/&gt;</span>
<span class="nt">&lt;/group&gt;</span>
<span class="nt">&lt;group</span> <span class="na">name=</span><span class="s">&quot;GROUP-B&quot;</span><span class="nt">&gt;</span>
<span class="nt">&lt;node</span> <span class="na">addr=</span><span class="s">&quot;192.168.20.121&quot;</span> <span class="na">port=</span><span class="s">&quot;7070&quot;</span><span class="nt">/&gt;</span>
<span class="nt">&lt;node</span> <span class="na">addr=</span><span class="s">&quot;192.168.20.122&quot;</span> <span class="na">port=</span><span class="s">&quot;7070&quot;</span><span class="nt">/&gt;</span>
<span class="nt">&lt;/group&gt;</span>
<span class="nt">&lt;group</span> <span class="na">name=</span><span class="s">&quot;GROUP-C&quot;</span><span class="nt">&gt;</span>
<span class="nt">&lt;node</span> <span class="na">addr=</span><span class="s">&quot;192.168.30.131&quot;</span> <span class="na">port=</span><span class="s">&quot;7070&quot;</span><span class="nt">/&gt;</span>
<span class="nt">&lt;node</span> <span class="na">addr=</span><span class="s">&quot;192.168.30.132&quot;</span> <span class="na">port=</span><span class="s">&quot;7070&quot;</span><span class="nt">/&gt;</span>
<span class="nt">&lt;/group&gt;</span>
<span class="nt">&lt;/resources&gt;</span>
<span class="c">&lt;!-- 配置UserService的节点组 ---&gt;</span>
<span class="nt">&lt;service</span> <span class="na">name=</span><span class="s">&quot;&quot;</span> <span class="na">value=</span><span class="s">&quot;org.redkale.demo.user.UserService&quot;</span> <span class="na">groups=</span><span class="s">&quot;GROUP-A;GROUP-B;GROUP-C&quot;</span><span class="nt">/&gt;</span>
</pre></div>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;如上配置若当前进程所在IP是192.168.10.111则UserService采用本地模式加载。执行register方法时 先本地执行超类的register然后远程执行同组的进程(192.168.10.112、192.168.10.113),最后远程执行异组的进程(192.168.20.121、192.168.20.122、192.168.30.131、192.168.30.132)。若当前进程所在IP是192.168.10.100则UserService采用远程模式加载。需要注意的一点是每个IP所在的服务必须开通SNCP协议服务以便能接收远程的调用请求。</p>
<h3><a id="service_remote" class="anchor" href="#" aria-hidden="true"><span class="octicon octicon-link"></span></a>Service 远程模式</h3>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;动态生成的远程模式UserService</p>
<div class="highlight"><pre><span class="nd">@Resource</span><span class="o">(</span><span class="n">name</span> <span class="o">=</span> <span class="s">&quot;&quot;</span><span class="o">)</span>
<span class="nd">@SncpDyn</span><span class="o">(</span><span class="n">remote</span> <span class="o">=</span> <span class="kc">true</span><span class="o">)</span>
<span class="nd">@ResourceType</span><span class="o">({</span><span class="n">UserService</span><span class="o">.</span><span class="na">class</span><span class="o">})</span>
<span class="kd">public</span> <span class="kd">final</span> <span class="kd">class</span> <span class="nc">_DynRemoteUserService</span> <span class="kd">extends</span> <span class="n">UserService</span> <span class="o">{</span>
<span class="nd">@Resource</span>
<span class="kd">private</span> <span class="n">BsonConvert</span> <span class="n">_convert</span><span class="o">;</span>
<span class="kd">private</span> <span class="n">Transport</span> <span class="n">_transport</span><span class="o">;</span>
<span class="kd">private</span> <span class="n">SncpClient</span> <span class="n">_client</span><span class="o">;</span>
<span class="kd">private</span> <span class="n">String</span> <span class="n">_selfstring</span><span class="o">;</span>
<span class="nd">@Override</span>
<span class="kd">public</span> <span class="n">String</span> <span class="nf">toString</span><span class="o">()</span> <span class="o">{</span>
<span class="k">return</span> <span class="n">_selfstring</span> <span class="o">==</span> <span class="kc">null</span> <span class="o">?</span> <span class="kd">super</span><span class="o">.</span><span class="na">toString</span><span class="o">()</span> <span class="o">:</span> <span class="n">_selfstring</span><span class="o">;</span>
<span class="o">}</span>
<span class="nd">@SncpDyn</span><span class="o">(</span><span class="n">remote</span> <span class="o">=</span> <span class="kc">false</span><span class="o">,</span> <span class="n">index</span> <span class="o">=</span> <span class="mi">0</span><span class="o">)</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">_register</span><span class="o">(</span><span class="kt">boolean</span> <span class="n">selfrunnable</span><span class="o">,</span> <span class="kt">boolean</span> <span class="n">samerunnable</span><span class="o">,</span> <span class="kt">boolean</span> <span class="n">diffrunnable</span><span class="o">,</span> <span class="n">UserInfo</span> <span class="n">user</span><span class="o">)</span> <span class="o">{</span>
<span class="n">_client</span><span class="o">.</span><span class="na">remote</span><span class="o">(</span><span class="n">_convert</span><span class="o">,</span> <span class="n">_transport</span><span class="o">,</span> <span class="mi">0</span><span class="o">,</span> <span class="n">selfrunnable</span><span class="o">,</span> <span class="n">samerunnable</span><span class="o">,</span> <span class="n">diffrunnable</span><span class="o">,</span> <span class="n">user</span><span class="o">);</span>
<span class="o">}</span>
<span class="nd">@SncpDyn</span><span class="o">(</span><span class="n">remote</span> <span class="o">=</span> <span class="kc">false</span><span class="o">,</span> <span class="n">index</span> <span class="o">=</span> <span class="mi">1</span><span class="o">)</span>
<span class="kd">public</span> <span class="n">UserInfo</span> <span class="nf">_updateUsername</span><span class="o">(</span><span class="kt">boolean</span> <span class="n">selfrunnable</span><span class="o">,</span> <span class="kt">boolean</span> <span class="n">samerunnable</span><span class="o">,</span> <span class="kt">boolean</span> <span class="n">diffrunnable</span><span class="o">,</span> <span class="kt">int</span> <span class="n">userid</span><span class="o">,</span> <span class="n">String</span> <span class="n">username</span><span class="o">)</span> <span class="o">{</span>
<span class="k">return</span> <span class="n">_client</span><span class="o">.</span><span class="na">remote</span><span class="o">(</span><span class="n">_convert</span><span class="o">,</span> <span class="n">_transport</span><span class="o">,</span> <span class="mi">1</span><span class="o">,</span> <span class="n">selfrunnable</span><span class="o">,</span> <span class="n">samerunnable</span><span class="o">,</span> <span class="n">diffrunnable</span><span class="o">,</span> <span class="n">userid</span><span class="o">,</span> <span class="n">username</span><span class="o">);</span>
<span class="o">}</span>
<span class="nd">@Override</span>
<span class="kd">public</span> <span class="n">UserInfo</span> <span class="nf">findUserInfo</span><span class="o">(</span><span class="kt">int</span> <span class="n">userid</span><span class="o">)</span> <span class="o">{</span>
<span class="k">return</span> <span class="n">_client</span><span class="o">.</span><span class="na">remote</span><span class="o">(</span><span class="n">_convert</span><span class="o">,</span> <span class="n">_transport</span><span class="o">,</span> <span class="mi">2</span><span class="o">,</span> <span class="n">userid</span><span class="o">);</span>
<span class="o">}</span>
<span class="nd">@Override</span>
<span class="kd">public</span> <span class="kt">int</span> <span class="nf">findUserid</span><span class="o">(</span><span class="kt">long</span> <span class="n">mobile</span><span class="o">)</span> <span class="o">{</span>
<span class="k">return</span> <span class="n">_client</span><span class="o">.</span><span class="na">remote</span><span class="o">(</span><span class="n">_convert</span><span class="o">,</span> <span class="n">_transport</span><span class="o">,</span> <span class="mi">3</span><span class="o">,</span> <span class="n">mobile</span><span class="o">);</span>
<span class="o">}</span>
<span class="nd">@Override</span>
<span class="kd">public</span> <span class="n">RetResult</span><span class="o">&lt;</span><span class="n">UserInfo</span><span class="o">&gt;</span> <span class="nf">login</span><span class="o">(</span><span class="n">LoginBean</span> <span class="n">bean</span><span class="o">)</span> <span class="o">{</span>
<span class="k">return</span> <span class="n">_client</span><span class="o">.</span><span class="na">remote</span><span class="o">(</span><span class="n">_convert</span><span class="o">,</span> <span class="n">_transport</span><span class="o">,</span> <span class="mi">4</span><span class="o">,</span> <span class="n">bean</span><span class="o">);</span>
<span class="o">}</span>
<span class="nd">@Override</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">putUserInfo</span><span class="o">(</span><span class="n">UserInfo</span> <span class="n">user</span><span class="o">)</span> <span class="o">{</span>
<span class="n">_client</span><span class="o">.</span><span class="na">remote</span><span class="o">(</span><span class="n">_convert</span><span class="o">,</span> <span class="n">_transport</span><span class="o">,</span> <span class="mi">5</span><span class="o">,</span> <span class="n">user</span><span class="o">);</span>
<span class="o">}</span>
<span class="nd">@Override</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">register</span><span class="o">(</span><span class="n">UserInfo</span> <span class="n">user</span><span class="o">)</span> <span class="o">{</span>
<span class="n">_client</span><span class="o">.</span><span class="na">remote</span><span class="o">(</span><span class="n">_convert</span><span class="o">,</span> <span class="n">_transport</span><span class="o">,</span> <span class="mi">6</span><span class="o">,</span> <span class="n">user</span><span class="o">);</span>
<span class="o">}</span>
<span class="nd">@Override</span>
<span class="kd">public</span> <span class="n">UserInfo</span> <span class="nf">updateUsername</span><span class="o">(</span><span class="kt">int</span> <span class="n">userid</span><span class="o">,</span> <span class="n">String</span> <span class="n">username</span><span class="o">)</span> <span class="o">{</span>
<span class="k">return</span> <span class="n">_client</span><span class="o">.</span><span class="na">remote</span><span class="o">(</span><span class="n">_convert</span><span class="o">,</span> <span class="n">_transport</span><span class="o">,</span> <span class="mi">7</span><span class="o">,</span> <span class="n">userid</span><span class="o">,</span> <span class="n">username</span><span class="o">);</span>
<span class="o">}</span>
<span class="o">}</span>
</pre></div>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;由以上代码可以看出来远程模式Service是根据本地模式Service临时类动态生成的。远程类执行方法时通过SNCP协议将参数序列化并带上当前方法信息传输到远程服务器上执行完后将结果流反序列化并返回, 其流程与WebService类似。与WebService最大的区别在于远程模式的Service允许修改参数本身的内容。范例如下</p>
<div class="highlight"><pre><span class="cm">/**</span>
<span class="cm"> * 由于该方法在处理过程中修改了参数bean的内容为了保证本地模式与远程模式的一致性需要提供@DynCall回调接口</span>
<span class="cm"> *</span>
<span class="cm"> * @param bean</span>
<span class="cm"> * @return</span>
<span class="cm"> */</span>
<span class="kd">public</span> <span class="n">RetResult</span><span class="o">&lt;</span><span class="n">UserInfo</span><span class="o">&gt;</span> <span class="nf">login</span><span class="o">(</span><span class="nd">@DynCall</span><span class="o">(</span><span class="n">DynCallLoginBeanAttribute</span><span class="o">.</span><span class="k">class</span><span class="o">)</span> <span class="n">LoginBean</span> <span class="n">bean</span><span class="o">)</span> <span class="o">{</span>
<span class="n">bean</span><span class="o">.</span><span class="na">setLogintime</span><span class="o">(</span><span class="n">System</span><span class="o">.</span><span class="na">currentTimeMillis</span><span class="o">());</span>
<span class="n">bean</span><span class="o">.</span><span class="na">setSessionid</span><span class="o">(</span><span class="s">&quot;SID&quot;</span> <span class="o">+</span> <span class="n">System</span><span class="o">.</span><span class="na">currentTimeMillis</span><span class="o">());</span>
<span class="c1">// 登陆逻辑</span>
<span class="k">return</span> <span class="k">new</span> <span class="n">RetResult</span><span class="o">&lt;&gt;(</span><span class="mi">100</span><span class="o">);</span>
<span class="o">}</span>
<span class="cm">/** DynCallLoginBeanAttribute 的实现 **/</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">DynCallLoginBeanAttribute</span> <span class="kd">implements</span> <span class="n">Attribute</span><span class="o">&lt;</span><span class="n">LoginBean</span><span class="o">,</span> <span class="n">Object</span><span class="o">[]&gt;</span> <span class="o">{</span>
<span class="nd">@Override</span>
<span class="kd">public</span> <span class="n">Object</span><span class="o">[]</span> <span class="nf">get</span><span class="o">(</span><span class="n">LoginBean</span> <span class="n">obj</span><span class="o">)</span> <span class="o">{</span>
<span class="k">return</span> <span class="k">new</span> <span class="n">Object</span><span class="o">[]{</span><span class="n">obj</span><span class="o">.</span><span class="na">getLogintime</span><span class="o">(),</span> <span class="n">obj</span><span class="o">.</span><span class="na">getSessionid</span><span class="o">()};</span>
<span class="o">}</span>
<span class="nd">@Override</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">set</span><span class="o">(</span><span class="n">LoginBean</span> <span class="n">obj</span><span class="o">,</span> <span class="n">Object</span><span class="o">[]</span> <span class="n">value</span><span class="o">)</span> <span class="o">{</span>
<span class="n">obj</span><span class="o">.</span><span class="na">setLogintime</span><span class="o">((</span><span class="n">Long</span><span class="o">)</span> <span class="n">value</span><span class="o">[</span><span class="mi">0</span><span class="o">]);</span>
<span class="n">obj</span><span class="o">.</span><span class="na">setSessionid</span><span class="o">((</span><span class="n">String</span><span class="o">)</span> <span class="n">value</span><span class="o">[</span><span class="mi">1</span><span class="o">]);</span>
<span class="o">}</span>
<span class="nd">@Override</span>
<span class="kd">public</span> <span class="n">Class</span><span class="o">&lt;?</span> <span class="kd">extends</span> <span class="n">Object</span><span class="o">[]&gt;</span> <span class="nf">type</span><span class="o">()</span> <span class="o">{</span>
<span class="k">return</span> <span class="n">Object</span><span class="o">[].</span><span class="k">class</span><span class="o">;</span> <span class="c1">//</span>
<span class="o">}</span>
<span class="nd">@Override</span>
<span class="kd">public</span> <span class="n">Class</span><span class="o">&lt;</span><span class="n">LoginBean</span><span class="o">&gt;</span> <span class="nf">declaringClass</span><span class="o">()</span> <span class="o">{</span>
<span class="k">return</span> <span class="n">LoginBean</span><span class="o">.</span><span class="k">class</span><span class="o">;</span> <span class="c1">//</span>
<span class="o">}</span>
<span class="nd">@Override</span>
<span class="kd">public</span> <span class="n">String</span> <span class="nf">field</span><span class="o">()</span> <span class="o">{</span>
<span class="k">return</span> <span class="s">&quot;&quot;</span><span class="o">;</span> <span class="c1">//可以随意值</span>
<span class="o">}</span>
<span class="o">}</span>
</pre></div>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;生成远程模式Service时发现参数带有@DynCall注解的方法在远程调用返回结果时会进行回调处理。</p>
<h3><a id="service_async" class="anchor" href="#" aria-hidden="true"><span class="octicon octicon-link"></span></a>Service 异步调用</h3>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;远程模式不仅对@DynCall注解进行处理而且对方法含有 <b>java.nio.channels.CompletionHandler</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">update</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">@DynAttachment</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;如上图DataSourceService的源码当DataSource为本地实例时异步接口(含<b>CompletionHandler</b>参数的)与同步接口执行流程相同。当DataSource为远程模式时调用异步接口时通信接口发到远程服务器时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>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3、调用远程数据源(DataSource)查询数据,耗时 150ms <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4、数据序列化与response的IO输出 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 耗时 10ms <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;如上描述,一个请求处理耗时 180ms同时占用一个线程的时间也是 180ms。若换成NIO使IO耗时减少为了方便计算假设IO耗时为0(当然实际情况是不可能的), 那么步骤1、4的耗时忽略不计线程的占用时间由180ms变成160ms。 假设数据查询接口IO操作本身耗时也是10ms那么有140ms是用于等待。若采用DataSource异步接口 则140ms的等待时间可以释放当前线程资源。虽然整个请求的处理时间还是180ms但是线程的占用时间却只有20ms。可以看出减少耗时多的步骤的等待时间才能事半功倍大幅度地提高性能。异步接口的主要作用是远程请求在等待过程中释放当前线程资源。大大减少线程数也减少大量线程之间的切换消耗。
</p>
<footer class="site-footer">
<span class="site-footer-owner"><a href="https://github.com/wentch/redkale">RedKale</a> © <a href="https://github.com/wentch">wentch</a> &nbsp;&nbsp;&nbsp;&nbsp;欢迎加入RedKale技术交流QQ群: 527523235</span>
</footer>
</section>
</body>
</html>