zoukankan      html  css  js  c++  java
  • RestTemplate 使用总结

    场景:

    认证服务器需要有个 http client 把前端发来的请求转发到 backend service, 然后把 backend service 的结果再返回给前端,服务器本身只做认证功能。

    遇到的问题:

    • 长连接以保证高性能。RestTemplate 本身也是一个 wrapper 其底层默认是 SimpleClientHttpRequestFactory ,如果要保证长连接, HttpComponentsClientHttpRequestFactory 是个更好的选择,它不仅可以控制能够建立的连接数还能细粒度的控制到某个 server 的连接数,非常方便。在默认情况下,RestTemplate 到某个 server 的最大连接数只有 2, 一般需要调的更高些,最好等于 server 的 CPU 个数

    • access_token 不应传到 backend service. backend service 之间通信不需要 token,因为到这些服务的请求都是已经认证过的,是可信赖的用户发出的请求。因此转发请求时要把 parameter 从 request url 中删掉。删除 parameter 说难不难,说简单其实还有点麻烦,网上有一个 UrlEncodedQueryString 可以参考下,它封装了很多函数,其中就包括从url 中摘掉指定 header

    • 请求的 HttpMethod 问题。 HttpMethod 有很多种,http client 不应该对每种 Http method 都单独处理,所以应选用 RestTemplate 的 exchange 方法。exchange 方法要求给出 RequestBody 参数,而对于 Get 请求,这部分往往为空,所以我们要在 controller 中声明 @RequestBody(required = false) String body

    • exchange 的返回值和 controller 的返回值。Restful API 一般都是返回 json 的,所以最简单的是 exchange 和 controller 直接返回 String,但是返回 String 会有很多问题: 首先是如果某些 API 返回的是图片,那么这个 client 就傻掉了,需要为图片接口专门写 API,此外如果 backend service 返回的是 Gzip,那么此 client 必须对 gzip 先解压缩再返回请求者,如果不解压缩的话,相当于对着 gzip 数据做了到 String 类型的强制转换,使得请求者拿到的数据无法解析,所以最好的返回值是 byte[]。对于那种比较大的 json 返回值,省去了对 String 的类型转换后还能带来很大的性能提升

    • 关于返回值是 byte[] 还是 ResponseEntity<byte[]> 的问题。我觉得还是 ResponseEntity<byte[]> 好些,因为它就是 backend service 的结果。如果返回 byte[] 的话,还要对 HttpServletResponse 的 Header 进行修改,设置 Content-type, Content-encoding 等等。

    下面是我的用法

        @PostConstruct
        public void setProperties() {
            clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory(
                    HttpClientBuilder.create()
                            .disableContentCompression()
                            .setMaxConnPerRoute(restTemplateConfig.getMaxConnPerRoute())
                            .setMaxConnTotal(restTemplateConfig.getMaxConn()).build());
            restTemplate = new RestTemplate(clientHttpRequestFactory);
        }
    
    
        public RestTemplate getInstance() {
            return new RestTemplate(new HttpComponentsClientHttpRequestFactory(HttpClientBuilder.create().build()));
        }
    
        public ResponseEntity<byte[]> mirrorRest(@RequestBody(required = false) String body, HttpMethod method,
                              HttpServletRequest request, HttpServletResponse response, URI uri) throws URISyntaxException {
    
            HttpEntity entities = new HttpEntity(body, extractHeaders(request));
    
            //delete accesstoken before mirror to backend server
            UrlEncodedQueryString queryString = UrlEncodedQueryString.parse(uri);
            queryString.remove("access_token");
            uri = queryString.apply(uri);
    
            ResponseEntity<byte[]> responseEntity = restTemplate.exchange(uri, method, entities, byte[].class);
    
            return responseEntity;
        }
    

    需要改进的地方

    • HttpComponentsClientHttpRequestFactory 的配置粒度不够细,可以配合 RequestConfig 确定某一个 service 需要多少连接数。

    • RestTemplate 有异步版本 asyncRestTemplate, 可以考虑用它结合 netty 进一步提升程序性能,但是目前来讲已经够好了

  • 相关阅读:
    [置顶] 从零开始学C++之STL(二):实现简单容器模板类Vec(vector capacity 增长问题、allocator 内存分配器)
    HDU4607(求树中的最长链)
    java从文件中读取数据然后插入到数据库表中
    rcp(插件开发)插件B需要引用插件A中的jar包-如何处理依赖关系
    HDU 2084 数塔
    Object-c学习之路二(oc内存管理黄金法则1)
    android adb命令 unable to connect to 192.168.1.155:5555
    安装node.js / npm / express / KMC
    oracle断电重启之ORA-00600[4194]
    virtualbox虚拟机迁移出现"connot find device eth0"错误
  • 原文地址:https://www.cnblogs.com/xinsheng/p/5546221.html
Copyright © 2011-2022 走看看