递归算法处理字典翻译超时处理

7 篇文章 0 订阅

代码上生产后,发现严重的效率问题,查询总是超时,优化效率

原先代码

  private void translateAllField(JSONObject item, Object record) {
        //边界处理
        //递归结束条件
        //递归
        // 遍历所有字段 取出字典code值,放到map中
        Field[] allFields = oConvertUtils.getAllFields(record);
        for(Field field:allFields){
            if(field.getAnnotation(QueryBaseDict.class)!=null) {
                String value = item.getString(field.getName());
                //如果内嵌对象
                if(field.getAnnotation(QueryBaseDict.class).isTranslation() && !StringUtils.isEmpty(value)) {
                    Class aClass = field.getAnnotation(QueryBaseDict.class).isClass();
                    if(value.charAt(0) == '[') {
                        ArrayList<Object> objects = new ArrayList<>();
                        List<JSONObject> jsonObjects = JSONObject.parseArray(value, JSONObject.class);
                        for(JSONObject stringJson:jsonObjects) {
                            translateAllField(stringJson,stringJson.toJavaObject(aClass));
                            objects.add(stringJson);
                        }
                        item.put(field.getName(),jsonObjects);
                    } else {
                        JSONObject jsonObject = JSONObject.parseObject(value);
                        translateAllField(jsonObject,jsonObject.toJavaObject(aClass));
                        item.put(field.getName(),jsonObject);
                    }

                } else {
                    String textValue = translateDictvalue(value);
                    item.put(field.getName()+"Text",textValue);
                }
                }
            }
        }


    private String translateDictvalue(String value) {
        return commonAPI.getDictName(value);
    }

这里一个递归算法,翻译切面翻译字典项码值,这段代码在内网环境执行尚可,但是到了生产环境查询效率就极其缓慢,甚至超时。

其中

String textValue = translateDictvalue(value);
item.put(field.getName()+"Text",textValue);

这段是feign调用用户中心,获得码值表翻译内容,并以属性+text ,增加字段翻译。

可以看出,首先这个是对每个需要翻译的字典项都feign调用,这里表单比较长,需要翻译字段很多,所以做了很多feign调用,而且没有从redis取值

优化:1 首先将字典值放入redis中,查询的时候先查询redis,查不到再在feign调用,从mysql中查找

    String textValue;
    String keyString = String.format("sys:cache:basedict::"+value);
  if (redisTemplate.hasKey(keyString)){
            textValue = oConvertUtils.getString(redisTemplate.opsForValue().get(keyString));
        }else {
            textValue = translateDictvalue(value);
        }
        item.put(field.getName()+"Text",textValue);
        baseDictHashMap.put(value,textValue);

优化完能查询出数据,大概快了2,3倍,但是仍然很慢。需要2s左右
2.因为字典项的值不会很多,所有可以设置有个公共静态map,将查询出的字典值放入map中,即jvm缓存中,这样map中存在的数据就不用从redis中查询,少做了IO查询。

    public static ConcurrentHashMap<String, String> baseDictHashMap = new ConcurrentHashMap<>();
...


                        String textValue;
                        String keyString = String.format("sys:cache:basedict::"+value);
                        if(baseDictHashMap.get(value)!=null) {
                            textValue = baseDictHashMap.get(value);
                            item.put(field.getName()+"Text",textValue);
                        } else {
                            if (redisTemplate.hasKey(keyString)){
                                textValue = oConvertUtils.getString(redisTemplate.opsForValue().get(keyString));
                            }else {
                                textValue = translateDictvalue(value);
                            }
                            item.put(field.getName()+"Text",textValue);
                            baseDictHashMap.put(value,textValue);
                        }

这次优化完,大概查询效率为1s左右,又提升了2倍。

3.最后我们应用云服务器是部署在北京,而mysql 和 redis等中间件服务器是部署在杭州,考虑不在一个地域,可能会有影响,所以销毁了北京的应用服务器,重新在杭州买了云服务器作为应用服务,同时提升了上传效率5m为20m,效率瞬间降到了200ms,看了下同在一个地域的云服务器走的是内网服务,而不再一个地域走的是公网,应该是很大影响。

最后其实还有个地方可以优化,就是在翻译字典时,可以将需要翻译的字段值一次性放入map集合中,feign调用或者查redis时,一次性查询来,便可以减少多次io调用

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值