Files
redkale/article_regain.html
Redkale d731dea66f
2021-04-28 21:44:46 +08:00

136 lines
22 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>Redkale 让你重新认识Java</h3>
<p>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Java 已经22岁了依靠强大的功能、庞大的开发社区和无人能及的生态系统长期占据世界编程语言排行榜首成为当之无愧的业界之王。本人在大学时期被这种很有艺术性的开发语言所吸引果断抛弃C学习方式很简单只看JDK API源码直到现在都是如此。刚毕业就一直从事Java开发方面的工作至今也有十来年了。从JSP、WebWork到Struts、JSF从JDBC、Hibernate到TopLink、JPA。从NIO、Mina到Netty、Grizzly。很多框架都用过研究过。后来渐渐觉得各阶段主流的框架功能很强大设计理念也很好但是我们大部分情况只使用其中一小部分功能框架在实现上性能也普遍一般(除少数追求性能的框架)且适应新版JDK发布的版本普及也会滞后两三年以上。慢慢地发现用了那么多整合的框架并没有比JBuilder时代的开发速度敏捷多少很多时候在原始的Servlet、JDBC基础上做一定的封装就能满足大部分的需求。个人觉得一个优秀的框架除了保证性能和稳定性也要注重简易性而不是满足开发者需求的同时大量依赖包、繁琐的配置(过多的配置性的注解也是配置)和臃肿的jar刷其存在感。在长期看JDK API源码、学习开源框架设计理念和参考JavaEE规范接口设计的习惯下自然有了自己的思路和设计想法开始学写自己的框架。于是在2015年框架基本雏形出来并命名为<a href="http://redkale.org" target="_blank">Redkale</a>2016年正式开源。<br/>
</p>
<p>&nbsp;&nbsp;<b>太臃肿</b></p>
<p>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;如今在Java界Tomcat、Struts2、Hibernate、MyBatis、Jetty、Spring MVC/Spring Boot/Spring XXX这些框架大家都耳熟能详似乎不懂其中一二都不好意思说自己会JavaSpring已经成了Java的代名词很多四五年以上的开发人员只识开源框架不识JDK谈起这些框架的原理、优缺点各种SOA、集群、分布式、事务、微服务概念头头是道都可以出书了但是写出来的代码或做出来的数据结构设计堪比实习生。2004年发布正式版的Spring以其轻量著称一战成名打败了J2EE成为Java事实上的"标准"。然而经过十几年的发展其生态越来越庞大功能的增多复杂的配置兼容性历史包袱使得整个框架体系越来越臃肿还有不计其数的衍生插件已经不比当年J2EE轻多少了。在那个JBuilder还是主流IDE的年代建一个Web系统还是比较简单除了Tomcat比较大点其他都算轻量。现在很多人建一个Web项目需要复杂的Maven建工程一行代码还没开始写仅仅是导入SSH/SSM这些框架就需要好几十M还得进行一堆SSH配置,简单的日志都需要配备log4j/snf4j。可能只是简单的管理系统必须要搞这么复杂吗 现在一个1-2M的框架大家都认为是轻量级MyBatis是JDBC基础上的再次封装jar包大小近6M但比Hibernate还是轻量些。这些只是基础框架如果系统还需要其他功能性的框架(Lucene、Mail、Json) 会使开发包更大。同时大量的开源框架抑制了新JDK的普及NIO出来都十五年 AIO(NIO.2)也出来六年了如今还有很多人把NIO给贴上高性能的标签JDK 5——Java第一个重大更新的版本在2004年发布直到五-六年后Spring的注解方式才得到普及(Spring旧版本xml方式普及度高) Java第二个重大更新的版本JDK 8发布也有三年了大部分人还停留在只识语法糖Lambda的程度在JDK功能越来越强大的情况下开发Java系统并不简化多少。相对于现在流行的NodeJs做个Web系统来说Java就是个巨无霸。其实呢Java无需这么复杂真的可以很简单。
</p>
<p>&nbsp;&nbsp;<b>异步呢</b></p>
<p>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;用Java开发异步系统是件很难的事情首先Java规范中异步接口很少Servlet 3.0虽然支持异步也出来好几年了但现在直接用Servlet写代码的人已经不多而基于Servlet的Struts、Spring Boot这些框架又没把异步太当回事基本都是实现的Servet同步方法。其次JDBC更是迄今为止还没有异步接口基于JDBC的Hibernate、MyBatis同样不会有异步接口。再者开源框架以异步接口为主的凤毛麟角。 所以Java程序员在写业务代码时基本都是用同步方式特别是最耗时的数据源操作JDBC无法异步。
</p>
<div class="highlight"><pre><span></span><span class="nd">@WebServlet</span><span class="o">(</span><span class="n">value</span> <span class="o">=</span> <span class="o">{</span><span class="s">&quot;/order/*&quot;</span><span class="o">},</span> <span class="n">comment</span> <span class="o">=</span> <span class="s">&quot;订单模块&quot;</span><span class="o">)</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">OrderServlet</span> <span class="kd">extends</span> <span class="n">HttpBaseServlet</span> <span class="o">{</span>
<span class="nd">@Resource</span>
<span class="kd">private</span> <span class="n">OrderService</span> <span class="n">service</span><span class="o">;</span>
<span class="nd">@HttpMapping</span><span class="o">(</span><span class="n">url</span> <span class="o">=</span> <span class="s">&quot;/order/find&quot;</span><span class="o">,</span> <span class="n">comment</span> <span class="o">=</span> <span class="s">&quot;查询单个订单&quot;</span><span class="o">)</span>
<span class="nd">@HttpParam</span><span class="o">(</span><span class="n">name</span> <span class="o">=</span> <span class="s">&quot;#&quot;</span><span class="o">,</span> <span class="n">type</span> <span class="o">=</span> <span class="kt">long</span><span class="o">.</span><span class="na">class</span><span class="o">,</span> <span class="n">comment</span> <span class="o">=</span> <span class="s">&quot;订单ID&quot;</span><span class="o">)</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">logout</span><span class="o">(</span><span class="n">HttpRequest</span> <span class="n">req</span><span class="o">,</span> <span class="n">HttpResponse</span> <span class="n">resp</span><span class="o">)</span> <span class="kd">throws</span> <span class="n">IOException</span> <span class="o">{</span>
<span class="kt">long</span> <span class="n">orderid</span> <span class="o">=</span> <span class="n">req</span><span class="o">.</span><span class="na">getRequstURILastPath</span><span class="o">(</span><span class="mi">0</span><span class="n">L</span><span class="o">);</span>
<span class="n">resp</span><span class="o">.</span><span class="na">finishJson</span><span class="o">(</span><span class="n">service</span><span class="o">.</span><span class="na">findOrder</span><span class="o">(</span><span class="n">orderid</span><span class="o">));</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="nd">@Comment</span><span class="o">(</span><span class="s">&quot;订单服务&quot;</span><span class="o">)</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">OrderService</span> <span class="kd">implements</span> <span class="n">Service</span> <span class="o">{</span>
<span class="nd">@Resource</span>
<span class="kd">private</span> <span class="n">DataSource</span> <span class="n">source</span><span class="o">;</span>
<span class="nd">@Comment</span><span class="o">(</span><span class="s">&quot;查询单个订单&quot;</span><span class="o">)</span>
<span class="kd">public</span> <span class="n">Order</span> <span class="nf">findOrder</span><span class="o">(</span><span class="kt">long</span> <span class="n">orderid</span><span class="o">)</span> <span class="o">{</span>
<span class="k">return</span> <span class="n">source</span><span class="o">.</span><span class="na">find</span><span class="o">(</span><span class="n">Order</span><span class="o">.</span><span class="na">class</span><span class="o">,</span> <span class="n">orderid</span><span class="o">);</span>
<span class="o">}</span>
<span class="o">}</span>
</pre></div>
<p>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;以上范例是大多数Java开发者的常规写法Servlet调用ServiceSerivce调用数据库操作返回结果都是同步操作, 而基于JDBC的开发使得最耗时的数据库操作占用了大量的线程时间即使HTTP使用NIO、AIO(NIO.2)都收效甚微。而在NodeJs里IO操作都是异步的。如下
</p>
<div class="highlight"><pre><span></span><span class="nx">http</span><span class="p">.</span><span class="nx">post</span><span class="p">(</span><span class="s">&quot;/url&quot;</span><span class="p">,</span> <span class="p">{</span><span class="nx">id</span><span class="o">:</span><span class="mi">10</span><span class="p">},</span> <span class="kd">function</span><span class="p">(</span><span class="nx">request</span><span class="p">,</span> <span class="nx">response</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">service</span><span class="p">.</span><span class="nx">getResource</span><span class="p">(</span><span class="nx">request</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">result</span><span class="p">){</span>
<span class="nx">response</span><span class="p">.</span><span class="nx">write</span><span class="p">(</span><span class="nx">JSON</span><span class="p">.</span><span class="nx">stringify</span><span class="p">(</span><span class="nx">result</span><span class="p">));</span>
<span class="nx">response</span><span class="p">.</span><span class="nx">end</span><span class="p">();</span>
<span class="p">});</span>
<span class="p">});</span>
<span class="kd">var</span> <span class="nx">mysql</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s">&#39;mysql&#39;</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">pool</span> <span class="o">=</span> <span class="nx">mysql</span><span class="p">.</span><span class="nx">createPool</span><span class="p">(</span><span class="nx">config</span><span class="p">);</span>
<span class="nx">pool</span><span class="p">.</span><span class="nx">getConnection</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">err</span><span class="p">,</span> <span class="nx">connection</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">connection</span><span class="p">.</span><span class="nx">query</span><span class="p">(</span> <span class="s">&#39;SELECT * FROM table&#39;</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">err</span><span class="p">,</span> <span class="nx">rows</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">connection</span><span class="p">.</span><span class="nx">end</span><span class="p">();</span>
<span class="p">});</span>
<span class="p">});</span>
</pre></div>
<p>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;这也是Nodejs做些小系统比Java还快。Java在语言和IO上的性能优势弥补不了同步来带的线程消耗。
</p>
<p>&nbsp;&nbsp;<b><a href="http://redkale.org" target="_blank">Redkale</a></b></p>
<p>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="http://redkale.org" target="_blank">Redkale</a> 一个全新设计的Java异步微服务框架。集HTTP、WebSocket、REST、JSON、RPC、DB操作、依赖注入等功能于一身<a href="http://repo.maven.apache.org/maven2/org/redkale/redkale/1.6.1/" target="_blank">redkale-1.6.1.jar</a> 包大小仅790K且不依赖任何第三方包。大部分框架自身就很庞大满足了开发者的需求同时也带来复杂的配置。如同上班只有三四里路要买辆汽车代步开车轻松的同时会带来车的保险保养堵车加油下车库找停车位等副作用 其效果还不如一辆自行车来得简单高效。<a href="http://redkale.org" target="_blank">Redkale</a> 返璞归真,抛弃沉重的历史包袱(javax.servlet、JPA等)基于JDK 8设计微服务架构尽可能挖掘新JDK的优势在保证高性能的情况下追求框架的简易性。其核心分三层结构接入层Servlet、逻辑层Service、数据层Source。 并且三层都支持异步接口从HTTP接收请求到Service处理逻辑再到Source拉取数据全程都可异步最大限度的提高CPU使用率。为适应前后台分工的开发场景<a href="http://redkale.org" target="_blank">Redkale</a>提供方便的API文档生成功能无需编写标准的Doc文档也能让前端开发人员知道后台API接口。<br>
</p>
<p>&nbsp;&nbsp;<b>Servlet</b></p>
<p>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;在API设计上<a href="http://redkale.org" target="_blank">Redkale</a>下足了功夫敢于抛弃标准。其HTTP服务不再是javax.servlet——J2EE中使用最多的规范的实现在接口形式上与NodeJs的HTTP模块很类似易于操作。Servlet规范对于现在的应用来说过于体系化。时下移动APP、发达的前端、高性能浏览器、静动分离、REST、分布式这些因素已经让JSP、PHP、ASP这些通过后台生成页面的集中式开发框架显得不适时宜。NodeJs中的HTTP模块源码不过十几K而Java里HTTP服务主流还是Tomcat——一个8M的重型机器。 <a href="http://redkale.org" target="_blank">Redkale</a>摒弃了已经落伍的规范和功能(JSP、InputStream/OutputStream操作、Session对象等)弱化Web概念HTTP与SNCP服务一样只是接入层无需做过重的设计。 <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;其他语言的HTTP框架在处理请求后大多是以response关闭整个请求处理的方式为主而Servlet规范却是在service方法执行后关闭Servlet3.0规范虽然支持异步显然与其他语言框架比比较生涩难懂其API使用方式还需与同步方式区别对待且接口设计本身就会导致实现上性能不佳而response关闭的方式天然的把同步与异步等同对待无论是当前线程还是另开线程处理请求都由response来结束请求处理。同样Servlet规范中WebSocket接口设计上也是过于复杂且只是针对协议本身的实现没有考虑大多开发者的使用场景WebSocket本质上就像一个keepalive的Http请求,雷同HttpServlet。所以<a href="http://redkale.org" target="_blank">Redkale</a>在设计WebSocket时尽量与HttpServlet形态保持一致同时还集成了分布式功能让开发者也可以很简单的实现多部署。 <br>
</p>
<p>&nbsp;&nbsp;<b>Service</b></p>
<p>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="http://redkale.org" target="_blank">Redkale</a>所有API设计中最精简的当属RPC功能RPC没有直接调用的API其功能依附在Service。RPC或类似功能的框架在Java里一直是比较重量级的从古老的Corba、RMI到后来的EJB、WebService还有其他很多RPC开源框架都有着复杂的配置和大量API学习成本有些还需要区分客户端和服务端(如WebService)。 Service不仅只是个逻辑层的规范定义还集成了很强大的RPC和异步调用功能远程模式的Service就是RPC功能系统在依赖注入过程中创建Service时通过基本的IP配置自动识别是创建本地模式的Service还是远程模式的Service远程模式的Service使用的就是RPC但在代码层Service的调用本地模式与远程模式完全一样。更神奇的是带有异步回调函数CompletionHandler 或返回类型为CompletableFuture的Service方法同样能执行远程模式。这种RPC的简易性是其他框架都无可匹敌的。REST风格的Service在接口设计上尽量减少注解性的配置同时保留灵活性,减少HttpServlet的编写。<br>
</p>
<p>&nbsp;&nbsp;<b>Source</b></p>
<p>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;除了开发类似数据库管理工具大部分情况下开发者只用基本的增删改查操作Hibernate、MyBatis这些框架对于对象新增/更新/删除和主键查找对象等接口定义都比较简单但是带有过滤条件的操作就变得难用。MyBatis需要配各种SQL大量if elseHibernate需要写HQL或SQLJPA规范需要写JPQL或使用Criteria功能。过滤查询、翻页查询、过滤修改、局部修改、过滤删除都是很常见的操作而主流ORM框架对这类操作进行简化程度很有限。<a href="http://redkale.org" target="_blank">Redkale</a> 结合常规的使用场景以JavaBean的方式提供过滤功能无需编写SQL或类似SQL的配置使过滤性的操作(删改查)API变得异常简单。DataSource另一个亮点是分表分库操作与单表操作的API一样。同时每个操作都提供成异步接口但是又限于JDBC的同步性DataSource的默认实现提供的异步接口也只是JDBC的同步操作若开发者追求性能极致的话可以使用AIO(NIO.2)技术编写不基于JDBC的DataSource异步实现。 DataSource提供的缓存功能还能保持进程间的同步(得利于RPC)。<br>
</p>
<p>&nbsp;&nbsp;<b>思维</b></p>
<p>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="http://redkale.org" target="_blank">Redkale</a> 追求大道至简不仅提供高性能的功能和简易的API还带来不同的设计思维。作为一名有追求的开发者不能只停留在API层面更多的是需要掌握设计能力一个好的设计方案往往能少写很多代码。Java里很多规范和框架就是考虑太过全面为了迎合各种良莠不齐的想法和设计。比如HTTP服务只是系统的一个接入层有必须设计ServletConfig、ServletContextListener、HttpSessionListener等这么多API吗开发者在系统初期养成定义全局的BaseHttpServlet这些基类的习惯就可以控制很多东西普通功能也无需去使用什么拦截器或AOP功能。提交表单前先将表单数据转换成JSON字符串传给后台后台的接口既可用于Web也可用于APP非要按原始表单提交那只能使用Struts这类笨重的框架了。再如DB操作开发者设计好的数据结构可以把关系型数据库当NoSQL数据库操作会发现对JDBC做一定的封装就可以基本杜绝写SQL。非要写存储过程、关联五六张表进行复杂查询再好的DB框架都满足不了你。再如DateDate对象的本质是long值很多人习惯性的数据库就用Date类型这样会增加很多麻烦增加数据库的通用性难度JSON还需要提供各种DateFormat如果使用long类型时间只交给页面去format就简单很多long的性能也更好。说了这么多只是想表达一个观点开发时摆脱传统思维的桎栲换个思路去思考很多东西会变得很简单。<br>
</p>
<p>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;想了解更多关于Redkale的资料 请访问Redkale官网: <a href="http://redkale.org" target="_blank">http://redkale.org</a>
</p>
<br/>
<p>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;转载请注明出处:<a href="https://redkale.org/article_regain.html" target="_blank">https://redkale.org/article_regain.html</a>
</p>
<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?aee2e6e1addaf28cd4e21e2d5a509123";
var s = document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(hm, s);
})();
</script>
</body>
</html>