小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

簡單之美 | Dubbo實現(xiàn)RPC調(diào)用使用入門

 feimishiwo 2015-09-09

使用Dubbo進(jìn)行遠(yuǎn)程調(diào)用實現(xiàn)服務(wù)交互,它支持多種協(xié)議,如Hessian、HTTP、RMI、Memcached、Redis、Thrift等等。由于Dubbo將這些協(xié)議的實現(xiàn)進(jìn)行了封裝了,無論是服務(wù)端(開發(fā)服務(wù))還是客戶端(調(diào)用服務(wù)),都不需要關(guān)心協(xié)議的細(xì)節(jié),只需要在配置中指定使用的協(xié)議即可,從而保證了服務(wù)提供方與服務(wù)消費方之間的透明。
另外,如果我們使用Dubbo的服務(wù)注冊中心組件,這樣服務(wù)提供方將服務(wù)發(fā)布到注冊的中心,只是將服務(wù)的名稱暴露給外部,而服務(wù)消費方只需要知道注冊中心和服務(wù)提供方提供的服務(wù)名稱,就能夠透明地調(diào)用服務(wù),后面我們會看到具體提供服務(wù)和消費服務(wù)的配置內(nèi)容,使得雙方之間交互的透明化。

示例場景

我們給出一個示例的應(yīng)用場景:
服務(wù)方提供一個搜索服務(wù),對服務(wù)方來說,它基于SolrCloud構(gòu)建了搜索服務(wù),包含兩個集群,ZooKeeper集群和Solr集群,然后在前端通過Nginx來進(jìn)行反向代理,達(dá)到負(fù)載均衡的目的。
服務(wù)消費方就是調(diào)用服務(wù)進(jìn)行查詢,給出查詢條件(滿足Solr的REST-like接口)。

應(yīng)用設(shè)計

基于上面的示例場景,我們打算使用ZooKeeper集群作為服務(wù)注冊中心。注冊中心會暴露給服務(wù)提供方和服務(wù)消費方,所以注冊服務(wù)的時候,服務(wù)先提供方只需要提供Nginx的地址給注冊中心,但是注冊中心并不會把這個地址暴露給服務(wù)消費方,如圖所示:
provider-registry-consumer
我們先定義一下,通信雙方需要使用的接口,如下所示:

01package org.shirdrn.platform.dubbo.service.rpc.api;
02 
03public interface SolrSearchService {
04 
05    String search(String collection, String q, ResponseType type, int start, int rows);
06     
07    public enum ResponseType {
08        JSON,
09        XML
10    }  
11}

基于上圖中的設(shè)計,下面我們分別詳細(xì)說明Provider和Consumer的設(shè)計及實現(xiàn)。

  • Provider服務(wù)設(shè)計

Provider所發(fā)布的服務(wù)組件,包含了一個SolrCloud集群,在SolrCloud集群前端又加了一個反向代理層,使用Nginx來均衡負(fù)載。Provider的搜索服務(wù)系統(tǒng),設(shè)計如下圖所示:
solrcloud-cluster
上圖中,實際Nginx中將請求直接轉(zhuǎn)發(fā)內(nèi)部的Web Servers上,在這個過程中,使用ZooKeeper來進(jìn)行協(xié)調(diào):從多個分片(Shard)服務(wù)器上并行搜索,最后合并結(jié)果。我們看一下Nginx配置的內(nèi)容片段:

01user  nginx;
02worker_processes  4;
03 
04error_log  /var/log/nginx/error.log warn;
05pid        /var/run/nginx.pid;
06 
07 
08events {
09    worker_connections  1024;
10}
11 
12 
13http {
14    include       /etc/nginx/mime.types;
15    default_type  application/octet-stream;
16 
17    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
18                      '$status $body_bytes_sent "$http_referer" '
19                      '"$http_user_agent" "$http_x_forwarded_for"';
20 
21    access_log  /var/log/nginx/access.log  main;
22 
23    sendfile        on;
24    #tcp_nopush     on;
25 
26    keepalive_timeout  65;
27 
28    #gzip  on;
29 
30    upstream master {
31        server slave1:8888 weight=1;
32        server slave4:8888 weight=1;
33        server slave6:8888 weight=1;
34    }
35 
36    server {
37        listen 80;
38        server_name master;
39        location / {
40            root /usr/share/nginx/html/solr-cloud;
41            index  index.html index.htm;
42            proxy_pass   http://master;
43            include /home/hadoop/servers/nginx/conf/proxy.conf;
44        }
45    }
46}

一共配置了3臺Solr服務(wù)器,因為SolrCloud集群中每一個節(jié)點都可以接收搜索請求,然后由整個集群去并行搜索。最后,我們要通過Dubbo服務(wù)框架來基于已有的系統(tǒng)來開發(fā)搜索服務(wù),并通過Dubbo的注冊中心來發(fā)布服務(wù)。
首先需要實現(xiàn)服務(wù)接口,實現(xiàn)代碼如下所示:

01package org.shirdrn.platform.dubbo.service.rpc.server;
02 
03import java.io.IOException;
04import java.util.HashMap;
05import java.util.Map;
06 
07import org.apache.commons.logging.Log;
08import org.apache.commons.logging.LogFactory;
09import org.shirdrn.platform.dubbo.service.rpc.api.SolrSearchService;
10import org.shirdrn.platform.dubbo.service.rpc.utils.QueryPostClient;
11import org.springframework.context.support.ClassPathXmlApplicationContext;
12 
13public class SolrSearchServer implements SolrSearchService {
14 
15    private static final Log LOG = LogFactory.getLog(SolrSearchServer.class);
16    private String baseUrl;
17    private final QueryPostClient postClient;
18    private static final Map<ResponseType, FormatHandler> handlers = new HashMap<ResponseType, FormatHandler>(0);
19    static {
20        handlers.put(ResponseType.XML, new FormatHandler() {
21            public String format() {
22                return "&wt=xml";
23            }
24        });
25        handlers.put(ResponseType.JSON, new FormatHandler() {
26            public String format() {
27                return "&wt=json";
28            }
29        });
30    }
31     
32    public SolrSearchServer() {
33        super();
34        postClient = QueryPostClient.newIndexingClient(null);
35    }
36     
37    public void setBaseUrl(String baseUrl) {
38        this.baseUrl = baseUrl;
39    }
40 
41    public String search(String collection, String q, ResponseType type,
42            int start, int rows) {
43        StringBuffer url = new StringBuffer();
44        url.append(baseUrl).append(collection).append("/select?").append(q);
45        url.append("&start=").append(start).append("&rows=").append(rows);
46        url.append(handlers.get(type).format());
47        LOG.info("[REQ] " + url.toString());
48        return postClient.request(url.toString());
49    }
50     
51    interface FormatHandler {
52        String format();
53    }
54     
55    public static void main(String[] args) throws IOException {
56        String config = SolrSearchServer.class.getPackage().getName().replace('.', '/') + "/search-provider.xml";
57        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(config);
58        context.start();
59        System.in.read();
60    }
61 
62}

對應(yīng)的Dubbo配置文件為search-provider.xml,內(nèi)容如下所示:

01<?xml version="1.0" encoding="UTF-8"?>
02 
03<beans xmlns="http://www./schema/beans"
07 
08    <dubbo:application name="search-provider" />
09    <dubbo:registry address="zookeeper://slave1:2188?backup=slave3:2188,slave4:2188" />
10    <dubbo:protocol name="dubbo" port="20880" />
11    <bean id="searchService" class="org.shirdrn.platform.dubbo.service.rpc.server.SolrSearchServer">
12        <property name="baseUrl" value="http://nginx-lbserver/solr-cloud/" />
13    </bean>
14    <dubbo:service interface="org.shirdrn.platform.dubbo.service.rpc.api.SolrSearchService" ref="searchService" />
15 
16</beans>

上面,Dubbo服務(wù)注冊中心指定ZooKeeper的地址:zookeeper://slave1:2188?backup=slave3:2188,slave4:2188,使用Dubbo協(xié)議。配置服務(wù)接口的時候,可以按照Spring的Bean的配置方式來配置,注入需要的內(nèi)容,我們這里指定了搜索集群的Nginx反向代理地址http://nginx-lbserver/solr-cloud/。

  • Consumer調(diào)用服務(wù)設(shè)計

這個就比較簡單了,拷貝服務(wù)接口,同時要配置一下Dubbo的配置文件,寫個簡單的客戶端調(diào)用就可以實現(xiàn)??蛻舳藢崿F(xiàn)的Java代碼如下所示:

01package org.shirdrn.platform.dubbo.service.rpc.client;
02 
03import java.util.concurrent.Callable;
04import java.util.concurrent.Future;
05 
06import org.shirdrn.platform.dubbo.service.rpc.api.SolrSearchService;
07import org.shirdrn.platform.dubbo.service.rpc.api.SolrSearchService.ResponseType;
08import org.springframework.beans.BeansException;
09import org.springframework.context.support.AbstractXmlApplicationContext;
10import org.springframework.context.support.ClassPathXmlApplicationContext;
11 
12import com.alibaba.dubbo.rpc.RpcContext;
13 
14public class SearchConsumer {
15     
16    private final String collection;
17    private AbstractXmlApplicationContext context;
18    private SolrSearchService searchService;
19     
20    public SearchConsumer(String collection, Callable<AbstractXmlApplicationContext> call) {
21        super();
22        this.collection = collection;
23        try {
24            context = call.call();
25            context.start();
26            searchService = (SolrSearchService) context.getBean("searchService");
27        } catch (BeansException e) {
28            e.printStackTrace();
29        } catch (Exception e) {
30            e.printStackTrace();
31        }
32    }
33     
34    public Future<String> asyncCall(final String q, final ResponseType type, final int start, final int rows) {
35        Future<String> future = RpcContext.getContext().asyncCall(new Callable<String>() {
36            public String call() throws Exception {
37                return search(q, type, start, rows);
38            }
39        });
40        return future;
41    }
42     
43    public String syncCall(final String q, final ResponseType type, final int start, final int rows) {
44        return search(q, type, start, rows);
45    }
46 
47    private String search(final String q, final ResponseType type, final int start, final int rows) {
48        return searchService.search(collection, q, type, start, rows);
49    }
50     
51    public static void main(String[] args) throws Exception {
52        final String collection = "tinycollection";
53        final String beanXML = "search-consumer.xml";
54        final String config = SearchConsumer.class.getPackage().getName().replace('.', '/') + "/" + beanXML;
55        SearchConsumer consumer = new SearchConsumer(collection, new Callable<AbstractXmlApplicationContext>() {
56            public AbstractXmlApplicationContext call() throws Exception {
57                final AbstractXmlApplicationContext context = new ClassPathXmlApplicationContext(config);
58                return context;
59            }
60        });
61         
62        String q = "q=上海&fl=*&fq=building_type:1";
63        int start = 0;
64        int rows = 10;
65        ResponseType type  = ResponseType.XML;
66        for (int k = 0; k < 10; k++) {
67            for (int i = 0; i < 10; i++) {
68                start = 1 * 10 * i;
69                if(i % 2 == 0) {
70                    type = ResponseType.XML;
71                } else {
72                    type = ResponseType.JSON;
73                }
74//              String result = consumer.syncCall(q, type, start, rows);
75//              System.out.println(result);
76                Future<String> future = consumer.asyncCall(q, type, start, rows);
77//              System.out.println(future.get());
78            }
79        }
80    }
81}

查詢的時候,需要提供查詢字符串,符合Solr語法,例如“q=上海&fl=*&fq=building_type:1”。配置文件,我們使用search-consumer.xml,內(nèi)容如下所示:

01<?xml version="1.0" encoding="UTF-8"?>
02 
03<beans xmlns="http://www./schema/beans"
07 
08    <dubbo:application name="search-consumer" />
09    <dubbo:registry address="zookeeper://slave1:2188?backup=slave3:2188,slave4:2188" />
10    <dubbo:reference id="searchService" interface="org.shirdrn.platform.dubbo.service.rpc.api.SolrSearchService" />
11 
12</beans>

運行說明

首先保證服務(wù)注冊中心的ZooKeeper集群正常運行,然后啟動SolrSearchServer,啟動的時候直接將服務(wù)注冊到ZooKeeper集群存儲中,可以通過ZooKeeper的客戶端腳本來查看注冊的服務(wù)數(shù)據(jù)。一切正常以后,可以啟動運行客戶端SearchConsumer,調(diào)用SolrSearchServer所實現(xiàn)的遠(yuǎn)程搜索服務(wù)。

參考鏈接

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多