Files
redkale/redkale.html
Redkale 89295b8265
2018-02-11 12:58:51 +08:00

820 lines
107 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 8全新的微服务开源框架 - Redkale官网</title>
<meta name="keywords" content="Redkale,redkale,java,微服务,架构"/>
<meta name="description" content="Redkale(红菜苔)是基于Java 8全新的微服务开源框架"/>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" type="text/css" href="stylesheets/stylesheet.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="plugins.html" class="btn">Redkale 插件</a>
<a href="articles.html" class="btn">技术文章</a>
</section>
<section class="main-content">
<h3><a id="redkale_start" class="anchor" href="#" aria-hidden="true"></a>Redkale 功能</h3>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Redkale虽然不到1M大小但是麻雀虽小五脏俱全。既可作为服务器使用也可当工具包使用。作为独立的工具包提供以下功能<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1、convert包提供JSON的序列化和反序列化功能类似Gson、Jackson。 <br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2、convert包提供Java对象二进制的序列化和反序列化功能类似Protobuf。 <br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3、source包提供很简便的数据库操作功能类似JPA、Hibernate。 <br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4、net包提供TCP/UDP服务功能 类似Mina。 <br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5、net.http提供HTTP服务 类似Tomcat、Netty。 <br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;6、ResourceFactory提供轻量级的依赖注入功能 类似Google Guice。 <br/>
</p>
<h3><a id="redkale_code" class="anchor" href="#" aria-hidden="true"></a>Java 源码</h3>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="https://github.com/redkale" target="_blank" >Github 源码 &nbsp;&nbsp; https://github.com/redkale</a></p>
<h3><a id="redkale_server" class="anchor" href="#" aria-hidden="true"></a>Redkale 服务器</h3>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Redkale作为服务器的目录如下: <br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<b>bin</b>&nbsp;&nbsp;&nbsp; 存放启动/关闭/apidoc脚本(start.sh、shutdown.sh、apidoc.sh、start.bat、shutdown.bat、apidoc.bat) <br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<b>conf</b>&nbsp; 存放服务器所需配置文件:<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a href="#redkale_confxml">application.xml</a> 服务配置文件 (必需)<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; logging.properties日志配置文件 (可选) <br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a href="source.html#source_confxml" target="_blank">persistence.xml</a>:数据库配置文件 (可选)<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<b>lib</b>&nbsp;&nbsp;&nbsp;&nbsp; 存放服务所依赖且不需要热更新的第三方包redkale.jar 放在此处。 <br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<b>libs</b>&nbsp;&nbsp; 存放自己的业务jar或需要热更新的jar。 <br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<b>logs</b> logging.properties 配置中默认的日志存放目录。<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<b>root</b>&nbsp; <a href="#redkale_confxml">application.xml</a> 配置中HTTP服务所需页面的默认根目录。 <br/>
</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Redkale启动的流程如下<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1、加载 <a href="#redkale_confxml">application.xml</a> 并解析。 <br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2、初始化 <b>&lt;resources&gt;</b> 节点中的资源。 <br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3、解析所有的 <b>&lt;server&gt;</b> 节点。 <br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4、初始化并启动所有<b>&lt;server&gt;</b> 节点的Server服务 (优先加载SNCP协议的Server最后加载WATCH协议的Server)。 <br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5、初始化单个Server <br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5.1、扫描classpath加载所有可用的Service实现类(没有标记为@AutoLoad(<span style="color: #0000FF;">false</span>)的类)并实例化,然后相互依赖注入。 <br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5.2、Service实例在依赖注入过程中加载所需的DataSource、CacheSource资源。 <br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5.3、调用所有本地模式Service的init方法。 <br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5.4、扫描classpath加载所有可用的Servlet实现类(没有标记为@AutoLoad(<span style="color: #0000FF;">false</span>)的类)并实例化 (WebSocketServlet优先)。<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5.5、给所有Servlet依赖注入所需的Service。 <br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5.6、调用所有Servlet的init方法。 <br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5.7、启动Server的服务监听。 <br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;6、启动进程本身的监听服务。 <br/>
</p>
<h3><a id="redkale_dev" class="anchor" href="#" aria-hidden="true"></a>基于Redkale的开发与调试</h3>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;基于Redkale创建一个Java应用程序工程(即使是Web项目也不要创建Java-Web工程)引用redkale.jar 并创建Redkale所需的几个目录和文件。一个普通的Web项目只需要编写业务层的Service和接入层的HttpServlet的代码。数据库DataSource通过配置文件进行设置。<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;编写完代码可以通过启动脚本进行调试, 也可以在IDE设置项目的主类为 org.redkale.boot.Application 或者工程内定义主类进行启动调试:
</p>
<div class="highlight"><pre><span class="kd">public</span> <span class="kd">final</span> <span class="kd">class</span> <span class="nc">Bootstrap</span> <span class="o">{</span>
<span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="n">String</span><span class="o">[]</span> <span class="n">args</span><span class="o">)</span> <span class="kd">throws</span> <span class="n">Exception</span> <span class="o">{</span>
<span class="n">org</span><span class="o">.</span><span class="na">redkale</span><span class="o">.</span><span class="na">boot</span><span class="o">.</span><span class="na">Application</span><span class="o">.</span><span class="na">main</span><span class="o">(</span><span class="n">args</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可以通过 <b>Application.singleton</b> 方法进行调试: </p>
<div class="highlight"><pre> <span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="n">String</span><span class="o">[]</span> <span class="n">args</span><span class="o">)</span> <span class="kd">throws</span> <span class="n">Exception</span> <span class="o">{</span>
<span class="n">UserService</span> <span class="n">service</span> <span class="o">=</span> <b><span class="n">Application</span><span class="o">.</span><span class="na">singleton</span></b><span class="o">(</span><span class="n">UserService</span><span class="o">.</span><span class="na">class</span><span class="o">);</span>
<span class="n">LoginBean</span> <span class="n">bean</span> <span class="o">=</span> <span class="k">new</span> <span class="nf">LoginBean</span><span class="o">();</span>
<span class="n">bean</span><span class="o">.</span><span class="na">setAccount</span><span class="o">(</span><span class="s">&quot;myaccount&quot;</span><span class="o">);</span>
<span class="n">bean</span><span class="o">.</span><span class="na">setPassword</span><span class="o">(</span><span class="s">&quot;123456&quot;</span><span class="o">);</span>
<span class="n">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">service</span><span class="o">.</span><span class="na">login</span><span class="o">(</span><span class="n">bean</span><span class="o">));</span>
<span class="o">}</span></pre></div>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Application.singleton 运行流程与通过bin脚本启动的流程基本一致区别在于singleton运行时不会启动Server和Application自身的服务监听。Redkale提倡接入层(Servlet)与业务层(Service)分开Service在代码上不能依赖于Servlet因此调试Service自身逻辑时不需要启动接入层服务(类似WebSocket依赖Servlet的功能除外)。 <br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<b>注:</b> Application.singleton的参数Service类不能是抽象类、接口或不存在非final的public方法。</p>
<h3><a id="redkale_inject" class="anchor" href="#" aria-hidden="true"></a>Redkale的依赖注入</h3>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Redkale内置的依赖注入实现很简单只有三个注解和一个类: javax.annotation.Resource、org.redkale.util.ResourceType、org.redkale.util.ResourceListener、org.redkale.util.ResourceFactory采用反射技术依赖注入通常不会在频繁的操作中进行因此性能要求不会很高。其中前两个是注解ResourceFactory是主要操作类主要提供注册和注入两个接口。ResourceFactory的依赖注入不仅提供其他依赖注入框架的常规功能还能动态的自动更新通过inject注入的资源。</p>
<div class="highlight"><pre><span class="kd">public</span> <span class="kd">class</span> <span class="nc">AService</span> <span class="o">{</span>
<span class="nd">@Resource</span><span class="o">(</span><span class="n">name</span> <span class="o">=</span> <span class="s">&quot;property.id&quot;</span><span class="o">)</span>
<span class="kd">private</span> <span class="n">String</span> <span class="n">id</span><span class="o">;</span>
<span class="nd">@Resource</span><span class="o">(</span><span class="n">name</span> <span class="o">=</span> <span class="s">&quot;property.id&quot;</span><span class="o">)</span> <span class="c1">//property.开头的资源名允许String自动转换成primitive数值类型</span>
<span class="kd">private</span> <span class="kt">int</span> <span class="n">intid</span><span class="o">;</span>
<span class="nd">@Resource</span><span class="o">(</span><span class="n">name</span> <span class="o">=</span> <span class="s">&quot;bigint&quot;</span><span class="o">)</span>
<span class="kd">private</span> <span class="n">BigInteger</span> <span class="n">bigint</span><span class="o">;</span>
<span class="nd">@Resource</span><span class="o">(</span><span class="n">name</span> <span class="o">=</span> <span class="s">&quot;seqid&quot;</span><span class="o">)</span>
<span class="kd">private</span> <span class="kt">int</span> <span class="n">seqid</span><span class="o">;</span>
<span class="nd">@Resource</span>
<span class="kd">private</span> <span class="na">BService</span> <span class="n">bservice</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="s">&quot;{id:\&quot;&quot;</span> <span class="o">+</span> <span class="n">id</span> <span class="o">+</span> <span class="s">&quot;\&quot;, intid: &quot;</span> <span class="o">+</span> <span class="n">intid</span> <span class="o">+</span> <span class="s">&quot;, bigint:&quot;</span> <span class="o">+</span> <span class="n">bigint</span> <span class="o">+</span> <span class="s">&quot;}&quot;</span><span class="o">;</span>
<span class="o">}</span>
<span class="cm">/** 以下省略getter setter方法 */</span>
<span class="o">}</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">BService</span> <span class="o">{</span>
<span class="nd">@Resource</span><span class="o">(</span><span class="n">name</span> <span class="o">=</span> <span class="s">&quot;property.id&quot;</span><span class="o">)</span>
<span class="kd">private</span> <span class="n">String</span> <span class="n">id</span><span class="o">;</span>
<span class="nd">@Resource</span>
<span class="kd">private</span> <span class="n">AService</span> <span class="n">aservice</span><span class="o">;</span>
<span class="kd">private</span> <span class="n">String</span> <span class="n">name</span> <span class="o">=</span> <span class="s">&quot;&quot;</span><span class="o">;</span>
<span class="nd">@java.beans.ConstructorProperties</span><span class="o">({</span><span class="s">&quot;name&quot;</span><span class="o">})</span>
<span class="kd">public</span> <span class="nf">BService</span><span class="o">(</span><span class="n">String</span> <span class="n">name</span><span class="o">)</span> <span class="o">{</span>
<span class="k">this</span><span class="o">.</span><span class="na">name</span> <span class="o">=</span> <span class="n">name</span><span class="o">;</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="s">&quot;{name:\&quot;&quot;</span> <span class="o">+</span> <span class="n">name</span> <span class="o">+</span> <span class="s">&quot;\&quot;, id: &quot;</span> <span class="o">+</span> <span class="n">id</span> <span class="o">+</span> <span class="s">&quot;, aserivce:&quot;</span> <span class="o">+</span> <span class="n">aservice</span> <span class="o">+</span> <span class="s">&quot;}&quot;</span><span class="o">;</span>
<span class="o">}</span>
<span class="cm">/** 以下省略getter setter方法 */</span>
<span class="o">}</span>
<span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="n">String</span><span class="o">[]</span> <span class="n">args</span><span class="o">)</span> <span class="kd">throws</span> <span class="n">Exception</span> <span class="o">{</span>
<span class="n">ResourceFactory</span> <span class="n">factory</span> <span class="o">=</span> <span class="n">ResourceFactory</span><span class="o">.</span><span class="na">root</span><span class="o">();</span>
<span class="n">factory</span><span class="o">.</span><span class="na">register</span><span class="o">(</span><span class="s">&quot;property.id&quot;</span><span class="o">,</span> <span class="s">&quot;2345&quot;</span><span class="o">);</span> <span class="c1">//注入String类型的property.id</span>
<span class="n">AService</span> <span class="n">aservice</span> <span class="o">=</span> <span class="k">new</span> <span class="nf">AService</span><span class="o">();</span>
<span class="n">BService</span> <span class="n">bservice</span> <span class="o">=</span> <span class="k">new</span> <span class="nf">BService</span><span class="o">(</span><span class="s">&quot;eee&quot;</span><span class="o">);</span>
<span class="n">factory</span><span class="o">.</span><span class="na">register</span><span class="o">(</span><span class="n">aservice</span><span class="o">);</span> <span class="c1">//放进Resource池内默认的资源名name为&quot;&quot;</span>
<span class="n">factory</span><span class="o">.</span><span class="na">register</span><span class="o">(</span><span class="n">bservice</span><span class="o">);</span> <span class="c1">//放进Resource池内默认的资源名name为&quot;&quot;</span>
<span class="n">factory</span><span class="o">.</span><span class="na">inject</span><span class="o">(</span><span class="n">aservice</span><span class="o">);</span> <span class="c1">//给aservice注入id、bservicebigint没有资源所以为null</span>
<span class="n">factory</span><span class="o">.</span><span class="na">inject</span><span class="o">(</span><span class="n">bservice</span><span class="o">);</span> <span class="c1">//给bservice注入id、aservice</span>
<span class="n">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">aservice</span><span class="o">);</span> <span class="c1">//输出结果为:{id:&quot;2345&quot;, intid:2345, bigint:null, bservice:{name:eee}}</span>
<span class="n">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">bservice</span><span class="o">);</span> <span class="c1">//输出结果为:{name:&quot;eee&quot;, id:2345, aserivce:{id:&quot;2345&quot;, intid:2345, bigint:null, bservice:{name:eee}}}</span>
<span class="n">factory</span><span class="o">.</span><span class="na">register</span><span class="o">(</span><span class="s">&quot;seqid&quot;</span><span class="o">,</span> <span class="mi">200</span><span class="o">);</span> <span class="c1">//放进Resource池内, 同时ResourceFactory会自动更新aservice的seqid值</span>
<span class="n">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">factory</span><span class="o">.</span><span class="na">find</span><span class="o">(</span><span class="s">&quot;seqid&quot;</span><span class="o">,</span> <span class="kt">int</span><span class="o">.</span><span class="na">class</span><span class="o">));</span> <span class="c1">//输出结果为200</span>
<span class="n">factory</span><span class="o">.</span><span class="na">register</span><span class="o">(</span><span class="s">&quot;bigint&quot;</span><span class="o">,</span> <span class="k">new</span> <span class="nf">BigInteger</span><span class="o">(</span><span class="s">&quot;66666&quot;</span><span class="o">));</span> <span class="c1">//放进Resource池内, 同时ResourceFactory会自动更新aservice对象的bigint值 </span>
<span class="n">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">aservice</span><span class="o">);</span> <span class="c1">//输出结果为:{id:&quot;2345&quot;, intid:2345, bigint:66666, bservice:{name:eee}}可以看出seqid与bigint值都已自动更新</span>
<span class="n">factory</span><span class="o">.</span><span class="na">register</span><span class="o">(</span><span class="s">&quot;property.id&quot;</span><span class="o">,</span> <span class="s">&quot;6789&quot;</span><span class="o">);</span> <span class="c1">//更新Resource池内的id资源值, 同时ResourceFactory会自动更新aservice、bservice的id值</span>
<span class="n">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">aservice</span><span class="o">);</span> <span class="c1">//输出结果为:{id:&quot;6789&quot;, intid:6789, bigint:66666, bservice:{name:eee}}</span>
<span class="n">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">bservice</span><span class="o">);</span> <span class="c1">//输出结果为:{name:&quot;eee&quot;, id:6789, aserivce:{id:&quot;6789&quot;, intid:6789, bigint:66666, bservice:{name:eee}}}</span>
<span class="n">bservice</span> <span class="o">=</span> <span class="k">new</span> <span class="nf">BService</span><span class="o">(</span><span class="s">&quot;ffff&quot;</span><span class="o">);</span>
<span class="n">factory</span><span class="o">.</span><span class="na">register</span><span class="o">(</span><span class="n">bservice</span><span class="o">);</span> <span class="c1">//更新Resource池内name=&quot;&quot;的BService资源, 同时ResourceFactory会自动更新aservice的bservice对象</span>
<span class="n">factory</span><span class="o">.</span><span class="na">inject</span><span class="o">(</span><span class="n">bservice</span><span class="o">);</span>
<span class="n">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">aservice</span><span class="o">);</span> <span class="c1">//输出结果为:{id:&quot;6789&quot;, intid: 6789, bigint:66666, bservice:{name:ffff}}</span>
<span class="o">}</span></pre></div>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;如上例通过ResourceFactory.inject注入的对象都会自动更新资源的变化若不想自动更新可以使用带boolean autoSync参数的register系列方法(autoSync传false)注册新资源。</p>
<h3><a id="redkale_deploy" class="anchor" href="#" aria-hidden="true"></a>Redkale 架构部署</h3>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;通常一个系统会分为三层接入层、业务层、数据层。对应到Redkale的组件是 Servlet、Service、Source。大部分系统提供的是HTTP服务为了方便演示Redkale从集中式到分布式的变化以一个简单的HTTP服务作为范例。<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;开发一个极简单的小论坛系统。包含三个模块: <br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;用户模块 &nbsp;&nbsp;&nbsp;UserSerivice: &nbsp;&nbsp;&nbsp;&nbsp;提供用户注册、登录、更新资料等功能, UserServlet作为接入层。<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;帖子模块 ForumSerivice: &nbsp;&nbsp;&nbsp;&nbsp;提供看帖、发帖、删帖等功能, ForumServlet作为接入层。<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;通知模块 &nbsp;NotifySerivice: &nbsp;&nbsp;&nbsp;&nbsp;提供用户操作、回帖等消息通知功能, NotifyWebSocket是WebSocket的Servlet, 且name为 <b>ws_notify</b>,作为接入层。 <br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;其中数据源有: <br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DataSource: &nbsp;&nbsp; 在persistence.xml里配置的数据库Source的name为demodb ,三个模块都需要使用demodb。<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CacheSource: &nbsp;&nbsp; 仅供UserSerivice用于存放session的缓存Servicename为 usersessions, 且session只存放用户ID( int 类型)。<br/>
</p>
<br/>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<b>1、单点部署</b></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;在早期用户量很少或者开发、调试环境中只需部署一个进程就可满足需求。 </p>
<p style="text-align: center;"><img src="images/distributeimg_1.png" alt=""/></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;如上图所有模块的HttpServlet、Service与Source数据库操作全部署在一起。 application.xml作简单的配置即可:</p>
<div class="highlight"><pre><span class="nt">&lt;application</span> <span class="na">port=</span><span class="s">&quot;5050&quot;</span><span class="nt">&gt;</span>
<span class="nt">&lt;server</span> <span class="na">protocol=</span><span class="s">&quot;HTTP&quot;</span> <span class="na">port=</span><span class="s">&quot;6060&quot;</span> <span class="na">root=</span><span class="s">&quot;root&quot;</span><span class="nt">&gt;</span>
<span class="nt">&lt;services</span> <span class="na">autoload=</span><span class="s">&quot;true&quot;</span> <span class="nt">/&gt;</span>
<span class="nt">&lt;servlets</span> <span class="na">autoload=</span><span class="s">&quot;true&quot;</span><span class="nt">/&gt;</span>
<span class="nt">&lt;/server&gt;</span>
<span class="nt">&lt;/application&gt;</span></pre></div>
<br/>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<b>2、多点部署</b></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;在生产环境需要避免单点问题一个服务一般会部署多套。在此做个简单的容灾部署最前端部署一个nginx作反向代理和负载均衡服务器后面部署两套系统。 </p>
<p style="text-align: center;"><img src="images/distributeimg_2.png" alt=""/></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;如上图两个进程间的Serivce都是本地模式两者会通过SNCP服务保持数据同步若DataSource开启了数据缓存也会自动同步。两套的配置文件相同配置如下:</p>
<div class="highlight"><pre><span class="nt">&lt;application</span> <span class="na">port=</span><span class="s">&quot;5050&quot;</span><span class="nt">&gt;</span>
<span class="nt">&lt;resources&gt;</span>
<span class="nt">&lt;group</span> <span class="na">name=</span><span class="s">&quot;ALL&quot;</span><span class="nt">&gt;</span>
<span class="nt">&lt;node</span> <span class="na">addr=</span><span class="s">&quot;192.168.50.110&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.50.120&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;!-- HTTP 监听 Server --&gt;</span>
<span class="nt">&lt;server</span> <span class="na">protocol=</span><span class="s">&quot;HTTP&quot;</span> <span class="na">port=</span><span class="s">&quot;6060&quot;</span> <span class="na">root=</span><span class="s">&quot;root&quot;</span><span class="nt">&gt;</span>
<span class="c">&lt;!-- 前端配置了nginx需要配置才能获取客户端真实的IP地址 --&gt;</span>
<span class="nt">&lt;request&gt;</span>
<span class="nt">&lt;remoteaddr</span> <span class="na">value=</span><span class="s">&quot;request.headers.X-RemoteAddress&quot;</span><span class="nt">/&gt;</span>
<span class="nt">&lt;/request&gt;</span>
<span class="nt">&lt;services</span> <span class="na">autoload=</span><span class="s">&quot;true&quot;</span> <span class="na">groups=</span><span class="s">&quot;ALL&quot;</span><span class="nt">/&gt;</span>
<span class="nt">&lt;servlets</span> <span class="na">autoload=</span><span class="s">&quot;true&quot;</span> <span class="nt">/&gt;</span>
<span class="nt">&lt;/server&gt;</span>
<span class="c">&lt;!-- SNCP 监听 Server --&gt;</span>
<span class="nt">&lt;server</span> <span class="na">protocol=</span><span class="s">&quot;SNCP&quot;</span> <span class="na">port=</span><span class="s">&quot;7070&quot;</span><span class="nt">&gt;</span>
<span class="nt">&lt;services</span> <span class="na">autoload=</span><span class="s">&quot;true&quot;</span> <span class="na">groups=</span><span class="s">&quot;ALL&quot;</span><span class="nt">&gt;</span>
<span class="c">&lt;!-- 有WebSocketServlet的服务必须配置WebSocketNodeService且Redkale同时会自动创建一个同名(ws_notify)的 CacheSource --&gt;</span>
<span class="nt">&lt;service</span> <span class="na">name=</span><span class="s">&quot;ws_notify&quot;</span> <span class="na">value=</span><span class="s">&quot;<b>org.redkale.service.WebSocketNodeService</b>&quot;</span><span class="nt">/&gt;</span>
<span class="c">&lt;!-- 存在DataSource必须配置DataSourceService --&gt;</span>
<span class="nt">&lt;service</span> <span class="na">name=</span><span class="s">&quot;demodb&quot;</span> <span class="na">value=</span><span class="s">&quot;<b>org.redkale.service.DataSourceService</b>&quot;</span><span class="nt">/&gt;</span>
<span class="c">&lt;!-- 存放用户HTTP session信息的CacheSource --&gt;</span>
<span class="nt">&lt;service</span> <span class="na">name=</span><span class="s">&quot;usersessions&quot;</span> <span class="na">value=</span><span class="s">&quot;<b>org.redkale.service.CacheSourceService</b>&quot;</span><span class="nt">&gt;</span>
<span class="nt">&lt;property</span> <span class="na">name=</span><span class="s">&quot;key-type&quot;</span> <span class="na">value=</span><span class="s">&quot;java.lang.String&quot;</span><span class="nt">/&gt;</span>
<span class="nt">&lt;property</span> <span class="na">name=</span><span class="s">&quot;value-type&quot;</span> <span class="na">value=</span><span class="s">&quot;java.lang.Integer&quot;</span><span class="nt">/&gt;</span>
<span class="nt">&lt;/service&gt;</span>
<span class="nt">&lt;/services&gt;</span>
<span class="nt">&lt;/server&gt;</span>
<span class="nt">&lt;/application&gt;</span></pre></div>
<br/>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<b>3、分层部署</b></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;随着业务的复杂度增加,接入层与业务层混在一起会越来越难部署和维护,因此需要进行分层部署。 </p>
<p style="text-align: center;"><img src="images/distributeimg_3.png" alt=""/></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;如上图对HttpServlet与Service进行了分离。每个接入层的Service都是远程模式业务层只需提供SNCP供远程调用。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;接入层中每个进程的配置相同,配置如下:</p>
<div class="highlight"><pre><span class="nt">&lt;application</span> <span class="na">port=</span><span class="s">&quot;5050&quot;</span><span class="nt">&gt;</span>
<span class="nt">&lt;resources&gt;</span>
<span class="nt">&lt;group</span> <span class="na">name=</span><span class="s">&quot;ALL&quot;</span><span class="nt">&gt;</span>
<span class="nt">&lt;node</span> <span class="na">addr=</span><span class="s">&quot;192.168.50.110&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.50.120&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;!-- HTTP 监听 Server --&gt;</span>
<span class="nt">&lt;server</span> <span class="na">protocol=</span><span class="s">&quot;HTTP&quot;</span> <span class="na">port=</span><span class="s">&quot;6060&quot;</span> <span class="na">root=</span><span class="s">&quot;root&quot;</span><span class="nt">&gt;</span>
<span class="c">&lt;!-- 前端配置了nginx需要配置才能获取客户端真实的IP地址 --&gt;</span>
<span class="nt">&lt;request&gt;</span>
<span class="nt">&lt;remoteaddr</span> <span class="na">value=</span><span class="s">&quot;request.headers.X-RemoteAddress&quot;</span><span class="nt">/&gt;</span>
<span class="nt">&lt;/request&gt;</span>
<span class="nt">&lt;services</span> <span class="na">autoload=</span><span class="s">&quot;true&quot;</span> <span class="na">groups=</span><span class="s">&quot;ALL&quot;</span><span class="nt">&gt;</span>
<span class="c">&lt;!-- 有WebSocketServlet的服务必须配置WebSocketNodeService且Redkale同时会自动创建一个同名(ws_notify)的 CacheSource --&gt;</span>
<span class="nt">&lt;service</span> <span class="na">name=</span><span class="s">&quot;ws_notify&quot;</span> <span class="na">value=</span><span class="s">&quot;<b>org.redkale.service.WebSocketNodeService</b>&quot;</span><span class="nt">/&gt;</span>
<span class="nt">&lt;/services&gt;</span>
<span class="nt">&lt;servlets</span> <span class="na">autoload=</span><span class="s">&quot;true&quot;</span> <span class="nt">/&gt;</span>
<span class="nt">&lt;/server&gt;</span>
<span class="nt">&lt;/application&gt;</span></pre></div>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;业务层中每个进程的配置相同,配置如下:</p>
<div class="highlight"><pre><span class="nt">&lt;application</span> <span class="na">port=</span><span class="s">&quot;5050&quot;</span><span class="nt">&gt;</span>
<span class="nt">&lt;resources&gt;</span>
<span class="nt">&lt;group</span> <span class="na">name=</span><span class="s">&quot;ALL&quot;</span><span class="nt">&gt;</span>
<span class="nt">&lt;node</span> <span class="na">addr=</span><span class="s">&quot;192.168.50.110&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.50.120&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;!-- SNCP 监听 Server --&gt;</span>
<span class="nt">&lt;server</span> <span class="na">protocol=</span><span class="s">&quot;SNCP&quot;</span> <span class="na">port=</span><span class="s">&quot;7070&quot;</span><span class="nt">&gt;</span>
<span class="nt">&lt;services</span> <span class="na">autoload=</span><span class="s">&quot;true&quot;</span> <span class="na">groups=</span><span class="s">&quot;ALL&quot;</span><span class="nt">&gt;</span>
<span class="c">&lt;!-- 有WebSocketServlet的服务必须配置WebSocketNodeService且Redkale同时会自动创建一个同名(ws_notify)的 CacheSource --&gt;</span>
<span class="nt">&lt;service</span> <span class="na">name=</span><span class="s">&quot;ws_notify&quot;</span> <span class="na">value=</span><span class="s">&quot;<b>org.redkale.service.WebSocketNodeService</b>&quot;</span><span class="nt">/&gt;</span>
<span class="c">&lt;!-- 存在DataSource必须配置DataSourceService --&gt;</span>
<span class="nt">&lt;service</span> <span class="na">name=</span><span class="s">&quot;demodb&quot;</span> <span class="na">value=</span><span class="s">&quot;<b>org.redkale.service.DataSourceService</b>&quot;</span><span class="nt">/&gt;</span>
<span class="c">&lt;!-- 存放用户HTTP session信息的CacheSource --&gt;</span>
<span class="nt">&lt;service</span> <span class="na">name=</span><span class="s">&quot;usersessions&quot;</span> <span class="na">value=</span><span class="s">&quot;<b>org.redkale.service.CacheSourceService</b>&quot;</span><span class="nt">&gt;</span>
<span class="nt">&lt;property</span> <span class="na">name=</span><span class="s">&quot;key-type&quot;</span> <span class="na">value=</span><span class="s">&quot;java.lang.String&quot;</span><span class="nt">/&gt;</span>
<span class="nt">&lt;property</span> <span class="na">name=</span><span class="s">&quot;value-type&quot;</span> <span class="na">value=</span><span class="s">&quot;java.lang.Integer&quot;</span><span class="nt">/&gt;</span>
<span class="nt">&lt;/service&gt;</span>
<span class="nt">&lt;/services&gt;</span>
<span class="nt">&lt;/server&gt;</span>
<span class="nt">&lt;/application&gt;</span></pre></div>
<br/>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<b>4、微服务部署</b></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;当用户量和发帖量增加到上百万的时候,明显地将所有模块的服务部署到一个进程里是不行的。 因此需要将Service服务都独立部署形成微服务架构。</p>
<p style="text-align: center;"><img src="images/distributeimg_4.png" alt=""/></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;如上图将Serivice都独立部署并进行容灾部署当然如果有需要Servlet之间、Source都可以各自分离独立部署。不同类型的Service之间都是远程模式调用。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;接入层中每个进程的配置相同,配置如下:</p>
<div class="highlight"><pre><span class="nt">&lt;application</span> <span class="na">port=</span><span class="s">&quot;5050&quot;</span><span class="nt">&gt;</span>
<span class="nt">&lt;resources&gt;</span>
<span class="nt">&lt;group</span> <span class="na">name=</span><span class="s">&quot;USER_SERVICE&quot;</span><span class="nt">&gt;</span>
<span class="nt">&lt;node</span> <span class="na">addr=</span><span class="s">&quot;192.168.50.110&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.50.111&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;NOTIFY_SERVICE&quot;</span><span class="nt">&gt;</span>
<span class="nt">&lt;node</span> <span class="na">addr=</span><span class="s">&quot;192.168.50.120&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.50.121&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;FORUM_SERVICE&quot;</span><span class="nt">&gt;</span>
<span class="nt">&lt;node</span> <span class="na">addr=</span><span class="s">&quot;192.168.50.130&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.50.131&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;!-- HTTP 监听 Server --&gt;</span>
<span class="nt">&lt;server</span> <span class="na">protocol=</span><span class="s">&quot;HTTP&quot;</span> <span class="na">port=</span><span class="s">&quot;6060&quot;</span> <span class="na">root=</span><span class="s">&quot;root&quot;</span><span class="nt">&gt;</span>
<span class="c">&lt;!-- 前端配置了nginx需要配置才能获取客户端真实的IP地址 --&gt;</span>
<span class="nt">&lt;request&gt;</span>
<span class="nt">&lt;remoteaddr</span> <span class="na">value=</span><span class="s">&quot;request.headers.X-RemoteAddress&quot;</span><span class="nt">/&gt;</span>
<span class="nt">&lt;/request&gt;</span>
<span class="nt">&lt;services</span> <span class="na">autoload=</span><span class="s">&quot;true&quot;</span><span class="nt">&gt;</span>
<span class="nt">&lt;service</span> <span class="na">value=</span><span class="s">&quot;org.redkale.demo.UserService&quot;</span> <span class="na">groups=</span><span class="s">&quot;USER_SERVICE&quot;</span><span class="nt">/&gt;</span>
<span class="nt">&lt;service</span> <span class="na">value=</span><span class="s">&quot;org.redkale.demo.NotifyService&quot;</span> <span class="na">groups=</span><span class="s">&quot;NOTIFY_SERVICE&quot;</span><span class="nt">/&gt;</span>
<span class="nt">&lt;service</span> <span class="na">value=</span><span class="s">&quot;org.redkale.demo.ForumService&quot;</span> <span class="na">groups=</span><span class="s">&quot;FORUM_SERVICE&quot;</span><span class="nt">/&gt;</span>
<span class="c">&lt;!-- 有WebSocketServlet的服务必须配置WebSocketNodeService且Redkale同时会自动创建一个同名(ws_notify)的 CacheSource --&gt;</span>
<span class="nt">&lt;service</span> <span class="na">name=</span><span class="s">&quot;ws_notify&quot;</span> <span class="na">value=</span><span class="s">&quot;<b>org.redkale.service.WebSocketNodeService</b>&quot;</span> <span class="na">groups=</span><span class="s">&quot;NOTIFY_SERVICE&quot;</span><span class="nt">/&gt;</span>
<span class="nt">&lt;/services&gt;</span>
<span class="nt">&lt;servlets</span> <span class="na">autoload=</span><span class="s">&quot;true&quot;</span> <span class="nt">/&gt;</span>
<span class="nt">&lt;/server&gt;</span>
<span class="nt">&lt;/application&gt;</span></pre></div>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;用户模块UserService服务群中各个进程的配置相同配置如下:</p>
<div class="highlight"><pre><span class="nt">&lt;application</span> <span class="na">port=</span><span class="s">&quot;5050&quot;</span><span class="nt">&gt;</span>
<span class="nt">&lt;resources&gt;</span>
<span class="nt">&lt;group</span> <span class="na">name=</span><span class="s">&quot;USER_SERVICE&quot;</span><span class="nt">&gt;</span>
<span class="nt">&lt;node</span> <span class="na">addr=</span><span class="s">&quot;192.168.50.110&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.50.111&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;NOTIFY_SERVICE&quot;</span><span class="nt">&gt;</span>
<span class="nt">&lt;node</span> <span class="na">addr=</span><span class="s">&quot;192.168.50.120&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.50.121&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;FORUM_SERVICE&quot;</span><span class="nt">&gt;</span>
<span class="nt">&lt;node</span> <span class="na">addr=</span><span class="s">&quot;192.168.50.130&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.50.131&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;!-- SNCP 监听 Server --&gt;</span>
<span class="nt">&lt;server</span> <span class="na">protocol=</span><span class="s">&quot;SNCP&quot;</span> <span class="na">port=</span><span class="s">&quot;7070&quot;</span><span class="nt">&gt;</span>
<span class="nt">&lt;services</span> <span class="na">autoload=</span><span class="s">&quot;true&quot;</span><span class="nt">&gt;</span>
<span class="nt">&lt;service</span> <span class="na">value=</span><span class="s">&quot;org.redkale.demo.NotifyService&quot;</span> <span class="na">groups=</span><span class="s">&quot;NOTIFY_SERVICE&quot;</span><span class="nt">/&gt;</span>
<span class="nt">&lt;service</span> <span class="na">value=</span><span class="s">&quot;org.redkale.demo.ForumService&quot;</span> <span class="na">groups=</span><span class="s">&quot;FORUM_SERVICE&quot;</span><span class="nt">/&gt;</span>
<span class="c">&lt;!-- 存在DataSource必须配置DataSourceService --&gt;</span>
<span class="nt">&lt;service</span> <span class="na">name=</span><span class="s">&quot;demodb&quot;</span> <span class="na">value=</span><span class="s">&quot;<b>org.redkale.service.DataSourceService</b>&quot;</span> <span class="na">groups=</span><span class="s">&quot;USER_SERVICE&quot;</span><span class="nt">/&gt;</span>
<span class="c">&lt;!-- 存放用户HTTP session信息的CacheSource --&gt;</span>
<span class="nt">&lt;service</span> <span class="na">name=</span><span class="s">&quot;usersessions&quot;</span> <span class="na">value=</span><span class="s">&quot;<b>org.redkale.service.CacheSourceService</b>&quot;</span> <span class="na">groups=</span><span class="s">&quot;USER_SERVICE&quot;</span><span class="nt">&gt;</span>
<span class="nt">&lt;property</span> <span class="na">name=</span><span class="s">&quot;key-type&quot;</span> <span class="na">value=</span><span class="s">&quot;java.lang.String&quot;</span><span class="nt">/&gt;</span>
<span class="nt">&lt;property</span> <span class="na">name=</span><span class="s">&quot;value-type&quot;</span> <span class="na">value=</span><span class="s">&quot;java.lang.Integer&quot;</span><span class="nt">/&gt;</span>
<span class="nt">&lt;/service&gt;</span>
<span class="nt">&lt;/services&gt;</span>
<span class="nt">&lt;/server&gt;</span>
<span class="nt">&lt;/application&gt;</span></pre></div>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;通知模块NotifyService服务群中各个进程的配置相同配置如下:</p>
<div class="highlight"><pre><span class="nt">&lt;application</span> <span class="na">port=</span><span class="s">&quot;5050&quot;</span><span class="nt">&gt;</span>
<span class="nt">&lt;resources&gt;</span>
<span class="nt">&lt;group</span> <span class="na">name=</span><span class="s">&quot;USER_SERVICE&quot;</span><span class="nt">&gt;</span>
<span class="nt">&lt;node</span> <span class="na">addr=</span><span class="s">&quot;192.168.50.110&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.50.111&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;NOTIFY_SERVICE&quot;</span><span class="nt">&gt;</span>
<span class="nt">&lt;node</span> <span class="na">addr=</span><span class="s">&quot;192.168.50.120&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.50.121&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;FORUM_SERVICE&quot;</span><span class="nt">&gt;</span>
<span class="nt">&lt;node</span> <span class="na">addr=</span><span class="s">&quot;192.168.50.130&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.50.131&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;!-- SNCP 监听 Server --&gt;</span>
<span class="nt">&lt;server</span> <span class="na">protocol=</span><span class="s">&quot;SNCP&quot;</span> <span class="na">port=</span><span class="s">&quot;7070&quot;</span><span class="nt">&gt;</span>
<span class="nt">&lt;services</span> <span class="na">autoload=</span><span class="s">&quot;true&quot;</span><span class="nt">&gt;</span>
<span class="nt">&lt;service</span> <span class="na">value=</span><span class="s">&quot;org.redkale.demo.UserService&quot;</span> <span class="na">groups=</span><span class="s">&quot;USER_SERVICE&quot;</span><span class="nt">/&gt;</span>
<span class="nt">&lt;service</span> <span class="na">value=</span><span class="s">&quot;org.redkale.demo.ForumService&quot;</span> <span class="na">groups=</span><span class="s">&quot;FORUM_SERVICE&quot;</span><span class="nt">/&gt;</span>
<span class="c">&lt;!-- 有WebSocketServlet的服务必须配置WebSocketNodeService且Redkale同时会自动创建一个同名(ws_notify)的 CacheSource --&gt;</span>
<span class="nt">&lt;service</span> <span class="na">name=</span><span class="s">&quot;ws_notify&quot;</span> <span class="na">value=</span><span class="s">&quot;<b>org.redkale.service.WebSocketNodeService</b>&quot;</span> <span class="na">groups=</span><span class="s">&quot;NOTIFY_SERVICE&quot;</span><span class="nt">/&gt;</span>
<span class="c">&lt;!-- 存在DataSource必须配置DataSourceService --&gt;</span>
<span class="nt">&lt;service</span> <span class="na">name=</span><span class="s">&quot;demodb&quot;</span> <span class="na">value=</span><span class="s">&quot;<b>org.redkale.service.DataSourceService</b>&quot;</span> <span class="na">groups=</span><span class="s">&quot;NOTIFY_SERVICE&quot;</span><span class="nt">/&gt;</span>
<span class="nt">&lt;/services&gt;</span>
<span class="nt">&lt;/server&gt;</span>
<span class="nt">&lt;/application&gt;</span></pre></div>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;帖子模块ForumService服务群中各个进程的配置相同配置如下:</p>
<div class="highlight"><pre><span class="nt">&lt;application</span> <span class="na">port=</span><span class="s">&quot;5050&quot;</span><span class="nt">&gt;</span>
<span class="nt">&lt;resources&gt;</span>
<span class="nt">&lt;group</span> <span class="na">name=</span><span class="s">&quot;USER_SERVICE&quot;</span><span class="nt">&gt;</span>
<span class="nt">&lt;node</span> <span class="na">addr=</span><span class="s">&quot;192.168.50.110&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.50.111&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;NOTIFY_SERVICE&quot;</span><span class="nt">&gt;</span>
<span class="nt">&lt;node</span> <span class="na">addr=</span><span class="s">&quot;192.168.50.120&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.50.121&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;FORUM_SERVICE&quot;</span><span class="nt">&gt;</span>
<span class="nt">&lt;node</span> <span class="na">addr=</span><span class="s">&quot;192.168.50.130&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.50.131&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;!-- SNCP 监听 Server --&gt;</span>
<span class="nt">&lt;server</span> <span class="na">protocol=</span><span class="s">&quot;SNCP&quot;</span> <span class="na">port=</span><span class="s">&quot;7070&quot;</span><span class="nt">&gt;</span>
<span class="nt">&lt;services</span> <span class="na">autoload=</span><span class="s">&quot;true&quot;</span><span class="nt">&gt;</span>
<span class="nt">&lt;service</span> <span class="na">value=</span><span class="s">&quot;org.redkale.demo.UserService&quot;</span> <span class="na">groups=</span><span class="s">&quot;USER_SERVICE&quot;</span><span class="nt">/&gt;</span>
<span class="nt">&lt;service</span> <span class="na">value=</span><span class="s">&quot;org.redkale.demo.NotifyService&quot;</span> <span class="na">groups=</span><span class="s">&quot;NOTIFY_SERVICE&quot;</span><span class="nt">/&gt;</span>
<span class="c">&lt;!-- 存在DataSource必须配置DataSourceService --&gt;</span>
<span class="nt">&lt;service</span> <span class="na">name=</span><span class="s">&quot;demodb&quot;</span> <span class="na">value=</span><span class="s">&quot;<b>org.redkale.service.DataSourceService</b>&quot;</span> <span class="na">groups=</span><span class="s">&quot;FORUM_SERVICE&quot;</span><span class="nt">/&gt;</span>
<span class="nt">&lt;/services&gt;</span>
<span class="nt">&lt;/server&gt;</span>
<span class="nt">&lt;/application&gt;</span></pre></div>
<br/>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<b>5、API网关式部署</b></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;随着用户量到了上千万时一个UserService的服务进程是无法提供全部用户服务。 因此可以考虑按用户段进行分布式部署。将192.168.50.110、192.168.50.111上的UserService服务改成网关式的服务。下面是以 <a href="service.html#service_local" target="_blank">Service本地模式介绍中的UserService</a> 为范例进行编写:</p>
<div class="highlight"><pre><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">class</span> <span class="nc">UserServiceGateWay</span> <span class="kd">extends</span> <span class="n">UserService</span> <span class="o">{</span>
<span class="nd">@Resource</span><span class="o">(</span><span class="n">name</span> <span class="o">=</span> <span class="s">&quot;userservice_reg&quot;</span><span class="o">)</span>
<span class="kd">private</span> <span class="n">UserService</span> <span class="n">regUserService</span><span class="o">;</span> <span class="c1">//只用于注册的服务节点</span>
<span class="nd">@Resource</span><span class="o">(</span><span class="n">name</span> <span class="o">=</span> <span class="s">&quot;userservice_mob&quot;</span><span class="o">)</span>
<span class="kd">private</span> <span class="n">UserService</span> <span class="n">mobUserService</span><span class="o">;</span> <span class="c1">//只用于查询手机号码对应的userid的服务节点</span>
<span class="nd">@Resource</span><span class="o">(</span><span class="n">name</span> <span class="o">=</span> <span class="s">&quot;userservice_node01&quot;</span><span class="o">)</span>
<span class="kd">private</span> <span class="n">UserService</span> <span class="n">userService01</span><span class="o">;</span> <span class="c1">//userid小于2000000的用户的服务节点</span>
<span class="nd">@Resource</span><span class="o">(</span><span class="n">name</span> <span class="o">=</span> <span class="s">&quot;userservice_node02&quot;</span><span class="o">)</span>
<span class="kd">private</span> <span class="n">UserService</span> <span class="n">userService02</span><span class="o">;</span> <span class="c1">//userid小于4000000的用户的服务节点</span>
<span class="nd">@Resource</span><span class="o">(</span><span class="n">name</span> <span class="o">=</span> <span class="s">&quot;userservice_node03&quot;</span><span class="o">)</span>
<span class="kd">private</span> <span class="n">UserService</span> <span class="n">userService03</span><span class="o">;</span> <span class="c1">//userid小于6000000的用户的服务节点</span>
<span class="nd">@Resource</span><span class="o">(</span><span class="n">name</span> <span class="o">=</span> <span class="s">&quot;userservice_node04&quot;</span><span class="o">)</span>
<span class="kd">private</span> <span class="n">UserService</span> <span class="n">userService04</span><span class="o">;</span> <span class="c1">//userid大于6000000的用户的服务节点</span>
<span class="kd">private</span> <span class="n">UserService</span> <span class="nf">getService</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">if</span> <span class="o">(</span><span class="n">userid</span> <span class="o">&lt;=</span> <span class="mi">200_0000</span><span class="o">)</span> <span class="k">return</span> <span class="n">userService01</span><span class="o">;</span>
<span class="k">if</span> <span class="o">(</span><span class="n">userid</span> <span class="o">&lt;=</span> <span class="mi">400_0000</span><span class="o">)</span> <span class="k">return</span> <span class="n">userService02</span><span class="o">;</span>
<span class="k">if</span> <span class="o">(</span><span class="n">userid</span> <span class="o">&lt;=</span> <span class="mi">600_0000</span><span class="o">)</span> <span class="k">return</span> <span class="n">userService03</span><span class="o">;</span>
<span class="k">return</span> <span class="n">userService04</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="k">this</span><span class="o">.</span><span class="na">getService</span><span class="o">(</span><span class="n">userid</span><span class="o">).</span><span class="na">findUserInfo</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="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">//手机号码用long存储0表示无手机号码</span>
<span class="kt">int</span> <span class="n">userid</span> <span class="o">=</span> <span class="n">mobUserService</span><span class="o">.</span><span class="na">findUserid</span><span class="o">(</span><span class="n">bean</span><span class="o">.</span><span class="na">getMobile</span><span class="o">());</span>
<span class="k">if</span> <span class="o">(</span><span class="n">userid</span> <span class="o">&lt;</span> <span class="mi">1</span><span class="o">)</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">10001</span><span class="o">,</span> <span class="s">&quot;not found mobile &quot;</span> <span class="o">+</span> <span class="n">bean</span><span class="o">.</span><span class="na">getMobile</span><span class="o">());</span>
<span class="k">return</span> <span class="k">this</span><span class="o">.</span><span class="na">getService</span><span class="o">(</span><span class="n">userid</span><span class="o">).</span><span class="na">login</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">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">regUserService</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="c1">//会生成userid</span>
<span class="k">this</span><span class="o">.</span><span class="na">getService</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="na">putUserInfo</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="k">this</span><span class="o">.</span><span class="na">getService</span><span class="o">(</span><span class="n">userid</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="o">}</span>
<span class="o">}</span>
</pre></div>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;从代码看出UserServiceGateWay继承了UserService 确保了UserService对外的服务接口不变上面代码是用户量在600-800万之间的写法通过简单的用户ID分段根据不同用户ID调不同的服务节点。</p>
<p style="text-align: center;"><img src="images/distributeimg_5.png" alt=""/></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;如上图网关下的UserService部署分三类 userservice_reg只用于注册用户userservice_mob提供查询手机号码与用户ID间的关系的服务userservice_node按用户段提供已有用户的服务。且每个UserService的实例在UserServiceGateWay都是远程模式。每种类型可以部署多个节点为了结构图简单上图每个类型只部署一个节点。UserServiceGateWay192.168.50.110、192.168.50.111)的配置如下:</p>
<div class="highlight"><pre><span class="nt">&lt;application</span> <span class="na">port=</span><span class="s">&quot;5050&quot;</span><span class="nt">&gt;</span>
<span class="nt">&lt;resources&gt;</span>
<span class="nt">&lt;group</span> <span class="na">name=</span><span class="s">&quot;USER_SERVICE_REG&quot;</span><span class="nt">&gt;</span>
<span class="nt">&lt;node</span> <span class="na">addr=</span><span class="s">&quot;192.168.70.110&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;USER_SERVICE_MOB&quot;</span><span class="nt">&gt;</span>
<span class="nt">&lt;node</span> <span class="na">addr=</span><span class="s">&quot;192.168.70.150&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;USER_SERVICE_NODE01&quot;</span><span class="nt">&gt;</span>
<span class="nt">&lt;node</span> <span class="na">addr=</span><span class="s">&quot;192.168.70.201&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;USER_SERVICE_NODE02&quot;</span><span class="nt">&gt;</span>
<span class="nt">&lt;node</span> <span class="na">addr=</span><span class="s">&quot;192.168.70.202&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;USER_SERVICE_NODE03&quot;</span><span class="nt">&gt;</span>
<span class="nt">&lt;node</span> <span class="na">addr=</span><span class="s">&quot;192.168.70.203&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;USER_SERVICE_NODE04&quot;</span><span class="nt">&gt;</span>
<span class="nt">&lt;node</span> <span class="na">addr=</span><span class="s">&quot;192.168.70.204&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;USER_SERVICE&quot;</span><span class="nt">&gt;</span>
<span class="nt">&lt;node</span> <span class="na">addr=</span><span class="s">&quot;192.168.50.110&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.50.111&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;!-- SNCP 监听 Server --&gt;</span>
<span class="nt">&lt;server</span> <span class="na">protocol=</span><span class="s">&quot;SNCP&quot;</span> <span class="na">port=</span><span class="s">&quot;7070&quot;</span><span class="nt">&gt;</span>
<span class="nt">&lt;services</span> <span class="na">autoload=</span><span class="s">&quot;true&quot;</span><span class="nt">&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.UserServiceGateWay&quot;</span> <span class="na">groups=</span><span class="s">&quot;USER_SERVICE&quot;</span><span class="nt">/&gt;</span>
<span class="c">&lt;!-- 配置UserService分段节点 --&gt;</span>
<span class="nt">&lt;service</span> <span class="na">name=</span><span class="s">&quot;userservice_reg&quot;</span> <span class="na">value=</span><span class="s">&quot;org.redkale.demo.UserService&quot;</span> <span class="na">groups=</span><span class="s">&quot;USER_SERVICE_REG&quot;</span><span class="nt">/&gt;</span>
<span class="nt">&lt;service</span> <span class="na">name=</span><span class="s">&quot;userservice_mob&quot;</span> <span class="na">value=</span><span class="s">&quot;org.redkale.demo.UserService&quot;</span> <span class="na">groups=</span><span class="s">&quot;USER_SERVICE_MOB&quot;</span><span class="nt">/&gt;</span>
<span class="nt">&lt;service</span> <span class="na">name=</span><span class="s">&quot;userservice_node01&quot;</span> <span class="na">value=</span><span class="s">&quot;org.redkale.demo.UserService&quot;</span> <span class="na">groups=</span><span class="s">&quot;USER_SERVICE_NODE01&quot;</span><span class="nt">/&gt;</span>
<span class="nt">&lt;service</span> <span class="na">name=</span><span class="s">&quot;userservice_node02&quot;</span> <span class="na">value=</span><span class="s">&quot;org.redkale.demo.UserService&quot;</span> <span class="na">groups=</span><span class="s">&quot;USER_SERVICE_NODE02&quot;</span><span class="nt">/&gt;</span>
<span class="nt">&lt;service</span> <span class="na">name=</span><span class="s">&quot;userservice_node03&quot;</span> <span class="na">value=</span><span class="s">&quot;org.redkale.demo.UserService&quot;</span> <span class="na">groups=</span><span class="s">&quot;USER_SERVICE_NODE03&quot;</span><span class="nt">/&gt;</span>
<span class="nt">&lt;service</span> <span class="na">name=</span><span class="s">&quot;userservice_node04&quot;</span> <span class="na">value=</span><span class="s">&quot;org.redkale.demo.UserService&quot;</span> <span class="na">groups=</span><span class="s">&quot;USER_SERVICE_NODE03&quot;</span><span class="nt">/&gt;</span>
<span class="nt">&lt;/services&gt;</span>
<span class="nt">&lt;/server&gt;</span>
<span class="nt">&lt;/application&gt;</span></pre></div>
<br/>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;由以上几种部署方式的范例可以看出Redkale提供了非常强大的架构集中式到微服务架构不需要增加修改一行代码即可随意切换即使网关式部署也只是新增很少的代码就可切换且不影响其他服务。真正可以做到敏捷开发复杂的系统都可如小系统般快速地开发出来。<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;为了降低接入层与业务层代码的耦合, 可以将Service分接口与实现两个类接入层只加载接口包、业务层使用实现包。
</p>
<br/>
<h3><a id="redkale_confxml" href="#" aria-hidden="true"></a>appplication.xml 配置说明</h3>
<div class="highlight"><pre><span></span><span class="cp">&lt;?xml version="1.0" encoding="UTF-8"?&gt;</span>
<span class="c">&lt;!-- </span>
<span class="c"> 文件说明:</span>
<span class="c"> ${APP_HOME} 指当前程序的根目录APP_HOME</span>
<span class="c"> 没注明唯一的节点可多个存在</span>
<span class="c"> required 被声明required的属性值不能为空</span>
<span class="c"> </span>
<span class="c"> group</span>
<span class="c"> / / \ \ </span>
<span class="c"> / / \ \ </span>
<span class="c"> / / \ \ </span>
<span class="c"> node1 node2 node3 node4</span>
<span class="c"> / \ </span>
<span class="c"> / \</span>
<span class="c"> / \</span>
<span class="c"> / \</span>
<span class="c"> serviceid1 serviceid2</span>
<span class="c"> / \ / \</span>
<span class="c"> serviceid1_name1 serviceid1_name2 serviceid2_name1 serviceid2_name2 </span>
<span class="c">--&gt;</span>
<span class="c">&lt;!-- </span>
<span class="c"> address: 本地局域网的IP地址 默认值为默认网卡的ip当不使用默认值需要指定值如192.168.1.22</span>
<span class="c"> port: required 程序的管理Server的端口用于关闭或者与监管系统进行数据交互</span>
<span class="c"> lib: 加上额外的lib路径,多个路径用分号;隔开; 默认为空。 例如: ${APP_HOME}/lib/a.jar;${APP_HOME}/lib2/b.jar;</span>
<span class="c">--&gt;</span>
<span class="p">&lt;</span><span class="nt">application</span> <span class="na">port</span><span class="o">=</span><span class="s">"6560"</span> <span class="na">lib</span><span class="o">=</span><span class="s">""</span><span class="p">&gt;</span>
<span class="c">&lt;!-- </span>
<span class="c"> 【节点全局唯一】</span>
<span class="c"> 所有服务所需的资源 </span>
<span class="c"> --&gt;</span>
<span class="p">&lt;</span><span class="nt">resources</span><span class="p">&gt;</span>
<span class="c">&lt;!--</span>
<span class="c"> 【节点全局唯一】</span>
<span class="c"> transport节点只能有一个用于配置所有Transport的池参数没配置该节点将自动创建一个。</span>
<span class="c"> threads 线程总数, 默认: &lt;group&gt;节点数*CPU核数*2</span>
<span class="c"> bufferCapacity: ByteBuffer的初始化大小 默认: 8K; </span>
<span class="c"> bufferPoolSize ByteBuffer池的大小默认: 线程总数*4</span>
<span class="c"> strategy: 远程请求的负载均衡策略, 必须是org.redkale.net.TransportStrategy的实现类</span>
<span class="c"> --&gt;</span>
<span class="p">&lt;</span><span class="nt">transport</span> <span class="na">bufferCapacity</span><span class="o">=</span><span class="s">"8K"</span> <span class="na">bufferPoolSize</span><span class="o">=</span><span class="s">"32"</span> <span class="na">threads</span><span class="o">=</span><span class="s">"32"</span><span class="p">/&gt;</span>
<span class="c">&lt;!--</span>
<span class="c"> 一个组包含多个node 同一Service服务可以由多个进程提供这些进程称为一个GROUP且同一GROUP内的进程必须在同一机房或局域网内</span>
<span class="c"> 一个group节点对应一个 Transport 对象。</span>
<span class="c"> name: 服务组ID长度不能超过11个字节. 默认为空字符串。 注意: name不能包含$符号。</span>
<span class="c"> protocol值范围UDP TCP 默认TCP</span>
<span class="c"> subprotocol: 子协议,预留字段。默认值为空</span>
<span class="c"> 注意: 一个node只能所属一个group。只要存在protocol=SNCP的Server节点信息 就必须有group节点信息。</span>
<span class="c"> --&gt;</span>
<span class="p">&lt;</span><span class="nt">group</span> <span class="na">name</span><span class="o">=</span><span class="s">""</span> <span class="na">protocol</span><span class="o">=</span><span class="s">"TCP"</span><span class="p">&gt;</span>
<span class="c">&lt;!--</span>
<span class="c"> 需要将本地node的addr与port列在此处。</span>
<span class="c"> 同一个&lt;node&gt;节点值只能存在一个&lt;group&gt;节点内即同一个addr+port只能属于一个group。</span>
<span class="c"> addr: required IP地址</span>
<span class="c"> port: required 端口</span>
<span class="c"> --&gt;</span>
<span class="p">&lt;</span><span class="nt">node</span> <span class="na">addr</span><span class="o">=</span><span class="s">"127.0.0.1"</span> <span class="na">port</span><span class="o">=</span><span class="s">"7070"</span><span class="p">/&gt;</span>
<span class="p">&lt;/</span><span class="nt">group</span><span class="p">&gt;</span>
<span class="c">&lt;!--</span>
<span class="c"> 全局的数据源设置, 可以是CacheSource、DataSource JDBC的DataSource通常通过persistence.xml配置此处多用于CacheSource的配置</span>
<span class="c"> name: 资源名,用于依赖注入。</span>
<span class="c"> value类名必须是CacheSource或DataSource的子类且必须实现Service接口。如果是DataSource.class系统自动映射成DataJdbcSource.class</span>
<span class="c"> groups: 指定groups。</span>
<span class="c"> xxx: 其他属性与子节点通过Service.init方法传入的AnyValue获取。</span>
<span class="c"> --&gt;</span>
<span class="p">&lt;</span><span class="nt">source</span> <span class="na">name</span><span class="o">=</span><span class="s">"redis"</span> <span class="na">value</span><span class="o">=</span><span class="s">"org.redkalex.cache.RedisCacheSource"</span> <span class="na">xxx</span><span class="o">=</span><span class="s">"16"</span><span class="p">&gt;</span>
<span class="p">&lt;</span><span class="nt">node</span> <span class="na">addr</span><span class="o">=</span><span class="s">"127.0.0.1"</span> <span class="na">port</span><span class="o">=</span><span class="s">"7070"</span><span class="p">/&gt;</span>
<span class="p">&lt;/</span><span class="nt">source</span><span class="p">&gt;</span>
<span class="c">&lt;!--</span>
<span class="c"> Application启动的监听事件,可配置多个节点</span>
<span class="c"> value: 类名必须是ApplicationListener的子类</span>
<span class="c"> --&gt;</span>
<span class="p">&lt;</span><span class="nt">listener</span> <span class="na">value</span><span class="o">=</span><span class="s">"org.redkalex.xxx.XXXApplicationListener"</span><span class="p">/&gt;</span>
<span class="c">&lt;!-- </span>
<span class="c"> 【节点全局唯一】</span>
<span class="c"> 全局的参数配置, 可以通过@Resource(name="property.xxxxxx") 进行注入&lt;property&gt;的信息, 被注解的字段类型只能是String、primitive class</span>
<span class="c"> 如果name是system.property.开头的值将会在进程启动时进行System.setProperty("yyyy", "YYYYYY")操作。</span>
<span class="c"> 如果name是mimetype.property.开头的值将会在进程启动时进行MimeType.add("yyyy", "YYYYYY")操作。</span>
<span class="c"> load: 加载文件,多个用;隔开。</span>
<span class="c"> 默认置入的system.property.的有:</span>
<span class="c"> System.setProperty("convert.json.tiny", "true");</span>
<span class="c"> System.setProperty("convert.bson.tiny", "true");</span>
<span class="c"> System.setProperty("convert.json.pool.size", "128");</span>
<span class="c"> System.setProperty("convert.bson.pool.size", "128");</span>
<span class="c"> System.setProperty("convert.json.writer.buffer.defsize", "4096");</span>
<span class="c"> System.setProperty("convert.bson.writer.buffer.defsize", "4096");</span>
<span class="c"> </span>
<span class="c"> &lt;properties&gt;节点下也可包含非&lt;property&gt;节点.</span>
<span class="c">&lt;property&gt;其节点可以通过@Resource(name="properties.xxxxxx")进行注入, 被注解的字段类型只能是AnyValue、AnyValue[]</span>
<span class="c"> --&gt;</span>
<span class="p">&lt;</span><span class="nt">properties</span> <span class="na">load</span><span class="o">=</span><span class="s">"config.properties"</span><span class="p">&gt;</span>
<span class="p">&lt;</span><span class="nt">property</span> <span class="na">name</span><span class="o">=</span><span class="s">"system.property.yyyy"</span> <span class="na">value</span><span class="o">=</span><span class="s">"YYYYYY"</span><span class="p">/&gt;</span>
<span class="p">&lt;</span><span class="nt">property</span> <span class="na">name</span><span class="o">=</span><span class="s">"xxxxxx"</span> <span class="na">value</span><span class="o">=</span><span class="s">"XXXXXXXX"</span><span class="p">/&gt;</span>
<span class="p">&lt;</span><span class="nt">property</span> <span class="na">name</span><span class="o">=</span><span class="s">"xxxxxx"</span> <span class="na">value</span><span class="o">=</span><span class="s">"XXXXXXXX"</span><span class="p">/&gt;</span>
<span class="p">&lt;</span><span class="nt">property</span> <span class="na">name</span><span class="o">=</span><span class="s">"xxxxxx"</span> <span class="na">value</span><span class="o">=</span><span class="s">"XXXXXXXX"</span><span class="p">/&gt;</span>
<span class="p">&lt;/</span><span class="nt">properties</span><span class="p">&gt;</span>
<span class="p">&lt;/</span><span class="nt">resources</span><span class="p">&gt;</span>
<span class="c">&lt;!--</span>
<span class="c"> protocol: required server所启动的协议Redkale内置的有HTTP、SNCP、WATCH。协议均使用TCP实现; WATCH服务只能存在一个。</span>
<span class="c"> name: 服务的名称用于监控识别一个配置文件中的server.name不能重复,命名规则: 字母、数字、下划线</span>
<span class="c"> host: 服务所占address 默认: 0.0.0.0</span>
<span class="c"> port: required 服务所占端口 </span>
<span class="c"> root: 如果是web类型服务则包含页面 默认:{APP_HOME}/root</span>
<span class="c"> lib: server额外的class目录 默认为${APP_HOME}/libs/*; </span>
<span class="c"> excludelibs: 排除lib.path与excludes中的正则表达式匹配的路径, 多个正则表达式用分号;隔开</span>
<span class="c"> charset: 文本编码, 默认: UTF-8</span>
<span class="c"> backlog: 默认10K</span>
<span class="c"> threads 线程总数, 默认: CPU核数*8</span>
<span class="c"> maxconns最大连接数, 小于1表示无限制 默认: 0</span>
<span class="c"> maxbody: request.body最大值 默认: 64K</span>
<span class="c"> bufferCapacity: ByteBuffer的初始化大小 默认: 8K; 如果是HTTP协议则默认: 16K + 16B (兼容HTTP 2.0、WebSocket)</span>
<span class="c"> bufferPoolSize ByteBuffer池的大小线程总数*4</span>
<span class="c"> responsePoolSize Response池的大小线程总数*2</span>
<span class="c"> readTimeoutSecond: 读操作超时秒数, 默认0 表示永久不超时</span>
<span class="c"> writeTimeoutSecond: 写操作超时秒数, 默认0 表示永久不超时</span>
<span class="c"> interceptor: 启动/关闭NodeServer时被调用的拦截器实现类必须是org.redkale.boot.NodeInterceptor的子类默认为null</span>
<span class="c"> --&gt;</span>
<span class="p">&lt;</span><span class="nt">server</span> <span class="na">protocol</span><span class="o">=</span><span class="s">"HTTP"</span> <span class="na">host</span><span class="o">=</span><span class="s">"127.0.0.1"</span> <span class="na">port</span><span class="o">=</span><span class="s">"6060"</span> <span class="na">root</span><span class="o">=</span><span class="s">"root"</span> <span class="na">lib</span><span class="o">=</span><span class="s">""</span><span class="p">&gt;</span>
<span class="c">&lt;!-- </span>
<span class="c"> 加载所有的Service服务;</span>
<span class="c"> 在同一个进程中同一个name同一类型的Service将共用同一个实例</span>
<span class="c"> autoload="true" 默认值. 自动加载classpath下所有的Service类 </span>
<span class="c"> autoload="false" 需要显著的指定Service类</span>
<span class="c"> includes 当autoload="true" 拉取类名与includes中的正则表达式匹配的类, 多个正则表达式用分号;隔开</span>
<span class="c"> excludes 当autoload="true" 排除类名与excludes中的正则表达式匹配的类, 多个正则表达式用分号;隔开 </span>
<span class="c"> groups: 所属组的节点,多个节点值用;隔开如果配置文件中存在多个SNCP协议的Server节点需要显式指定group属性.</span>
<span class="c"> 当 protocol == SNCP 时 group表示当前Server与哪些节点组关联。</span>
<span class="c"> 当 protocol != SNCP 时 group只能是空或者一个group的节点值不能为多个节点值。</span>
<span class="c"> --&gt;</span>
<span class="p">&lt;</span><span class="nt">services</span> <span class="na">autoload</span><span class="o">=</span><span class="s">"true"</span> <span class="na">includes</span><span class="o">=</span><span class="s">""</span> <span class="na">excludes</span><span class="o">=</span><span class="s">""</span><span class="p">&gt;</span>
<span class="c">&lt;!-- 显著加载指定的Service的接口类 --&gt;</span>
<span class="p">&lt;</span><span class="nt">service</span> <span class="na">value</span><span class="o">=</span><span class="s">"com.xxx.XXX1Service"</span><span class="p">/&gt;</span>
<span class="c">&lt;!-- </span>
<span class="c"> name: 显式指定name覆盖默认的空字符串值。 注意: name不能包含$符号。</span>
<span class="c"> groups: 显式指定groups覆盖&lt;services&gt;节点的groups默认值。</span>
<span class="c"> ignore: 是否禁用, 默认为false。</span>
<span class="c"> --&gt;</span>
<span class="p">&lt;</span><span class="nt">service</span> <span class="na">value</span><span class="o">=</span><span class="s">"com.xxx.XXX2Service"</span> <span class="na">name</span><span class="o">=</span><span class="s">""</span> <span class="na">groups</span><span class="o">=</span><span class="s">"xxx;yyy"</span><span class="p">/&gt;</span>
<span class="c">&lt;!-- 给Service增加配置属性 --&gt;</span>
<span class="p">&lt;</span><span class="nt">service</span> <span class="na">value</span><span class="o">=</span><span class="s">"com.xxx.XXX1Service"</span><span class="p">&gt;</span>
<span class="c">&lt;!-- property值在public void init(AnyValue conf)方法中可以通过AnyValue properties=conf.getAnyValue("properties")获取 --&gt;</span>
<span class="p">&lt;</span><span class="nt">property</span> <span class="na">name</span><span class="o">=</span><span class="s">"xxxxxx"</span> <span class="na">value</span><span class="o">=</span><span class="s">"XXXXXXXX"</span><span class="p">/&gt;</span>
<span class="p">&lt;</span><span class="nt">property</span> <span class="na">name</span><span class="o">=</span><span class="s">"xxxxxx"</span> <span class="na">value</span><span class="o">=</span><span class="s">"XXXXXXXX"</span><span class="p">/&gt;</span>
<span class="p">&lt;/</span><span class="nt">service</span><span class="p">&gt;</span>
<span class="p">&lt;/</span><span class="nt">services</span><span class="p">&gt;</span>
<span class="c">&lt;!-- </span>
<span class="c"> 加载所有的Filter服务;</span>
<span class="c"> autoload="true" 默认值. </span>
<span class="c"> autoload="false" 需要显著的指定Filter类</span>
<span class="c"> includes 当autoload="true" 拉取类名与includes中的正则表达式匹配的类, 多个正则表达式用分号;隔开</span>
<span class="c"> excludes 当autoload="true" 排除类名与excludes中的正则表达式匹配的类, 多个正则表达式用分号;隔开 </span>
<span class="c"> --&gt;</span>
<span class="p">&lt;</span><span class="nt">filters</span> <span class="na">autoload</span><span class="o">=</span><span class="s">"true"</span> <span class="na">includes</span><span class="o">=</span><span class="s">""</span> <span class="na">excludes</span><span class="o">=</span><span class="s">""</span><span class="p">&gt;</span>
<span class="c">&lt;!-- </span>
<span class="c"> 显著加载指定的Filter类</span>
<span class="c"> value=: Filter类名。必须与Server的协议层相同HTTP必须是HttpFilter</span>
<span class="c"> ignore: 是否禁用, 默认为false。</span>
<span class="c"> --&gt;</span>
<span class="c">&lt;!-- 显著加载指定的Filter类 --&gt;</span>
<span class="p">&lt;</span><span class="nt">filter</span> <span class="na">value</span><span class="o">=</span><span class="s">"com.xxx.XXX1Filter"</span><span class="p">/&gt;</span>
<span class="c">&lt;!-- 给Filter增加配置属性 --&gt;</span>
<span class="p">&lt;</span><span class="nt">filter</span> <span class="na">value</span><span class="o">=</span><span class="s">"com.xxx.XXX12Filter"</span><span class="p">&gt;</span>
<span class="c">&lt;!-- property值在public void init(AnyValue conf)方法中可以通过AnyValue properties=conf.getAnyValue("properties")获取 --&gt;</span>
<span class="p">&lt;</span><span class="nt">property</span> <span class="na">name</span><span class="o">=</span><span class="s">"xxxxxx"</span> <span class="na">value</span><span class="o">=</span><span class="s">"XXXXXXXX"</span><span class="p">/&gt;</span>
<span class="p">&lt;</span><span class="nt">property</span> <span class="na">name</span><span class="o">=</span><span class="s">"xxxxxx"</span> <span class="na">value</span><span class="o">=</span><span class="s">"XXXXXXXX"</span><span class="p">/&gt;</span>
<span class="p">&lt;/</span><span class="nt">filter</span><span class="p">&gt;</span>
<span class="p">&lt;/</span><span class="nt">filters</span><span class="p">&gt;</span>
<span class="c">&lt;!-- </span>
<span class="c"> REST的核心配置项</span>
<span class="c"> 当Server为HTTP协议时, rest节点才有效。存在[rest]节点则Server启动时会加载REST服务, 节点可以多个,(WATCH协议不需要设置系统会自动生成)</span>
<span class="c"> path: servlet的ContextPath前缀 默认为空</span>
<span class="c"> base: REST服务的BaseServlet必须是 org.redkale.net.http.HttpServlet 的子类,且子类必须标记@HttpUserType。</span>
<span class="c"> autoload默认值"true" 默认值. 加载当前server所能使用的Servce对象; </span>
<span class="c"> includes当autoload="true" 拉取类名与includes中的正则表达式匹配的类, 多个正则表达式用分号;隔开</span>
<span class="c"> excludes当autoload="true" 排除类名与excludes中的正则表达式匹配的类, 多个正则表达式用分号;隔开</span>
<span class="c"> --&gt;</span>
<span class="p">&lt;</span><span class="nt">rest</span> <span class="na">path</span><span class="o">=</span><span class="s">"/pipes"</span> <span class="na">base</span><span class="o">=</span><span class="s">"org.redkale.net.http.HttpServlet"</span> <span class="na">autoload</span><span class="o">=</span><span class="s">"true"</span> <span class="na">includes</span><span class="o">=</span><span class="s">""</span> <span class="na">excludes</span><span class="o">=</span><span class="s">""</span><span class="p">&gt;</span>
<span class="c">&lt;!-- </span>
<span class="c"> value: Service类名列出的表示必须被加载的Service对象</span>
<span class="c"> ignore: 是否忽略设置为true则不会加载该Service对象默认值为false</span>
<span class="c"> --&gt;</span>
<span class="p">&lt;</span><span class="nt">service</span> <span class="na">value</span><span class="o">=</span><span class="s">"com.xxx.XXXXService"</span><span class="p">/&gt;</span>
<span class="c">&lt;!-- </span>
<span class="c"> value: WebSocket类名列出的表示必须被加载且标记为@RestWebSocket的WebSocket对象</span>
<span class="c"> ignore: 是否忽略设置为true则不会加载该RestWebSocket对象默认值为false</span>
<span class="c"> --&gt;</span>
<span class="p">&lt;</span><span class="nt">websocket</span> <span class="na">value</span><span class="o">=</span><span class="s">"com.xxx.XXXXRestWebSocket"</span><span class="p">/&gt;</span>
<span class="p">&lt;/</span><span class="nt">rest</span><span class="p">&gt;</span>
<span class="c">&lt;!--</span>
<span class="c"> 【节点在&lt;server&gt;中唯一】</span>
<span class="c"> 当Server为HTTP协议时, request节点才有效。</span>
<span class="c"> remoteaddr 节点: 替换请求方节点的IP地址 通常请求方是由nginx等web静态服务器转发过的则需要配置该节点。</span>
<span class="c"> 且value值只能是以request.headers.开头表示从request.headers中获取对应的header值。</span>
<span class="c"> 例如下面例子获取request.getRemoteAddr()值如果header存在X-RemoteAddress值则返回X-RemoteAddress值不存在返回getRemoteAddress()。</span>
<span class="c"> --&gt;</span>
<span class="p">&lt;</span><span class="nt">request</span><span class="p">&gt;</span>
<span class="p">&lt;</span><span class="nt">remoteaddr</span> <span class="na">value</span><span class="o">=</span><span class="s">"request.headers.X-RemoteAddress"</span><span class="p">/&gt;</span>
<span class="p">&lt;/</span><span class="nt">request</span><span class="p">&gt;</span>
<span class="c">&lt;!--</span>
<span class="c"> 【节点在&lt;server&gt;中唯一】</span>
<span class="c"> 当Server为HTTP协议时, response节点才有效。</span>
<span class="c"> defcookie 节点: 当response里输出的cookie没有指定domain 和path时使用该节点的默认值。</span>
<span class="c"> 如果addheader、setheader 的value值以request.parameters.开头则表示从request.parameters中获取对应的parameter值</span>
<span class="c"> 如果addheader、setheader 的value值以request.headers.开头则表示从request.headers中获取对应的header值</span>
<span class="c"> 例如下面例子是在Response输出header时添加两个header一个addHeader 一个setHeader</span>
<span class="c"> options 节点: 设置了该节点却auto=true当request的method=OPTIONS自动设置addheader、setheader并返回200状态码</span>
<span class="c"> --&gt;</span>
<span class="p">&lt;</span><span class="nt">response</span><span class="p">&gt;</span>
<span class="p">&lt;</span><span class="nt">defcookie</span> <span class="na">domain</span><span class="o">=</span><span class="s">""</span> <span class="na">path</span><span class="o">=</span><span class="s">""</span><span class="p">/&gt;</span>
<span class="p">&lt;</span><span class="nt">addheader</span> <span class="na">name</span><span class="o">=</span><span class="s">"Access-Control-Allow-Origin"</span> <span class="na">value</span><span class="o">=</span><span class="s">"request.headers.Origin"</span> <span class="p">/&gt;</span>
<span class="p">&lt;</span><span class="nt">setheader</span> <span class="na">name</span><span class="o">=</span><span class="s">"Access-Control-Allow-Headers"</span> <span class="na">value</span><span class="o">=</span><span class="s">"request.headers.Access-Control-Request-Headers"</span><span class="p">/&gt;</span>
<span class="p">&lt;</span><span class="nt">setheader</span> <span class="na">name</span><span class="o">=</span><span class="s">"Access-Control-Allow-Credentials"</span> <span class="na">value</span><span class="o">=</span><span class="s">"true"</span><span class="p">/&gt;</span>
<span class="p">&lt;</span><span class="nt">options</span> <span class="na">auto</span><span class="o">=</span><span class="s">"true"</span> <span class="p">/&gt;</span>
<span class="p">&lt;/</span><span class="nt">response</span><span class="p">&gt;</span>
<span class="c">&lt;!-- </span>
<span class="c"> 【节点在&lt;server&gt;中唯一】</span>
<span class="c"> 当Server为HTTP协议时ResourceServlet才有效. 默认存在一个有默认属性的resource-servlet节点</span>
<span class="c"> webroot: web资源的根目录, 默认取server节点中的root值</span>
<span class="c"> servlet: 静态资源HttpServlet的实现默认使用HttpResourceServlet</span>
<span class="c"> index : 启始页默认值index.html</span>
<span class="c"> --&gt;</span>
<span class="p">&lt;</span><span class="nt">resource-servlet</span> <span class="na">webroot</span><span class="o">=</span><span class="s">"root"</span> <span class="na">index</span><span class="o">=</span><span class="s">"index.html"</span><span class="p">&gt;</span>
<span class="c">&lt;!--</span>
<span class="c"> 【节点在&lt;resource-servlet&gt;中唯一】</span>
<span class="c"> 资源缓存的配置, 默认存在一个含默认属性的caches节点</span>
<span class="c"> limit: 资源缓存最大容量, 默认: 0, 为0表示不缓存 单位可以是B、K、M、G不区分大小写</span>
<span class="c"> lengthmax: 可缓存的文件大小上限, 默认: 1M超过1M的文件不会被缓存</span>
<span class="c"> watch: 是否监控缓存文件的变化, 默认为false不监控</span>
<span class="c"> --&gt;</span>
<span class="p">&lt;</span><span class="nt">cache</span> <span class="na">limit</span><span class="o">=</span><span class="s">"0M"</span> <span class="na">lengthmax</span><span class="o">=</span><span class="s">"1M"</span> <span class="na">watch</span><span class="o">=</span><span class="s">"false"</span><span class="p">/&gt;</span>
<span class="c">&lt;!--</span>
<span class="c"> 支持类似nginx中的rewrite 目前只支持静态资源对静态资源的跳转。</span>
<span class="c"> type: 匹配的类型, 目前只支持location(匹配requestURI), 默认: location</span>
<span class="c"> match: 匹配的正则表达式</span>
<span class="c"> forward: 需跳转后的资源链接</span>
<span class="c"> 例如下面例子是将/xxx-yyy.html的页面全部跳转到/xxx.html</span>
<span class="c"> --&gt;</span>
<span class="p">&lt;</span><span class="nt">rewrite</span> <span class="na">type</span><span class="o">=</span><span class="s">"location"</span> <span class="na">match</span><span class="o">=</span><span class="s">"^/([^-]+)-[^-\.]+\.html(.*)"</span> <span class="na">forward</span><span class="o">=</span><span class="s">"/$1.html"</span><span class="p">/&gt;</span>
<span class="p">&lt;/</span><span class="nt">resource-servlet</span><span class="p">&gt;</span>
<span class="c">&lt;!-- </span>
<span class="c"> 加载所有的Servlet服务;</span>
<span class="c"> path: servlet的ContextPath前缀 默认为空</span>
<span class="c"> autoload="true" 默认值. 自动加载classpath下所有的Servlet类 </span>
<span class="c"> autoload="false" 需要显著的指定Service类</span>
<span class="c"> includes 当autoload="true" 拉取类名与includes中的正则表达式匹配的类, 多个正则表达式用分号;隔开</span>
<span class="c"> excludes 当autoload="true" 排除类名与excludes中的正则表达式匹配的类, 多个正则表达式用分号;隔开</span>
<span class="c"> --&gt;</span>
<span class="p">&lt;</span><span class="nt">servlets</span> <span class="na">path</span><span class="o">=</span><span class="s">"/pipes"</span> <span class="na">autoload</span><span class="o">=</span><span class="s">"true"</span> <span class="na">includes</span><span class="o">=</span><span class="s">""</span> <span class="na">excludes</span><span class="o">=</span><span class="s">""</span><span class="p">&gt;</span>
<span class="c">&lt;!-- </span>
<span class="c"> 显著加载指定的Servlet类</span>
<span class="c"> value=: Servlet类名。必须与Server的协议层相同HTTP必须是HttpServlet</span>
<span class="c"> ignore: 是否禁用, 默认为false。</span>
<span class="c"> --&gt;</span>
<span class="p">&lt;</span><span class="nt">servlet</span> <span class="na">value</span><span class="o">=</span><span class="s">"com.xxx.XXX1Servlet"</span> <span class="p">/&gt;</span>
<span class="p">&lt;</span><span class="nt">servlet</span> <span class="na">value</span><span class="o">=</span><span class="s">"com.xxx.XXX2Servlet"</span> <span class="p">/&gt;</span>
<span class="p">&lt;</span><span class="nt">servlet</span> <span class="na">value</span><span class="o">=</span><span class="s">"com.xxx.XXX3Servlet"</span> <span class="p">&gt;</span>
<span class="p">&lt;</span><span class="nt">property</span> <span class="na">name</span><span class="o">=</span><span class="s">"xxxxxx"</span> <span class="na">value</span><span class="o">=</span><span class="s">"XXXXXXXX"</span><span class="p">/&gt;</span>
<span class="p">&lt;</span><span class="nt">property</span> <span class="na">name</span><span class="o">=</span><span class="s">"yyyyyy"</span> <span class="na">value</span><span class="o">=</span><span class="s">"YYYYYYYY"</span><span class="p">/&gt;</span>
<span class="p">&lt;/</span><span class="nt">servlet</span><span class="p">&gt;</span>
<span class="p">&lt;/</span><span class="nt">servlets</span><span class="p">&gt;</span>
<span class="p">&lt;/</span><span class="nt">server</span><span class="p">&gt;</span>
<span class="p">&lt;</span><span class="nt">server</span> <span class="na">protocol</span><span class="o">=</span><span class="s">"SNCP"</span> <span class="na">host</span><span class="o">=</span><span class="s">"127.0.0.1"</span> <span class="na">port</span><span class="o">=</span><span class="s">"7070"</span> <span class="na">root</span><span class="o">=</span><span class="s">"root"</span> <span class="na">lib</span><span class="o">=</span><span class="s">""</span><span class="p">&gt;</span>
<span class="c">&lt;!-- 参数完全同上 --&gt;</span>
<span class="p">&lt;</span><span class="nt">services</span> <span class="na">autoload</span><span class="o">=</span><span class="s">"true"</span> <span class="na">includes</span><span class="o">=</span><span class="s">""</span> <span class="na">excludes</span><span class="o">=</span><span class="s">""</span> <span class="p">/&gt;</span>
<span class="p">&lt;/</span><span class="nt">server</span><span class="p">&gt;</span>
<span class="p">&lt;/</span><span class="nt">application</span><span class="p">&gt;</span>
</pre></div>
<footer class="site-footer">
<span class="site-footer-owner">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;欢迎加入Redkale QQ群: 527523235</span>
</footer>
</section>
<script>
var _hmt = _hmt || [];
(function () {
var hm = document.createElement("script");
hm.src = "//hm.baidu.com/hm.js?b4e05d7de8b5f3401dd93e3c6b35ffa5";
var s = document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(hm, s);
})();
</script>
</body>
</html>