2017年4月

Java RPC协议设计

调用流程

rpc-protocol.png

motan的协议设计

包括 request 级别的 header 和 body,request 的 body 中又包含了 header 和 body; 其中 requestId, request/response 的标记是冗余的

motan-protocol.png

dubbo的协议设计

2017-05-02_15-04-12.png

Server参数的优化

bootstrap.option(ChannelOption.SO_BACKLOG, 128); // 3次握手连接队列
bootstrap.childOption(ChannelOption.SO_KEEPALIVE, true); // 默认false
bootstrap.childOption(ChannelOption.TCP_NODELAY, true);

Decoder

1387967596_4585.png

public class MessageDecoder extends ByteToMessageDecoder {

    @Override
    protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List<Object> list) throws Exception {
        if (byteBuf.readableBytes() <= MessageConstant.HEADER_LEN) {
            return;
        }
        byteBuf.markReaderIndex();

        short type = byteBuf.readShort();
        if (type != MessageConstant.MAGIC_TYPE) {
            byteBuf.resetReaderIndex();
            throw new Exception("error magic type");
        }
        byte messageType = (byte) byteBuf.readShort();
        long requestId = byteBuf.readLong();
        int dataLength = byteBuf.readInt();
        if (byteBuf.readableBytes() < dataLength) {
            byteBuf.resetReaderIndex();
            return;
        }

        byte[] data = new byte[dataLength];
        byteBuf.readBytes(data, 0, dataLength);
        // debug
        String r = new String(data, StandardCharsets.UTF_8);
        System.out.println(r);
        list.add(new Message(r));
    }

}

参考

Netty4学习笔记(4)-- ByteBuf和设计模式

Keynote中怎么展示代码

背景

在做技术分享的时候,经常需要去展示自己的代码;下面是整理的需求:

  1. 代码高亮显示
  2. 在能看清代码的情况下,容纳代码的上下文

做法

代码高亮

  1. IDE代码高亮截图
  2. 使用RTF格式插入文字格式的高亮代码

看清代码

放大局部代码

1. 使用截图的方式

优点:

  1. 制作方便

缺点:

  1. 在演讲屏幕比较大的时候,代码显示会比较模糊
  2. 因为代码已经变成了图片,所以不能copy和编辑

1、打开IDEA的演示模式 View - Enter Presentation Mode,截图放入Keynote

WX20170415-235214@2x.png

2、第二张幻灯片放大代码图片, 添加两个形状,遮挡不需要展示的代码

WX20170415-235310@2x.png

3、设置效果神奇移动

WX20170415-235359@2x.png

2. 使用RTF格式的方式

优点:

  1. 清晰度不受屏幕大小的影响
  2. 代码可copy,可编辑

缺点:

  1. 准备工作麻烦

1、安装代码高亮工具

brew install highlight

2、copy代码或者创建需要展示的代码文件

# 如果是copy的代码
# 注意需要指定 --syntax 扩展名
#            -u 编码,否则中文会乱码
#            -t 最好将代码中的tab转换成空格,keynote中\t的展示宽度可能会不一致
pbpaste | highlight --syntax=sh --style=github -k "Fira Code" -K 18 -u "utf-8" -t 4 -O rtf | pbcopy

# 如果是文件中的代码
highlight --style=github -k "Fira Code" -K 18 -u "utf-8" -t 4 -O rtf <filename> | pbcopy

3、直接在keynote中粘贴代码
4、设置效果神奇移动

WX20170416-001528@2x.png

增加callout

如果使用过 asciidoc,对这个应该不陌生

WX20170416-003300@2x.png

参考

  1. 如何使用keynote进行代码演示
  2. Code highlighting for Keynote presentations

ElasticSearch玄学问题

排序

"sort" : [
  "_score",
  {"created_at": "desc"}
]

// 多值字段,选择处理模式,这里是取平均值
"sort" : [
  {"price": {"order" : "asc", "mode" : "avg"}}
]

// 缺失字段的记录排最后
"sort" : [
  {"price": {"missing": "_last"} }
],

// 按照指定值的顺序
"script_score": {
  "params": {
    "ids": [
        50,
        80
        12
    ]
  },
  "script": """
    count = ids.size();
    id    = doc['status'].value;
    return count - ids.indexOf(i);
  """,
}

距离降权排序

{
  "query": {
    "function_score": {
      "query": {
        "term": {
          "city_id": 110000
        }
      },
      "functions": [{
        "gauss": {
          "geo_location_loc": {
            "origin": "39.908006,116.297453",
            "scale": "10km",
            "offset": 0,
            "decay": 0.2
          }
        }
      }]
    }
  },
  "script_fields": {
    "distance": {
      "script": "doc['geo_location_loc'].arcDistance(39.908006,116.297453)"
    }
  }
}
  1. 使用 ES 提供的衰减函数计算距离带来的权重影响
  2. script 中使用 groovy 脚本计算距离进行返回

同义词配置

{
  "index": {
    "analysis": {
      "filter": {
        "my_synonym_filter": {
          "synonyms_path": "analysis/synonym.txt",
          "type": "synonym"
        }
      },
      "analyzer": {
        "ik_syno": {
          "filter": [
            "my_synonym_filter"
          ],
          "type": "custom",
          "tokenizer": "ik_max_word"
        }
      }
    }
  }
}

索引优化

  1. 批量索引时,关闭elasticsearch备份,刷新时间设置为-1
  2. 使用bulk批量索引数据
  3. 使用单生产者扫表,多消费者建立es索引
  4. 使用SSD,相较HDD性能可提升3倍
1. {"refresh_interval": -1, number_of_replicas: 0}

查询优化

一般

  1. 在数据量比较大的时候,可以分片,将每个分片的数据量控制在百万级别;使用指定的字段值作为路由,查询的时候带上路由。
  2. 查询条件中不要使用变量,如时间查询中的 now, 这样不会缓存结果
  3. 对只读索引进行强制合并段 _optimize

GEO

  1. 为避免将所有的坐标点都加载到内存中,可以使用 geo_bounding_box 来优化查询
  2. 在精度要求不是很高的情况下,可以降低精度
  3. 坐标过滤的代价相对较为昂贵,可以使用其他条件过滤出一个较小的数据集,再使用坐标过滤
{
  "location": {
    "type": "geo_point",
    "fielddata": {
      "format":    "compressed",
      "precision": "1km"
    }
  }
}

Nested查询高亮

{
    "nested": {
        "path": "files",
        "query": {}
        "inner_hits": {
            "highlight": {
                "fields": {
                    "files.path": {}
                }
            }
        }
    }
}