From 1e30918740af384ce19e587d38a26eacd8096621 Mon Sep 17 00:00:00 2001 From: Redkale <22250530@qq.com> Date: Fri, 17 Mar 2017 18:54:39 +0800 Subject: [PATCH] --- service.html | 36 ++++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/service.html b/service.html index ffcfc2f82..543fa6abc 100644 --- a/service.html +++ b/service.html @@ -290,7 +290,7 @@

        生成远程模式Service时发现参数带有@RpcCall注解的方法,在远程调用返回结果时会进行回调处理。

Service REST

-

        RestService提供类似Spring Boot的功能。开启REST功能的HTTP Server在实例化标记为@RestService的Service后自动生成对应的HttpServlet,免去开发人员编写HttpServlet的工作量。RestService生成的HttpServlet均是RestHttpServlet的子类。主要通过@RestService@RestMapping@RestParam这三个注解来实现,同时为了获取其他类型的参数也有@RestAddress@RestCookie@RestHeader@RestSessionidRestOutput提供其扩展功能。

+

        RestService提供类似Spring Boot的功能。开启REST功能的HTTP Server在实例化标记为@RestService的Service后自动生成对应的HttpServlet,免去开发人员编写HttpServlet的工作量。RestService生成的HttpServlet均是RestHttpServlet的子类。主要通过@RestService@RestMapping@RestParam这三个注解来实现,同时为了获取其他类型的参数也有@RestAddress@RestCookie@RestHeader@RestSessionidRestOutput 提供其扩展功能。

    @RestService :

@@ -534,6 +534,12 @@ public HelloEntity findHello(@RestParam(name = "#", comment = "Hello对象id") int id) { //通过 /hello/find/1234 查询对象 return source.find(HelloEntity.class, id); } + + //异步查询单个 + @RestMapping(name = "asyncfind", auth = false, comment = "根据id查找单个Hello对象") + public HelloEntity findHello(AsyncHandler handler, @RestParam(name = "#") int id) { //通过 /pipes/hello/asyncfind/1234 查询对象 + return source.find(handler, HelloEntity.class, id); + } } @@ -609,10 +615,36 @@ HelloEntity bean = service.findHello(id); resp.finishJson(bean); } -} + + @AuthIgnore + @WebMapping(url = "/hello/asyncfind/", comment = "根据id删除Hello对象") + @WebParam(name = "#", type = int.class, comment = "Hello对象id") + public void asyncfind(HttpRequest req, HttpResponse resp) throws IOException { + HelloService service = _servicemap == null ? _service : _servicemap.get(req.getHeader(Rest.REST_HEADER_RESOURCE_NAME, "")); + int id = Integer.parseInt(req.getRequstURILastPath()); + service.findHello(resp.createAsyncHandler(), id); + } +} +

Service 异步调用

+

        远程模式不仅对@RpcCall注解进行处理,而且对方法含有 AsyncHandler 的参数也进行异步特殊处理。异步调用对远程模式非常有意义,可以减少同步方式对当前线程的占用时间。也给Source组件的异步调用提供了基础。

+
    @Override
+    public <T> void update(final AsyncHandler<Void, T[]> handler, @RpcAttachment final T... values) {
+        source.update(values);
+        if (handler != null) handler.completed(null, values);
+    }
+

+         如上图DataSourceService的源码,当DataSource为本地实例时,异步接口(含AsyncHandler参数的)与同步接口执行流程相同。当DataSource为远程模式时,调用异步接口时,通信接口发到远程服务器时AsyncHandler参数的值传null,返回数据后再调用本地的AsyncHandler参数值执行。
+         异步调用方式是提高服务并发性的有效手段,特别是在远程模式Service比较多的情况下效果更明显。以HTTP服务为例,在Tomcat刚刚改版成NIO的时候,网上随处可见都是大谈NIO性能比BIO多好,认为BIO与NIO的不同,是BIO往往会引入多线程,每个连接一个单独的线程;NIO则是使用单线程或者只使用少量的多线程,每个连接共用一个线程。而事实上呢,通常还是通过增加线程数来提高并发量。为什么NIO作用不大呢, 因为一个HTTP动态请求耗时最多的业务逻辑层,IO操作的耗时比重小得多,只有在静态资源请求这种纯IO操作才能体现NIO、AIO(NIO.2)的优势。举例一个简单的数据查询请求,采用BIO方式耗时(为了方便比较将所耗时间扩大几倍)如下:
+                 1、服务器TCP连接开始到进入HttpServlet,耗时 10ms
+                 2、用户态判断和参数验证,                         耗时 10ms
+                 3、调用远程数据源(DataSource)查询数据,耗时 150ms
+                 4、数据序列化与response的IO输出,          耗时 10ms
+         如上描述,一个请求处理耗时 180ms,同时占用一个线程的时间也是 180ms。若换成NIO使IO耗时减少,为了方便计算假设IO耗时为0(当然实际情况是不可能的), 那么步骤1、4的耗时忽略不计,线程的占用时间由180ms变成160ms。 假设数据查询接口IO操作本身耗时也是10ms,那么有140ms是用于等待。若采用DataSource异步接口, 则140ms的等待时间可以释放当前线程资源。虽然整个请求的处理时间还是180ms,但是线程的占用时间却只有20ms。可以看出减少耗时多的步骤的等待时间才能事半功倍,大幅度地提高性能。异步接口的主要作用是远程请求在等待过程中释放当前线程资源。大大减少线程数,也减少大量线程之间的切换消耗。 +

+