• 服务器端接入华为推送遇到的connection reset问题


    整个四月份都在做服务器端推送接入的工作,第一期接入的平台只包括小米,魅族,华为。

    其中,小米魅族是支持用户全量推送的,不需要客户端上报用户的pushId,接入过程比较方便快速。

    华为则比较坑了:

    开发文档写的烂;

    不支持全量推送,需要客户端上报一个推送一个;

    为了解决开发中遇到的一些问题,专门加了华为官方的开发者群,但是提的问题基本上没人回答,导致开发进度一度暂停。

    通过其他渠道解决了开发中遇到的问题后,就把项目部署到测试服务器了,但是测试服务器上,项目并不像在本地开发时一样良好运行,在调用推送接口时出现了这个错误。

    在华为的群里问了官方,但是没人理,其他开发者也没有遇到这种情况,只有自己找出原因了。

    测试服务器与本地开发环境主要的不同有两点:

    ①测试服务器在日本,而我在中国大陆

    ②测试服务器是linux,我的电脑是Windows

    接下来就是使用排除法排除了。

    刚好公司在阿里云上还有一台闲置的linux服务器,在简单搭建环境后,我把项目部署到了这台阿里云服务器上,发现可以正常推送。

    可以看出,同是linux服务器,中国区的ip访问华为推送后台是没有问题的,但是日本东京的ip不可以。那就应该是华为的后台限制了日本的ip访问了。

    不过这个需要华为官方的确认。于是我找到产品经理,产品经理通过公司运营那边的关系,终于得到了华为的回复:不支持日本。

    那就很尴尬了,毕竟公司的测试服以及以后生产服务器都在东京。

    和其他同事讨论这个情况后,他们提出了一种解决办法:在国内搭建一个转发的服务,华为推送请求先从日本发到这个转发服务,通过转发服务发到华为后台,华为的响应也是按照这个路径处理。

    在仔细考虑可行性后,认为可以这么处理,于是开干。

    这个中转服务器要做的非常简单,就是原封不动的转发我们服务器的请求及华为服务器的响应。一个action类就可以满足了,具体代码如下:

    @Controller
    @RequestMapping(value = "push")
    public class PushCtrl {
        private Logger logger = LoggerFactory.getLogger(this.getClass());
        private static String apiUrl = "https://api.push.hicloud.com/pushsend.do"; // 应用级消息下发API
        @ResponseBody
        @RequestMapping(value = "doTransfer",method=RequestMethod.POST)
        public void doTransfer(HttpServletRequest request,HttpServletResponse httpServletResponse)
                throws Exception {
            byte[] data = FileCopyUtils.copyToByteArray(request.getInputStream());
            String jsonData = new String(data, "UTF-8");
            JSONObject jo = JSONObject.fromObject(new String(request.getParameter("nsp_ctx")));
            String appId = (String)jo.get("appId");
            String postUrl = apiUrl + "?nsp_ctx=" + URLEncoder.encode("{"ver":"1", "appId":"" + appId + ""}", "UTF-8");
            String response = httpPost(postUrl, jsonData, 50000, 50000);
            httpServletResponse.setContentType("text/plain;charset=utf-8");
            PrintWriter responseStream = httpServletResponse.getWriter();
            responseStream.println(response);
            responseStream.close();
        }
    
        @ResponseBody
        @RequestMapping(value = "test",method=RequestMethod.GET)
        public ModelMap test(ModelMap m) {
            m.put("key", "value");
            return m;
        }
        
        public String httpPost(String httpUrl, String data, int connectTimeout,
                int readTimeout) throws Exception {
            OutputStream outPut = null;
            HttpURLConnection urlConnection = null;
            InputStream in = null;
    
            try {
                URL url = new URL(httpUrl);
                urlConnection = (HttpURLConnection) url.openConnection();
                urlConnection.setRequestMethod("POST");
                urlConnection.setDoOutput(true);
                urlConnection.setDoInput(true);
                urlConnection.setRequestProperty("Content-Type",
                        "application/x-www-form-urlencoded; charset=UTF-8");
                urlConnection.setConnectTimeout(connectTimeout);
                urlConnection.setReadTimeout(readTimeout);
                urlConnection.connect();
    
                // POST data
                outPut = urlConnection.getOutputStream();
                outPut.write(data.getBytes("UTF-8"));
                outPut.flush();
    
                // read response
                if (urlConnection.getResponseCode() < 400) {
                    in = urlConnection.getInputStream();
                } else {
                    in = urlConnection.getErrorStream();
                }
    
                List<String> lines = IOUtils.readLines(in,
                        urlConnection.getContentEncoding());
                StringBuffer strBuf = new StringBuffer();
                for (String line : lines) {
                    strBuf.append(line);
                }
                logger.info(strBuf.toString());
                return strBuf.toString();
            } finally {
                IOUtils.closeQuietly(outPut);
                IOUtils.closeQuietly(in);
                if (urlConnection != null) {
                    urlConnection.disconnect();
                }
            }
        }
    }
    View Code

    接下来,就是部署,测试,竟然真的可行。那这个问题就算是解决了。

  • 相关阅读:
    108. Convert Sorted Array to Binary Search Tree
    How to check if one path is a child of another path?
    Why there is two completely different version of Reverse for List and IEnumerable?
    在Jenkins中集成Sonarqube
    如何查看sonarqube的版本 how to check the version of sonarqube
    Queue
    BFS广度优先 vs DFS深度优先 for Binary Tree
    Depth-first search and Breadth-first search 深度优先搜索和广度优先搜索
    102. Binary Tree Level Order Traversal 广度优先遍历
    How do I check if a type is a subtype OR the type of an object?
  • 原文地址:https://www.cnblogs.com/wangchaoBlog/p/9001908.html
Copyright © 2020-2023  润新知