摘要:介紹是一個(gè)輕量級(jí)的服務(wù)框架,源代碼位于。是的消息路由器,是具體負(fù)責(zé)每一個(gè)請(qǐng)求的路由過(guò)程。當(dāng)執(zhí)行結(jié)束后,向服務(wù)池歸還資源。在多線程模式下,同樣也是在服務(wù)線程中執(zhí)行接口的三種方法。是一個(gè)接口,主要代表服務(wù)輸出的消息實(shí)例。
1.0 Alogic-FrameWork介紹
Alogic-FrameWork是一個(gè)輕量級(jí)的Java服務(wù)框架,源代碼位于Alogic-Github。具有快速開(kāi)發(fā)服務(wù)的特點(diǎn),在alogic-framework下,一個(gè)成熟的Java開(kāi)發(fā)者可以快速的開(kāi)發(fā)出實(shí)現(xiàn)自己業(yè)務(wù)邏輯的Restful服務(wù)。在這里我們不談具體的開(kāi)發(fā)邏輯,而是專注于分析該框架的源碼。
Alogic-FrameWork的一個(gè)HelloWorld級(jí)別代碼如下:Alogic的HelloWorld-Github
其中主要包括以下幾個(gè)部分:
HelloWorld.java 服務(wù)調(diào)用的具體內(nèi)容
web.xml web項(xiàng)目構(gòu)建的配置文件
settings.xml Alogic服務(wù)目錄配置文件
servant.xml 服務(wù)描述配置文件
1.1 服務(wù)初始化入口服務(wù)由servlet進(jìn)行攔截,servlet-class對(duì)請(qǐng)求進(jìn)行處理,并返回響應(yīng)。
在一個(gè)HelloWorld級(jí)別的應(yīng)用中,一個(gè)典型的web.xml配置如下:
MessageRouter MessageRouter com.anysoft.webloader.ServletAgent handler com.logicbus.backend.server.http.MessageRouterServletHandler 1 MessageRouter /services/*
服務(wù)通過(guò)注冊(cè)ServletAgent類攔截/services/*的全部路由,其中初始化參數(shù)handler為MessageRouterServletHandler類。我們來(lái)看一下如何進(jìn)行這個(gè)過(guò)程:
1.2 服務(wù)上下文的處理ServletAgent是一個(gè)代理類,繼承自HttpServlet,主要代理了Servlet的初始化、執(zhí)行和銷毀,其中重寫(xiě)了init(ServletConfig servletConfig),它通過(guò)ClassLoader類加載器加載實(shí)際處理的ServletHandler,并由ServletHandler去執(zhí)行它的初始化方法。
public void init(ServletConfig servletConfig) throws ServletException { // 獲取handler參數(shù) String handlerClass = servletConfig.getInitParameter("handler"); // 獲取當(dāng)前Servlet的上下文 ServletContext sc = servletConfig.getServletContext(); // 獲取當(dāng)前web項(xiàng)目類加載器 ClassLoader classLoader = (ClassLoader) sc.getAttribute("classLoader"); if (classLoader != null) { try { //創(chuàng)建Handler實(shí)例 handler = (ServletHandler) classLoader.loadClass(handlerClass) .newInstance(); //執(zhí)行Handler的初始化方法 handler.init(servletConfig); } catch (Exception e) { logger.error("Error occurs when creating handler:" + handlerClass, e); } } else { logger.error("Can not find classLoader"); } }
ServletHandler是一個(gè)接口,重新封裝了關(guān)于Servlet的init、service、destory方法;在web.xml中需要配置它的實(shí)現(xiàn)方法,MessageRouterServletHandler是它的具體實(shí)現(xiàn)類,在init實(shí)現(xiàn)方法中,設(shè)置了一些關(guān)鍵屬性,如Http的編碼、跨域、緩存等屬性,以及獲取服務(wù)id、目錄、訪問(wèn)控制等。
在doService實(shí)現(xiàn)方法中,將上述初始化的一些列屬性設(shè)置,達(dá)到重新封裝Http請(qǐng)求的目的;service方法初始化Context,并將參數(shù)作為輸入傳入到action方法中。如下:
// 初始化HttpContext,HttpContext是Context類的一個(gè)實(shí)現(xiàn),它是一個(gè)封裝后的Http請(qǐng)求的上下文。 HttpContext ctx = new HttpContext(request,response,encoding,interceptMode); // 獲取當(dāng)前服務(wù)路徑的id Path id = normalizer.normalize(ctx, request); MessageRouter.action(id,ctx,ac);1.3 服務(wù)請(qǐng)求過(guò)程
上文提到過(guò),MessageRouterServletHandler實(shí)現(xiàn)了ServletHandler接口,將Http上下文封裝起來(lái),同時(shí)將doService方法中獲取得到的服務(wù)id,訪問(wèn)控制給MessageRouter的action方法。MessageRouter是Alogic的消息路由器,是具體負(fù)責(zé)每一個(gè)請(qǐng)求的路由過(guò)程。在action方法中,包括以下邏輯:
處理路由追蹤
獲取服務(wù)實(shí)例池
通過(guò)訪問(wèn)控制器分配訪問(wèn)優(yōu)先級(jí)
從服務(wù)實(shí)例池獲取實(shí)例
日志記錄
首先,MessageRouter根據(jù)獲取得到的服務(wù)id來(lái)獲取一個(gè)服務(wù)實(shí)例池,通過(guò)資源池模式來(lái)保證服務(wù)實(shí)例的不斷重復(fù)利用。資源池獲取代碼如下:
// 獲取服務(wù)實(shí)例池 ServantFactory factory = servantFactory; // 根據(jù)服務(wù)id獲取服務(wù)工廠 pool = factory.getPool(id); if (!pool.isRunning()){ throw new ServantException("core.service_paused", "The Service is paused:service id:" + id); }
而接著,對(duì)于已經(jīng)獲得的資源池中根據(jù)優(yōu)先級(jí)獲得服務(wù)實(shí)例。在非線程模式下調(diào)用execute()方法,在多線程模式下建立服務(wù)工作線程。當(dāng)執(zhí)行結(jié)束后,向服務(wù)池歸還資源。
//從服務(wù)實(shí)例池中拿服務(wù)實(shí)例,并執(zhí)行 servant = pool.borrowObject(priority); // 判斷是否獲取到了服務(wù)并輸出錯(cuò)誤日志 if (servant == null){ logger.warn("Can not get a servant from pool in the limited time,check servant.queueTimeout variable."); ctx.setReturn("core.time_out", "Can not get a servant from pool in the limited time,check servant.queueTimeout variable."); }else{ if (!threadMode){ //在非線程模式下,不支持服務(wù)超時(shí) execute(servant,ctx); }else{ // 構(gòu)建CountDownLatch,用于等待服務(wù)工作線程建立。 CountDownLatch latch = new CountDownLatch(1); //建立服務(wù)工作線程 ServantWorkerThread thread = new ServantWorkerThread(servant,ctx,latch,tc != null ? tc.newChild() : null); thread.start(); // 判斷服務(wù)工作線程是否在指定的時(shí)間內(nèi)建立完成。如果超時(shí)則取消主線程阻塞狀態(tài),并 if (!latch.await(servant.getTimeOutValue(), TimeUnit.MILLISECONDS)){ ctx.setReturn("core.time_out","Time out or interrupted."); } thread = null; } } }catch (ServantException ex){ ctx.setReturn(ex.getCode(), ex.getMessage()); logger.error(ex.getCode() + ":" + ex.getMessage()); }catch (Exception ex){ ctx.setReturn("core.fatalerror",ex.getMessage()); logger.error("core.fatalerror:" + ex.getMessage(),ex); }catch (Throwable t){ ctx.setReturn("core.fatalerror",t.getMessage()); logger.error("core.fatalerror:" + t.getMessage(),t); } finally { ctx.setEndTime(System.currentTimeMillis()); if (ctx != null){ // 完成Context ctx.finish(); } if (pool != null){ if (servant != null){ // 向服務(wù)池歸還資源 pool.returnObject(servant); } // 服務(wù)池訪問(wèn)一次 pool.visited(ctx.getDuration(),ctx.getReturnCode()); if (ac != null){ ac.accessEnd(sessionId,id, pool.getDescription(), ctx); } } if (bizLogger != null){ //需要記錄日志 log(id,sessionId,pool == null ? null : pool.getDescription(),ctx); } if (tracerEnable){ boolean ok = ctx.getReturnCode().equals("core.ok"); Tool.end(tc, "ALOGIC", id.getPath(), ok ?"OK":"FAILED", ok ? ctx.getQueryString() : ctx.getReason(), ctx.getContentLength()); } }
在非線程模式下的execute方法執(zhí)行了服務(wù)調(diào)用的前置方法、執(zhí)行方法和后置方法。
protected static int execute(Servant servant,Context ctx) throws Exception { servant.actionBefore(ctx); servant.actionProcess(ctx); servant.actionAfter(ctx); return 0; }
在多線程模式下,同樣也是在服務(wù)線程中執(zhí)行Servant接口的三種方法。
public void run(){ TraceContext tc = null; if (traceCtx != null){ tc = Tool.start(traceCtx.sn(), traceCtx.order()); } boolean error = false; try { m_servant.actionBefore(m_ctx); m_servant.actionProcess(m_ctx); m_servant.actionAfter(m_ctx); } }1.4 服務(wù)響應(yīng)
在MessageRouter的acion方法中,服務(wù)調(diào)用的最后會(huì)調(diào)用ctx.finish(),在這個(gè)方法中調(diào)用了msg的finish方法。
try { if (!isIgnore()){ if (msg == null){ if (getReturnCode().equals("core.ok")){ response.sendError(404, "No message is found,check servant implemention."); }else{ response.sendError(404, getReturnCode() + ":" + getReason()); } }else{ response.setCharacterEncoding(encoding); msg.finish(this,!cometMode()); } } }
Message是一個(gè)接口,主要代表服務(wù)輸出的消息實(shí)例。在Alogic中,Message可以有XML、JSON等協(xié)議的消息實(shí)例,如輸出為RawMessage時(shí),finish方法如下:
public void finish(Context ctx,boolean closeStream) { // 設(shè)置輸出流 OutputStream out = null; try { // 設(shè)置返回內(nèi)容格式 ctx.setResponseContentType(contentType); out = ctx.getOutputStream(); byte [] bytes = buf.toString().getBytes(ctx.getEncoding()); contentLength += bytes.length; // 將字符串寫(xiě)到輸出流中 Context.writeToOutpuStream(out, bytes); // 輸出打印 out.flush(); }catch (Exception ex){ logger.error("Error when writing data to outputstream",ex); }finally{ if (closeStream) IOTools.close(out); } }
到此,一個(gè)服務(wù)的執(zhí)行邏輯如下:
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/67378.html
摘要:引言給迷失在如何學(xué)習(xí)區(qū)塊鏈技術(shù)的同學(xué)一個(gè)指引,區(qū)塊鏈技術(shù)是隨比特幣誕生,因此要搞明白區(qū)塊鏈技術(shù),應(yīng)該先了解下比特幣。但區(qū)塊鏈技術(shù)不單應(yīng)用于比特幣,還有非常多的現(xiàn)實(shí)應(yīng)用場(chǎng)景,想做區(qū)塊鏈應(yīng)用開(kāi)發(fā),可進(jìn)一步閱讀以太坊系列。 本文始發(fā)于深入淺出區(qū)塊鏈社區(qū), 原文:區(qū)塊鏈技術(shù)學(xué)習(xí)指引 原文已更新,請(qǐng)讀者前往原文閱讀 本章的文章越來(lái)越多,本文是一個(gè)索引帖,方便找到自己感興趣的文章,你也可以使用左側(cè)...
摘要:而用于主線程池的屬性都定義在中本篇只是簡(jiǎn)單介紹了一下引導(dǎo)類的配置屬性,下一篇我將詳細(xì)介紹服務(wù)端引導(dǎo)類的過(guò)程分析。 從Java1.4開(kāi)始, Java引入了non-blocking IO,簡(jiǎn)稱NIO。NIO與傳統(tǒng)socket最大的不同就是引入了Channel和多路復(fù)用selector的概念。傳統(tǒng)的socket是基于stream的,它是單向的,有InputStream表示read和Outpu...
摘要:雖然蘋(píng)果官方提供了關(guān)于的與使用說(shuō)明,但這并不能滿足開(kāi)發(fā)者們的需求,各類復(fù)雜場(chǎng)景依舊讓我們焦頭爛額,而解決方案卻不易尋找。二源碼下載編譯及調(diào)試之前我們首先需要獲取一份蘋(píng)果官方的源碼。 一、前言移動(dòng)互聯(lián)網(wǎng)時(shí)代,網(wǎng)頁(yè)依舊是內(nèi)容展示的重要媒介,這離不開(kāi) WebKit 瀏覽內(nèi)核技術(shù)的支持與發(fā)展。在 iOS 平臺(tái)下開(kāi)發(fā)者們...
摘要:它是第一個(gè)把數(shù)據(jù)分布在全球范圍內(nèi)的系統(tǒng),并且支持外部一致性的分布式事務(wù)。目的是使得開(kāi)發(fā)者閱讀之后,能對(duì)項(xiàng)目有一個(gè)初步了解,更好的參與進(jìn)入的開(kāi)發(fā)中。深度探索數(shù)據(jù)庫(kù)并發(fā)控制技術(shù)并發(fā)控制技術(shù)是數(shù)據(jù)庫(kù)事務(wù)處理的核心技術(shù)。 存儲(chǔ)過(guò)程高級(jí)篇 講解了一些存儲(chǔ)過(guò)程的高級(jí)特性,包括 cursor、schema、控制語(yǔ)句、事務(wù)等。 數(shù)據(jù)庫(kù)索引與事務(wù)管理 本篇文章為對(duì)數(shù)據(jù)庫(kù)知識(shí)的查缺補(bǔ)漏,從索引,事務(wù)管理,...
閱讀 1848·2021-11-22 15:24
閱讀 1307·2021-11-12 10:36
閱讀 3194·2021-09-28 09:36
閱讀 1837·2021-09-02 15:15
閱讀 2745·2019-08-30 15:54
閱讀 2391·2019-08-30 11:02
閱讀 2392·2019-08-29 13:52
閱讀 3539·2019-08-26 11:53