国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

也來談談RPC

NSFish / 2869人閱讀

摘要:前言,顧名思義即遠程過程調(diào)用,可以說是分部式應用的基礎,也是概念中的核心部分。對于來說,可以分為之間的調(diào)用與和其他平臺之間的調(diào)用。和分別代表了這兩種模式。

前言

RPC,顧名思義即遠程過程調(diào)用,可以說是分部式WEB應用的基礎,也是SOA概念中的核心部分。對于J2EE來說,可以分為JVM之間的調(diào)用與和其他平臺之間的調(diào)用。前者主要是RMI,而后者則五花八門,比如Apache的Thrift框架就支持多語言系統(tǒng)之間的調(diào)用.今天就讓我們來初窺以下這大名鼎鼎的RPC。

問題描述

要想實現(xiàn)RPC,本質(zhì)上是服務發(fā)布方與服務調(diào)用方的通信,主要集中在以下幾個問題上:

調(diào)用方首先需要知道如何找到對應服務所在的遠程Server

調(diào)用方與服務提供方能以特定的雙方能夠解析的數(shù)據(jù)格式封裝自己的調(diào)用請求和調(diào)用結果

對多個服務提供方Server提供的不同服務以及它們的狀態(tài)應該予以有效的管理,比如新增服務需要注冊該服務

對于不同系統(tǒng)間的調(diào)用可能還需要一定的容錯和調(diào)度

首先我們給出一個最簡單的解決思路,就是直接利用HTTP協(xié)議,將調(diào)用方看做客戶端,而服務提供方看做服務器,以JSON來做數(shù)據(jù)傳輸,默認一套key-value的含義解釋,直接發(fā)起請求,然后等待響應并解析返回的JSON串。聽起來似乎可行,但是卻有許多弊端:

每個調(diào)用者需要提前保有一份服務者以及它提供的相應服務的記錄信息

大量的Http請求與解析響應的代碼混雜在原有的業(yè)務代碼中,對于使用服務的開發(fā)者不透明,惡劣的設計

對于服務變更和新增的情況不友好

如果有多個提供者提供同一服務,不利于增加均衡策略,不利于擴展

。。。。

還有很多,這就是為什么許多RPC框架和標準存在的原因,下面我們就主要從RMI出發(fā)來繼續(xù)探討這一問題。

我們以Apache的CXF框架來說明RMI調(diào)用,首先介紹一下JAX-WS和JAX-RS的概念。

JAX-WS:JavaTM API forXML-Based Web Services,JAX-WS是面向消息的,每次請求的時候指定了請求的方法。J

JAX-RS:JavaTM API forRESTful Web Services,AX-RS是面向資源的。后則將網(wǎng)絡上的東西當做一種資源,每次請求都是對該資源進行操作,比如對資源的增刪查改。

SOAP和JAXRS分別代表了這兩種模式。

JAXRS

首先關注服務提供方:

在ApplicatiionContext.xml中加入




    Apache CXF的Restful Web Service配置
    
    
    
        
            
        
        
            
        
    

    
    

然后添加服務

/**
 * WebService服務端實現(xiàn)類.
 * 
 * 為演示方便,直接調(diào)用了Service層.客戶端實現(xiàn)見功能測試用例.
 * 
 */
@Path("/user")
public class UserJaxRsService {

    private static Logger logger = LoggerFactory.getLogger(UserJaxRsService.class);

    @Autowired
    private UserService userService;
    
    @GET
    @Path("/{id}.xml")
    @Produces(MediaTypes.APPLICATION_XML_UTF_8)
    public UserDTO getAsXml(@PathParam("id") Long id) {
        Optional user = userService.load(id);
        if (!user.isPresent()) {
            String message = "用戶不存在(id:" + id + ")";
            logger.warn(message);
            throw buildException(Status.NOT_FOUND, message);
        }
        return bindDTO(user.get());
    }
    
    @GET
    @Path("/{id}.json")
    @Produces(MediaTypes.JSON_UTF_8)
    public UserDTO getAsJson(@PathParam("id") Long id) {
        Optional user = userService.load(id);
        if (!user.isPresent()) {
            String message = "用戶不存在(id:" + id + ")";
            logger.warn(message);
            throw buildException(Status.NOT_FOUND, message);
        }
        return bindDTO(user.get());
    }

    private UserDTO bindDTO(User user) {
        UserDTO dto = BeanMapper.map(user, UserDTO.class);
        // 補充Dozer不能自動綁定的屬性
        return dto;
    }

    private WebApplicationException buildException(Status status, String message) {
        return new WebApplicationException(Response.status(status).entity(message).type(MediaTypes.TEXT_PLAIN_UTF_8)
                .build());
    }
    
}

接下來看服務調(diào)用方

/**
 * 對基于JAX-RS的實現(xiàn)Restful的測試
 * 
 * @author calvin
 */
public class UserJaxRsFT extends BaseFunctionalTestCase {

    private static String resourceUrl = baseUrl + "/cxf/jaxrs/user";

    private RestTemplate restTemplate = new RestTemplate();

    @Test
    public void getUser() {
        UserDTO user = restTemplate.getForObject(resourceUrl + "/{id}.xml", UserDTO.class, 1L);
        assertThat(user.getLoginName()).isEqualTo("admin");
        assertThat(user.getName()).isEqualTo("管理員");
        assertThat(user.getTeamId()).isEqualTo(1);

        try {
            user = restTemplate.getForObject(resourceUrl + "/{id}.json", UserDTO.class, 1L);
        } catch (HttpStatusCodeException e) {
            fail(e.getMessage());
        }
        assertThat(user.getLoginName()).isEqualTo("admin");
        assertThat(user.getName()).isEqualTo("管理員");
        assertThat(user.getTeamId()).isEqualTo(1);
    }
}
SOAP

首先解釋一下SOAP的概念:一種輕量的、簡單的、基于XML的交換數(shù)據(jù)協(xié)議規(guī)范,也就是說它定義了Server之間通信的規(guī)范。SOAP的使用方式較為復雜,故我們只截取其中的核心部分闡述。

首先,看服務提供方:

配置文件




    Apache CXF的 SOAP Web Service配置
    
    
    
        
    

    
    

然后是服務的實現(xiàn):

/**
 * WebService服務端實現(xiàn)類.
 * 
 * 為演示方便,直接調(diào)用了Dao層.客戶端實現(xiàn)見功能測試用例.
 * 
 */
// serviceName指明WSDL中元素的名稱, endpointInterface屬性指向Interface類全稱.
@WebService(serviceName = "AccountService", endpointInterface = "org.springside.examples.showcase.webservice.soap.AccountSoapService", targetNamespace = WsConstants.NS)
// 增加inbound/outbound SOAP內(nèi)容的日志
@Features(features = "org.apache.cxf.feature.LoggingFeature")
public class AccountSoapServiceImpl implements AccountSoapService {

    private static Logger logger = LoggerFactory.getLogger(AccountSoapServiceImpl.class);

    @Autowired
    private AccountService accountService;

    @Autowired
    private Validator validator;

    /**
     * @see AccountSoapService#getUser(Long)
     */
    @Override
    public GetUserResult getUser(Long id) {
        GetUserResult result = new GetUserResult();
        try {

            Validate.notNull(id, "id參數(shù)為空");

            User user = accountService.getUser(id);

            Validate.notNull(user, "用戶不存在(id:" + id + ")");

            UserDTO dto = BeanMapper.map(user, UserDTO.class);
            result.setUser(dto);

            return result;

        } catch (IllegalArgumentException e) {
            return handleParameterError(result, e);
        } catch (RuntimeException e) {
            return handleGeneralError(result, e);
        }
    }

    /**
     * @see AccountSoapService#searchUser(String, String)
     */
    @Override
    public SearchUserResult searchUser(String loginName, String name) {
        SearchUserResult result = new SearchUserResult();
        try {
            List userList = accountService.searchUser(loginName, name);

            List dtoList = BeanMapper.mapList(userList, UserDTO.class);
            result.setUserList(dtoList);
            return result;
        } catch (RuntimeException e) {
            return handleGeneralError(result, e);
        }
    }

    /**
     * @see AccountSoapService#createUser(UserDTO)
     */
    @Override
    public IdResult createUser(UserDTO user) {
        IdResult result = new IdResult();
        try {
            Validate.notNull(user, "用戶參數(shù)為空");

            User userEntity = BeanMapper.map(user, User.class);
            BeanValidators.validateWithException(validator, userEntity);

            accountService.saveUser(userEntity);

            return new IdResult(userEntity.getId());
        } catch (ConstraintViolationException e) {
            String message = StringUtils.join(BeanValidators.extractPropertyAndMessageAsList(e, " "), "
");
            return handleParameterError(result, e, message);
        } catch (RuntimeException e) {
            if (Exceptions.isCausedBy(e, DuplicateKeyException.class)) {
                String message = "新建用戶參數(shù)存在唯一性沖突(用戶:" + user + ")";
                return handleParameterError(result, e, message);
            } else {
                return handleGeneralError(result, e);
            }
        }
    }

    private  T handleParameterError(T result, Exception e, String message) {
        logger.error(message, e.getMessage());
        result.setError(WSResult.PARAMETER_ERROR, message);
        return result;
    }

    private  T handleParameterError(T result, Exception e) {
        logger.error(e.getMessage());
        result.setError(WSResult.PARAMETER_ERROR, e.getMessage());
        return result;
    }

    private  T handleGeneralError(T result, Exception e) {
        logger.error(e.getMessage());
        result.setDefaultError();
        return result;
    }
}

下面我們再來看服務調(diào)用者:

配置文件



    Apache CXF Web Service Client端配置

        
    
    

調(diào)用流程

/**
 * 
 * 以用JAXWS的API, 根據(jù)AccountWebService接口自行創(chuàng)建.
 * 使用在Spring applicaitonContext.xml中用,根據(jù)AccountWebService接口創(chuàng)建的Client.
 * 
 */
public class AccountWebServiceWithDynamicCreateClientFT extends BaseFunctionalTestCase {
    
    //predefine client
    @Autowired
    private AccountSoapService accountWebServiceClient;


    //dynamic client
    public AccountSoapService creatClient() {
        String address = baseUrl + "/cxf/soap/accountservice";

        JaxWsProxyFactoryBean proxyFactory = new JaxWsProxyFactoryBean();
        proxyFactory.setAddress(address);
        proxyFactory.setServiceClass(AccountSoapService.class);
        AccountSoapService accountWebServiceProxy = (AccountSoapService) proxyFactory.create();

        // (可選)演示重新設定endpoint address.
        ((BindingProvider) accountWebServiceProxy).getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY,
                address);

        // (可選)演示重新設定Timeout時間
        Client client = ClientProxy.getClient(accountWebServiceProxy);
        HTTPConduit conduit = (HTTPConduit) client.getConduit();
        HTTPClientPolicy policy = conduit.getClient();
        policy.setReceiveTimeout(600000);

        return accountWebServiceProxy;
    }

    public void getUser() {
        GetUserResult response = accountWebServiceClient.getUser(1L);
        return response;
    }

    /**
     * 測試搜索用戶
     */
    @Test
    public void searchUser() {
        SearchUserResult response = accountWebServiceClient.searchUser(null, null);
        return response;
    }

    /**
     * 測試創(chuàng)建用戶.
     */
    @Test
    public void createUser() {
        User user = UserData.randomUser();
        UserDTO userDTO = BeanMapper.map(user, UserDTO.class);

        IdResult response = accountWebServiceClient.createUser(userDTO);
        assertThat(response.getId()).isNotNull();
        GetUserResult response2 = accountWebServiceClient.getUser(response.getId());
    }

}

文章版權歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/64714.html

相關文章

  • 談談為什么需要服務治理(Dubbo)

    摘要:服務治理主要針對于當前分布式架構下多服務微服務等。隨著業(yè)務的增長,服務不能一味地隨之增長,需要管理治理。服務設計期主要針對于服務的設計評審以及標準的制定。服務治理后期的重點放在消除冗余。 服務治理主要針對于當前分布式架構下多服務、微服務等。 服務是分布式系統(tǒng)下的一個不大不小的部分,有了服務的組成,整個系統(tǒng)才能活起來。 隨著業(yè)務的增長,服務不能一味地隨之增長,需要管理、治理。沒有服務治理...

    yunhao 評論0 收藏0
  • Spring Cloud Alibaba到底坑不坑?

    摘要:我沒有能力去控制那些自媒體發(fā)布這些不實的內(nèi)容,但是在我了解的范圍內(nèi),還是盡力輸出一些我的理解。 之前我發(fā)過一篇《說說我為什么看好Spring Cloud Alibaba》,然后這兩天有網(wǎng)友給我轉(zhuǎn)了這篇文章《坑爹項目spring-cloud-alibaba,我們也來一個》,問我的看法是怎么樣的,聊天時候簡單說了一下。今天在家休息,抽空整理一下內(nèi)容,逐點說一下我的看法,主要還是覺得這篇文章...

    娣辯孩 評論0 收藏0
  • 服務器部署工具 - 收藏集 - 掘金

    摘要:基本入門前端掘金作者本文屬于翻譯文章,原文鏈接為。如果如何把應用放在容器中運行掘金本文適合零基礎,且希望使用運行應用的人士。后端掘金使用構建網(wǎng)站。 nginx 基本入門 - 前端 - 掘金作者:villainthr 本文屬于翻譯文章,原文鏈接為 nginx Beginner’s Guide。是至今為止見過最好的 nginx 入門文章。額。。。沒有之一。 這篇教程簡單介紹了 nginx ...

    Shonim 評論0 收藏0
  • RabbitMQ快速入門

    摘要:就是交換機生產(chǎn)者發(fā)送消息給交換機,然后由交換機將消息轉(zhuǎn)發(fā)給隊列。對應于中則是發(fā)送一個,處理完成之后將其返回給。這樣來說一個是級別而不是級別的了。當然這些也都是官網(wǎng)的入門例子,后續(xù)有機會的話再深入研究。 一、前言 RabbitMQ其實是我最早接觸的一個MQ框架,我記得當時是在大學的時候跑到圖書館一個人去看,由于RabbitMQ官網(wǎng)的英文還不算太難,因此也是參考官網(wǎng)學習的,一共有6章,當時...

    Moxmi 評論0 收藏0
  • 架構 - 收藏集 - 掘金

    摘要:淺談秒殺系統(tǒng)架構設計后端掘金秒殺是電子商務網(wǎng)站常見的一種營銷手段。這兩個項目白話網(wǎng)站架構演進后端掘金這是白話系列的文章。 淺談秒殺系統(tǒng)架構設計 - 后端 - 掘金秒殺是電子商務網(wǎng)站常見的一種營銷手段。 不要整個系統(tǒng)宕機。 即使系統(tǒng)故障,也不要將錯誤數(shù)據(jù)展示出來。 盡量保持公平公正。 實現(xiàn)效果 秒殺開始前,搶購按鈕為活動未開始。 秒殺開始時,搶購按鈕可以點擊下單。 秒殺結束后,按鈕按鈕變...

    Riddler 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<