目標:介紹webservice協議的設計和實現,介紹dubbo-rpc-webservice的源碼。
dubbo集成webservice協議,基於 Apache CXF 的 frontend-simple
和 transports-http
實現 ,CXF 是 Apache 開源的一個 RPC 框架,由 Xfire 和 Celtix 合併而來。關於webservice協議的優點以及介紹能夠查看官方文檔,我就很少贅述。java
該類繼承了AbstractProxyProtocol,是webservice協議的關鍵邏輯實現。git
/** * 默認端口 */ public static final int DEFAULT_PORT = 80; /** * 服務集合 */ private final Map<String, HttpServer> serverMap = new ConcurrentHashMap<String, HttpServer>(); /** * 總線,該總線使用CXF內置的擴展管理器來加載組件(而不是使用Spring總線實現)。雖然加載速度更快,但它不容許像Spring總線那樣進行大量配置和定製。 */ private final ExtensionManagerBus bus = new ExtensionManagerBus(); /** * http通訊工廠對象 */ private final HTTPTransportFactory transportFactory = new HTTPTransportFactory(); /** * http綁定者 */ private HttpBinder httpBinder;
@Override protected <T> Runnable doExport(T impl, Class<T> type, URL url) throws RpcException { // 得到地址 String addr = getAddr(url); // 得到http服務 HttpServer httpServer = serverMap.get(addr); // 若是服務爲空,則從新建立服務器。而且加入集合 if (httpServer == null) { httpServer = httpBinder.bind(url, new WebServiceHandler()); serverMap.put(addr, httpServer); } // 服務加載器 final ServerFactoryBean serverFactoryBean = new ServerFactoryBean(); // 設置地址 serverFactoryBean.setAddress(url.getAbsolutePath()); // 設置服務類型 serverFactoryBean.setServiceClass(type); // 設置實現類 serverFactoryBean.setServiceBean(impl); // 設置總線 serverFactoryBean.setBus(bus); // 設置通訊工廠 serverFactoryBean.setDestinationFactory(transportFactory); // 建立 serverFactoryBean.create(); return new Runnable() { @Override public void run() { if(serverFactoryBean.getServer()!= null) { serverFactoryBean.getServer().destroy(); } if(serverFactoryBean.getBus()!=null) { serverFactoryBean.getBus().shutdown(true); } } }; }
該方法是服務暴露的邏輯實現,基於cxf一些類。github
@Override @SuppressWarnings("unchecked") protected <T> T doRefer(final Class<T> serviceType, final URL url) throws RpcException { // 建立代理工廠 ClientProxyFactoryBean proxyFactoryBean = new ClientProxyFactoryBean(); // 設置地址 proxyFactoryBean.setAddress(url.setProtocol("http").toIdentityString()); // 設置服務類型 proxyFactoryBean.setServiceClass(serviceType); // 設置總線 proxyFactoryBean.setBus(bus); // 建立 T ref = (T) proxyFactoryBean.create(); // 得到代理 Client proxy = ClientProxy.getClient(ref); // 得到HTTPConduit 處理「http」和「https」傳輸協議。實例由顯式設置或配置的策略控制 HTTPConduit conduit = (HTTPConduit) proxy.getConduit(); // 用於配置客戶端HTTP端口的屬性 HTTPClientPolicy policy = new HTTPClientPolicy(); // 配置鏈接超時時間 policy.setConnectionTimeout(url.getParameter(Constants.CONNECT_TIMEOUT_KEY, Constants.DEFAULT_CONNECT_TIMEOUT)); // 配置調用超時時間 policy.setReceiveTimeout(url.getParameter(Constants.TIMEOUT_KEY, Constants.DEFAULT_TIMEOUT)); conduit.setClient(policy); return ref; }
該方法是服務引用的邏輯實現。web
private class WebServiceHandler implements HttpHandler { private volatile ServletController servletController; @Override public void handle(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { // 若是servletController爲空,則從新加載一個 if (servletController == null) { HttpServlet httpServlet = DispatcherServlet.getInstance(); if (httpServlet == null) { response.sendError(500, "No such DispatcherServlet instance."); return; } // 建立servletController synchronized (this) { if (servletController == null) { servletController = new ServletController(transportFactory.getRegistry(), httpServlet.getServletConfig(), httpServlet); } } } // 設置遠程地址 RpcContext.getContext().setRemoteAddress(request.getRemoteAddr(), request.getRemotePort()); // 調用方法 servletController.invoke(request, response); } }
該內部類實現了HttpHandler接口,是WebService協議的請求的處理類。apache
該部分相關的源碼解析地址: https://github.com/CrazyHZM/i...
該文章講解了遠程調用中關於webservice協議實現的部分,到這裏關於rpc遠程調用的部分就結束了,關於遠程調用核心的幾個內容就是代理、協議,再加上不一樣功能加強的過濾器等,關鍵是要把api中關於接口設計方面的內容看清楚,後面各種協議由於不少都是基於第三方的框架去實現,雖然方法邏輯有所區別,可是總體的思路和框架必定順着api設計的去實現。接下來我將開始對cluster集羣模塊進行講解。api