136 lines
22 KiB
HTML
136 lines
22 KiB
HTML
<!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>
|
||
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> <b>太臃肿</b></p>
|
||
<p>
|
||
如今在Java界,Tomcat、Struts2、Hibernate、MyBatis、Jetty、Spring MVC/Spring Boot/Spring XXX这些框架大家都耳熟能详,似乎不懂其中一二都不好意思说自己会Java,Spring已经成了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> <b>异步呢</b></p>
|
||
<p>
|
||
用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">"/order/*"</span><span class="o">},</span> <span class="n">comment</span> <span class="o">=</span> <span class="s">"订单模块"</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">@WebMapping</span><span class="o">(</span><span class="n">url</span> <span class="o">=</span> <span class="s">"/order/find"</span><span class="o">,</span> <span class="n">comment</span> <span class="o">=</span> <span class="s">"查询单个订单"</span><span class="o">)</span>
|
||
<span class="nd">@WebParam</span><span class="o">(</span><span class="n">name</span> <span class="o">=</span> <span class="s">"#"</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">"订单ID"</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">"订单服务"</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">"查询单个订单"</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>
|
||
以上范例是大多数Java开发者的常规写法,Servlet调用Service,Serivce调用数据库操作返回结果,都是同步操作, 而基于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">"/url"</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">'mysql'</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">'SELECT * FROM table'</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>
|
||
这也是Nodejs做些小系统比Java还快。Java在语言和IO上的性能优势弥补不了同步来带的线程消耗。
|
||
</p>
|
||
|
||
<p> <b><a href="http://redkale.org" target="_blank">Redkale</a></b></p>
|
||
<p>
|
||
<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> <b>Servlet</b></p>
|
||
<p>
|
||
在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对象、Filter等),弱化Web概念,HTTP与SNCP服务一样,只是接入层,无需做过重的设计。 <br>
|
||
其他语言的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> <b>Service</b></p>
|
||
<p>
|
||
<a href="http://redkale.org" target="_blank">Redkale</a>所有API设计中最精简的当属RPC功能,RPC没有直接调用的API,其功能依附在Service。RPC或类似功能的框架在Java里一直是比较重量级的,从古老的Corba、RMI到后来的EJB、WebService,还有其他很多RPC开源框架,都有着复杂的配置和大量API学习成本,有些还需要区分客户端和服务端(如WebService)。 Service不仅只是个逻辑层的规范定义,还集成了很强大的RPC和异步调用功能,远程模式的Service就是RPC功能,系统在依赖注入过程中创建Service时通过基本的IP配置自动识别是创建本地模式的Service还是远程模式的Service,远程模式的Service使用的就是RPC,但在代码层Service的调用本地模式与远程模式完全一样。更神奇的是,带有异步回调函数AsyncHandler 的Service方法同样能执行远程模式。这种RPC的简易性是其他框架都无可匹敌的。REST风格的Service在接口设计上尽量减少注解性的配置,同时保留灵活性,减少HttpServlet的编写。<br>
|
||
</p>
|
||
<p> <b>Source</b></p>
|
||
<p>
|
||
除了开发类似数据库管理工具,大部分情况下开发者只用基本的增删改查操作,Hibernate、MyBatis这些框架对于对象新增/更新/删除和主键查找对象等接口定义都比较简单,但是带有过滤条件的操作,就变得难用。MyBatis需要配各种SQL,大量if else,Hibernate需要写HQL或SQL,JPA规范需要写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> <b>思维</b></p>
|
||
<p>
|
||
<a href="http://redkale.org" target="_blank">Redkale</a> 追求大道至简,不仅提供高性能的功能和简易的API,还带来不同的设计思维。作为一名有追求的开发者,不能只停留在API层面,更多的是需要掌握设计能力,一个好的设计方案往往能少写很多代码。Java里很多规范和框架就是考虑太过全面,为了迎合各种良莠不齐的想法和设计。比如HTTP服务,只是系统的一个接入层,有必须设计ServletConfig、ServletContextListener、Filter、HttpSessionListener等这么多API吗,开发者在系统初期养成定义全局的BaseHttpServlet这些基类的习惯就可以控制很多东西,也无需去使用什么拦截器或AOP功能。提交表单前先将表单数据转换成JSON字符串传给后台,后台的接口既可用于Web也可用于APP,非要按原始表单提交,那只能使用Struts这类笨重的框架了。再如DB操作,开发者设计好的数据结构可以把关系型数据库当NoSQL数据库操作,会发现对JDBC做一定的封装就可以基本杜绝写SQL。非要写存储过程、关联五六张表进行复杂查询,再好的DB框架都满足不了你。再如Date,Date对象的本质是long值,很多人习惯性的数据库就用Date类型,这样会增加很多麻烦,增加数据库的通用性难度,JSON还需要提供各种DateFormat,如果使用long类型,时间只交给页面去format就简单很多,long的性能也更好。说了这么多,只是想表达一个观点,开发时摆脱传统思维的桎栲,换个思路去思考,很多东西会变得很简单。<br>
|
||
</p>
|
||
<p>
|
||
想了解更多关于Redkale的资料, 请访问Redkale官网: :<a href="http://redkale.org" target="_blank">http://redkale.org</a>。
|
||
</p>
|
||
<br/>
|
||
<p>
|
||
转载请注明出处:<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"> 欢迎加入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>
|