目標:介紹webservice協議的設計和實現,介紹dubbo-rpc-webservice的源碼。java
dubbo集成webservice協議,基於 Apache CXF 的 frontend-simple
和 transports-http
實現 ,CXF 是 Apache 開源的一個 RPC 框架,由 Xfire 和 Celtix 合併而來。關於webservice協議的優點以及介紹能夠查看官方文檔,我就很少贅述。git
該類繼承了AbstractProxyProtocol,是webservice協議的關鍵邏輯實現。github
/** * 默認端口 */
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一些類。web
@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;
}
複製代碼
該方法是服務引用的邏輯實現。apache
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協議的請求的處理類。api
該部分相關的源碼解析地址:github.com/CrazyHZM/in…服務器
該文章講解了遠程調用中關於webservice協議實現的部分,到這裏關於rpc遠程調用的部分就結束了,關於遠程調用核心的幾個內容就是代理、協議,再加上不一樣功能加強的過濾器等,關鍵是要把api中關於接口設計方面的內容看清楚,後面各種協議由於不少都是基於第三方的框架去實現,雖然方法邏輯有所區別,可是總體的思路和框架必定順着api設計的去實現。接下來我將開始對cluster集羣模塊進行講解。框架