认证服务器须要有个 http client 把前端发来的请求转发到 backend service, 而后把 backend service 的结果再返回给前端,服务器自己只作认证功能。前端
长链接以保证高性能。RestTemplate 自己也是一个 wrapper 其底层默认是 SimpleClientHttpRequestFactory ,若是要保证长链接, HttpComponentsClientHttpRequestFactory 是个更好的选择,它不只能够控制可以创建的链接数还能细粒度的控制到某个 server 的链接数,很是方便。在默认状况下,RestTemplate 到某个 server 的最大链接数只有 2, 通常须要调的更高些,最好等于 server 的 CPU 个数json
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 bodyapp
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 等等。async
@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 进一步提高程序性能,可是目前来说已经够好了性能