diff --git a/plugins/wireshark/README.md b/plugins/wireshark/README.md new file mode 100644 index 00000000..1dbca5f9 --- /dev/null +++ b/plugins/wireshark/README.md @@ -0,0 +1,49 @@ +# Bolt wireshark plugin + +How to use it: + +* For Mac or Linux: +``` +$ sh install.sh +``` +* For Windows: +``` +$ .\install.bat +``` + +Then open wireshark and decode package as BOLT. + +Bolt package will be decoded like this: + +``` +Bolt Protocol Data + Header + rpc_trace_context.sofaRpcId: 0 + rpc_trace_context.sofaTraceId: 0bxxxx335162832343267634611586 + rpc_trace_context.sofaCallerIp: 1.2.3.4 + service: com.sofastack.demo.Service:1.0 + rpc_trace_context.sofaCallerApp: test-app + sofa_head_method_name: hello + Payload + payload + proto: 2 (BOLTv2) + ver1: 1 + type: 1 (request) + cmdcode: 1 (request) + ver2: 1 + req_id: 0 + codec: 11 (protobuf) + switch: 1 + timeout: 3000 + class_len: 44 + header_len: 691 + content_len: 65 + classname: com.alipay.sofa.rpc.core.request.SofaRequest + rpc_id: 0 + trace_id: 0bxxxx335162832343267634611586 +``` + +For advanced usage, you can search for any property under the bolt protocol, such as: +``` +bolt.trace_id == 0bxxxx335162832343267634611586 +``` diff --git a/plugins/wireshark/bolt.lua b/plugins/wireshark/bolt.lua new file mode 100644 index 00000000..a51fa736 --- /dev/null +++ b/plugins/wireshark/bolt.lua @@ -0,0 +1,441 @@ +--[[ + + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +]] +-- ###################################################################################################### +-- +-- WARN(dunjut): +-- +-- This is just an alpha version of wireshark bolt protocol dissector, potential bugs could mislead your +-- troubleshooting to a wrong direction (for example fields may not be correctly parsed in corner cases). +-- +-- Bug reports and optimizations are welcomed (not a lua expert here...) +-- +-- ###################################################################################################### +-- Request command protocol for v1 +-- ** request definition ** +-- +-- 0 1 2 4 6 8 10 12 14 16 +-- +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+ +-- |proto| type| cmdcode |ver2 | requestId |codec| timeout | classLen | +-- +-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+ +-- |headerLen | contentLen | ... ... | +-- +-----------+-----------+-----------+ + +-- | className + header + content bytes | +-- + + +-- | ... ... | +-- +-----------------------------------------------------------------------------------------------+ +-- +-- +-- Response command protocol for v1 +-- ** response definition ** +-- +-- 0 1 2 3 4 6 8 10 12 14 16 +-- +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+ +-- |proto| type| cmdcode |ver2 | requestId |codec|respstatus | classLen |headerLen | +-- +-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+ +-- | contentLen | ... ... | +-- +-----------------------+ + +-- | header + content bytes | +-- + + +-- | ... ... | +-- +-----------------------------------------------------------------------------------------------+ +-- +-- +-- ###################################################################################################### +-- Request command protocol for v2 +-- ** request definition ** +-- +-- 0 1 2 4 6 8 10 11 12 14 16 +-- +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+------+-----+-----+-----+-----+ +-- |proto| ver1|type | cmdcode |ver2 | requestId |codec|switch| timeout | +-- +-----------+-----------+-----------+-----------+-----------+------------+-----------+-----------+ +-- |classLen |headerLen |contentLen | ... | +-- +-----------+-----------+-----------+-----------+ + +-- | className + header + content bytes | +-- + + +-- | ... ... | CRC32(optional) | +-- +------------------------------------------------------------------------------------------------+ +-- +-- +-- Response command protocol for v2 +-- ** response definition ** +-- +-- 0 1 2 3 4 6 8 10 11 12 14 16 +-- +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+------+-----+-----+-----+-----+ +-- |proto| ver1| type| cmdcode |ver2 | requestId |codec|switch|respstatus | classLen | +-- +-----------+-----------+-----------+-----------+-----------+------------+-----------+-----------+ +-- |headerLen | contentLen | ... | +-- +-----------------------------------+ + +-- | className + header + content bytes | +-- + + +-- | ... ... | CRC32(optional) | +-- +------------------------------------------------------------------------------------------------+ +-- respstatus: response status +-- +-- Author: dunjut +-- Modified by JervyShi + + +bolt_protocol = Proto("Bolt", "SOFA Bolt Protocol") + +-- common fields +proto = ProtoField.int8("bolt.proto", "proto", base.DEC) +typ = ProtoField.int8("bolt.type", "type", base.DEC) +cmdcode = ProtoField.int16("bolt.cmdcode", "cmdcode", base.DEC) +ver2 = ProtoField.int8("bolt.ver2", "ver2", base.DEC) -- not sure what 'ver' actually means +req_id = ProtoField.int32("bolt.req_id", "req_id", base.DEC) +codec = ProtoField.int8("bolt.codec", "codec", base.DEC) + +classLen = ProtoField.int16("bolt.class_len", "class_len", base.DEC) +headerLen = ProtoField.int16("bolt.header_len", "header_len", base.DEC) +contentLen = ProtoField.int32("bolt.content_len", "content_len", base.DEC) +bufferLen = ProtoField.int32("bolt.buffer_len", "buffer_len", base.DEC) + +-- reqeust only +timeout = ProtoField.int32("bolt.timeout", "timeout", base.DEC) + +-- response only +status = ProtoField.int16("bolt.status", "status", base.DEC) +-- for both +classname = ProtoField.string("bolt.classname", "classname", base.ASCII) +payload = ProtoField.none("bolt.payload", "payload", base.HEX) + +-- not predefined fields but frequetly used data +trace_id = ProtoField.string("bolt.trace_id", "trace_id", base.ASCII) +rpc_id = ProtoField.string("bolt.rpc_id", "rpc_id", base.ASCII) + +-- boltv2 only fields +ver1 = ProtoField.int8("bolt.ver1", "ver1", base.DEC) -- bolt v2 only +switch = ProtoField.int8("bolt.switch", "switch", base.DEC) -- bolt v2 only, crc switch + +bolt_protocol.fields = { + proto, + ver1, -- boltv2 only + typ, cmdcode, ver2, req_id, codec, + switch, -- boltv2 only + timeout, -- request only + status, -- response only + classLen, + headerLen, + contentLen, + bufferLen, + classname, + payload, + crc, -- boltv2 optional + trace_id, rpc_id +} + +function bolt_protocol.dissector(buffer, pinfo, tree) + -- Ignore zero-length packets. + length = buffer:len() + if length == 0 then + return + end + + pinfo.cols.protocol = bolt_protocol.name + + local subtree = tree:add(bolt_protocol, buffer(), "Bolt Protocol Data") + local headerSubtree = subtree:add(bolt_protocol, buffer(), "Header") + local payloadSubtree = subtree:add(bolt_protocol, buffer(), "Payload") + + local reader_index = 0 + + -- Parse common fields + local proto_num = buffer(reader_index, 1):uint() + local proto_name = get_proto_name(proto_num) + subtree:add(proto, buffer(reader_index, 1)):append_text(" (" .. proto_name .. ")") + + reader_index = reader_index + 1 + + if proto_name == "BOLTv1" then + local type_num = buffer(reader_index, 1):uint() + local type_name = get_type_name(type_num) + subtree:add(typ, buffer(reader_index, 1)):append_text(" (" .. type_name .. ")") + reader_index = reader_index + 1 + + local cmdcode_num = buffer(reader_index, 2):uint() + local cmdcode_name = get_cmdcode_name(cmdcode_num) + subtree:add(cmdcode, buffer(reader_index, 2)):append_text(" (" .. cmdcode_name .. ")") + reader_index = reader_index + 2 + + subtree:add(ver2, buffer(reader_index, 1)) + reader_index = reader_index + 1 + subtree:add(req_id, buffer(reader_index, 4)) + reader_index = reader_index + 4 + + local codec_num = buffer(reader_index, 1):uint() + local codec_name = get_codec_name(codec_num) + subtree:add(codec, buffer(reader_index, 1)):append_text(" (" .. codec_name .. ")") + reader_index = reader_index + 1 + + -- for request packets -- + if type_name == "request" or type_name == "oneway" then + parse_request(buffer, subtree, headerSubtree, payloadSubtree, reader_index) + end + + -- for response packets -- + if cmdcode_name == "response" then + parse_response(buffer, subtree, headerSubtree, payloadSubtree, reader_index) + end + end + + if proto_name == "BOLTv2" then + subtree:add(ver1, buffer(reader_index, 1)) + reader_index = reader_index + 1 + + local type_num = buffer(reader_index, 1):uint() + local type_name = get_type_name(type_num) + subtree:add(typ, buffer(reader_index, 1)):append_text(" (" .. type_name .. ")") + reader_index = reader_index + 1 + + local cmdcode_num = buffer(reader_index, 2):uint() + local cmdcode_name = get_cmdcode_name(cmdcode_num) + subtree:add(cmdcode, buffer(reader_index, 2)):append_text(" (" .. cmdcode_name .. ")") + reader_index = reader_index + 2 + + subtree:add(ver2, buffer(reader_index, 1)) + reader_index = reader_index + 1 + subtree:add(req_id, buffer(reader_index, 4)) + reader_index = reader_index + 4 + + local codec_num = buffer(reader_index, 1):uint() + local codec_name = get_codec_name(codec_num) + subtree:add(codec, buffer(reader_index, 1)):append_text(" (" .. codec_name .. ")") + reader_index = reader_index + 1 + + subtree:add(switch, buffer(reader_index, 1)) + reader_index = reader_index + 1 + + -- for request packets -- + if type_name == "request" or type_name == "oneway" then + parse_request(buffer, subtree, headerSubtree, payloadSubtree, reader_index) + end + + -- for response packets -- + if type_name == "response" then + parse_response(buffer, subtree, headerSubtree, payloadSubtree, reader_index) + end + end +end + +function parse_request(buffer, subtree, headerSubtree, payloadSubtree, reader_index) + subtree:add(timeout, buffer(reader_index, 4)) + reader_index = reader_index + 4 + + local class_len = buffer(reader_index, 2):uint() + subtree:add(classLen, buffer(reader_index, 2)) + reader_index = reader_index + 2 + + -- headers + local header_len = buffer(reader_index, 2):uint() + subtree:add(headerLen, buffer(reader_index, 2)) + reader_index = reader_index + 2 + + -- payload + local content_len = buffer(reader_index, 4):uint() + subtree:add(contentLen, buffer(reader_index, 4)) + reader_index = reader_index + 4 + + subtree:add(classname, buffer(reader_index, class_len)) + reader_index = reader_index + class_len + + -- parse header + parse_headers(buffer, subtree, headerSubtree, reader_index, header_len) + reader_index = reader_index + header_len + + if buffer:len() >= reader_index + content_len then + -- parse payload + payloadSubtree:add(payload, buffer(reader_index, content_len)) + reader_index = reader_index + content_len + end +end + +function parse_response(buffer, subtree, headerSubtree, payloadSubtree, reader_index) + local status_code = buffer(reader_index, 2):uint() + local status_name = get_status_name(status_code) + subtree:add(status, buffer(reader_index, 2)):append_text(" (" .. status_name .. ")") + reader_index = reader_index + 2 + + local class_len = buffer(reader_index, 2):uint() + subtree:add(classLen, buffer(reader_index, 2)) + reader_index = reader_index + 2 + + -- headers + local header_len = buffer(reader_index, 2):uint() + subtree:add(headerLen, buffer(reader_index, 2)) + reader_index = reader_index + 2 + + -- payload + local content_len = buffer(reader_index, 4):uint() + subtree:add(contentLen, buffer(reader_index, 4)) + reader_index = reader_index + 4 + + -- parse className + subtree:add(classname, buffer(reader_index, class_len)) + reader_index = reader_index + class_len + + -- parse headers + parse_headers(buffer, subtree, headerSubtree, reader_index, header_len) + reader_index = reader_index + header_len + + if buffer:len() >= reader_index + content_len then + -- parse payload + payloadSubtree:add(payload, buffer(reader_index, content_len)) + reader_index = reader_index + content_len + end +end + +-- parse headers from buffer(start, len) and add KV pairs into tree (packet details pane of wireshark) +function parse_headers(buffer, subtree, headerTree, start, len) + local remain = len + local index = start + while remain > 0 do + local from = index + local kv_len = 0 + + -- header key + local key_len = buffer(index, 4):uint() + index = index + 4 + + local key_name = buffer(index, key_len):string(ENC_UTF_8) + index = index + key_len + + -- header value + local val_len = buffer(index, 4):uint() + index = index + 4 + + kv_len = 4 + key_len + 4 + val_len + + local value = buffer(index, val_len):string(ENC_UTF_8) + headerTree:add(buffer(from, kv_len), key_name .. ": " .. value) + + -- special cases + if key_name == "rpc_trace_context.sofaTraceId" then + subtree:add(trace_id, buffer(index, val_len)) + end + + if key_name == "rpc_trace_context.sofaRpcId" then + subtree:add(rpc_id, buffer(index, val_len)) + end + + index = index + val_len + remain = remain - kv_len + end +end + +-- map proto number to proto string. +function get_proto_name(proto) + local proto_name = "Unknown" + + if proto == 1 then + proto_name = "BOLTv1" + elseif proto == 2 then + proto_name = "BOLTv2" + elseif proto == 13 then + proto_name = "TR" + end + + return proto_name +end + +-- map type number to request type string. +function get_type_name(typ) + local type_name = "Unknown" + + if typ == 0 then + type_name = "response" + elseif typ == 1 then + type_name = "request" + elseif typ == 2 then + type_name = "oneway" + end + + return type_name +end + +-- map cmdcode to string representation of command type. +function get_cmdcode_name(cmdcode) + local cmdcode_name = "Unknown" + + if cmdcode == 0 then + cmdcode_name = "heartbeat" + elseif cmdcode == 1 then + cmdcode_name = "request" + elseif cmdcode == 2 then + cmdcode_name = "response" + end + + return cmdcode_name +end + +-- map codec number to codec name. +function get_codec_name(codec) + local codec_name = "Unknown" + + if codec == 0 then + codec_name = "hessian" + elseif codec == 1 then + codec_name = "hessian2" + elseif codec == 11 then + codec_name = "protobuf" + elseif codec == 12 then + codec_name = "json" + end + + return codec_name +end + +-- map status code to status string. +function get_status_name(statuscode) + local status_name = "Unknown" + + if statuscode == 0 then + status_name = "Success" + elseif statuscode == 1 then + status_name = "Error" + elseif statuscode == 2 then + status_name = "Server Exception" + elseif statuscode == 3 then + status_name = "Unknown" + elseif statuscode == 4 then + status_name = "Server Thread Pool Busy" + elseif statuscode == 5 then + status_name = "Error Comm" -- not sure what exactly this means... + elseif statuscode == 6 then + status_name = "No Processor" + elseif statuscode == 7 then + status_name = "Timeout" + elseif statuscode == 8 then + status_name = "Client Send Error" + elseif statuscode == 9 then + status_name = "Codec Exception" + elseif statuscode == 16 then + status_name = "Connection Closed" -- 16 is from 0x10 ... (previous codes are 0x00..0x09 -.-!) + elseif statuscode == 17 then + status_name = "Server Serial Exception" + elseif statuscode == 18 then + status_name = "Server Deserial Exception" + end + + return status_name +end + +-- register our dissector upon tcp port 12200 (default) +bolt_protocol.prefs.port = Pref.uint("Bolt TCP port", 12200) +local tcp_port = DissectorTable.get("tcp.port") +tcp_port:add(bolt_protocol.prefs.port, bolt_protocol) diff --git a/plugins/wireshark/install.bat b/plugins/wireshark/install.bat new file mode 100644 index 00000000..2f1388dc --- /dev/null +++ b/plugins/wireshark/install.bat @@ -0,0 +1,24 @@ +@REM +@REM Licensed to the Apache Software Foundation (ASF) under one or more +@REM contributor license agreements. See the NOTICE file distributed with +@REM this work for additional information regarding copyright ownership. +@REM The ASF licenses this file to You under the Apache License, Version 2.0 +@REM (the "License"); you may not use this file except in compliance with +@REM the License. You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, software +@REM distributed under the License is distributed on an "AS IS" BASIS, +@REM WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@REM See the License for the specific language governing permissions and +@REM limitations under the License. +@REM + +@echo off +:: Get personal plugin folder from https://www.wireshark.org/docs/wsug_html_chunked/ChPluginFolders.html +SET plugin_dir=%APPDATA%\Wireshark\plugins +SET script_dir=%cd% +if not exist %plugin_dir% mkdir %plugin_dir% +copy %script_dir%\bolt.lua %plugin_dir% +echo Wireshark bolt protocol extension has been installed successfully, please restart Wireshark before using it. \ No newline at end of file diff --git a/plugins/wireshark/install.sh b/plugins/wireshark/install.sh new file mode 100755 index 00000000..2ec8422f --- /dev/null +++ b/plugins/wireshark/install.sh @@ -0,0 +1,24 @@ +#!/bin/bash +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + + +plugin_dir=~/.config/wireshark/plugins +script_dir=`dirname $0` +mkdir -p ${plugin_dir} +cp $script_dir/bolt.lua ${plugin_dir} +echo "Wireshark bolt protocol extension has been installed successfully, please restart Wireshark before using it." \ No newline at end of file diff --git a/pom.xml b/pom.xml index 46b30823..245011e5 100644 --- a/pom.xml +++ b/pom.xml @@ -22,7 +22,7 @@ 4.0.0 com.alipay.sofa bolt - 1.6.3-SNAPSHOT + 1.6.4 jar ${project.groupId}:${project.artifactId} @@ -38,20 +38,20 @@ - tsui - xiaomin.cxm@antfin.com + chengyi + mark.lx@antfin.com Ant Financial https://www.alipay.com/ - jiangping - jiangping@antfin.com + tsui + xiaomin.cxm@antfin.com Ant Financial https://www.alipay.com/ - yueliang - yueliang.yml@antfin.com + jiangping + jiangping@antfin.com Ant Financial https://www.alipay.com/ @@ -116,7 +116,7 @@ junit junit - 4.11 + 4.13.1 test @@ -128,7 +128,7 @@ org.apache.logging.log4j log4j-core - 2.3 + 2.13.2 test @@ -143,24 +143,6 @@ 3.2.0 test - - org.mockito - mockito-all - 1.8.5 - test - - - org.openjdk.jmh - jmh-core - 1.20 - test - - - org.openjdk.jmh - jmh-generator-annprocess - 1.20 - test - diff --git a/src/main/java/com/alipay/remoting/AbstractBoltClient.java b/src/main/java/com/alipay/remoting/AbstractBoltClient.java index 9d3d3c1c..958cb914 100644 --- a/src/main/java/com/alipay/remoting/AbstractBoltClient.java +++ b/src/main/java/com/alipay/remoting/AbstractBoltClient.java @@ -16,14 +16,13 @@ */ package com.alipay.remoting; +import com.alipay.remoting.config.BoltClientOption; import com.alipay.remoting.config.BoltOption; import com.alipay.remoting.config.BoltOptions; import com.alipay.remoting.config.ConfigManager; -import com.alipay.remoting.config.Configurable; +import com.alipay.remoting.config.Configuration; import com.alipay.remoting.config.ConfigurableInstance; import com.alipay.remoting.config.configs.ConfigContainer; -import com.alipay.remoting.config.configs.ConfigItem; -import com.alipay.remoting.config.configs.ConfigType; import com.alipay.remoting.config.configs.DefaultConfigContainer; import com.alipay.remoting.config.switches.GlobalSwitch; @@ -34,14 +33,23 @@ public abstract class AbstractBoltClient extends AbstractLifeCycle implements Bo ConfigurableInstance { private final BoltOptions options; - private final ConfigType configType; private final GlobalSwitch globalSwitch; private final ConfigContainer configContainer; public AbstractBoltClient() { this.options = new BoltOptions(); - this.configType = ConfigType.CLIENT_SIDE; this.globalSwitch = new GlobalSwitch(); + if (ConfigManager.conn_reconnect_switch()) { + option(BoltClientOption.CONN_RECONNECT_SWITCH, true); + } else { + option(BoltClientOption.CONN_RECONNECT_SWITCH, false); + } + + if (ConfigManager.conn_monitor_switch()) { + option(BoltClientOption.CONN_MONITOR_SWITCH, true); + } else { + option(BoltClientOption.CONN_MONITOR_SWITCH, false); + } this.configContainer = new DefaultConfigContainer(); } @@ -51,44 +59,36 @@ public T option(BoltOption option) { } @Override - public Configurable option(BoltOption option, T value) { + public Configuration option(BoltOption option, T value) { options.option(option, value); return this; } @Override + @Deprecated public ConfigContainer conf() { return this.configContainer; } @Override + @Deprecated public GlobalSwitch switches() { return this.globalSwitch; } @Override public void initWriteBufferWaterMark(int low, int high) { - this.configContainer.set(configType, ConfigItem.NETTY_BUFFER_LOW_WATER_MARK, low); - this.configContainer.set(configType, ConfigItem.NETTY_BUFFER_HIGH_WATER_MARK, high); + option(BoltClientOption.NETTY_BUFFER_LOW_WATER_MARK, low); + option(BoltClientOption.NETTY_BUFFER_HIGH_WATER_MARK, high); } @Override public int netty_buffer_low_watermark() { - Object config = configContainer.get(configType, ConfigItem.NETTY_BUFFER_LOW_WATER_MARK); - if (config != null) { - return (Integer) config; - } else { - return ConfigManager.netty_buffer_low_watermark(); - } + return option(BoltClientOption.NETTY_BUFFER_LOW_WATER_MARK); } @Override public int netty_buffer_high_watermark() { - Object config = configContainer.get(configType, ConfigItem.NETTY_BUFFER_HIGH_WATER_MARK); - if (config != null) { - return (Integer) config; - } else { - return ConfigManager.netty_buffer_high_watermark(); - } + return option(BoltClientOption.NETTY_BUFFER_HIGH_WATER_MARK); } } diff --git a/src/main/java/com/alipay/remoting/AbstractRemotingServer.java b/src/main/java/com/alipay/remoting/AbstractRemotingServer.java index ebcd7cb2..f1351365 100644 --- a/src/main/java/com/alipay/remoting/AbstractRemotingServer.java +++ b/src/main/java/com/alipay/remoting/AbstractRemotingServer.java @@ -20,16 +20,14 @@ import com.alipay.remoting.config.BoltOption; import com.alipay.remoting.config.BoltOptions; -import com.alipay.remoting.config.ConfigManager; -import com.alipay.remoting.config.Configurable; +import com.alipay.remoting.config.BoltServerOption; +import com.alipay.remoting.config.Configuration; import com.alipay.remoting.config.ConfigurableInstance; import com.alipay.remoting.config.configs.ConfigContainer; -import com.alipay.remoting.config.configs.ConfigItem; import com.alipay.remoting.config.configs.DefaultConfigContainer; import com.alipay.remoting.config.switches.GlobalSwitch; import org.slf4j.Logger; -import com.alipay.remoting.config.configs.ConfigType; import com.alipay.remoting.log.BoltLoggerFactory; /** @@ -47,7 +45,6 @@ public abstract class AbstractRemotingServer extends AbstractLifeCycle implement private int port; private final BoltOptions options; - private final ConfigType configType; private final GlobalSwitch globalSwitch; private final ConfigContainer configContainer; @@ -64,7 +61,6 @@ public AbstractRemotingServer(String ip, int port) { this.port = port; this.options = new BoltOptions(); - this.configType = ConfigType.SERVER_SIDE; this.globalSwitch = new GlobalSwitch(); this.configContainer = new DefaultConfigContainer(); } @@ -149,44 +145,36 @@ public T option(BoltOption option) { } @Override - public Configurable option(BoltOption option, T value) { + public Configuration option(BoltOption option, T value) { options.option(option, value); return this; } @Override + @Deprecated public ConfigContainer conf() { return this.configContainer; } @Override + @Deprecated public GlobalSwitch switches() { return this.globalSwitch; } @Override public void initWriteBufferWaterMark(int low, int high) { - this.configContainer.set(configType, ConfigItem.NETTY_BUFFER_LOW_WATER_MARK, low); - this.configContainer.set(configType, ConfigItem.NETTY_BUFFER_HIGH_WATER_MARK, high); + option(BoltServerOption.NETTY_BUFFER_LOW_WATER_MARK, low); + option(BoltServerOption.NETTY_BUFFER_HIGH_WATER_MARK, high); } @Override public int netty_buffer_low_watermark() { - Object config = configContainer.get(configType, ConfigItem.NETTY_BUFFER_LOW_WATER_MARK); - if (config != null) { - return (Integer) config; - } else { - return ConfigManager.netty_buffer_low_watermark(); - } + return option(BoltServerOption.NETTY_BUFFER_LOW_WATER_MARK); } @Override public int netty_buffer_high_watermark() { - Object config = configContainer.get(configType, ConfigItem.NETTY_BUFFER_HIGH_WATER_MARK); - if (config != null) { - return (Integer) config; - } else { - return ConfigManager.netty_buffer_high_watermark(); - } + return option(BoltServerOption.NETTY_BUFFER_HIGH_WATER_MARK); } } diff --git a/src/main/java/com/alipay/remoting/BaseRemoting.java b/src/main/java/com/alipay/remoting/BaseRemoting.java index 519f890e..f65f3b7e 100644 --- a/src/main/java/com/alipay/remoting/BaseRemoting.java +++ b/src/main/java/com/alipay/remoting/BaseRemoting.java @@ -36,8 +36,10 @@ * @version $Id: BaseRemoting.java, v 0.1 Mar 4, 2016 12:09:56 AM tao Exp $ */ public abstract class BaseRemoting { - /** logger */ - private static final Logger logger = BoltLoggerFactory.getLogger("CommonDefault"); + + private final static Logger LOGGER = BoltLoggerFactory + .getLogger("CommonDefault"); + private final static long ABANDONING_REQUEST_THRESHOLD = 0L; protected CommandFactory commandFactory; @@ -58,9 +60,25 @@ public BaseRemoting(CommandFactory commandFactory) { protected RemotingCommand invokeSync(final Connection conn, final RemotingCommand request, final int timeoutMillis) throws RemotingException, InterruptedException { + int remainingTime = remainingTime(request, timeoutMillis); + if (remainingTime <= ABANDONING_REQUEST_THRESHOLD) { + // already timeout + LOGGER + .warn( + "already timeout before writing to the network, requestId: {}, remoting address: {}", + request.getId(), + conn.getUrl() != null ? conn.getUrl() : RemotingUtil.parseRemoteAddress(conn + .getChannel())); + return this.commandFactory.createTimeoutResponse(conn.getRemoteAddress()); + } + final InvokeFuture future = createInvokeFuture(request, request.getInvokeContext()); conn.addInvokeFuture(future); final int requestId = request.getId(); + InvokeContext invokeContext = request.getInvokeContext(); + if (null != invokeContext) { + invokeContext.put(InvokeContext.BOLT_PROCESS_CLIENT_BEFORE_SEND, System.nanoTime()); + } try { conn.getChannel().writeAndFlush(request).addListener(new ChannelFutureListener() { @@ -70,22 +88,29 @@ public void operationComplete(ChannelFuture f) throws Exception { conn.removeInvokeFuture(requestId); future.putResponse(commandFactory.createSendFailedResponse( conn.getRemoteAddress(), f.cause())); - logger.error("Invoke send failed, id={}", requestId, f.cause()); + LOGGER.error("Invoke send failed, id={}", requestId, f.cause()); } } }); + if (null != invokeContext) { + invokeContext.put(InvokeContext.BOLT_PROCESS_CLIENT_AFTER_SEND, System.nanoTime()); + } } catch (Exception e) { conn.removeInvokeFuture(requestId); future.putResponse(commandFactory.createSendFailedResponse(conn.getRemoteAddress(), e)); - logger.error("Exception caught when sending invocation, id={}", requestId, e); + LOGGER.error("Exception caught when sending invocation, id={}", requestId, e); + } + RemotingCommand response = future.waitResponse(remainingTime); + + if (null != invokeContext) { + invokeContext.put(InvokeContext.BOLT_PROCESS_CLIENT_RECEIVED, System.nanoTime()); } - RemotingCommand response = future.waitResponse(timeoutMillis); if (response == null) { conn.removeInvokeFuture(requestId); response = this.commandFactory.createTimeoutResponse(conn.getRemoteAddress()); - logger.warn("Wait response, request id={} timeout!", requestId); + LOGGER.warn("Wait response, request id={} timeout!", requestId); } return response; @@ -104,6 +129,18 @@ protected void invokeWithCallback(final Connection conn, final RemotingCommand r final InvokeCallback invokeCallback, final int timeoutMillis) { final InvokeFuture future = createInvokeFuture(conn, request, request.getInvokeContext(), invokeCallback); + int remainingTime = remainingTime(request, timeoutMillis); + if (remainingTime <= ABANDONING_REQUEST_THRESHOLD) { + LOGGER + .warn( + "already timeout before writing to the network, requestId: {}, remoting address: {}", + request.getId(), + conn.getUrl() != null ? conn.getUrl() : RemotingUtil.parseRemoteAddress(conn + .getChannel())); + future.putResponse(commandFactory.createTimeoutResponse(conn.getRemoteAddress())); + future.tryAsyncExecuteInvokeCallbackAbnormally(); + return; + } conn.addInvokeFuture(future); final int requestId = request.getId(); try { @@ -118,7 +155,7 @@ public void run(Timeout timeout) throws Exception { } } - }, timeoutMillis, TimeUnit.MILLISECONDS); + }, remainingTime, TimeUnit.MILLISECONDS); future.addTimeout(timeout); conn.getChannel().writeAndFlush(request).addListener(new ChannelFutureListener() { @@ -132,7 +169,7 @@ public void operationComplete(ChannelFuture cf) throws Exception { conn.getRemoteAddress(), cf.cause())); f.tryAsyncExecuteInvokeCallbackAbnormally(); } - logger.error("Invoke send failed. The address is {}", + LOGGER.error("Invoke send failed. The address is {}", RemotingUtil.parseRemoteAddress(conn.getChannel()), cf.cause()); } } @@ -145,7 +182,7 @@ public void operationComplete(ChannelFuture cf) throws Exception { f.putResponse(commandFactory.createSendFailedResponse(conn.getRemoteAddress(), e)); f.tryAsyncExecuteInvokeCallbackAbnormally(); } - logger.error("Exception caught when sending invocation. The address is {}", + LOGGER.error("Exception caught when sending invocation. The address is {}", RemotingUtil.parseRemoteAddress(conn.getChannel()), e); } } @@ -163,6 +200,18 @@ protected InvokeFuture invokeWithFuture(final Connection conn, final RemotingCom final InvokeFuture future = createInvokeFuture(request, request.getInvokeContext()); conn.addInvokeFuture(future); + int remainingTime = remainingTime(request, timeoutMillis); + if (remainingTime <= ABANDONING_REQUEST_THRESHOLD) { + LOGGER + .warn( + "already timeout before writing to the network, requestId: {}, remoting address: {}", + request.getId(), + conn.getUrl() != null ? conn.getUrl() : RemotingUtil.parseRemoteAddress(conn + .getChannel())); + future.putResponse(commandFactory.createTimeoutResponse(conn.getRemoteAddress())); + return future; + } + final int requestId = request.getId(); try { Timeout timeout = TimerHolder.getTimer().newTimeout(new TimerTask() { @@ -175,7 +224,7 @@ public void run(Timeout timeout) throws Exception { } } - }, timeoutMillis, TimeUnit.MILLISECONDS); + }, remainingTime, TimeUnit.MILLISECONDS); future.addTimeout(timeout); conn.getChannel().writeAndFlush(request).addListener(new ChannelFutureListener() { @@ -189,7 +238,7 @@ public void operationComplete(ChannelFuture cf) throws Exception { f.putResponse(commandFactory.createSendFailedResponse( conn.getRemoteAddress(), cf.cause())); } - logger.error("Invoke send failed. The address is {}", + LOGGER.error("Invoke send failed. The address is {}", RemotingUtil.parseRemoteAddress(conn.getChannel()), cf.cause()); } } @@ -201,7 +250,7 @@ public void operationComplete(ChannelFuture cf) throws Exception { f.cancelTimeout(); f.putResponse(commandFactory.createSendFailedResponse(conn.getRemoteAddress(), e)); } - logger.error("Exception caught when sending invocation. The address is {}", + LOGGER.error("Exception caught when sending invocation. The address is {}", RemotingUtil.parseRemoteAddress(conn.getChannel()), e); } return future; @@ -215,25 +264,40 @@ public void operationComplete(ChannelFuture cf) throws Exception { * @throws InterruptedException */ protected void oneway(final Connection conn, final RemotingCommand request) { + if (conn == null) { + LOGGER.error("conn is null"); + return; + } + + Url url = conn.getUrl(); + if (url != null) { + int remainingTime = remainingTime(request, url.getConnectTimeout()); + if (remainingTime <= ABANDONING_REQUEST_THRESHOLD) { + LOGGER + .warn( + "already timeout before writing to the network, requestId: {}, remoting address: {}", + request.getId(), + conn.getUrl() != null ? conn.getUrl() : RemotingUtil + .parseRemoteAddress(conn.getChannel())); + return; + } + } + try { conn.getChannel().writeAndFlush(request).addListener(new ChannelFutureListener() { @Override public void operationComplete(ChannelFuture f) throws Exception { if (!f.isSuccess()) { - logger.error("Invoke send failed. The address is {}", + LOGGER.error("Invoke send failed. The address is {}", RemotingUtil.parseRemoteAddress(conn.getChannel()), f.cause()); } } }); } catch (Exception e) { - if (null == conn) { - logger.error("Conn is null"); - } else { - logger.error("Exception caught when sending invocation. The address is {}", - RemotingUtil.parseRemoteAddress(conn.getChannel()), e); - } + LOGGER.error("Exception caught when sending invocation. The address is {}", + RemotingUtil.parseRemoteAddress(conn.getChannel()), e); } } @@ -262,4 +326,17 @@ protected abstract InvokeFuture createInvokeFuture(final Connection conn, protected CommandFactory getCommandFactory() { return commandFactory; } + + private int remainingTime(RemotingCommand request, int timeout) { + InvokeContext invokeContext = request.getInvokeContext(); + if (invokeContext == null) { + return timeout; + } + Long cost = invokeContext.get(InvokeContext.CLIENT_CONN_CREATETIME); + if (cost == null) { + return timeout; + } + + return (int) (timeout - cost); + } } diff --git a/src/main/java/com/alipay/remoting/BoltClient.java b/src/main/java/com/alipay/remoting/BoltClient.java index f2e2eb2a..f767e94c 100644 --- a/src/main/java/com/alipay/remoting/BoltClient.java +++ b/src/main/java/com/alipay/remoting/BoltClient.java @@ -16,7 +16,7 @@ */ package com.alipay.remoting; -import com.alipay.remoting.config.Configurable; +import com.alipay.remoting.config.Configuration; import com.alipay.remoting.exception.RemotingException; import com.alipay.remoting.rpc.RpcClient; import com.alipay.remoting.rpc.RpcConfigs; @@ -32,7 +32,7 @@ * * @author chengyi (mark.lx@antfin.com) 2018-11-07 11:56 */ -public interface BoltClient extends Configurable, LifeCycle { +public interface BoltClient extends Configuration, LifeCycle { /** * One way invocation using a string address, address format example - 127.0.0.1:12200?key1=value1&key2=value2
@@ -653,7 +653,14 @@ Connection getConnection(Url url, int connectTimeout) throws RemotingException, * * @return property value of connectionManager */ - DefaultConnectionManager getConnectionManager(); + ConnectionManager getConnectionManager(); + + /** + * Setter method for property connectionManager. + * + * @param connectionManager ConnectionManager + */ + void setConnectionManager(ConnectionManager connectionManager); /** * Getter method for property addressParser. diff --git a/src/main/java/com/alipay/remoting/ConnectionEventHandler.java b/src/main/java/com/alipay/remoting/ConnectionEventHandler.java index 154005de..a5dda17c 100644 --- a/src/main/java/com/alipay/remoting/ConnectionEventHandler.java +++ b/src/main/java/com/alipay/remoting/ConnectionEventHandler.java @@ -22,9 +22,10 @@ import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; +import com.alipay.remoting.config.BoltClientOption; +import com.alipay.remoting.config.Configuration; import org.slf4j.Logger; -import com.alipay.remoting.config.switches.GlobalSwitch; import com.alipay.remoting.log.BoltLoggerFactory; import com.alipay.remoting.util.RemotingUtil; import com.alipay.remoting.util.StringUtils; @@ -54,14 +55,14 @@ public class ConnectionEventHandler extends ChannelDuplexHandler { private Reconnector reconnectManager; - private GlobalSwitch globalSwitch; + private Configuration configuration; public ConnectionEventHandler() { } - public ConnectionEventHandler(GlobalSwitch globalSwitch) { - this.globalSwitch = globalSwitch; + public ConnectionEventHandler(Configuration configuration) { + this.configuration = configuration; } /** @@ -207,7 +208,8 @@ public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws E } private void submitReconnectTaskIfNecessary(Url url) { - if (globalSwitch.isOn(GlobalSwitch.CONN_RECONNECT_SWITCH) && reconnectManager != null) { + if (configuration.option(BoltClientOption.CONN_RECONNECT_SWITCH) + && reconnectManager != null) { reconnectManager.reconnect(url); } } diff --git a/src/main/java/com/alipay/remoting/ConnectionManager.java b/src/main/java/com/alipay/remoting/ConnectionManager.java index f7aa6420..39f2b4ad 100644 --- a/src/main/java/com/alipay/remoting/ConnectionManager.java +++ b/src/main/java/com/alipay/remoting/ConnectionManager.java @@ -27,7 +27,7 @@ * @author xiaomin.cxm * @version $Id: ConnectionManager.java, v 0.1 Mar 7, 2016 2:42:46 PM xiaomin.cxm Exp $ */ -public interface ConnectionManager extends Scannable, LifeCycle { +public interface ConnectionManager extends Scannable, ConnectionHeartbeatManager, LifeCycle { /** * Deprecated, use startup instead. diff --git a/src/main/java/com/alipay/remoting/DefaultClientConnectionManager.java b/src/main/java/com/alipay/remoting/DefaultClientConnectionManager.java index 6f067ba0..5e357628 100644 --- a/src/main/java/com/alipay/remoting/DefaultClientConnectionManager.java +++ b/src/main/java/com/alipay/remoting/DefaultClientConnectionManager.java @@ -16,7 +16,6 @@ */ package com.alipay.remoting; -import com.alipay.remoting.config.switches.GlobalSwitch; import com.alipay.remoting.connection.ConnectionFactory; /** @@ -35,15 +34,6 @@ public DefaultClientConnectionManager(ConnectionSelectStrategy connectionSelectS connectionEventListener); } - public DefaultClientConnectionManager(ConnectionSelectStrategy connectionSelectStrategy, - ConnectionFactory connectionFactory, - ConnectionEventHandler connectionEventHandler, - ConnectionEventListener connectionEventListener, - GlobalSwitch globalSwitch) { - super(connectionSelectStrategy, connectionFactory, connectionEventHandler, - connectionEventListener, globalSwitch); - } - @Override public void startup() throws LifeCycleException { super.startup(); diff --git a/src/main/java/com/alipay/remoting/DefaultConnectionManager.java b/src/main/java/com/alipay/remoting/DefaultConnectionManager.java index f1cc4e49..08d501e6 100644 --- a/src/main/java/com/alipay/remoting/DefaultConnectionManager.java +++ b/src/main/java/com/alipay/remoting/DefaultConnectionManager.java @@ -36,7 +36,6 @@ import org.slf4j.Logger; import com.alipay.remoting.config.ConfigManager; -import com.alipay.remoting.config.switches.GlobalSwitch; import com.alipay.remoting.connection.ConnectionFactory; import com.alipay.remoting.exception.RemotingException; import com.alipay.remoting.util.FutureTaskUtil; @@ -50,7 +49,6 @@ * @version $Id: DefaultConnectionManager.java, v 0.1 Mar 8, 2016 10:43:51 AM xiaomin.cxm Exp $ */ public class DefaultConnectionManager extends AbstractLifeCycle implements ConnectionManager, - ConnectionHeartbeatManager, Scannable, LifeCycle { private static final Logger logger = BoltLoggerFactory @@ -61,11 +59,6 @@ public class DefaultConnectionManager extends AbstractLifeCycle implements Conne */ private ThreadPoolExecutor asyncCreateConnectionExecutor; - /** - * switch status - */ - private GlobalSwitch globalSwitch; - /** * connection pool initialize tasks */ @@ -101,15 +94,6 @@ public class DefaultConnectionManager extends AbstractLifeCycle implements Conne */ protected ConnectionEventListener connectionEventListener; - /** - * Default constructor. - */ - public DefaultConnectionManager() { - this.connTasks = new ConcurrentHashMap>(); - this.healTasks = new ConcurrentHashMap>(); - this.connectionSelectStrategy = new RandomSelectStrategy(globalSwitch); - } - /** * Construct with parameters. * @@ -164,25 +148,6 @@ public DefaultConnectionManager(ConnectionSelectStrategy connectionSelectStrateg this.connectionEventListener = connectionEventListener; } - /** - * Construct with parameters. - * - * @param connectionSelectStrategy connection selection strategy. - * @param connectionFactory connection factory - * @param connectionEventHandler connection event handler - * @param connectionEventListener connection event listener - * @param globalSwitch global switch - */ - public DefaultConnectionManager(ConnectionSelectStrategy connectionSelectStrategy, - ConnectionFactory connectionFactory, - ConnectionEventHandler connectionEventHandler, - ConnectionEventListener connectionEventListener, - GlobalSwitch globalSwitch) { - this(connectionSelectStrategy, connectionFactory, connectionEventHandler, - connectionEventListener); - this.globalSwitch = globalSwitch; - } - @Override public void startup() throws LifeCycleException { super.startup(); diff --git a/src/main/java/com/alipay/remoting/DefaultConnectionMonitor.java b/src/main/java/com/alipay/remoting/DefaultConnectionMonitor.java index 05545a72..eaf668f7 100644 --- a/src/main/java/com/alipay/remoting/DefaultConnectionMonitor.java +++ b/src/main/java/com/alipay/remoting/DefaultConnectionMonitor.java @@ -37,13 +37,13 @@ public class DefaultConnectionMonitor extends AbstractLifeCycle { private static final Logger logger = BoltLoggerFactory.getLogger("CommonDefault"); - private final DefaultConnectionManager connectionManager; + private final ConnectionManager connectionManager; private final ConnectionMonitorStrategy strategy; private ScheduledThreadPoolExecutor executor; public DefaultConnectionMonitor(ConnectionMonitorStrategy strategy, - DefaultConnectionManager connectionManager) { + ConnectionManager connectionManager) { if (strategy == null) { throw new IllegalArgumentException("null strategy"); } @@ -72,8 +72,10 @@ public void startup() throws LifeCycleException { @Override public void run() { try { - Map> connPools = connectionManager - .getConnPools(); + Map> connPools = null; + if (connectionManager instanceof DefaultConnectionManager) { + connPools = ((DefaultConnectionManager) connectionManager).getConnPools(); + } strategy.monitor(connPools); } catch (Exception e) { logger.warn("MonitorTask error", e); diff --git a/src/main/java/com/alipay/remoting/config/configs/NettyConfigure.java b/src/main/java/com/alipay/remoting/ExtendedNettyChannelHandler.java similarity index 52% rename from src/main/java/com/alipay/remoting/config/configs/NettyConfigure.java rename to src/main/java/com/alipay/remoting/ExtendedNettyChannelHandler.java index e32747f2..734ff8f9 100644 --- a/src/main/java/com/alipay/remoting/config/configs/NettyConfigure.java +++ b/src/main/java/com/alipay/remoting/ExtendedNettyChannelHandler.java @@ -14,34 +14,27 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.alipay.remoting.config.configs; +package com.alipay.remoting; + +import io.netty.channel.ChannelHandler; + +import java.util.List; /** - * netty related configuration items - * - * @author tsui - * @version $Id: NettyConfigure.java, v 0.1 2018-07-30 21:42 tsui Exp $$ + * Leave it to external expansion and + * support the addition of extended handler in the channel pipeline. */ -public interface NettyConfigure { - /** - * Initialize netty write buffer water mark for remoting instance. - *

- * Notice: This api should be called before init remoting instance. - * - * @param low [0, high] - * @param high [high, Integer.MAX_VALUE) - */ - void initWriteBufferWaterMark(int low, int high); +public interface ExtendedNettyChannelHandler { /** - * get the low water mark for netty write buffer - * @return low watermark + * Netty ChannelHandlers to be added before Bolt's built-in Handler. + * @return Netty ChannelHandler list */ - int netty_buffer_low_watermark(); + List frontChannelHandlers(); /** - * get the high water mark for netty write buffer - * @return high watermark + * Netty ChannelHandlers to be added after Bolt's built-in Handler. + * @return Netty ChannelHandler list */ - int netty_buffer_high_watermark(); -} \ No newline at end of file + List backChannelHandlers(); +} diff --git a/src/main/java/com/alipay/remoting/InvokeContext.java b/src/main/java/com/alipay/remoting/InvokeContext.java index 6aae5614..5cfaf402 100644 --- a/src/main/java/com/alipay/remoting/InvokeContext.java +++ b/src/main/java/com/alipay/remoting/InvokeContext.java @@ -18,7 +18,7 @@ import java.util.concurrent.ConcurrentHashMap; -/**
 +/** * Invoke context * * @author tsui
 @@ -26,28 +26,47 @@ */ public class InvokeContext { // ~~~ invoke context keys of client side - public final static String CLIENT_LOCAL_IP = "bolt.client.local.ip"; - public final static String CLIENT_LOCAL_PORT = "bolt.client.local.port"; - public final static String CLIENT_REMOTE_IP = "bolt.client.remote.ip"; - public final static String CLIENT_REMOTE_PORT = "bolt.client.remote.port"; + public final static String CLIENT_LOCAL_IP = "bolt.client.local.ip"; + public final static String CLIENT_LOCAL_PORT = "bolt.client.local.port"; + public final static String CLIENT_REMOTE_IP = "bolt.client.remote.ip"; + public final static String CLIENT_REMOTE_PORT = "bolt.client.remote.port"; /** time consumed during connection creating, this is a timespan */ - public final static String CLIENT_CONN_CREATETIME = "bolt.client.conn.createtime"; + public final static String CLIENT_CONN_CREATETIME = "bolt.client.conn.createtime"; + public final static String CLIENT_CONN_CREATE_START_IN_NANO = "bolt.client.conn.create.start.nano"; + public final static String CLIENT_CONN_CREATE_END_IN_NANO = "bolt.client.conn.create.end.nano"; // ~~~ invoke context keys of server side - public final static String SERVER_LOCAL_IP = "bolt.server.local.ip"; - public final static String SERVER_LOCAL_PORT = "bolt.server.local.port"; - public final static String SERVER_REMOTE_IP = "bolt.server.remote.ip"; - public final static String SERVER_REMOTE_PORT = "bolt.server.remote.port"; + public final static String SERVER_LOCAL_IP = "bolt.server.local.ip"; + public final static String SERVER_LOCAL_PORT = "bolt.server.local.port"; + public final static String SERVER_REMOTE_IP = "bolt.server.remote.ip"; + public final static String SERVER_REMOTE_PORT = "bolt.server.remote.port"; // ~~~ invoke context keys of bolt client and server side - public final static String BOLT_INVOKE_REQUEST_ID = "bolt.invoke.request.id"; + public final static String BOLT_INVOKE_REQUEST_ID = "bolt.invoke.request.id"; /** time consumed start from the time when request arrive, to the time when request be processed, this is a timespan */ - public final static String BOLT_PROCESS_WAIT_TIME = "bolt.invoke.wait.time"; - public final static String BOLT_CUSTOM_SERIALIZER = "bolt.invoke.custom.serializer"; - public final static String BOLT_CRC_SWITCH = "bolt.invoke.crc.switch"; + public final static String BOLT_PROCESS_WAIT_TIME = "bolt.invoke.wait.time"; + /** time request arrived in nano seconds , collected by System.nanoTime() */ + public final static String BOLT_PROCESS_ARRIVE_HEADER_IN_NANO = "bolt.invoke.request.arrive.header.in.nano"; + public final static String BOLT_PROCESS_ARRIVE_BODY_IN_NANO = "bolt.invoke.request.arrive.body.in.nano"; + + /** time before send request to user thread in nano seconds , collected by System.nanoTime() */ + public final static String BOLT_PROCESS_BEFORE_DISPATCH_IN_NANO = "bolt.invoke.before.dispatch.in.nano"; + + /** time before send request to user thread in nano seconds , collected by System.nanoTime() */ + public final static String BOLT_PROCESS_START_PROCESS_IN_NANO = "bolt.invoke.start.process.in.nano"; + + public final static String BOLT_CUSTOM_SERIALIZER = "bolt.invoke.custom.serializer"; + public final static String BOLT_CRC_SWITCH = "bolt.invoke.crc.switch"; + + /** time before send request to net in nano seconds , collected by System.nanoTime() **/ + public final static String BOLT_PROCESS_CLIENT_BEFORE_SEND = "bolt.invoke.client.before.send"; + /** time after send request to net in nano seconds , collected by System.nanoTime() **/ + public final static String BOLT_PROCESS_CLIENT_AFTER_SEND = "bolt.invoke.client.after.send"; + /** time after receive response from server in nano seconds , collected by System.nanoTime() **/ + public final static String BOLT_PROCESS_CLIENT_RECEIVED = "bolt.invoke.client.received"; // ~~~ constants - public final static int INITIAL_SIZE = 8; + public final static int INITIAL_SIZE = 8; /** context */ private ConcurrentHashMap context; diff --git a/src/main/java/com/alipay/remoting/RandomSelectStrategy.java b/src/main/java/com/alipay/remoting/RandomSelectStrategy.java index bb317de1..9477da4b 100644 --- a/src/main/java/com/alipay/remoting/RandomSelectStrategy.java +++ b/src/main/java/com/alipay/remoting/RandomSelectStrategy.java @@ -20,10 +20,11 @@ import java.util.List; import java.util.Random; +import com.alipay.remoting.config.BoltClientOption; +import com.alipay.remoting.config.Configuration; import org.slf4j.Logger; import com.alipay.remoting.config.Configs; -import com.alipay.remoting.config.switches.GlobalSwitch; import com.alipay.remoting.log.BoltLoggerFactory; import com.alipay.remoting.util.StringUtils; @@ -39,14 +40,10 @@ public class RandomSelectStrategy implements ConnectionSelectStrategy { private static final int MAX_TIMES = 5; private final Random random = new Random(); - private final GlobalSwitch globalSwitch; + private final Configuration configuration; - public RandomSelectStrategy() { - this(null); - } - - public RandomSelectStrategy(GlobalSwitch globalSwitch) { - this.globalSwitch = globalSwitch; + public RandomSelectStrategy(Configuration configuration) { + this.configuration = configuration; } @Override @@ -61,8 +58,7 @@ public Connection select(List connections) { } Connection result; - if (null != this.globalSwitch - && this.globalSwitch.isOn(GlobalSwitch.CONN_MONITOR_SWITCH)) { + if (configuration != null && configuration.option(BoltClientOption.CONN_MONITOR_SWITCH)) { List serviceStatusOnConnections = new ArrayList(); for (Connection conn : connections) { String serviceStatus = (String) conn.getAttribute(Configs.CONN_SERVICE_STATUS); diff --git a/src/main/java/com/alipay/remoting/RemotingServer.java b/src/main/java/com/alipay/remoting/RemotingServer.java index 59e74c6d..a947aaf1 100644 --- a/src/main/java/com/alipay/remoting/RemotingServer.java +++ b/src/main/java/com/alipay/remoting/RemotingServer.java @@ -18,13 +18,13 @@ import java.util.concurrent.ExecutorService; -import com.alipay.remoting.config.Configurable; +import com.alipay.remoting.config.Configuration; import com.alipay.remoting.rpc.protocol.UserProcessor; /** * @author chengyi (mark.lx@antfin.com) 2018-06-16 06:55 */ -public interface RemotingServer extends Configurable, LifeCycle { +public interface RemotingServer extends Configuration, LifeCycle { /** * init the server diff --git a/src/main/java/com/alipay/remoting/codec/ProtocolCodeBasedDecoder.java b/src/main/java/com/alipay/remoting/codec/ProtocolCodeBasedDecoder.java index c603fb4c..9e585a22 100644 --- a/src/main/java/com/alipay/remoting/codec/ProtocolCodeBasedDecoder.java +++ b/src/main/java/com/alipay/remoting/codec/ProtocolCodeBasedDecoder.java @@ -79,8 +79,15 @@ protected byte decodeProtocolVersion(ByteBuf in) { @Override protected void decode(ChannelHandlerContext ctx, ByteBuf in, List out) throws Exception { in.markReaderIndex(); - ProtocolCode protocolCode = decodeProtocolCode(in); - if (null != protocolCode) { + ProtocolCode protocolCode; + Protocol protocol; + try { + protocolCode = decodeProtocolCode(in); + if (protocolCode == null) { + // read to end + return; + } + byte protocolVersion = decodeProtocolVersion(in); if (ctx.channel().attr(Connection.PROTOCOL).get() == null) { ctx.channel().attr(Connection.PROTOCOL).set(protocolCode); @@ -88,14 +95,19 @@ protected void decode(ChannelHandlerContext ctx, ByteBuf in, List out) t ctx.channel().attr(Connection.VERSION).set(protocolVersion); } } - Protocol protocol = ProtocolManager.getProtocol(protocolCode); - if (null != protocol) { - in.resetReaderIndex(); - protocol.getDecoder().decode(ctx, in, out); - } else { - throw new CodecException("Unknown protocol code: [" + protocolCode - + "] while decode in ProtocolDecoder."); - } + + protocol = ProtocolManager.getProtocol(protocolCode); + } finally { + // reset the readerIndex before throwing an exception or decoding content + // to ensure that the packet is complete + in.resetReaderIndex(); } + + if (protocol == null) { + throw new CodecException("Unknown protocol code: [" + protocolCode + + "] while decode in ProtocolDecoder."); + } + + protocol.getDecoder().decode(ctx, in, out); } } diff --git a/src/main/java/com/alipay/remoting/config/BoltClientOption.java b/src/main/java/com/alipay/remoting/config/BoltClientOption.java index d62185a3..de5192e1 100644 --- a/src/main/java/com/alipay/remoting/config/BoltClientOption.java +++ b/src/main/java/com/alipay/remoting/config/BoltClientOption.java @@ -16,6 +16,8 @@ */ package com.alipay.remoting.config; +import javax.net.ssl.TrustManagerFactory; + /** * Supported options in client side. * @@ -43,6 +45,31 @@ public class BoltClientOption extends BoltGenericOption { "bolt.conn.create.tp.keepalive", 60); + public static final BoltOption CONN_RECONNECT_SWITCH = valueOf( + "bolt.conn.reconnect", + false); + public static final BoltOption CONN_MONITOR_SWITCH = valueOf( + "bolt.conn.monitor", + false); + + public static final BoltOption CLI_SSL_ENABLE = valueOf( + "bolt.client.ssl.enable", + false); + public static final BoltOption CLI_SSL_KEYSTORE_TYPE = valueOf( + "bolt.client.ssl.keystore.type", + null); + public static final BoltOption CLI_SSL_KEYSTORE = valueOf( + "bolt.client.ssl.keystore", + null); + + public static final BoltOption CLI_SSL_KEYSTORE_PASS = valueOf( + "bolt.client.ssl.keystore.password", + null); + public static final BoltOption CLI_SSL_TMF_ALGO = valueOf( + "bolt.client.ssl.tmf.algorithm", + TrustManagerFactory + .getDefaultAlgorithm()); + private BoltClientOption(String name, T defaultValue) { super(name, defaultValue); } diff --git a/src/main/java/com/alipay/remoting/config/BoltGenericOption.java b/src/main/java/com/alipay/remoting/config/BoltGenericOption.java index daf640f3..59861d08 100644 --- a/src/main/java/com/alipay/remoting/config/BoltGenericOption.java +++ b/src/main/java/com/alipay/remoting/config/BoltGenericOption.java @@ -17,6 +17,7 @@ package com.alipay.remoting.config; import com.alipay.remoting.ConnectionSelectStrategy; +import com.alipay.remoting.ExtendedNettyChannelHandler; /** * Supported options both in client and server side. @@ -26,60 +27,68 @@ public class BoltGenericOption extends BoltOption { /*------------ NETTY Config Start ------------*/ - public static final BoltOption TCP_NODELAY = valueOf( - "bolt.tcp.nodelay", - true); - public static final BoltOption TCP_SO_REUSEADDR = valueOf( - "bolt.tcp.so.reuseaddr", - true); - public static final BoltOption TCP_SO_KEEPALIVE = valueOf( - "bolt.tcp.so.keepalive", - true); + public static final BoltOption TCP_NODELAY = valueOf( + "bolt.tcp.nodelay", + true); + public static final BoltOption TCP_SO_REUSEADDR = valueOf( + "bolt.tcp.so.reuseaddr", + true); + public static final BoltOption TCP_SO_KEEPALIVE = valueOf( + "bolt.tcp.so.keepalive", + true); - public static final BoltOption TCP_SO_SNDBUF = valueOf("bolt.tcp.so.sndbuf"); + public static final BoltOption TCP_SO_SNDBUF = valueOf("bolt.tcp.so.sndbuf"); - public static final BoltOption TCP_SO_RCVBUF = valueOf("bolt.tcp.so.rcvbuf"); + public static final BoltOption TCP_SO_RCVBUF = valueOf("bolt.tcp.so.rcvbuf"); - public static final BoltOption NETTY_IO_RATIO = valueOf( - "bolt.netty.io.ratio", - 70); - public static final BoltOption NETTY_BUFFER_POOLED = valueOf( - "bolt.netty.buffer.pooled", - true); + public static final BoltOption NETTY_IO_RATIO = valueOf( + "bolt.netty.io.ratio", + 70); + public static final BoltOption NETTY_BUFFER_POOLED = valueOf( + "bolt.netty.buffer.pooled", + true); - public static final BoltOption NETTY_BUFFER_HIGH_WATER_MARK = valueOf( - "bolt.netty.buffer.high.watermark", - 64 * 1024); - public static final BoltOption NETTY_BUFFER_LOW_WATER_MARK = valueOf( - "bolt.netty.buffer.low.watermark", - 32 * 1024); + public static final BoltOption NETTY_BUFFER_HIGH_WATER_MARK = valueOf( + "bolt.netty.buffer.high.watermark", + 64 * 1024); + public static final BoltOption NETTY_BUFFER_LOW_WATER_MARK = valueOf( + "bolt.netty.buffer.low.watermark", + 32 * 1024); - public static final BoltOption NETTY_EPOLL_SWITCH = valueOf( - "bolt.netty.epoll.switch", - true); + public static final BoltOption NETTY_EPOLL_SWITCH = valueOf( + "bolt.netty.epoll.switch", + true); - public static final BoltOption TCP_IDLE_SWITCH = valueOf( - "bolt.tcp.heartbeat.switch", - true); + public static final BoltOption TCP_IDLE_SWITCH = valueOf( + "bolt.tcp.heartbeat.switch", + true); /*------------ NETTY Config End ------------*/ /*------------ Thread Pool Config Start ------------*/ - public static final BoltOption TP_MIN_SIZE = valueOf( - "bolt.tp.min", - 20); - public static final BoltOption TP_MAX_SIZE = valueOf( - "bolt.tp.max", - 400); - public static final BoltOption TP_QUEUE_SIZE = valueOf( - "bolt.tp.queue", - 600); - public static final BoltOption TP_KEEPALIVE_TIME = valueOf( - "bolt.tp.keepalive", - 60); + public static final BoltOption TP_MIN_SIZE = valueOf( + "bolt.tp.min", + 20); + public static final BoltOption TP_MAX_SIZE = valueOf( + "bolt.tp.max", + 400); + public static final BoltOption TP_QUEUE_SIZE = valueOf( + "bolt.tp.queue", + 600); + public static final BoltOption TP_KEEPALIVE_TIME = valueOf( + "bolt.tp.keepalive", + 60); /*------------ Thread Pool Config End ------------*/ - public static final BoltOption CONNECTION_SELECT_STRATEGY = valueOf("CONNECTION_SELECT_STRATEGY"); + public static final BoltOption CONNECTION_SELECT_STRATEGY = valueOf("CONNECTION_SELECT_STRATEGY"); + + public static final BoltOption NETTY_FLUSH_CONSOLIDATION = valueOf( + "bolt.netty.flush_consolidation", + false); + + public static final BoltOption EXTENDED_NETTY_CHANNEL_HANDLER = valueOf( + "bolt.extend.netty.channel.handler", + null); protected BoltGenericOption(String name, T defaultValue) { super(name, defaultValue); diff --git a/src/main/java/com/alipay/remoting/config/BoltServerOption.java b/src/main/java/com/alipay/remoting/config/BoltServerOption.java index 74c0ac07..9270c074 100644 --- a/src/main/java/com/alipay/remoting/config/BoltServerOption.java +++ b/src/main/java/com/alipay/remoting/config/BoltServerOption.java @@ -16,6 +16,8 @@ */ package com.alipay.remoting.config; +import javax.net.ssl.KeyManagerFactory; + /** * Supported options in server side. * @@ -23,13 +25,45 @@ */ public class BoltServerOption extends BoltGenericOption { - public static final BoltOption TCP_SO_BACKLOG = valueOf("bolt.tcp.so.backlog", 1024); + public static final BoltOption TCP_SO_BACKLOG = valueOf( + "bolt.tcp.so.backlog", + 1024); + + public static final BoltOption NETTY_EPOLL_LT = valueOf( + "bolt.netty.epoll.lt", + true); + + public static final BoltOption TCP_SERVER_IDLE = valueOf( + "bolt.tcp.server.idle.interval", + 90 * 1000); + + public static final BoltOption SERVER_MANAGE_CONNECTION_SWITCH = valueOf( + "bolt.server.manage.connection", + false); - public static final BoltOption NETTY_EPOLL_LT = valueOf("bolt.netty.epoll.lt", true); + public static final BoltOption SERVER_SYNC_STOP = valueOf( + "bolt.server.sync.stop", + false); - public static final BoltOption TCP_SERVER_IDLE = valueOf( - "bolt.tcp.server.idle.interval", - 90 * 1000); + public static final BoltOption SRV_SSL_ENABLE = valueOf( + "bolt.server.ssl.enable", + false); + public static final BoltOption SRV_SSL_KEYSTORE_TYPE = valueOf( + "bolt.server.ssl.keystore.type", + null); + public static final BoltOption SRV_SSL_NEED_CLIENT_AUTH = valueOf( + "bolt.server.ssl.clientAuth", + false); + public static final BoltOption SRV_SSL_KEYSTORE = valueOf( + "bolt.server.ssl.keystore", + null); + public static final BoltOption SRV_SSL_KEYSTORE_PASS = valueOf( + "bolt.server.ssl.keystore.password", + null); + public static final BoltOption SRV_SSL_KMF_ALGO = valueOf( + "bolt.server.ssl.kmf.algorithm", + KeyManagerFactory + .getDefaultAlgorithm()); private BoltServerOption(String name, T defaultValue) { super(name, defaultValue); diff --git a/src/main/java/com/alipay/remoting/config/ConfigManager.java b/src/main/java/com/alipay/remoting/config/ConfigManager.java index ee296541..e7da8f6c 100644 --- a/src/main/java/com/alipay/remoting/config/ConfigManager.java +++ b/src/main/java/com/alipay/remoting/config/ConfigManager.java @@ -43,11 +43,11 @@ public static boolean tcp_so_keepalive() { } public static Integer tcp_so_sndbuf() { - return getInteger(Configs.TCP_SO_SNDBUF, null); + return getInteger(Configs.TCP_SO_SNDBUF); } public static Integer tcp_so_rcvbuf() { - return getInteger(Configs.TCP_SO_RCVBUF, null); + return getInteger(Configs.TCP_SO_RCVBUF); } public static int netty_io_ratio() { @@ -58,14 +58,12 @@ public static boolean netty_buffer_pooled() { return getBool(Configs.NETTY_BUFFER_POOLED, Configs.NETTY_BUFFER_POOLED_DEFAULT); } - public static int netty_buffer_low_watermark() { - return getInt(Configs.NETTY_BUFFER_LOW_WATERMARK, - Configs.NETTY_BUFFER_LOW_WATERMARK_DEFAULT); + public static Integer netty_buffer_low_watermark() { + return getInteger(Configs.NETTY_BUFFER_LOW_WATERMARK); } - public static int netty_buffer_high_watermark() { - return getInt(Configs.NETTY_BUFFER_HIGH_WATERMARK, - Configs.NETTY_BUFFER_HIGH_WATERMARK_DEFAULT); + public static Integer netty_buffer_high_watermark() { + return getInteger(Configs.NETTY_BUFFER_HIGH_WATERMARK); } public static boolean netty_epoll() { @@ -171,7 +169,7 @@ public static int getInt(final String key, final String defaultValue) { return Integer.parseInt(getProperty(key, defaultValue)); } - public static Integer getInteger(final String key, final String defaultValue) { + public static Integer getInteger(final String key) { String value = System.getProperty(key, null); return value != null ? Integer.parseInt(value) : null; } diff --git a/src/main/java/com/alipay/remoting/config/ConfigurableInstance.java b/src/main/java/com/alipay/remoting/config/ConfigurableInstance.java index 23c9a207..11c550bd 100644 --- a/src/main/java/com/alipay/remoting/config/ConfigurableInstance.java +++ b/src/main/java/com/alipay/remoting/config/ConfigurableInstance.java @@ -17,7 +17,6 @@ package com.alipay.remoting.config; import com.alipay.remoting.config.configs.ConfigContainer; -import com.alipay.remoting.config.configs.NettyConfigure; import com.alipay.remoting.config.switches.GlobalSwitch; /** @@ -26,18 +25,51 @@ * @author tsui * @version $Id: ConfigurableInstance.java, v 0.1 2018-07-30 21:09 tsui Exp $$ */ -public interface ConfigurableInstance extends NettyConfigure { +public interface ConfigurableInstance { /** * get the config container for current instance * * @return the config container */ + @Deprecated ConfigContainer conf(); /** * get the global switch for current instance * @return the global switch */ + @Deprecated GlobalSwitch switches(); + + /** + * Initialize netty write buffer water mark for remoting instance. + *

+ * Notice: This api should be called before init remoting instance. + * + * deprecated, use option() instead: + * instance#option(BoltOption.NETTY_BUFFER_LOW_WATER_MARK, low); + * instance#option(BoltOption.NETTY_BUFFER_HIGH_WATER_MARK, high); + * + * @param low [0, high] + * @param high [high, Integer.MAX_VALUE) + */ + @Deprecated + void initWriteBufferWaterMark(int low, int high); + + /** + * get the low water mark for netty write buffer + * deprecated, use instance#option(BoltClientOption.NETTY_BUFFER_LOW_WATER_MARK) instead + * @return low watermark + */ + @Deprecated + int netty_buffer_low_watermark(); + + /** + * get the high water mark for netty write buffer + * deprecated, use instance#option(BoltClientOption.NETTY_BUFFER_HIGH_WATER_MARK) instead + * @return high watermark + */ + @Deprecated + int netty_buffer_high_watermark(); } \ No newline at end of file diff --git a/src/main/java/com/alipay/remoting/config/Configurable.java b/src/main/java/com/alipay/remoting/config/Configuration.java similarity index 90% rename from src/main/java/com/alipay/remoting/config/Configurable.java rename to src/main/java/com/alipay/remoting/config/Configuration.java index 5bafcae9..28a254f2 100644 --- a/src/main/java/com/alipay/remoting/config/Configurable.java +++ b/src/main/java/com/alipay/remoting/config/Configuration.java @@ -21,7 +21,7 @@ * * @author chengyi (mark.lx@antfin.com) 2018-11-06 14:46 */ -public interface Configurable { +public interface Configuration { /** * Get the option value. @@ -32,13 +32,13 @@ public interface Configurable { T option(BoltOption option); /** - * Allow to specify a {@link BoltOption} which is used for the {@link Configurable} instances once they got + * Allow to specify a {@link BoltOption} which is used for the {@link Configuration} instances once they got * created. Use a value of {@code null} to remove a previous set {@link BoltOption}. * * @param option target option * @param value option value, null to remove the previous option * @return Configurable instance */ - Configurable option(BoltOption option, T value); + Configuration option(BoltOption option, T value); } diff --git a/src/main/java/com/alipay/remoting/config/configs/ConfigContainer.java b/src/main/java/com/alipay/remoting/config/configs/ConfigContainer.java index c62a2b82..1109292e 100644 --- a/src/main/java/com/alipay/remoting/config/configs/ConfigContainer.java +++ b/src/main/java/com/alipay/remoting/config/configs/ConfigContainer.java @@ -25,6 +25,7 @@ * @author tsui * @version $Id: ConfigContainer.java, v 0.1 2018-07-28 18:31 tsui Exp $$ */ +@Deprecated public interface ConfigContainer { /** * check whether a config item of a certain config type exist. diff --git a/src/main/java/com/alipay/remoting/config/configs/ConfigItem.java b/src/main/java/com/alipay/remoting/config/configs/ConfigItem.java index fb29460a..1db07933 100644 --- a/src/main/java/com/alipay/remoting/config/configs/ConfigItem.java +++ b/src/main/java/com/alipay/remoting/config/configs/ConfigItem.java @@ -25,8 +25,12 @@ * @author tsui * @version $Id: ConfigItem.java, v 0.1 2018-07-28 17:43 tsui Exp $$ */ +// fixme: remove in next version +@Deprecated public enum ConfigItem { // ~~~ netty related + @Deprecated NETTY_BUFFER_LOW_WATER_MARK, // netty writer buffer low water mark + @Deprecated NETTY_BUFFER_HIGH_WATER_MARK // netty writer buffer high water mark } \ No newline at end of file diff --git a/src/main/java/com/alipay/remoting/config/configs/ConfigType.java b/src/main/java/com/alipay/remoting/config/configs/ConfigType.java index f001bef7..f987860e 100644 --- a/src/main/java/com/alipay/remoting/config/configs/ConfigType.java +++ b/src/main/java/com/alipay/remoting/config/configs/ConfigType.java @@ -22,6 +22,7 @@ * @author tsui * @version $Id: ConfigType.java, v 0.1 2018-07-28 17:41 tsui Exp $$ */ +@Deprecated public enum ConfigType { CLIENT_SIDE, // configs of this type can only be used in client side SERVER_SIDE // configs of this type can only be used in server side diff --git a/src/main/java/com/alipay/remoting/config/configs/DefaultConfigContainer.java b/src/main/java/com/alipay/remoting/config/configs/DefaultConfigContainer.java index 59712bac..c1a5a566 100644 --- a/src/main/java/com/alipay/remoting/config/configs/DefaultConfigContainer.java +++ b/src/main/java/com/alipay/remoting/config/configs/DefaultConfigContainer.java @@ -29,6 +29,7 @@ * @author tsui * @version $Id: DefaultConfigContainer.java, v 0.1 2018-07-28 18:11 tsui Exp $$ */ +@Deprecated public class DefaultConfigContainer implements ConfigContainer { /** logger */ private static final Logger logger = BoltLoggerFactory diff --git a/src/main/java/com/alipay/remoting/config/switches/GlobalSwitch.java b/src/main/java/com/alipay/remoting/config/switches/GlobalSwitch.java index 99499c54..af295107 100644 --- a/src/main/java/com/alipay/remoting/config/switches/GlobalSwitch.java +++ b/src/main/java/com/alipay/remoting/config/switches/GlobalSwitch.java @@ -18,8 +18,6 @@ import java.util.BitSet; -import com.alipay.remoting.config.ConfigManager; - /** * Global switches used in client or server *

@@ -31,17 +29,11 @@ * @author tsui * @version $Id: GlobalSwitch.java, v 0.1 2017-08-03 15:50 tsui Exp $ */ +@Deprecated public class GlobalSwitch implements Switch { - // switches - public static final int CONN_RECONNECT_SWITCH = 0; - public static final int CONN_MONITOR_SWITCH = 1; - public static final int SERVER_MANAGE_CONNECTION_SWITCH = 2; - public static final int SERVER_SYNC_STOP = 3; - public static final int CODEC_FLUSH_CONSOLIDATION = 4; - /** user settings */ - private BitSet userSettings = new BitSet(); + private BitSet userSettings = new BitSet(); /** * Init with system default value @@ -50,17 +42,7 @@ public class GlobalSwitch implements Switch { * All these settings can be overwrite by user api settings. */ public GlobalSwitch() { - if (ConfigManager.conn_reconnect_switch()) { - userSettings.set(CONN_RECONNECT_SWITCH); - } else { - userSettings.clear(CONN_RECONNECT_SWITCH); - } - if (ConfigManager.conn_monitor_switch()) { - userSettings.set(CONN_MONITOR_SWITCH); - } else { - userSettings.clear(CONN_MONITOR_SWITCH); - } } // ~~~ public methods diff --git a/src/main/java/com/alipay/remoting/config/switches/ProtocolSwitch.java b/src/main/java/com/alipay/remoting/config/switches/ProtocolSwitch.java index a43df9d7..4a213b5e 100644 --- a/src/main/java/com/alipay/remoting/config/switches/ProtocolSwitch.java +++ b/src/main/java/com/alipay/remoting/config/switches/ProtocolSwitch.java @@ -111,10 +111,10 @@ public static byte toByte(BitSet bs) { } } if (bs.length() > 7) { - throw new IllegalArgumentException("The byte value " + value - + " generated according to bit set " + bs - + " is out of range, should be limited between [" - + Byte.MIN_VALUE + "] to [" + Byte.MAX_VALUE + "]"); + throw new IllegalArgumentException( + "The byte value " + value + " generated according to bit set " + bs + + " is out of range, should be limited between [0] to [" + Byte.MAX_VALUE + + "]"); } return (byte) value; } @@ -125,10 +125,10 @@ public static byte toByte(BitSet bs) { * @return bit set represent the byte */ public static BitSet toBitSet(int value) { - if (value > Byte.MAX_VALUE || value < Byte.MIN_VALUE) { + if (value < 0 || value > Byte.MAX_VALUE) { throw new IllegalArgumentException( - "The value " + value + " is out of byte range, should be limited between [" - + Byte.MIN_VALUE + "] to [" + Byte.MAX_VALUE + "]"); + "The value " + value + " is out of byte range, should be limited between [0] to [" + + Byte.MAX_VALUE + "]"); } BitSet bs = new BitSet(); int index = 0; diff --git a/src/main/java/com/alipay/remoting/connection/AbstractConnectionFactory.java b/src/main/java/com/alipay/remoting/connection/AbstractConnectionFactory.java index f3e1ef1f..f26e4c22 100644 --- a/src/main/java/com/alipay/remoting/connection/AbstractConnectionFactory.java +++ b/src/main/java/com/alipay/remoting/connection/AbstractConnectionFactory.java @@ -20,10 +20,17 @@ import java.io.InputStream; import java.net.InetSocketAddress; import java.security.KeyStore; +import java.util.List; import java.util.concurrent.TimeUnit; +import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLEngine; import javax.net.ssl.TrustManagerFactory; +import com.alipay.remoting.config.BoltClientOption; +import com.alipay.remoting.config.BoltGenericOption; +import com.alipay.remoting.config.BoltServerOption; +import com.alipay.remoting.config.Configuration; +import com.alipay.remoting.ExtendedNettyChannelHandler; import org.slf4j.Logger; import com.alipay.remoting.Connection; @@ -34,9 +41,7 @@ import com.alipay.remoting.Url; import com.alipay.remoting.codec.Codec; import com.alipay.remoting.config.ConfigManager; -import com.alipay.remoting.config.ConfigurableInstance; import com.alipay.remoting.constant.Constants; -import com.alipay.remoting.config.switches.GlobalSwitch; import com.alipay.remoting.log.BoltLoggerFactory; import com.alipay.remoting.rpc.RpcConfigManager; import com.alipay.remoting.rpc.protocol.RpcProtocol; @@ -77,7 +82,7 @@ public abstract class AbstractConnectionFactory implements ConnectionFactory { new NamedThreadFactory( "bolt-netty-client-worker", true)); - private final ConfigurableInstance confInstance; + private final Configuration configuration; private final Codec codec; private final ChannelHandler heartbeatHandler; private final ChannelHandler handler; @@ -85,7 +90,7 @@ public abstract class AbstractConnectionFactory implements ConnectionFactory { protected Bootstrap bootstrap; public AbstractConnectionFactory(Codec codec, ChannelHandler heartbeatHandler, - ChannelHandler handler, ConfigurableInstance confInstance) { + ChannelHandler handler, Configuration configuration) { if (codec == null) { throw new IllegalArgumentException("null codec"); } @@ -93,7 +98,7 @@ public AbstractConnectionFactory(Codec codec, ChannelHandler heartbeatHandler, throw new IllegalArgumentException("null handler"); } - this.confInstance = confInstance; + this.configuration = configuration; this.codec = codec; this.heartbeatHandler = heartbeatHandler; this.handler = handler; @@ -119,14 +124,29 @@ public void init(final ConnectionEventHandler connectionEventHandler) { this.bootstrap.option(ChannelOption.ALLOCATOR, UnpooledByteBufAllocator.DEFAULT); } - final boolean flushConsolidationSwitch = this.confInstance.switches().isOn( - GlobalSwitch.CODEC_FLUSH_CONSOLIDATION); + final boolean flushConsolidationSwitch = this.configuration + .option(BoltClientOption.NETTY_FLUSH_CONSOLIDATION); bootstrap.handler(new ChannelInitializer() { @Override protected void initChannel(SocketChannel channel) { ChannelPipeline pipeline = channel.pipeline(); - if (RpcConfigManager.client_ssl_enable()) { + ExtendedNettyChannelHandler extendedHandlers = configuration + .option(BoltClientOption.EXTENDED_NETTY_CHANNEL_HANDLER); + if (extendedHandlers != null) { + List frontHandlers = extendedHandlers.frontChannelHandlers(); + if (frontHandlers != null) { + for (ChannelHandler channelHandler : frontHandlers) { + pipeline.addLast(channelHandler.getClass().getName(), channelHandler); + } + } + } + Boolean sslEnable = configuration.option(BoltClientOption.CLI_SSL_ENABLE); + if (!sslEnable) { + // fixme: remove in next version + sslEnable = RpcConfigManager.client_ssl_enable(); + } + if (sslEnable) { SSLEngine engine = initSSLContext().newEngine(channel.alloc()); engine.setUseClientMode(true); pipeline.addLast(Constants.SSL_HANDLER, new SslHandler(engine)); @@ -148,6 +168,14 @@ protected void initChannel(SocketChannel channel) { pipeline.addLast("connectionEventHandler", connectionEventHandler); pipeline.addLast("handler", handler); + if (extendedHandlers != null) { + List backHandlers = extendedHandlers.backChannelHandlers(); + if (backHandlers != null) { + for (ChannelHandler channelHandler : backHandlers) { + pipeline.addLast(channelHandler.getClass().getName(), channelHandler); + } + } + } } }); } @@ -199,8 +227,19 @@ public Connection createConnection(String targetIP, int targetPort, byte version * init netty write buffer water mark */ private void initWriteBufferWaterMark() { - int lowWaterMark = this.confInstance.netty_buffer_low_watermark(); - int highWaterMark = this.confInstance.netty_buffer_high_watermark(); + // init with system properties + Integer lowWaterMarkConfig = ConfigManager.netty_buffer_low_watermark(); + if (lowWaterMarkConfig != null) { + configuration.option(BoltServerOption.NETTY_BUFFER_LOW_WATER_MARK, lowWaterMarkConfig); + } + Integer highWaterMarkConfig = ConfigManager.netty_buffer_high_watermark(); + if (highWaterMarkConfig != null) { + configuration + .option(BoltServerOption.NETTY_BUFFER_HIGH_WATER_MARK, highWaterMarkConfig); + } + + int lowWaterMark = configuration.option(BoltGenericOption.NETTY_BUFFER_LOW_WATER_MARK); + int highWaterMark = configuration.option(BoltGenericOption.NETTY_BUFFER_HIGH_WATER_MARK); if (lowWaterMark > highWaterMark) { throw new IllegalArgumentException( String @@ -219,14 +258,37 @@ private void initWriteBufferWaterMark() { private SslContext initSSLContext() { InputStream in = null; try { - KeyStore ks = KeyStore.getInstance(RpcConfigManager.client_ssl_keystore_type()); - in = new FileInputStream(RpcConfigManager.client_ssl_keystore()); - char[] passChs = RpcConfigManager.client_ssl_keystore_pass().toCharArray(); + String sslKeyStoreType = configuration.option(BoltClientOption.CLI_SSL_KEYSTORE_TYPE); + if (sslKeyStoreType == null) { + // fixme: remove in next version + sslKeyStoreType = RpcConfigManager.client_ssl_keystore_type(); + } + KeyStore ks = KeyStore.getInstance(sslKeyStoreType); + String sslKeyStore = configuration.option(BoltClientOption.CLI_SSL_KEYSTORE); + if (sslKeyStore == null) { + sslKeyStore = RpcConfigManager.client_ssl_keystore(); + } + in = new FileInputStream(sslKeyStore); + String keyStorePass = configuration.option(BoltClientOption.CLI_SSL_KEYSTORE_PASS); + if (keyStorePass == null) { + keyStorePass = RpcConfigManager.client_ssl_keystore_pass(); + } + char[] passChs = keyStorePass.toCharArray(); ks.load(in, passChs); - TrustManagerFactory tmf = TrustManagerFactory.getInstance(RpcConfigManager - .client_ssl_tmf_algorithm()); + String serverSslAlgorithm = configuration.option(BoltServerOption.SRV_SSL_KMF_ALGO); + if (serverSslAlgorithm == null) { + serverSslAlgorithm = RpcConfigManager.server_ssl_kmf_algorithm(); + } + KeyManagerFactory kmf = KeyManagerFactory.getInstance(serverSslAlgorithm); + kmf.init(ks, passChs); + String sslAlgorithm = configuration.option(BoltClientOption.CLI_SSL_TMF_ALGO); + if (sslAlgorithm == null) { + sslAlgorithm = RpcConfigManager.client_ssl_tmf_algorithm(); + } + TrustManagerFactory tmf = TrustManagerFactory.getInstance(sslAlgorithm); tmf.init(ks); - return SslContextBuilder.forClient().trustManager(tmf).build(); + + return SslContextBuilder.forClient().keyManager(kmf).trustManager(tmf).build(); } catch (Exception e) { logger.error("Fail to init SSL context for connection factory.", e); throw new IllegalStateException("Fail to init SSL context", e); @@ -238,12 +300,15 @@ private SslContext initSSLContext() { protected Channel doCreateConnection(String targetIP, int targetPort, int connectTimeout) throws Exception { - // prevent unreasonable value, at least 1000 - connectTimeout = Math.max(connectTimeout, 1000); String address = targetIP + ":" + targetPort; if (logger.isDebugEnabled()) { logger.debug("connectTimeout of address [{}] is [{}].", address, connectTimeout); } + if (connectTimeout <= 0) { + throw new IllegalArgumentException(String.format( + "illegal timeout for creating connection, address: %s, timeout: %d", address, + connectTimeout)); + } bootstrap.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, connectTimeout); ChannelFuture future = bootstrap.connect(new InetSocketAddress(targetIP, targetPort)); diff --git a/src/main/java/com/alipay/remoting/connection/DefaultConnectionFactory.java b/src/main/java/com/alipay/remoting/connection/DefaultConnectionFactory.java index 045cbbd3..2fdc62f7 100644 --- a/src/main/java/com/alipay/remoting/connection/DefaultConnectionFactory.java +++ b/src/main/java/com/alipay/remoting/connection/DefaultConnectionFactory.java @@ -17,7 +17,7 @@ package com.alipay.remoting.connection; import com.alipay.remoting.codec.Codec; -import com.alipay.remoting.config.ConfigurableInstance; +import com.alipay.remoting.config.Configuration; import io.netty.channel.ChannelHandler; @@ -29,7 +29,7 @@ public class DefaultConnectionFactory extends AbstractConnectionFactory { public DefaultConnectionFactory(Codec codec, ChannelHandler heartbeatHandler, - ChannelHandler handler, ConfigurableInstance configInstance) { - super(codec, heartbeatHandler, handler, configInstance); + ChannelHandler handler, Configuration configuration) { + super(codec, heartbeatHandler, handler, configuration); } } diff --git a/src/main/java/com/alipay/remoting/log/BoltLoggerFactory.java b/src/main/java/com/alipay/remoting/log/BoltLoggerFactory.java index 4c37acde..0b67f5e2 100644 --- a/src/main/java/com/alipay/remoting/log/BoltLoggerFactory.java +++ b/src/main/java/com/alipay/remoting/log/BoltLoggerFactory.java @@ -74,14 +74,14 @@ public class BoltLoggerFactory { public static Logger getLogger(Class clazz) { if (clazz == null) { - return null; + return getLogger(""); } return getLogger(clazz.getCanonicalName()); } public static Logger getLogger(String name) { if (name == null || name.isEmpty()) { - return null; + return LoggerSpaceManager.getLoggerBySpace("", BOLT_LOG_SPACE); } return LoggerSpaceManager.getLoggerBySpace(name, BOLT_LOG_SPACE); } diff --git a/src/main/java/com/alipay/remoting/rpc/RpcClient.java b/src/main/java/com/alipay/remoting/rpc/RpcClient.java index 61719e62..16526773 100644 --- a/src/main/java/com/alipay/remoting/rpc/RpcClient.java +++ b/src/main/java/com/alipay/remoting/rpc/RpcClient.java @@ -21,10 +21,12 @@ import java.util.concurrent.ConcurrentHashMap; import com.alipay.remoting.AbstractBoltClient; +import com.alipay.remoting.ConnectionManager; import com.alipay.remoting.ConnectionSelectStrategy; import com.alipay.remoting.DefaultClientConnectionManager; import com.alipay.remoting.LifeCycleException; import com.alipay.remoting.Reconnector; +import com.alipay.remoting.config.BoltClientOption; import com.alipay.remoting.config.BoltGenericOption; import org.slf4j.Logger; @@ -34,7 +36,6 @@ import com.alipay.remoting.ConnectionEventProcessor; import com.alipay.remoting.ConnectionEventType; import com.alipay.remoting.ConnectionMonitorStrategy; -import com.alipay.remoting.DefaultConnectionManager; import com.alipay.remoting.DefaultConnectionMonitor; import com.alipay.remoting.InvokeCallback; import com.alipay.remoting.InvokeContext; @@ -43,7 +44,6 @@ import com.alipay.remoting.RemotingAddressParser; import com.alipay.remoting.ScheduledDisconnectStrategy; import com.alipay.remoting.Url; -import com.alipay.remoting.config.switches.GlobalSwitch; import com.alipay.remoting.exception.RemotingException; import com.alipay.remoting.log.BoltLoggerFactory; import com.alipay.remoting.rpc.protocol.UserProcessor; @@ -65,7 +65,7 @@ public class RpcClient extends AbstractBoltClient { private final ConnectionEventHandler connectionEventHandler; private final ConnectionEventListener connectionEventListener; - private DefaultClientConnectionManager connectionManager; + private ConnectionManager connectionManager; private Reconnector reconnectManager; private RemotingAddressParser addressParser; private DefaultConnectionMonitor connectionMonitor; @@ -77,7 +77,7 @@ public class RpcClient extends AbstractBoltClient { public RpcClient() { this.taskScanner = new RpcTaskScanner(); this.userProcessors = new ConcurrentHashMap>(); - this.connectionEventHandler = new RpcConnectionEventHandler(switches()); + this.connectionEventHandler = new RpcConnectionEventHandler(this); this.connectionEventListener = new ConnectionEventListener(); } @@ -133,19 +133,22 @@ public void startup() throws LifeCycleException { ConnectionSelectStrategy connectionSelectStrategy = option(BoltGenericOption.CONNECTION_SELECT_STRATEGY); if (connectionSelectStrategy == null) { - connectionSelectStrategy = new RandomSelectStrategy(switches()); + connectionSelectStrategy = new RandomSelectStrategy(this); + } + if (this.connectionManager == null) { + DefaultClientConnectionManager defaultConnectionManager = new DefaultClientConnectionManager( + connectionSelectStrategy, new RpcConnectionFactory(userProcessors, this), + connectionEventHandler, connectionEventListener); + defaultConnectionManager.setAddressParser(this.addressParser); + defaultConnectionManager.startup(); + this.connectionManager = defaultConnectionManager; } - this.connectionManager = new DefaultClientConnectionManager(connectionSelectStrategy, - new RpcConnectionFactory(userProcessors, this), connectionEventHandler, - connectionEventListener, switches()); - this.connectionManager.setAddressParser(this.addressParser); - this.connectionManager.startup(); this.rpcRemoting = new RpcClientRemoting(new RpcCommandFactory(), this.addressParser, this.connectionManager); this.taskScanner.add(this.connectionManager); this.taskScanner.startup(); - if (switches().isOn(GlobalSwitch.CONN_MONITOR_SWITCH)) { + if (isConnectionMonitorSwitchOn()) { if (monitorStrategy == null) { connectionMonitor = new DefaultConnectionMonitor(new ScheduledDisconnectStrategy(), this.connectionManager); @@ -156,8 +159,8 @@ public void startup() throws LifeCycleException { connectionMonitor.startup(); logger.warn("Switch on connection monitor"); } - if (switches().isOn(GlobalSwitch.CONN_RECONNECT_SWITCH)) { - reconnectManager = new ReconnectManager(connectionManager); + if (isReconnectSwitchOn()) { + reconnectManager = new ReconnectManager(this.connectionManager); reconnectManager.startup(); connectionEventHandler.setReconnector(reconnectManager); @@ -477,7 +480,7 @@ public boolean checkConnection(String address, boolean createIfAbsent, boolean c public void closeConnection(String addr) { ensureStarted(); Url url = this.addressParser.parse(addr); - if (switches().isOn(GlobalSwitch.CONN_RECONNECT_SWITCH) && reconnectManager != null) { + if (isReconnectSwitchOn() && reconnectManager != null) { reconnectManager.disableReconnect(url); } this.connectionManager.remove(url.getUniqueKey()); @@ -486,7 +489,7 @@ public void closeConnection(String addr) { @Override public void closeConnection(Url url) { ensureStarted(); - if (switches().isOn(GlobalSwitch.CONN_RECONNECT_SWITCH) && reconnectManager != null) { + if (isReconnectSwitchOn() && reconnectManager != null) { reconnectManager.disableReconnect(url); } this.connectionManager.remove(url.getUniqueKey()); @@ -523,40 +526,51 @@ public void disableConnHeartbeat(Url url) { } @Override + @Deprecated public void enableReconnectSwitch() { - this.switches().turnOn(GlobalSwitch.CONN_RECONNECT_SWITCH); + option(BoltClientOption.CONN_RECONNECT_SWITCH, true); } @Override + @Deprecated public void disableReconnectSwith() { - this.switches().turnOff(GlobalSwitch.CONN_RECONNECT_SWITCH); + option(BoltClientOption.CONN_RECONNECT_SWITCH, false); } @Override + @Deprecated public boolean isReconnectSwitchOn() { - return this.switches().isOn(GlobalSwitch.CONN_RECONNECT_SWITCH); + return option(BoltClientOption.CONN_RECONNECT_SWITCH); } @Override + @Deprecated public void enableConnectionMonitorSwitch() { - this.switches().turnOn(GlobalSwitch.CONN_MONITOR_SWITCH); + option(BoltClientOption.CONN_MONITOR_SWITCH, true); } @Override + @Deprecated public void disableConnectionMonitorSwitch() { - this.switches().turnOff(GlobalSwitch.CONN_MONITOR_SWITCH); + option(BoltClientOption.CONN_MONITOR_SWITCH, false); } @Override + @Deprecated public boolean isConnectionMonitorSwitchOn() { - return this.switches().isOn(GlobalSwitch.CONN_MONITOR_SWITCH); + return option(BoltClientOption.CONN_MONITOR_SWITCH); } @Override - public DefaultConnectionManager getConnectionManager() { + public ConnectionManager getConnectionManager() { return this.connectionManager; } + @Override + public void setConnectionManager(ConnectionManager connectionManager) { + this.connectionManager = connectionManager; + } + @Override public RemotingAddressParser getAddressParser() { return this.addressParser; diff --git a/src/main/java/com/alipay/remoting/rpc/RpcClientRemoting.java b/src/main/java/com/alipay/remoting/rpc/RpcClientRemoting.java index 5a500e2b..43e2b644 100644 --- a/src/main/java/com/alipay/remoting/rpc/RpcClientRemoting.java +++ b/src/main/java/com/alipay/remoting/rpc/RpcClientRemoting.java @@ -18,7 +18,7 @@ import com.alipay.remoting.CommandFactory; import com.alipay.remoting.Connection; -import com.alipay.remoting.DefaultConnectionManager; +import com.alipay.remoting.ConnectionManager; import com.alipay.remoting.InvokeCallback; import com.alipay.remoting.InvokeContext; import com.alipay.remoting.RemotingAddressParser; @@ -36,7 +36,7 @@ public class RpcClientRemoting extends RpcRemoting { public RpcClientRemoting(CommandFactory commandFactory, RemotingAddressParser addressParser, - DefaultConnectionManager connectionManager) { + ConnectionManager connectionManager) { super(commandFactory, addressParser, connectionManager); } @@ -47,6 +47,9 @@ public RpcClientRemoting(CommandFactory commandFactory, RemotingAddressParser ad public void oneway(Url url, Object request, InvokeContext invokeContext) throws RemotingException, InterruptedException { + if (invokeContext == null) { + invokeContext = new InvokeContext(); + } final Connection conn = getConnectionAndInitInvokeContext(url, invokeContext); this.connectionManager.check(conn); this.oneway(conn, request, invokeContext); @@ -59,6 +62,11 @@ public void oneway(Url url, Object request, InvokeContext invokeContext) public Object invokeSync(Url url, Object request, InvokeContext invokeContext, int timeoutMillis) throws RemotingException, InterruptedException { + // Use the specified timeout to overwrite the configuration in the url + url.setConnectTimeout(timeoutMillis); + if (invokeContext == null) { + invokeContext = new InvokeContext(); + } final Connection conn = getConnectionAndInitInvokeContext(url, invokeContext); this.connectionManager.check(conn); return this.invokeSync(conn, request, invokeContext, timeoutMillis); @@ -71,6 +79,10 @@ public Object invokeSync(Url url, Object request, InvokeContext invokeContext, i public RpcResponseFuture invokeWithFuture(Url url, Object request, InvokeContext invokeContext, int timeoutMillis) throws RemotingException, InterruptedException { + url.setConnectTimeout(timeoutMillis); + if (invokeContext == null) { + invokeContext = new InvokeContext(); + } final Connection conn = getConnectionAndInitInvokeContext(url, invokeContext); this.connectionManager.check(conn); return this.invokeWithFuture(conn, request, invokeContext, timeoutMillis); @@ -84,6 +96,10 @@ public void invokeWithCallback(Url url, Object request, InvokeContext invokeCont InvokeCallback invokeCallback, int timeoutMillis) throws RemotingException, InterruptedException { + url.setConnectTimeout(timeoutMillis); + if (invokeContext == null) { + invokeContext = new InvokeContext(); + } final Connection conn = getConnectionAndInitInvokeContext(url, invokeContext); this.connectionManager.check(conn); this.invokeWithCallback(conn, request, invokeContext, invokeCallback, timeoutMillis); @@ -119,6 +135,7 @@ protected Connection getConnectionAndInitInvokeContext(Url url, InvokeContext in throws RemotingException, InterruptedException { long start = System.currentTimeMillis(); + long startInNano = System.nanoTime(); Connection conn; try { conn = this.connectionManager.getAndCreateIfAbsent(url); @@ -126,6 +143,10 @@ protected Connection getConnectionAndInitInvokeContext(Url url, InvokeContext in if (null != invokeContext) { invokeContext.putIfAbsent(InvokeContext.CLIENT_CONN_CREATETIME, (System.currentTimeMillis() - start)); + invokeContext.putIfAbsent(InvokeContext.CLIENT_CONN_CREATE_START_IN_NANO, + startInNano); + invokeContext.putIfAbsent(InvokeContext.CLIENT_CONN_CREATE_END_IN_NANO, + System.nanoTime()); } } return conn; diff --git a/src/main/java/com/alipay/remoting/rpc/RpcConfigManager.java b/src/main/java/com/alipay/remoting/rpc/RpcConfigManager.java index 325f5763..be1e1867 100644 --- a/src/main/java/com/alipay/remoting/rpc/RpcConfigManager.java +++ b/src/main/java/com/alipay/remoting/rpc/RpcConfigManager.java @@ -31,47 +31,58 @@ public static boolean dispatch_msg_list_in_default_executor() { RpcConfigs.DISPATCH_MSG_LIST_IN_DEFAULT_EXECUTOR_DEFAULT); } + @Deprecated public static boolean server_ssl_enable() { return ConfigManager.getBool(RpcConfigs.SRV_SSL_ENABLE, "false"); } + @Deprecated public static boolean server_ssl_need_client_auth() { return ConfigManager.getBool(RpcConfigs.SRV_SSL_NEED_CLIENT_AUTH, "false"); } + @Deprecated public static String server_ssl_keystore() { return ConfigManager.getString(RpcConfigs.SRV_SSL_KEYSTORE, null); } + @Deprecated public static String server_ssl_keystore_pass() { return ConfigManager.getString(RpcConfigs.SRV_SSL_KEYSTORE_PASS, null); } + @Deprecated public static String server_ssl_keystore_type() { return ConfigManager.getString(RpcConfigs.SRV_SSL_KEYTSTORE_YPE, null); } + @Deprecated public static String server_ssl_kmf_algorithm() { return ConfigManager.getString(RpcConfigs.SRV_SSL_KMF_ALGO, KeyManagerFactory.getDefaultAlgorithm()); } + @Deprecated public static boolean client_ssl_enable() { return ConfigManager.getBool(RpcConfigs.CLI_SSL_ENABLE, "false"); } + @Deprecated public static String client_ssl_keystore() { return ConfigManager.getString(RpcConfigs.CLI_SSL_KEYSTORE, null); } + @Deprecated public static String client_ssl_keystore_pass() { return ConfigManager.getString(RpcConfigs.CLI_SSL_KEYSTORE_PASS, null); } + @Deprecated public static String client_ssl_keystore_type() { return ConfigManager.getString(RpcConfigs.CLI_SSL_KEYTSTORE_YPE, null); } + @Deprecated public static String client_ssl_tmf_algorithm() { return ConfigManager.getString(RpcConfigs.CLI_SSL_TMF_ALGO, TrustManagerFactory.getDefaultAlgorithm()); diff --git a/src/main/java/com/alipay/remoting/rpc/RpcConnectionEventHandler.java b/src/main/java/com/alipay/remoting/rpc/RpcConnectionEventHandler.java index c3743d5a..e183b4ca 100644 --- a/src/main/java/com/alipay/remoting/rpc/RpcConnectionEventHandler.java +++ b/src/main/java/com/alipay/remoting/rpc/RpcConnectionEventHandler.java @@ -18,7 +18,7 @@ import com.alipay.remoting.Connection; import com.alipay.remoting.ConnectionEventHandler; -import com.alipay.remoting.config.switches.GlobalSwitch; +import com.alipay.remoting.config.Configuration; import io.netty.channel.ChannelHandlerContext; @@ -34,8 +34,8 @@ public RpcConnectionEventHandler() { super(); } - public RpcConnectionEventHandler(GlobalSwitch globalSwitch) { - super(globalSwitch); + public RpcConnectionEventHandler(Configuration configuration) { + super(configuration); } /** diff --git a/src/main/java/com/alipay/remoting/rpc/RpcConnectionFactory.java b/src/main/java/com/alipay/remoting/rpc/RpcConnectionFactory.java index d25deb1b..93de77db 100644 --- a/src/main/java/com/alipay/remoting/rpc/RpcConnectionFactory.java +++ b/src/main/java/com/alipay/remoting/rpc/RpcConnectionFactory.java @@ -18,7 +18,7 @@ import java.util.concurrent.ConcurrentHashMap; -import com.alipay.remoting.config.ConfigurableInstance; +import com.alipay.remoting.config.Configuration; import com.alipay.remoting.connection.DefaultConnectionFactory; import com.alipay.remoting.rpc.protocol.UserProcessor; @@ -30,8 +30,8 @@ public class RpcConnectionFactory extends DefaultConnectionFactory { public RpcConnectionFactory(ConcurrentHashMap> userProcessors, - ConfigurableInstance configInstance) { + Configuration configurations) { super(new RpcCodec(), new HeartbeatHandler(), new RpcHandler(userProcessors), - configInstance); + configurations); } } \ No newline at end of file diff --git a/src/main/java/com/alipay/remoting/rpc/RpcHandler.java b/src/main/java/com/alipay/remoting/rpc/RpcHandler.java index 47837be3..ccbb4d11 100644 --- a/src/main/java/com/alipay/remoting/rpc/RpcHandler.java +++ b/src/main/java/com/alipay/remoting/rpc/RpcHandler.java @@ -42,10 +42,6 @@ public class RpcHandler extends ChannelInboundHandlerAdapter { private ConcurrentHashMap> userProcessors; - public RpcHandler() { - serverSide = false; - } - public RpcHandler(ConcurrentHashMap> userProcessors) { serverSide = false; this.userProcessors = userProcessors; @@ -62,5 +58,6 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception Protocol protocol = ProtocolManager.getProtocol(protocolCode); protocol.getCommandHandler().handleCommand( new RemotingContext(ctx, new InvokeContext(), serverSide, userProcessors), msg); + ctx.fireChannelRead(msg); } } diff --git a/src/main/java/com/alipay/remoting/rpc/RpcRemoting.java b/src/main/java/com/alipay/remoting/rpc/RpcRemoting.java index f047ce89..32b33bb0 100644 --- a/src/main/java/com/alipay/remoting/rpc/RpcRemoting.java +++ b/src/main/java/com/alipay/remoting/rpc/RpcRemoting.java @@ -16,12 +16,12 @@ */ package com.alipay.remoting.rpc; +import com.alipay.remoting.ConnectionManager; import org.slf4j.Logger; import com.alipay.remoting.BaseRemoting; import com.alipay.remoting.CommandFactory; import com.alipay.remoting.Connection; -import com.alipay.remoting.DefaultConnectionManager; import com.alipay.remoting.InvokeCallback; import com.alipay.remoting.InvokeContext; import com.alipay.remoting.InvokeFuture; @@ -48,13 +48,13 @@ public abstract class RpcRemoting extends BaseRemoting { RpcProtocolManager.initProtocols(); } /** logger */ - private static final Logger logger = BoltLoggerFactory.getLogger("RpcRemoting"); + private static final Logger logger = BoltLoggerFactory.getLogger("RpcRemoting"); /** address parser to get custom args */ - protected RemotingAddressParser addressParser; + protected RemotingAddressParser addressParser; /** connection manager */ - protected DefaultConnectionManager connectionManager; + protected ConnectionManager connectionManager; /** * default constructor @@ -68,7 +68,7 @@ public RpcRemoting(CommandFactory commandFactory) { * @param connectionManager */ public RpcRemoting(CommandFactory commandFactory, RemotingAddressParser addressParser, - DefaultConnectionManager connectionManager) { + ConnectionManager connectionManager) { this(commandFactory); this.addressParser = addressParser; this.connectionManager = connectionManager; @@ -183,9 +183,8 @@ public Object invokeSync(final Connection conn, final Object request, timeoutMillis); responseCommand.setInvokeContext(invokeContext); - Object responseObject = RpcResponseResolver.resolveResponseObject(responseCommand, + return RpcResponseResolver.resolveResponseObject(responseCommand, RemotingUtil.parseRemoteAddress(conn.getChannel())); - return responseObject; } /** @@ -339,7 +338,7 @@ protected RemotingCommand toRemotingCommand(Object request, Connection conn, // enable crc by default, user can disable by set invoke context `false` for key `InvokeContext.BOLT_CRC_SWITCH` Boolean crcSwitch = invokeContext.get(InvokeContext.BOLT_CRC_SWITCH, ProtocolSwitch.CRC_SWITCH_DEFAULT_VALUE); - if (null != crcSwitch && crcSwitch) { + if (crcSwitch == null || crcSwitch) { command.setProtocolSwitch(ProtocolSwitch .create(new int[] { ProtocolSwitch.CRC_SWITCH_INDEX })); } @@ -359,9 +358,6 @@ protected RemotingCommand toRemotingCommand(Object request, Connection conn, protected abstract void preProcessInvokeContext(InvokeContext invokeContext, RemotingCommand cmd, Connection connection); - /** - * @param requestCommand - */ private void logDebugInfo(RemotingCommand requestCommand) { if (logger.isDebugEnabled()) { logger.debug("Send request, requestId=" + requestCommand.getId()); diff --git a/src/main/java/com/alipay/remoting/rpc/RpcServer.java b/src/main/java/com/alipay/remoting/rpc/RpcServer.java index cfe6428a..2423fde6 100644 --- a/src/main/java/com/alipay/remoting/rpc/RpcServer.java +++ b/src/main/java/com/alipay/remoting/rpc/RpcServer.java @@ -20,18 +20,21 @@ import java.io.InputStream; import java.net.InetSocketAddress; import java.security.KeyStore; +import java.util.List; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutorService; import java.util.concurrent.TimeUnit; import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLEngine; +import javax.net.ssl.TrustManagerFactory; + import com.alipay.remoting.*; import com.alipay.remoting.config.BoltGenericOption; +import com.alipay.remoting.config.BoltServerOption; import org.slf4j.Logger; import com.alipay.remoting.codec.Codec; import com.alipay.remoting.config.ConfigManager; -import com.alipay.remoting.config.switches.GlobalSwitch; import com.alipay.remoting.constant.Constants; import com.alipay.remoting.exception.RemotingException; import com.alipay.remoting.log.BoltLoggerFactory; @@ -196,7 +199,7 @@ public RpcServer(int port, boolean manageConnection) { super(port); /* server connection management feature enabled or not, default value false, means disabled. */ if (manageConnection) { - this.switches().turnOn(GlobalSwitch.SERVER_MANAGE_CONNECTION_SWITCH); + option(BoltServerOption.SERVER_MANAGE_CONNECTION_SWITCH, true); } } @@ -218,7 +221,7 @@ public RpcServer(String ip, int port, boolean manageConnection) { super(ip, port); /* server connection management feature enabled or not, default value false, means disabled. */ if (manageConnection) { - this.switches().turnOn(GlobalSwitch.SERVER_MANAGE_CONNECTION_SWITCH); + option(BoltServerOption.SERVER_MANAGE_CONNECTION_SWITCH, true); } } @@ -234,7 +237,7 @@ public RpcServer(String ip, int port, boolean manageConnection) { public RpcServer(int port, boolean manageConnection, boolean syncStop) { this(port, manageConnection); if (syncStop) { - this.switches().turnOn(GlobalSwitch.SERVER_SYNC_STOP); + option(BoltServerOption.SERVER_SYNC_STOP, true); } } @@ -243,17 +246,17 @@ protected void doInit() { if (this.addressParser == null) { this.addressParser = new RpcAddressParser(); } - if (this.switches().isOn(GlobalSwitch.SERVER_MANAGE_CONNECTION_SWITCH)) { + if (option(BoltServerOption.SERVER_MANAGE_CONNECTION_SWITCH)) { // in server side, do not care the connection service state, so use null instead of global switch - ConnectionSelectStrategy connectionSelectStrategy = new RandomSelectStrategy(null); + ConnectionSelectStrategy connectionSelectStrategy = new RandomSelectStrategy(this); this.connectionManager = new DefaultServerConnectionManager(connectionSelectStrategy); this.connectionManager.startup(); - this.connectionEventHandler = new RpcConnectionEventHandler(switches()); + this.connectionEventHandler = new RpcConnectionEventHandler(this); this.connectionEventHandler.setConnectionManager(this.connectionManager); this.connectionEventHandler.setConnectionEventListener(this.connectionEventListener); } else { - this.connectionEventHandler = new ConnectionEventHandler(switches()); + this.connectionEventHandler = new ConnectionEventHandler(this); this.connectionEventHandler.setConnectionEventListener(this.connectionEventListener); } initRpcRemoting(); @@ -290,8 +293,7 @@ protected void doInit() { NettyEventLoopUtil.enableTriggeredMode(bootstrap); final boolean idleSwitch = ConfigManager.tcp_idle_switch(); - final boolean flushConsolidationSwitch = switches().isOn( - GlobalSwitch.CODEC_FLUSH_CONSOLIDATION); + final boolean flushConsolidationSwitch = option(BoltServerOption.NETTY_FLUSH_CONSOLIDATION); final int idleTime = ConfigManager.tcp_server_idle(); final ChannelHandler serverIdleHandler = new ServerIdleHandler(); final RpcHandler rpcHandler = new RpcHandler(true, this.userProcessors); @@ -300,10 +302,27 @@ protected void doInit() { @Override protected void initChannel(SocketChannel channel) { ChannelPipeline pipeline = channel.pipeline(); - if (RpcConfigManager.server_ssl_enable()) { + ExtendedNettyChannelHandler extendedHandlers = option(BoltServerOption.EXTENDED_NETTY_CHANNEL_HANDLER); + if (extendedHandlers != null) { + List frontHandlers = extendedHandlers.frontChannelHandlers(); + if (frontHandlers != null) { + for (ChannelHandler channelHandler : frontHandlers) { + pipeline.addLast(channelHandler.getClass().getName(), channelHandler); + } + } + } + + Boolean sslEnable = option(BoltServerOption.SRV_SSL_ENABLE); + if (!sslEnable) { + // fixme: remove in next version + sslEnable = RpcConfigManager.server_ssl_enable(); + } + if (sslEnable) { SSLEngine engine = initSSLContext().newEngine(channel.alloc()); engine.setUseClientMode(false); - engine.setNeedClientAuth(RpcConfigManager.server_ssl_need_client_auth()); + // fixme: update in next version + engine.setNeedClientAuth(option(BoltServerOption.SRV_SSL_NEED_CLIENT_AUTH) + || RpcConfigManager.server_ssl_need_client_auth()); pipeline.addLast(Constants.SSL_HANDLER, new SslHandler(engine)); } @@ -320,6 +339,14 @@ protected void initChannel(SocketChannel channel) { } pipeline.addLast("connectionEventHandler", connectionEventHandler); pipeline.addLast("handler", rpcHandler); + if (extendedHandlers != null) { + List backHandlers = extendedHandlers.backChannelHandlers(); + if (backHandlers != null) { + for (ChannelHandler channelHandler : backHandlers) { + pipeline.addLast(channelHandler.getClass().getName(), channelHandler); + } + } + } createConnection(channel); } @@ -332,7 +359,7 @@ protected void initChannel(SocketChannel channel) { */ private void createConnection(SocketChannel channel) { Url url = addressParser.parse(RemotingUtil.parseRemoteAddress(channel)); - if (switches().isOn(GlobalSwitch.SERVER_MANAGE_CONNECTION_SWITCH)) { + if (option(BoltServerOption.SERVER_MANAGE_CONNECTION_SWITCH)) { connectionManager.add(new Connection(channel, url), url.getUniqueKey()); } else { new Connection(channel, url); @@ -345,14 +372,34 @@ private void createConnection(SocketChannel channel) { private SslContext initSSLContext() { InputStream in = null; try { - KeyStore ks = KeyStore.getInstance(RpcConfigManager.server_ssl_keystore_type()); - in = new FileInputStream(RpcConfigManager.server_ssl_keystore()); - char[] passChs = RpcConfigManager.server_ssl_keystore_pass().toCharArray(); + String keyStoreType = option(BoltServerOption.SRV_SSL_KEYSTORE_TYPE); + if (keyStoreType == null) { + keyStoreType = RpcConfigManager.server_ssl_keystore_type(); + } + KeyStore ks = KeyStore.getInstance(keyStoreType); + String filePath = option(BoltServerOption.SRV_SSL_KEYSTORE); + if (filePath == null) { + filePath = RpcConfigManager.server_ssl_keystore(); + } + in = new FileInputStream(filePath); + + String keyStorePass = option(BoltServerOption.SRV_SSL_KEYSTORE_PASS); + if (keyStorePass == null) { + keyStorePass = RpcConfigManager.server_ssl_keystore_pass(); + } + char[] passChs = keyStorePass.toCharArray(); ks.load(in, passChs); - KeyManagerFactory kmf = KeyManagerFactory.getInstance(RpcConfigManager - .server_ssl_kmf_algorithm()); + String sslAlgorithm = RpcConfigManager.server_ssl_kmf_algorithm(); + if (sslAlgorithm == null) { + sslAlgorithm = option(BoltServerOption.SRV_SSL_KMF_ALGO); + } + KeyManagerFactory kmf = KeyManagerFactory.getInstance(sslAlgorithm); kmf.init(ks, passChs); - return SslContextBuilder.forServer(kmf).build(); + + TrustManagerFactory tmf = TrustManagerFactory.getInstance(RpcConfigManager + .client_ssl_tmf_algorithm()); + tmf.init(ks); + return SslContextBuilder.forServer(kmf).trustManager(tmf).build(); } catch (Exception e) { logger.error("Fail to init SSL context for server.", e); throw new IllegalStateException("Fail to init SSL context", e); @@ -381,7 +428,7 @@ protected boolean doStart() throws InterruptedException { } /** - * Notice: only {@link GlobalSwitch#SERVER_MANAGE_CONNECTION_SWITCH} switch on, will close all connections. + * Notice: only RpcServer#option(BoltServerOption.SERVER_MANAGE_CONNECTION_SWITCH, true) switch on, will close all connections. * * @see AbstractRemotingServer#doStop() */ @@ -390,12 +437,12 @@ protected boolean doStop() { if (null != this.channelFuture) { this.channelFuture.channel().close(); } - if (this.switches().isOn(GlobalSwitch.SERVER_SYNC_STOP)) { + if (option(BoltServerOption.SERVER_SYNC_STOP)) { this.bossGroup.shutdownGracefully().awaitUninterruptibly(); } else { this.bossGroup.shutdownGracefully(); } - if (this.switches().isOn(GlobalSwitch.SERVER_MANAGE_CONNECTION_SWITCH) + if (option(BoltServerOption.SERVER_MANAGE_CONNECTION_SWITCH) && null != this.connectionManager) { this.connectionManager.shutdown(); logger.warn("Close all connections from server side!"); @@ -988,7 +1035,7 @@ public boolean isConnected(Url url) { * check whether connection manage feature enabled */ private void check() { - if (!this.switches().isOn(GlobalSwitch.SERVER_MANAGE_CONNECTION_SWITCH)) { + if (!option(BoltServerOption.SERVER_MANAGE_CONNECTION_SWITCH)) { throw new UnsupportedOperationException( "Please enable connection manage feature of Rpc Server before call this method! See comments in constructor RpcServer(int port, boolean manageConnection) to find how to enable!"); } @@ -998,6 +1045,16 @@ private void check() { * init netty write buffer water mark */ private void initWriteBufferWaterMark() { + // init with system properties + Integer lowWaterMarkConfig = ConfigManager.netty_buffer_low_watermark(); + if (lowWaterMarkConfig != null) { + option(BoltServerOption.NETTY_BUFFER_LOW_WATER_MARK, lowWaterMarkConfig); + } + Integer highWaterMarkConfig = ConfigManager.netty_buffer_high_watermark(); + if (highWaterMarkConfig != null) { + option(BoltServerOption.NETTY_BUFFER_HIGH_WATER_MARK, highWaterMarkConfig); + } + int lowWaterMark = this.netty_buffer_low_watermark(); int highWaterMark = this.netty_buffer_high_watermark(); if (lowWaterMark > highWaterMark) { diff --git a/src/main/java/com/alipay/remoting/rpc/protocol/RpcCommandDecoder.java b/src/main/java/com/alipay/remoting/rpc/protocol/RpcCommandDecoder.java index 1618279d..3fd9bd4d 100644 --- a/src/main/java/com/alipay/remoting/rpc/protocol/RpcCommandDecoder.java +++ b/src/main/java/com/alipay/remoting/rpc/protocol/RpcCommandDecoder.java @@ -19,6 +19,8 @@ import java.net.InetSocketAddress; import java.util.List; +import com.alipay.remoting.util.ThreadLocalArriveTimeHolder; +import io.netty.channel.Channel; import org.slf4j.Logger; import com.alipay.remoting.CommandCode; @@ -96,6 +98,8 @@ public void decode(ChannelHandlerContext ctx, ByteBuf in, List out) thro byte[] clazz = null; byte[] header = null; byte[] content = null; + Channel channel = ctx.channel(); + ThreadLocalArriveTimeHolder.arrive(channel, requestId); if (in.readableBytes() >= classLen + headerLen + contentLen) { if (classLen > 0) { clazz = new byte[classLen]; @@ -114,10 +118,12 @@ public void decode(ChannelHandlerContext ctx, ByteBuf in, List out) thro return; } RequestCommand command; + long headerArriveTimeInNano = ThreadLocalArriveTimeHolder.getAndClear( + channel, requestId); if (cmdCode == CommandCode.HEARTBEAT_VALUE) { command = new HeartbeatCommand(); } else { - command = createRequestCommand(cmdCode); + command = createRequestCommand(cmdCode, headerArriveTimeInNano); } command.setType(type); command.setVersion(ver2); @@ -207,10 +213,12 @@ private ResponseCommand createResponseCommand(short cmdCode) { return command; } - private RpcRequestCommand createRequestCommand(short cmdCode) { + private RpcRequestCommand createRequestCommand(short cmdCode, long headerArriveTimeInNano) { RpcRequestCommand command = new RpcRequestCommand(); command.setCmdCode(RpcCommandCode.valueOf(cmdCode)); command.setArriveTime(System.currentTimeMillis()); + command.setArriveHeaderTimeInNano(headerArriveTimeInNano); + command.setArriveBodyTimeInNano(System.nanoTime()); return command; } diff --git a/src/main/java/com/alipay/remoting/rpc/protocol/RpcCommandDecoderV2.java b/src/main/java/com/alipay/remoting/rpc/protocol/RpcCommandDecoderV2.java index 7e86ec71..3c6bd921 100644 --- a/src/main/java/com/alipay/remoting/rpc/protocol/RpcCommandDecoderV2.java +++ b/src/main/java/com/alipay/remoting/rpc/protocol/RpcCommandDecoderV2.java @@ -20,6 +20,8 @@ import java.util.List; import com.alipay.remoting.log.BoltLoggerFactory; +import com.alipay.remoting.util.ThreadLocalArriveTimeHolder; +import io.netty.channel.Channel; import org.slf4j.Logger; import com.alipay.remoting.CommandCode; @@ -103,6 +105,9 @@ public void decode(ChannelHandlerContext ctx, ByteBuf in, List out) thro byte[] header = null; byte[] content = null; + Channel channel = ctx.channel(); + ThreadLocalArriveTimeHolder.arrive(channel, requestId); + // decide the at-least bytes length for each version int lengthAtLeastForV1 = classLen + headerLen + contentLen; boolean crcSwitchOn = ProtocolSwitch.isOn( @@ -135,11 +140,15 @@ public void decode(ChannelHandlerContext ctx, ByteBuf in, List out) thro in.resetReaderIndex(); return; } + + long headerArriveTimeInNano = ThreadLocalArriveTimeHolder.getAndClear( + channel, requestId); + RequestCommand command; if (cmdCode == CommandCode.HEARTBEAT_VALUE) { command = new HeartbeatCommand(); } else { - command = createRequestCommand(cmdCode); + command = createRequestCommand(cmdCode, headerArriveTimeInNano); } command.setType(type); command.setVersion(ver2); @@ -261,10 +270,12 @@ private ResponseCommand createResponseCommand(short cmdCode) { return command; } - private RpcRequestCommand createRequestCommand(short cmdCode) { + private RpcRequestCommand createRequestCommand(short cmdCode, long headerArriveTimeInNano) { RpcRequestCommand command = new RpcRequestCommand(); command.setCmdCode(RpcCommandCode.valueOf(cmdCode)); command.setArriveTime(System.currentTimeMillis()); + command.setArriveHeaderTimeInNano(headerArriveTimeInNano); + command.setArriveBodyTimeInNano(System.nanoTime()); return command; } diff --git a/src/main/java/com/alipay/remoting/rpc/protocol/RpcRequestCommand.java b/src/main/java/com/alipay/remoting/rpc/protocol/RpcRequestCommand.java index 9787f420..08c3942c 100644 --- a/src/main/java/com/alipay/remoting/rpc/protocol/RpcRequestCommand.java +++ b/src/main/java/com/alipay/remoting/rpc/protocol/RpcRequestCommand.java @@ -36,14 +36,17 @@ */ public class RpcRequestCommand extends RequestCommand { /** For serialization */ - private static final long serialVersionUID = -4602613826188210946L; + private static final long serialVersionUID = -4602613826188210946L; private Object requestObject; private String requestClass; private CustomSerializer customSerializer; private Object requestHeader; - private transient long arriveTime = -1; + private transient long arriveTime = -1; + private transient long arriveHeaderTimeInNano = -1; + private transient long arriveBodyTimeInNano = -1; + private transient long beforeEnterQueueTime = -1; /** * create request command without id @@ -247,4 +250,28 @@ public long getArriveTime() { public void setArriveTime(long arriveTime) { this.arriveTime = arriveTime; } + + public long getArriveHeaderTimeInNano() { + return arriveHeaderTimeInNano; + } + + public void setArriveHeaderTimeInNano(long arriveHeaderTimeInNano) { + this.arriveHeaderTimeInNano = arriveHeaderTimeInNano; + } + + public long getArriveBodyTimeInNano() { + return arriveBodyTimeInNano; + } + + public void setArriveBodyTimeInNano(long arriveBodyTimeInNano) { + this.arriveBodyTimeInNano = arriveBodyTimeInNano; + } + + public long getBeforeEnterQueueTime() { + return beforeEnterQueueTime; + } + + public void setBeforeEnterQueueTime(long beforeEnterQueueTime) { + this.beforeEnterQueueTime = beforeEnterQueueTime; + } } diff --git a/src/main/java/com/alipay/remoting/rpc/protocol/RpcRequestProcessor.java b/src/main/java/com/alipay/remoting/rpc/protocol/RpcRequestProcessor.java index 17810690..9b92adc1 100644 --- a/src/main/java/com/alipay/remoting/rpc/protocol/RpcRequestProcessor.java +++ b/src/main/java/com/alipay/remoting/rpc/protocol/RpcRequestProcessor.java @@ -120,6 +120,7 @@ public void process(RemotingContext ctx, RpcRequestCommand cmd, ExecutorService executor = (this.getExecutor() == null ? defaultExecutor : this.getExecutor()); } + cmd.setBeforeEnterQueueTime(System.nanoTime()); // use the final executor dispatch process task executor.execute(new ProcessTask(ctx, cmd)); } @@ -317,6 +318,14 @@ private void preProcessRemotingContext(RemotingContext ctx, RpcRequestCommand cm ctx.setRpcCommandType(cmd.getType()); ctx.getInvokeContext().putIfAbsent(InvokeContext.BOLT_PROCESS_WAIT_TIME, currentTimestamp - cmd.getArriveTime()); + ctx.getInvokeContext().putIfAbsent(InvokeContext.BOLT_PROCESS_ARRIVE_HEADER_IN_NANO, + cmd.getArriveHeaderTimeInNano()); + ctx.getInvokeContext().putIfAbsent(InvokeContext.BOLT_PROCESS_ARRIVE_BODY_IN_NANO, + cmd.getArriveBodyTimeInNano()); + ctx.getInvokeContext().putIfAbsent(InvokeContext.BOLT_PROCESS_BEFORE_DISPATCH_IN_NANO, + cmd.getBeforeEnterQueueTime()); + ctx.getInvokeContext().putIfAbsent(InvokeContext.BOLT_PROCESS_START_PROCESS_IN_NANO, + System.nanoTime()); } /** diff --git a/src/main/java/com/alipay/remoting/util/ThreadLocalArriveTimeHolder.java b/src/main/java/com/alipay/remoting/util/ThreadLocalArriveTimeHolder.java new file mode 100644 index 00000000..5000a467 --- /dev/null +++ b/src/main/java/com/alipay/remoting/util/ThreadLocalArriveTimeHolder.java @@ -0,0 +1,62 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alipay.remoting.util; + +import io.netty.channel.Channel; +import io.netty.util.concurrent.FastThreadLocal; + +import java.util.HashMap; +import java.util.Map; +import java.util.WeakHashMap; + +/** + * @author zhaowang + * @version : ThreadLocalTimeHolder.java, v 0.1 2021年07月01日 3:05 下午 zhaowang + */ +public class ThreadLocalArriveTimeHolder { + + private static FastThreadLocal>> arriveTimeInNano = new FastThreadLocal>>(); + + public static void arrive(Channel channel, Integer key) { + Map map = getArriveTimeMap(channel); + if (map.get(key) == null) { + map.put(key, System.nanoTime()); + } + } + + public static long getAndClear(Channel channel, Integer key) { + Map map = getArriveTimeMap(channel); + Long result = map.remove(key); + if (result == null) { + return -1; + } + return result; + } + + private static Map getArriveTimeMap(Channel channel) { + WeakHashMap> map = arriveTimeInNano.get(); + if (map == null) { + arriveTimeInNano.set(new WeakHashMap>(256)); + map = arriveTimeInNano.get(); + } + Map subMap = map.get(channel); + if (subMap == null) { + map.put(channel, new HashMap()); + } + return map.get(channel); + } +} diff --git a/src/test/java/com/alipay/remoting/RemotingServerTest.java b/src/test/java/com/alipay/remoting/RemotingServerTest.java index 9f46ff78..f8af07ac 100644 --- a/src/test/java/com/alipay/remoting/RemotingServerTest.java +++ b/src/test/java/com/alipay/remoting/RemotingServerTest.java @@ -16,11 +16,8 @@ */ package com.alipay.remoting; -import static org.mockito.Mockito.when; - import org.junit.Assert; import org.junit.Test; -import org.mockito.Mockito; import com.alipay.remoting.rpc.RpcServer; @@ -45,14 +42,6 @@ public void testStartRepeatedly() { rpcServer.stop(); } - @Test - public void testStartFailed() throws InterruptedException { - AbstractRemotingServer remotingServer = Mockito.mock(AbstractRemotingServer.class); - when(remotingServer.doStart()).thenThrow(new RuntimeException("start error")); - - Assert.assertFalse(remotingServer.start()); - } - @Test public void testStopRepeatedly() { RpcServer rpcServer = new RpcServer(1111); diff --git a/src/test/java/com/alipay/remoting/benchmark/BenchmarkClient.java b/src/test/java/com/alipay/remoting/benchmark/BenchmarkClient.java index a1b50c6c..50e96531 100644 --- a/src/test/java/com/alipay/remoting/benchmark/BenchmarkClient.java +++ b/src/test/java/com/alipay/remoting/benchmark/BenchmarkClient.java @@ -22,7 +22,7 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicLong; -import com.alipay.remoting.config.switches.GlobalSwitch; +import com.alipay.remoting.config.BoltClientOption; import com.alipay.remoting.exception.RemotingException; import com.alipay.remoting.rpc.RpcClient; import com.alipay.remoting.rpc.RpcResponseFuture; @@ -67,7 +67,7 @@ public static void main(String[] args) throws RemotingException, InterruptedExce System.setProperty("bolt.netty.buffer.high.watermark", String.valueOf(64 * 1024 * 1024)); System.setProperty("bolt.netty.buffer.low.watermark", String.valueOf(32 * 1024 * 1024)); RpcClient rpcClient = new RpcClient(); - rpcClient.switches().turnOn(GlobalSwitch.CODEC_FLUSH_CONSOLIDATION); + rpcClient.option(BoltClientOption.NETTY_FLUSH_CONSOLIDATION, true); rpcClient.startup(); int processors = Runtime.getRuntime().availableProcessors(); diff --git a/src/test/java/com/alipay/remoting/benchmark/BenchmarkServer.java b/src/test/java/com/alipay/remoting/benchmark/BenchmarkServer.java index 9612c91a..e9705c33 100644 --- a/src/test/java/com/alipay/remoting/benchmark/BenchmarkServer.java +++ b/src/test/java/com/alipay/remoting/benchmark/BenchmarkServer.java @@ -16,7 +16,7 @@ */ package com.alipay.remoting.benchmark; -import com.alipay.remoting.config.switches.GlobalSwitch; +import com.alipay.remoting.config.BoltServerOption; import com.alipay.remoting.rpc.RpcServer; /** @@ -28,7 +28,7 @@ public static void main(String[] args) { System.setProperty("bolt.netty.buffer.high.watermark", String.valueOf(64 * 1024 * 1024)); System.setProperty("bolt.netty.buffer.low.watermark", String.valueOf(32 * 1024 * 1024)); RpcServer rpcServer = new RpcServer(18090, true, true); - rpcServer.switches().turnOn(GlobalSwitch.CODEC_FLUSH_CONSOLIDATION); + rpcServer.option(BoltServerOption.NETTY_FLUSH_CONSOLIDATION, true); rpcServer.registerUserProcessor(new BenchmarkUserProcessor()); rpcServer.startup(); } diff --git a/src/test/java/com/alipay/remoting/benchmark/JMHBenchmarkClient.java b/src/test/java/com/alipay/remoting/benchmark/JMHBenchmarkClient.java deleted file mode 100644 index 7020d216..00000000 --- a/src/test/java/com/alipay/remoting/benchmark/JMHBenchmarkClient.java +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.alipay.remoting.benchmark; - -import java.util.Random; -import java.util.concurrent.TimeUnit; - -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.BenchmarkMode; -import org.openjdk.jmh.annotations.Mode; -import org.openjdk.jmh.annotations.OutputTimeUnit; -import org.openjdk.jmh.annotations.Scope; -import org.openjdk.jmh.annotations.Setup; -import org.openjdk.jmh.annotations.State; -import org.openjdk.jmh.annotations.TearDown; -import org.openjdk.jmh.runner.Runner; -import org.openjdk.jmh.runner.RunnerException; -import org.openjdk.jmh.runner.options.Options; -import org.openjdk.jmh.runner.options.OptionsBuilder; -import org.openjdk.jmh.runner.options.TimeValue; - -import com.alipay.remoting.config.switches.GlobalSwitch; -import com.alipay.remoting.exception.RemotingException; -import com.alipay.remoting.rpc.RpcClient; - -/** - * @author jiachun.fjc - */ -@State(Scope.Benchmark) -public class JMHBenchmarkClient { - - /** - * CODEC_FLUSH_CONSOLIDATION=turnOn - * Benchmark Mode Cnt Score Error Units - * JMHBenchmarkClient.send1024 thrpt 3 46.887 ± 22.766 ops/ms - * JMHBenchmarkClient.send128 thrpt 3 66.376 ± 28.429 ops/ms - * JMHBenchmarkClient.send1024 avgt 3 0.674 ± 0.986 ms/op - * JMHBenchmarkClient.send128 avgt 3 0.479 ± 0.239 ms/op - * JMHBenchmarkClient.send1024 sample 1525751 0.629 ± 0.001 ms/op - * JMHBenchmarkClient.send1024:send1024·p0.00 sample 0.150 ms/op - * JMHBenchmarkClient.send1024:send1024·p0.50 sample 0.602 ms/op - * JMHBenchmarkClient.send1024:send1024·p0.90 sample 0.775 ms/op - * JMHBenchmarkClient.send1024:send1024·p0.95 sample 0.854 ms/op - * JMHBenchmarkClient.send1024:send1024·p0.99 sample 1.614 ms/op - * JMHBenchmarkClient.send1024:send1024·p0.999 sample 2.249 ms/op - * JMHBenchmarkClient.send1024:send1024·p0.9999 sample 4.280 ms/op - * JMHBenchmarkClient.send1024:send1024·p1.00 sample 6.431 ms/op - * JMHBenchmarkClient.send128 sample 1913189 0.501 ± 0.001 ms/op - * JMHBenchmarkClient.send128:send128·p0.00 sample 0.150 ms/op - * JMHBenchmarkClient.send128:send128·p0.50 sample 0.481 ms/op - * JMHBenchmarkClient.send128:send128·p0.90 sample 0.618 ms/op - * JMHBenchmarkClient.send128:send128·p0.95 sample 0.688 ms/op - * JMHBenchmarkClient.send128:send128·p0.99 sample 1.190 ms/op - * JMHBenchmarkClient.send128:send128·p0.999 sample 2.097 ms/op - * JMHBenchmarkClient.send128:send128·p0.9999 sample 4.391 ms/op - * JMHBenchmarkClient.send128:send128·p1.00 sample 7.053 ms/op - * JMHBenchmarkClient.send1024 ss 3 5.179 ± 18.142 ms/op - * JMHBenchmarkClient.send128 ss 3 3.788 ± 10.388 ms/op - * - * CODEC_FLUSH_CONSOLIDATION=turnOff - * Benchmark Mode Cnt Score Error Units - * JMHBenchmarkClient.send1024 thrpt 3 35.946 ± 10.332 ops/ms - * JMHBenchmarkClient.send128 thrpt 3 41.364 ± 36.002 ops/ms - * JMHBenchmarkClient.send1024 avgt 3 0.846 ± 0.272 ms/op - * JMHBenchmarkClient.send128 avgt 3 0.731 ± 0.306 ms/op - * JMHBenchmarkClient.send1024 sample 1003714 0.956 ± 0.001 ms/op - * JMHBenchmarkClient.send1024:send1024·p0.00 sample 0.183 ms/op - * JMHBenchmarkClient.send1024:send1024·p0.50 sample 0.886 ms/op - * JMHBenchmarkClient.send1024:send1024·p0.90 sample 1.294 ms/op - * JMHBenchmarkClient.send1024:send1024·p0.95 sample 1.495 ms/op - * JMHBenchmarkClient.send1024:send1024·p0.99 sample 2.241 ms/op - * JMHBenchmarkClient.send1024:send1024·p0.999 sample 3.977 ms/op - * JMHBenchmarkClient.send1024:send1024·p0.9999 sample 8.448 ms/op - * JMHBenchmarkClient.send1024:send1024·p1.00 sample 21.660 ms/op - * JMHBenchmarkClient.send128 sample 1346879 0.712 ± 0.001 ms/op - * JMHBenchmarkClient.send128:send128·p0.00 sample 0.124 ms/op - * JMHBenchmarkClient.send128:send128·p0.50 sample 0.684 ms/op - * JMHBenchmarkClient.send128:send128·p0.90 sample 0.927 ms/op - * JMHBenchmarkClient.send128:send128·p0.95 sample 1.016 ms/op - * JMHBenchmarkClient.send128:send128·p0.99 sample 1.571 ms/op - * JMHBenchmarkClient.send128:send128·p0.999 sample 2.322 ms/op - * JMHBenchmarkClient.send128:send128·p0.9999 sample 4.375 ms/op - * JMHBenchmarkClient.send128:send128·p1.00 sample 5.865 ms/op - * JMHBenchmarkClient.send1024 ss 3 5.932 ± 13.160 ms/op - * JMHBenchmarkClient.send128 ss 3 5.028 ± 10.273 ms/op - */ - - public static final int CONCURRENCY = 32; - - private static final byte[] BYTES_128 = new byte[128]; - private static final byte[] BYTES_1024 = new byte[1024]; - - static { - new Random().nextBytes(BYTES_128); - new Random().nextBytes(BYTES_1024); - } - - private RpcClient client; - - @Setup - public void setup() { - System.setProperty("bolt.netty.buffer.high.watermark", String.valueOf(64 * 1024 * 1024)); - System.setProperty("bolt.netty.buffer.low.watermark", String.valueOf(32 * 1024 * 1024)); - client = new RpcClient(); - client.switches().turnOn(GlobalSwitch.CODEC_FLUSH_CONSOLIDATION); - client.startup(); - } - - @TearDown - public void tearDown() { - client.shutdown(); - } - - @Benchmark - @BenchmarkMode(Mode.All) - @OutputTimeUnit(TimeUnit.MILLISECONDS) - public void send128() throws RemotingException, InterruptedException { - client.invokeSync("127.0.0.1:18090", new Request(BYTES_128), 5000); - } - - @Benchmark - @BenchmarkMode(Mode.All) - @OutputTimeUnit(TimeUnit.MILLISECONDS) - public void send1024() throws RemotingException, InterruptedException { - client.invokeSync("127.0.0.1:18090", new Request(BYTES_1024), 5000); - } - - public static void main(String[] args) throws RunnerException { - Options opt = new OptionsBuilder()// - .include(JMHBenchmarkClient.class.getSimpleName())// - .warmupIterations(3)// - .warmupTime(TimeValue.seconds(10))// - .measurementIterations(3)// - .measurementTime(TimeValue.seconds(10))// - .threads(CONCURRENCY)// - .forks(1)// - .build(); - - new Runner(opt).run(); - } -} diff --git a/src/test/java/com/alipay/remoting/codec/ProtocolCodeBasedDecoderTest.java b/src/test/java/com/alipay/remoting/codec/ProtocolCodeBasedDecoderTest.java new file mode 100644 index 00000000..b7b16da9 --- /dev/null +++ b/src/test/java/com/alipay/remoting/codec/ProtocolCodeBasedDecoderTest.java @@ -0,0 +1,538 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alipay.remoting.codec; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufAllocator; +import io.netty.buffer.Unpooled; +import io.netty.channel.Channel; +import io.netty.channel.ChannelConfig; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelId; +import io.netty.channel.ChannelMetadata; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.ChannelProgressivePromise; +import io.netty.channel.ChannelPromise; +import io.netty.channel.EventLoop; +import io.netty.util.Attribute; +import io.netty.util.AttributeKey; +import io.netty.util.concurrent.EventExecutor; +import org.junit.Assert; +import org.junit.Test; + +import java.net.SocketAddress; +import java.util.ArrayList; + +/** + * @author chengyi (mark.lx@antfin.com) 2021-05-24 20:07 + */ +public class ProtocolCodeBasedDecoderTest { + + @Test + public void testDecodeIllegalPacket() throws Exception { + ChannelHandlerContext context = new MockedChannelHandlerContext(); + ByteBuf byteBuf = Unpooled.buffer(8); + byteBuf.writeByte((byte) 13); + ProtocolCodeBasedDecoder decoder = new ProtocolCodeBasedDecoder(1); + + int readerIndex = byteBuf.readerIndex(); + Assert.assertEquals(0, readerIndex); + + Exception exception = null; + try { + // decode exception + decoder.decode(context, byteBuf, new ArrayList()); + } catch (Exception e) { + // ignore + exception = e; + } + Assert.assertNotNull(exception); + + readerIndex = byteBuf.readerIndex(); + Assert.assertEquals(0, readerIndex); + } + + class MockedChannel implements Channel { + + @Override + public ChannelId id() { + return null; + } + + @Override + public EventLoop eventLoop() { + return null; + } + + @Override + public Channel parent() { + return null; + } + + @Override + public ChannelConfig config() { + return null; + } + + @Override + public boolean isOpen() { + return false; + } + + @Override + public boolean isRegistered() { + return false; + } + + @Override + public boolean isActive() { + return false; + } + + @Override + public ChannelMetadata metadata() { + return null; + } + + @Override + public SocketAddress localAddress() { + return null; + } + + @Override + public SocketAddress remoteAddress() { + return null; + } + + @Override + public ChannelFuture closeFuture() { + return null; + } + + @Override + public boolean isWritable() { + return false; + } + + @Override + public long bytesBeforeUnwritable() { + return 0; + } + + @Override + public long bytesBeforeWritable() { + return 0; + } + + @Override + public Unsafe unsafe() { + return null; + } + + @Override + public ChannelPipeline pipeline() { + return null; + } + + @Override + public ByteBufAllocator alloc() { + return null; + } + + @Override + public ChannelFuture bind(SocketAddress localAddress) { + return null; + } + + @Override + public ChannelFuture connect(SocketAddress remoteAddress) { + return null; + } + + @Override + public ChannelFuture connect(SocketAddress remoteAddress, SocketAddress localAddress) { + return null; + } + + @Override + public ChannelFuture disconnect() { + return null; + } + + @Override + public ChannelFuture close() { + return null; + } + + @Override + public ChannelFuture deregister() { + return null; + } + + @Override + public ChannelFuture bind(SocketAddress localAddress, ChannelPromise promise) { + return null; + } + + @Override + public ChannelFuture connect(SocketAddress remoteAddress, ChannelPromise promise) { + return null; + } + + @Override + public ChannelFuture connect(SocketAddress remoteAddress, SocketAddress localAddress, + ChannelPromise promise) { + return null; + } + + @Override + public ChannelFuture disconnect(ChannelPromise promise) { + return null; + } + + @Override + public ChannelFuture close(ChannelPromise promise) { + return null; + } + + @Override + public ChannelFuture deregister(ChannelPromise promise) { + return null; + } + + @Override + public Channel read() { + return null; + } + + @Override + public ChannelFuture write(Object msg) { + return null; + } + + @Override + public ChannelFuture write(Object msg, ChannelPromise promise) { + return null; + } + + @Override + public Channel flush() { + return null; + } + + @Override + public ChannelFuture writeAndFlush(Object msg, ChannelPromise promise) { + return null; + } + + @Override + public ChannelFuture writeAndFlush(Object msg) { + return null; + } + + @Override + public ChannelPromise newPromise() { + return null; + } + + @Override + public ChannelProgressivePromise newProgressivePromise() { + return null; + } + + @Override + public ChannelFuture newSucceededFuture() { + return null; + } + + @Override + public ChannelFuture newFailedFuture(Throwable cause) { + return null; + } + + @Override + public ChannelPromise voidPromise() { + return null; + } + + @Override + public Attribute attr(AttributeKey key) { + return new Attribute() { + @Override + public AttributeKey key() { + return null; + } + + @Override + public T get() { + return null; + } + + @Override + public void set(T value) { + + } + + @Override + public T getAndSet(T value) { + return null; + } + + @Override + public T setIfAbsent(T value) { + return null; + } + + @Override + public T getAndRemove() { + return null; + } + + @Override + public boolean compareAndSet(T oldValue, T newValue) { + return false; + } + + @Override + public void remove() { + + } + }; + } + + @Override + public boolean hasAttr(AttributeKey key) { + return false; + } + + @Override + public int compareTo(Channel o) { + return 0; + } + } + + class MockedChannelHandlerContext implements ChannelHandlerContext { + + @Override + public Channel channel() { + return new MockedChannel(); + } + + @Override + public EventExecutor executor() { + return null; + } + + @Override + public String name() { + return null; + } + + @Override + public ChannelHandler handler() { + return null; + } + + @Override + public boolean isRemoved() { + return false; + } + + @Override + public ChannelHandlerContext fireChannelRegistered() { + return null; + } + + @Override + public ChannelHandlerContext fireChannelUnregistered() { + return null; + } + + @Override + public ChannelHandlerContext fireChannelActive() { + return null; + } + + @Override + public ChannelHandlerContext fireChannelInactive() { + return null; + } + + @Override + public ChannelHandlerContext fireExceptionCaught(Throwable cause) { + return null; + } + + @Override + public ChannelHandlerContext fireUserEventTriggered(Object evt) { + return null; + } + + @Override + public ChannelHandlerContext fireChannelRead(Object msg) { + return null; + } + + @Override + public ChannelHandlerContext fireChannelReadComplete() { + return null; + } + + @Override + public ChannelHandlerContext fireChannelWritabilityChanged() { + return null; + } + + @Override + public ChannelFuture bind(SocketAddress localAddress) { + return null; + } + + @Override + public ChannelFuture connect(SocketAddress remoteAddress) { + return null; + } + + @Override + public ChannelFuture connect(SocketAddress remoteAddress, SocketAddress localAddress) { + return null; + } + + @Override + public ChannelFuture disconnect() { + return null; + } + + @Override + public ChannelFuture close() { + return null; + } + + @Override + public ChannelFuture deregister() { + return null; + } + + @Override + public ChannelFuture bind(SocketAddress localAddress, ChannelPromise promise) { + return null; + } + + @Override + public ChannelFuture connect(SocketAddress remoteAddress, ChannelPromise promise) { + return null; + } + + @Override + public ChannelFuture connect(SocketAddress remoteAddress, SocketAddress localAddress, + ChannelPromise promise) { + return null; + } + + @Override + public ChannelFuture disconnect(ChannelPromise promise) { + return null; + } + + @Override + public ChannelFuture close(ChannelPromise promise) { + return null; + } + + @Override + public ChannelFuture deregister(ChannelPromise promise) { + return null; + } + + @Override + public ChannelHandlerContext read() { + return null; + } + + @Override + public ChannelFuture write(Object msg) { + return null; + } + + @Override + public ChannelFuture write(Object msg, ChannelPromise promise) { + return null; + } + + @Override + public ChannelHandlerContext flush() { + return null; + } + + @Override + public ChannelFuture writeAndFlush(Object msg, ChannelPromise promise) { + return null; + } + + @Override + public ChannelFuture writeAndFlush(Object msg) { + return null; + } + + @Override + public ChannelPromise newPromise() { + return null; + } + + @Override + public ChannelProgressivePromise newProgressivePromise() { + return null; + } + + @Override + public ChannelFuture newSucceededFuture() { + return null; + } + + @Override + public ChannelFuture newFailedFuture(Throwable cause) { + return null; + } + + @Override + public ChannelPromise voidPromise() { + return null; + } + + @Override + public ChannelPipeline pipeline() { + return null; + } + + @Override + public ByteBufAllocator alloc() { + return null; + } + + @Override + public Attribute attr(AttributeKey key) { + return null; + } + + @Override + public boolean hasAttr(AttributeKey key) { + return false; + } + } +} diff --git a/src/test/java/com/alipay/remoting/config/DefaultConfigContainerTest.java b/src/test/java/com/alipay/remoting/config/DefaultConfigContainerTest.java deleted file mode 100644 index 33c88824..00000000 --- a/src/test/java/com/alipay/remoting/config/DefaultConfigContainerTest.java +++ /dev/null @@ -1,170 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.alipay.remoting.config; - -import org.junit.Assert; -import org.junit.Test; - -import com.alipay.remoting.config.configs.ConfigContainer; -import com.alipay.remoting.config.configs.ConfigItem; -import com.alipay.remoting.config.configs.ConfigType; -import com.alipay.remoting.config.configs.DefaultConfigContainer; - -/** - * - * @author tsui - * @version $Id: DefaultConfigContainerTest.java, v 0.1 2018-07-30 10:53 tsui Exp $$ - */ -public class DefaultConfigContainerTest { - @Test - public void testNormalArgs() { - ConfigContainer configContainer = new DefaultConfigContainer(); - // test set one - int expected_int = 123; - configContainer.set(ConfigType.CLIENT_SIDE, ConfigItem.NETTY_BUFFER_LOW_WATER_MARK, - expected_int); - Assert.assertEquals(expected_int, - configContainer.get(ConfigType.CLIENT_SIDE, ConfigItem.NETTY_BUFFER_LOW_WATER_MARK)); - Assert.assertNull(configContainer.get(ConfigType.CLIENT_SIDE, - ConfigItem.NETTY_BUFFER_HIGH_WATER_MARK)); - Assert.assertNull(configContainer.get(ConfigType.SERVER_SIDE, - ConfigItem.NETTY_BUFFER_LOW_WATER_MARK)); - Assert.assertNull(configContainer.get(ConfigType.SERVER_SIDE, - ConfigItem.NETTY_BUFFER_HIGH_WATER_MARK)); - - Assert.assertTrue(configContainer.contains(ConfigType.CLIENT_SIDE, - ConfigItem.NETTY_BUFFER_LOW_WATER_MARK)); - Assert.assertFalse(configContainer.contains(ConfigType.CLIENT_SIDE, - ConfigItem.NETTY_BUFFER_HIGH_WATER_MARK)); - Assert.assertFalse(configContainer.contains(ConfigType.SERVER_SIDE, - ConfigItem.NETTY_BUFFER_LOW_WATER_MARK)); - Assert.assertFalse(configContainer.contains(ConfigType.SERVER_SIDE, - ConfigItem.NETTY_BUFFER_HIGH_WATER_MARK)); - - // test set all - configContainer.set(ConfigType.CLIENT_SIDE, ConfigItem.NETTY_BUFFER_HIGH_WATER_MARK, - expected_int); - configContainer.set(ConfigType.SERVER_SIDE, ConfigItem.NETTY_BUFFER_LOW_WATER_MARK, - expected_int); - configContainer.set(ConfigType.SERVER_SIDE, ConfigItem.NETTY_BUFFER_HIGH_WATER_MARK, - expected_int); - - Assert.assertTrue(configContainer.contains(ConfigType.CLIENT_SIDE, - ConfigItem.NETTY_BUFFER_LOW_WATER_MARK)); - Assert.assertTrue(configContainer.contains(ConfigType.CLIENT_SIDE, - ConfigItem.NETTY_BUFFER_HIGH_WATER_MARK)); - Assert.assertTrue(configContainer.contains(ConfigType.SERVER_SIDE, - ConfigItem.NETTY_BUFFER_LOW_WATER_MARK)); - Assert.assertTrue(configContainer.contains(ConfigType.SERVER_SIDE, - ConfigItem.NETTY_BUFFER_HIGH_WATER_MARK)); - - // test overwrite - int expected_int_overwrite = 456; - configContainer.set(ConfigType.CLIENT_SIDE, ConfigItem.NETTY_BUFFER_LOW_WATER_MARK, - expected_int_overwrite); - Assert.assertEquals(expected_int_overwrite, - configContainer.get(ConfigType.CLIENT_SIDE, ConfigItem.NETTY_BUFFER_LOW_WATER_MARK)); - Assert.assertEquals(expected_int, - configContainer.get(ConfigType.CLIENT_SIDE, ConfigItem.NETTY_BUFFER_HIGH_WATER_MARK)); - Assert.assertEquals(expected_int, - configContainer.get(ConfigType.SERVER_SIDE, ConfigItem.NETTY_BUFFER_LOW_WATER_MARK)); - Assert.assertEquals(expected_int, - configContainer.get(ConfigType.SERVER_SIDE, ConfigItem.NETTY_BUFFER_HIGH_WATER_MARK)); - } - - @Test - public void testNullArgs() { - ConfigContainer configContainer = new DefaultConfigContainer(); - - try { - configContainer.set(null, null, null); - Assert.fail("Should not reach here!"); - } catch (IllegalArgumentException e) { - } - - try { - configContainer.set(ConfigType.CLIENT_SIDE, null, null); - Assert.fail("Should not reach here!"); - } catch (IllegalArgumentException e) { - } - - try { - configContainer.set(null, ConfigItem.NETTY_BUFFER_LOW_WATER_MARK, null); - Assert.fail("Should not reach here!"); - } catch (IllegalArgumentException e) { - } - - try { - configContainer.set(null, null, 123); - Assert.fail("Should not reach here!"); - } catch (IllegalArgumentException e) { - } - - try { - configContainer.set(ConfigType.CLIENT_SIDE, ConfigItem.NETTY_BUFFER_LOW_WATER_MARK, - null); - Assert.fail("Should not reach here!"); - } catch (IllegalArgumentException e) { - } - - try { - configContainer.set(ConfigType.CLIENT_SIDE, null, "hehe"); - Assert.fail("Should not reach here!"); - } catch (IllegalArgumentException e) { - } - - try { - configContainer.set(null, ConfigItem.NETTY_BUFFER_LOW_WATER_MARK, "hehe"); - Assert.fail("Should not reach here!"); - } catch (IllegalArgumentException e) { - } - - try { - configContainer.get(null, null); - Assert.fail("Should not reach here!"); - } catch (IllegalArgumentException e) { - } - - try { - configContainer.get(null, ConfigItem.NETTY_BUFFER_LOW_WATER_MARK); - Assert.fail("Should not reach here!"); - } catch (IllegalArgumentException e) { - } - - try { - configContainer.get(ConfigType.CLIENT_SIDE, null); - Assert.fail("Should not reach here!"); - } catch (IllegalArgumentException e) { - } - - try { - configContainer.contains(null, null); - Assert.fail("Should not reach here!"); - } catch (IllegalArgumentException e) { - } - try { - configContainer.contains(ConfigType.CLIENT_SIDE, null); - Assert.fail("Should not reach here!"); - } catch (IllegalArgumentException e) { - } - try { - configContainer.contains(null, ConfigItem.NETTY_BUFFER_LOW_WATER_MARK); - Assert.fail("Should not reach here!"); - } catch (IllegalArgumentException e) { - } - } -} \ No newline at end of file diff --git a/src/test/java/com/alipay/remoting/inner/connection/ConnectionCreatingTest.java b/src/test/java/com/alipay/remoting/inner/connection/ConnectionCreatingTest.java new file mode 100644 index 00000000..ceae984b --- /dev/null +++ b/src/test/java/com/alipay/remoting/inner/connection/ConnectionCreatingTest.java @@ -0,0 +1,138 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alipay.remoting.inner.connection; + +import com.alipay.remoting.BizContext; +import com.alipay.remoting.Connection; +import com.alipay.remoting.ConnectionEventListener; +import com.alipay.remoting.DefaultClientConnectionManager; +import com.alipay.remoting.RandomSelectStrategy; +import com.alipay.remoting.Url; +import com.alipay.remoting.exception.RemotingException; +import com.alipay.remoting.rpc.RpcClient; +import com.alipay.remoting.rpc.RpcConnectionEventHandler; +import com.alipay.remoting.rpc.RpcConnectionFactory; +import com.alipay.remoting.rpc.common.BoltServer; +import com.alipay.remoting.rpc.protocol.SyncUserProcessor; +import com.alipay.remoting.rpc.protocol.UserProcessor; +import com.alipay.remoting.util.ThreadTestUtils; +import org.junit.Assert; +import org.junit.Test; + +import java.util.concurrent.ConcurrentHashMap; + +public class ConnectionCreatingTest { + + @Test + public void testCreateConnection() throws RemotingException, InterruptedException { + // 启动一个MOCK的Server + BoltServer boltServer = new BoltServer(8888); + boltServer.registerUserProcessor(new SyncUserProcessor() { + @Override + public Object handleRequest(BizContext bizCtx, String request) { + return "Hello"; + } + + @Override + public String interest() { + return "java.lang.String"; + } + }); + // 初始Server建连成功,验证创建连接正常 + boltServer.start(); + ThreadTestUtils.sleep(1000); + + RpcClient rpcClient = new RpcClient(); + rpcClient.startup(); + + long start = System.currentTimeMillis(); + Object response = rpcClient.invokeSync("127.0.0.1:8888", "TEST", 3000); + Assert.assertEquals("Hello", response); + long cost = System.currentTimeMillis() - start; + Assert.assertTrue(cost < 1000); + rpcClient.shutdown(); + // 关闭Server + boltServer.stop(); + } + + @Test + public void testCreateConnectionWithTimeout() { + // 启动一个MOCK的Server + BoltServer boltServer = new BoltServer(8888); + boltServer.registerUserProcessor(new SyncUserProcessor() { + @Override + public Object handleRequest(BizContext bizCtx, String request) throws Exception { + return "Hello"; + } + + @Override + public String interest() { + return "java.lang.String"; + } + }); + // 初始Server建连成功,验证创建连接正常 + boltServer.start(); + ThreadTestUtils.sleep(1000); + + RpcClient rpcClient = new RpcClient(); + MockConnectionManager connectionManager = new MockConnectionManager(rpcClient); + connectionManager.setSleepTime(500); + connectionManager.startup(); + rpcClient.setConnectionManager(connectionManager); + rpcClient.startup(); + long start = System.currentTimeMillis(); + try { + Object object = rpcClient.invokeSync("127.0.0.1:8888", "TEST", 499); + System.out.println(object); + } catch (Exception e) { + // ignore + // create connection timeout + e.printStackTrace(); + } + long cost = System.currentTimeMillis() - start; + Assert.assertTrue(cost >= 500 && cost < 800); + + rpcClient.shutdown(); + // 关闭Server + boltServer.stop(); + } + + class MockConnectionManager extends DefaultClientConnectionManager { + + private volatile long sleepTime = 0L; + + public void setSleepTime(long sleepTime) { + this.sleepTime = sleepTime; + } + + public MockConnectionManager(RpcClient rpcClient) { + super(new RandomSelectStrategy(null), new RpcConnectionFactory( + new ConcurrentHashMap>(), rpcClient), + new RpcConnectionEventHandler(), new ConnectionEventListener()); + } + + @Override + public Connection getAndCreateIfAbsent(Url url) throws InterruptedException, + RemotingException { + Connection connection = super.getAndCreateIfAbsent(url); + if (sleepTime > 0L) { + ThreadTestUtils.sleep(sleepTime); + } + return connection; + } + } +} diff --git a/src/test/java/com/alipay/remoting/inner/connection/RpcConnectionManagerTest.java b/src/test/java/com/alipay/remoting/inner/connection/RpcConnectionManagerTest.java index b4012338..e05cdefd 100644 --- a/src/test/java/com/alipay/remoting/inner/connection/RpcConnectionManagerTest.java +++ b/src/test/java/com/alipay/remoting/inner/connection/RpcConnectionManagerTest.java @@ -33,7 +33,6 @@ import com.alipay.remoting.ConnectionEventListener; import com.alipay.remoting.ConnectionEventType; import com.alipay.remoting.ConnectionSelectStrategy; -import com.alipay.remoting.DefaultConnectionManager; import com.alipay.remoting.RandomSelectStrategy; import com.alipay.remoting.RemotingAddressParser; import com.alipay.remoting.Url; diff --git a/src/test/java/com/alipay/remoting/inner/utiltest/ConfigManagerTest.java b/src/test/java/com/alipay/remoting/inner/utiltest/ConfigManagerTest.java index bb475346..f3141c9a 100644 --- a/src/test/java/com/alipay/remoting/inner/utiltest/ConfigManagerTest.java +++ b/src/test/java/com/alipay/remoting/inner/utiltest/ConfigManagerTest.java @@ -72,9 +72,5 @@ public void testSystemSettings() { Assert.assertNotNull(ConfigManager.conn_threshold()); Assert.assertNotNull(ConfigManager.retry_detect_period()); Assert.assertNotNull(ConfigManager.serializer()); - int low_default = Integer.parseInt(Configs.NETTY_BUFFER_LOW_WATERMARK_DEFAULT); - int high_default = Integer.parseInt(Configs.NETTY_BUFFER_HIGH_WATERMARK_DEFAULT); - Assert.assertEquals(low_default, ConfigManager.netty_buffer_low_watermark()); - Assert.assertEquals(high_default, ConfigManager.netty_buffer_high_watermark()); } } diff --git a/src/test/java/com/alipay/remoting/inner/utiltest/ProtocolSwitchTest.java b/src/test/java/com/alipay/remoting/inner/utiltest/ProtocolSwitchTest.java index 9bbb5190..201d1fbd 100644 --- a/src/test/java/com/alipay/remoting/inner/utiltest/ProtocolSwitchTest.java +++ b/src/test/java/com/alipay/remoting/inner/utiltest/ProtocolSwitchTest.java @@ -187,6 +187,15 @@ public void test_byteToBitSet() { for (int i = 0; i <= 6; ++i) { Assert.assertTrue(bs.get(i)); } + + Exception exception = null; + try { + ProtocolSwitch.toBitSet(-1); + } catch (Exception e) { + exception = e; + } + Assert.assertNotNull(exception); + Assert.assertTrue(exception instanceof IllegalArgumentException); } @Test diff --git a/src/test/java/com/alipay/remoting/rpc/BasicSSLUsageTest.java b/src/test/java/com/alipay/remoting/rpc/BasicSSLUsageTest.java index b576c106..dbcf6f57 100644 --- a/src/test/java/com/alipay/remoting/rpc/BasicSSLUsageTest.java +++ b/src/test/java/com/alipay/remoting/rpc/BasicSSLUsageTest.java @@ -16,6 +16,11 @@ */ package com.alipay.remoting.rpc; +import com.alipay.remoting.exception.RemotingException; +import com.alipay.remoting.rpc.common.RequestBody; +import org.junit.Assert; +import org.junit.Test; + import static org.junit.Assert.assertFalse; import java.io.File; @@ -30,6 +35,7 @@ public void init() { // For server System.setProperty(RpcConfigs.SRV_SSL_ENABLE, "true"); + System.setProperty(RpcConfigs.SRV_SSL_NEED_CLIENT_AUTH, "true"); System.setProperty(RpcConfigs.SRV_SSL_KEYSTORE, getResourceFile("bolt.pfx") .getAbsolutePath()); System.setProperty(RpcConfigs.SRV_SSL_KEYSTORE_PASS, PASSWORD); @@ -60,4 +66,28 @@ public void stop() { assertFalse(RpcConfigManager.client_ssl_enable()); } + @Test + public void testSync0() throws InterruptedException { + RequestBody req = new RequestBody(1, "hello world sync"); + for (int i = 0; i < invokeTimes; i++) { + try { + String res = (String) client.invokeSync(addr, req, 3000); + logger.warn("Result received in sync: " + res); + Assert.assertEquals(RequestBody.DEFAULT_SERVER_RETURN_STR, res); + } catch (RemotingException e) { + String errMsg = "RemotingException caught in sync!"; + logger.error(errMsg, e); + Assert.fail(errMsg); + } catch (InterruptedException e) { + String errMsg = "InterruptedException caught in sync!"; + logger.error(errMsg, e); + Assert.fail(errMsg); + } + } + + Assert.assertTrue(serverConnectProcessor.isConnected()); + Assert.assertEquals(1, serverConnectProcessor.getConnectTimes()); + Assert.assertEquals(invokeTimes, serverUserProcessor.getInvokeTimes()); + } + } diff --git a/src/test/java/com/alipay/remoting/rpc/callback/RejectionProcessableInvokeCallbackTest.java b/src/test/java/com/alipay/remoting/rpc/callback/RejectionProcessableInvokeCallbackTest.java index 9c34e35c..6926b2de 100644 --- a/src/test/java/com/alipay/remoting/rpc/callback/RejectionProcessableInvokeCallbackTest.java +++ b/src/test/java/com/alipay/remoting/rpc/callback/RejectionProcessableInvokeCallbackTest.java @@ -41,7 +41,6 @@ public class RejectionProcessableInvokeCallbackTest { private RpcClient client; private int port = PortScan.select(); - private String ip = "127.0.0.1"; private String addr = "127.0.0.1:" + port; private SimpleServerUserProcessor serverUserProcessor = new SimpleServerUserProcessor(); diff --git a/src/test/java/com/alipay/remoting/rpc/client/ClientConnectionTest.java b/src/test/java/com/alipay/remoting/rpc/client/ClientConnectionTest.java index fea4e5f5..3b041e1e 100644 --- a/src/test/java/com/alipay/remoting/rpc/client/ClientConnectionTest.java +++ b/src/test/java/com/alipay/remoting/rpc/client/ClientConnectionTest.java @@ -48,11 +48,8 @@ public class ClientConnectionTest { RpcClient client; int port = PortScan.select(); - String ip = "127.0.0.1"; String addr = "127.0.0.1:" + port; - int invokeTimes = 5; - SimpleServerUserProcessor serverUserProcessor = new SimpleServerUserProcessor(); SimpleClientUserProcessor clientUserProcessor = new SimpleClientUserProcessor(); CONNECTEventProcessor clientConnectProcessor = new CONNECTEventProcessor(); @@ -113,7 +110,7 @@ public void testCheckAndConnection() throws InterruptedException { client.closeConnection(addr); Assert.assertFalse(client.checkConnection(addr)); - Assert.assertTrue(client.checkConnection(addr, true, true)); + Assert.assertTrue(client.checkConnection(addr, true, false)); Thread.sleep(100); try { Connection connection = client.getConnection(addr, 1); @@ -127,9 +124,8 @@ public void testCheckAndConnection() throws InterruptedException { @Test public void testGetAll() throws InterruptedException { - Connection conn = null; try { - conn = client.getConnection(addr, 3000); + client.getConnection(addr, 3000); } catch (RemotingException e) { Assert.fail("should not reach here"); } diff --git a/src/test/java/com/alipay/remoting/rpc/connectionmanage/ConnectionExceptionTest.java b/src/test/java/com/alipay/remoting/rpc/connectionmanage/ConnectionExceptionTest.java index 1dc6d42b..a103ee44 100644 --- a/src/test/java/com/alipay/remoting/rpc/connectionmanage/ConnectionExceptionTest.java +++ b/src/test/java/com/alipay/remoting/rpc/connectionmanage/ConnectionExceptionTest.java @@ -58,7 +58,7 @@ public void onEvent(String remoteAddr, Connection conn) { connection.getChannel().close(); Thread.sleep(100); - Assert.assertTrue("127.0.0.1:1024".equals(closedUrl[0])); + Assert.assertEquals("127.0.0.1:1024", closedUrl[0]); // connection has been created by ReconnectManager Thread.sleep(1000 * 2); diff --git a/src/test/java/com/alipay/remoting/rpc/connectionmanage/ScheduledDisconnectStrategyTest.java b/src/test/java/com/alipay/remoting/rpc/connectionmanage/ScheduledDisconnectStrategyTest.java index 3f7f9635..f6c4c818 100644 --- a/src/test/java/com/alipay/remoting/rpc/connectionmanage/ScheduledDisconnectStrategyTest.java +++ b/src/test/java/com/alipay/remoting/rpc/connectionmanage/ScheduledDisconnectStrategyTest.java @@ -175,7 +175,7 @@ public void testCloseFreshSelectConnections_byUserSetting() throws RemotingExcep connection.addInvokeFuture(new DefaultInvokeFuture(1, null, null, RpcCommandType.REQUEST, null)); Thread.sleep(2100); - Assert.assertTrue(0 == clientDisConnectProcessor.getDisConnectTimes()); + Assert.assertEquals(0, clientDisConnectProcessor.getDisConnectTimes()); Assert.assertEquals(1, clientConnectProcessor.getConnectTimes()); connection.removeInvokeFuture(1); /* Monitor task sleep 500ms*/ diff --git a/src/test/java/com/alipay/remoting/rpc/lock/CreateConnLockTest.java b/src/test/java/com/alipay/remoting/rpc/lock/CreateConnLockTest.java deleted file mode 100644 index 46c5d52f..00000000 --- a/src/test/java/com/alipay/remoting/rpc/lock/CreateConnLockTest.java +++ /dev/null @@ -1,184 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.alipay.remoting.rpc.lock; - -import java.util.concurrent.atomic.AtomicBoolean; - -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.alipay.remoting.ConnectionEventType; -import com.alipay.remoting.InvokeContext; -import com.alipay.remoting.Url; -import com.alipay.remoting.exception.RemotingException; -import com.alipay.remoting.rpc.RpcAddressParser; -import com.alipay.remoting.rpc.RpcClient; -import com.alipay.remoting.rpc.common.BoltServer; -import com.alipay.remoting.rpc.common.CONNECTEventProcessor; -import com.alipay.remoting.rpc.common.ConcurrentServerUserProcessor; -import com.alipay.remoting.rpc.common.DISCONNECTEventProcessor; -import com.alipay.remoting.rpc.common.RequestBody; -import com.alipay.remoting.rpc.common.SimpleClientUserProcessor; - -/**
 - * alipay-com/bolt#110 - * - * @author tsui
 - * @version $Id: CreateConnLockTest.java, v 0.1 2016-09-26 11:49 tsui Exp $ - */ -public class CreateConnLockTest { - - static Logger logger = LoggerFactory - .getLogger(CreateConnLockTest.class); - - BoltServer server; - RpcClient client; - - int port = 12200; //PortScan.select(); - String ip = "127.0.0.1"; - String bad_ip = "127.0.0.2"; - String ip_prefix = "127.0.0."; - String addr = "127.0.0.1:" + port; - - int invokeTimes = 3; - - ConcurrentServerUserProcessor serverUserProcessor = new ConcurrentServerUserProcessor(); - SimpleClientUserProcessor clientUserProcessor = new SimpleClientUserProcessor(); - CONNECTEventProcessor clientConnectProcessor = new CONNECTEventProcessor(); - CONNECTEventProcessor serverConnectProcessor = new CONNECTEventProcessor(); - DISCONNECTEventProcessor clientDisConnectProcessor = new DISCONNECTEventProcessor(); - DISCONNECTEventProcessor serverDisConnectProcessor = new DISCONNECTEventProcessor(); - - private AtomicBoolean whetherConnectTimeoutConsumedTooLong = new AtomicBoolean(); - - @Before - public void init() { - whetherConnectTimeoutConsumedTooLong.set(false); - server = new BoltServer(port, true); - server.start(); - server.addConnectionEventProcessor(ConnectionEventType.CONNECT, serverConnectProcessor); - server.addConnectionEventProcessor(ConnectionEventType.CLOSE, serverDisConnectProcessor); - server.registerUserProcessor(serverUserProcessor); - - client = new RpcClient(); - client.addConnectionEventProcessor(ConnectionEventType.CONNECT, clientConnectProcessor); - client.addConnectionEventProcessor(ConnectionEventType.CLOSE, clientDisConnectProcessor); - client.registerUserProcessor(clientUserProcessor); - client.init(); - } - - @After - public void stop() { - try { - server.stop(); - Thread.sleep(100); - } catch (InterruptedException e) { - logger.error("Stop server failed!", e); - } - } - - @Test - public void testSync_DiffAddressOnePort() throws InterruptedException { - for (int i = 0; i < invokeTimes; ++i) { - Url url = new Url(ip_prefix + i, port);//127.0.0.1:12200, 127.0.0.2:12200, 127.0.0.3:12200... - MyThread thread = new MyThread(url, 1, false); - new Thread(thread).start(); - } - - Thread.sleep(5000); - Assert.assertFalse(whetherConnectTimeoutConsumedTooLong.get()); - } - - @Test - public void testSync_OneAddressDiffPort() throws InterruptedException { - for (int i = 0; i < invokeTimes; ++i) { - Url url = new Url(ip, port++);//127.0.0.1:12200, 127.0.0.2:12201, 127.0.0.3:12202... - MyThread thread = new MyThread(url, 1, false); - new Thread(thread).start(); - } - - Thread.sleep(5000); - Assert.assertFalse(whetherConnectTimeoutConsumedTooLong.get()); - } - - /** - * enable this case only when non-lock feature of ConnectionManager implemented - */ - @Test - public void testSync_OneAddressOnePort() throws InterruptedException { - for (int i = 0; i < invokeTimes; ++i) { - Url url = new Url(bad_ip, port);//127.0.0.2:12200 - MyThread thread = new MyThread(url, 1, false); - new Thread(thread).start(); - } - - Thread.sleep(5000); - Assert.assertFalse(whetherConnectTimeoutConsumedTooLong.get()); - } - - class MyThread implements Runnable { - Url url; - int connNum; - boolean warmup; - RpcAddressParser parser; - - public MyThread(Url url, int connNum, boolean warmup) { - this.url = url; - this.connNum = connNum; - this.warmup = warmup; - this.parser = new RpcAddressParser(); - } - - @Override - public void run() { - InvokeContext ctx = new InvokeContext(); - try { - RequestBody req = new RequestBody(1, "hello world sync"); - url.setConnectTimeout(100);// default to be 1000 - url.setConnNum(connNum); - url.setConnWarmup(warmup); - this.parser.initUrlArgs(url); - client.invokeSync(url, req, ctx, 3000); - long time = getAndPrintCreateConnTime(ctx); - // Assert.assertTrue(time < 1500); - } catch (RemotingException e) { - logger.error("error!", e); - long time = getAndPrintCreateConnTime(ctx); - // Assert.assertTrue(time < 1500); - } catch (Exception e) { - logger.error("error!", e); - long time = getAndPrintCreateConnTime(ctx); - // Assert.assertTrue(time < 1500); - } - } - - private long getAndPrintCreateConnTime(InvokeContext ctx) { - long time = ctx.get(InvokeContext.CLIENT_CONN_CREATETIME) == null ? -1l : (Long) ctx - .get(InvokeContext.CLIENT_CONN_CREATETIME); - if (time > 1500) { - whetherConnectTimeoutConsumedTooLong.set(true); - } - logger.warn("CREATE CONN TIME CONSUMED: " + time); - return time; - } - - } -} \ No newline at end of file diff --git a/src/test/java/com/alipay/remoting/rpc/prehandle/ExtendHandlerTest.java b/src/test/java/com/alipay/remoting/rpc/prehandle/ExtendHandlerTest.java new file mode 100644 index 00000000..1144be05 --- /dev/null +++ b/src/test/java/com/alipay/remoting/rpc/prehandle/ExtendHandlerTest.java @@ -0,0 +1,386 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alipay.remoting.rpc.prehandle; + +import com.alipay.remoting.ConnectionEventType; +import com.alipay.remoting.ExtendedNettyChannelHandler; +import com.alipay.remoting.config.BoltClientOption; +import com.alipay.remoting.exception.RemotingException; +import com.alipay.remoting.rpc.BasicUsageTest; +import com.alipay.remoting.rpc.RpcClient; +import com.alipay.remoting.rpc.common.BoltServer; +import com.alipay.remoting.rpc.common.CONNECTEventProcessor; +import com.alipay.remoting.rpc.common.DISCONNECTEventProcessor; +import com.alipay.remoting.rpc.common.PortScan; +import com.alipay.remoting.rpc.common.RequestBody; +import com.alipay.remoting.rpc.common.SimpleClientUserProcessor; +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInboundHandler; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Collections; +import java.util.List; + +/** + * @author chengyi (mark.lx@antfin.com) 2021-07-19 17:21 + */ +public class ExtendHandlerTest { + static Logger logger = LoggerFactory + .getLogger(BasicUsageTest.class); + + BoltServer server; + RpcClient client; + + int port = PortScan.select(); + String addr = "127.0.0.1:" + port; + + PreHandleUserProcessor serverUserProcessor = new PreHandleUserProcessor(); + SimpleClientUserProcessor clientUserProcessor = new SimpleClientUserProcessor(); + CONNECTEventProcessor clientConnectProcessor = new CONNECTEventProcessor(); + CONNECTEventProcessor serverConnectProcessor = new CONNECTEventProcessor(); + DISCONNECTEventProcessor clientDisConnectProcessor = new DISCONNECTEventProcessor(); + DISCONNECTEventProcessor serverDisConnectProcessor = new DISCONNECTEventProcessor(); + + private final Boolean[] serverPreHandlerResult = new Boolean[1]; + private final Boolean[] serverPostHandlerResult = new Boolean[1]; + private final Boolean[] clientPreHandlerResult = new Boolean[1]; + private final Boolean[] clientPostHandlerResult = new Boolean[1]; + + @Before + public void init() { + server = new BoltServer(port); + server.getRpcServer().option(BoltClientOption.EXTENDED_NETTY_CHANNEL_HANDLER, + new ExtendedNettyChannelHandler() { + @Override + public List frontChannelHandlers() { + ChannelHandler channelHandler = new ChannelInboundHandler() { + @Override + public void channelRegistered(ChannelHandlerContext ctx) throws Exception { + + } + + @Override + public void channelUnregistered(ChannelHandlerContext ctx) throws Exception { + + } + + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { + + } + + @Override + public void channelInactive(ChannelHandlerContext ctx) throws Exception { + + } + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) + throws Exception { + serverPreHandlerResult[0] = true; + ctx.fireChannelRead(msg); + } + + @Override + public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { + + } + + @Override + public void userEventTriggered(ChannelHandlerContext ctx, Object evt) + throws Exception { + + } + + @Override + public void channelWritabilityChanged(ChannelHandlerContext ctx) + throws Exception { + + } + + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) + throws Exception { + + } + + @Override + public void handlerAdded(ChannelHandlerContext ctx) throws Exception { + + } + + @Override + public void handlerRemoved(ChannelHandlerContext ctx) throws Exception { + + } + }; + return Collections.singletonList(channelHandler); + } + + @Override + public List backChannelHandlers() { + ChannelHandler channelHandler = new ChannelInboundHandler() { + + @Override + public void channelRegistered(ChannelHandlerContext ctx) throws Exception { + + } + + @Override + public void channelUnregistered(ChannelHandlerContext ctx) throws Exception { + + } + + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { + + } + + @Override + public void channelInactive(ChannelHandlerContext ctx) throws Exception { + + } + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) + throws Exception { + serverPostHandlerResult[0] = true; + ctx.fireChannelRead(msg); + } + + @Override + public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { + + } + + @Override + public void userEventTriggered(ChannelHandlerContext ctx, Object evt) + throws Exception { + + } + + @Override + public void channelWritabilityChanged(ChannelHandlerContext ctx) + throws Exception { + + } + + @Override + public void handlerAdded(ChannelHandlerContext ctx) throws Exception { + + } + + @Override + public void handlerRemoved(ChannelHandlerContext ctx) throws Exception { + + } + + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) + throws Exception { + + } + }; + return Collections.singletonList(channelHandler); + } + }); + server.start(); + server.addConnectionEventProcessor(ConnectionEventType.CONNECT, serverConnectProcessor); + server.addConnectionEventProcessor(ConnectionEventType.CLOSE, serverDisConnectProcessor); + server.registerUserProcessor(serverUserProcessor); + + client = new RpcClient(); + client.option(BoltClientOption.EXTENDED_NETTY_CHANNEL_HANDLER, + new ExtendedNettyChannelHandler() { + @Override + public List frontChannelHandlers() { + ChannelHandler channelHandler = new ChannelInboundHandler() { + @Override + public void channelRegistered(ChannelHandlerContext ctx) throws Exception { + + } + + @Override + public void channelUnregistered(ChannelHandlerContext ctx) throws Exception { + + } + + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { + + } + + @Override + public void channelInactive(ChannelHandlerContext ctx) throws Exception { + + } + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) + throws Exception { + clientPreHandlerResult[0] = true; + ctx.fireChannelRead(msg); + } + + @Override + public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { + + } + + @Override + public void userEventTriggered(ChannelHandlerContext ctx, Object evt) + throws Exception { + + } + + @Override + public void channelWritabilityChanged(ChannelHandlerContext ctx) + throws Exception { + + } + + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) + throws Exception { + + } + + @Override + public void handlerAdded(ChannelHandlerContext ctx) throws Exception { + + } + + @Override + public void handlerRemoved(ChannelHandlerContext ctx) throws Exception { + + } + }; + return Collections.singletonList(channelHandler); + } + + @Override + public List backChannelHandlers() { + ChannelHandler channelHandler = new ChannelInboundHandler() { + + @Override + public void channelRegistered(ChannelHandlerContext ctx) throws Exception { + + } + + @Override + public void channelUnregistered(ChannelHandlerContext ctx) throws Exception { + + } + + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { + + } + + @Override + public void channelInactive(ChannelHandlerContext ctx) throws Exception { + + } + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) + throws Exception { + clientPostHandlerResult[0] = true; + ctx.fireChannelRead(msg); + } + + @Override + public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { + + } + + @Override + public void userEventTriggered(ChannelHandlerContext ctx, Object evt) + throws Exception { + + } + + @Override + public void channelWritabilityChanged(ChannelHandlerContext ctx) + throws Exception { + + } + + @Override + public void handlerAdded(ChannelHandlerContext ctx) throws Exception { + + } + + @Override + public void handlerRemoved(ChannelHandlerContext ctx) throws Exception { + + } + + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) + throws Exception { + + } + }; + return Collections.singletonList(channelHandler); + } + }); + client.addConnectionEventProcessor(ConnectionEventType.CONNECT, clientConnectProcessor); + client.addConnectionEventProcessor(ConnectionEventType.CLOSE, clientDisConnectProcessor); + client.registerUserProcessor(clientUserProcessor); + client.init(); + } + + @After + public void stop() { + try { + server.stop(); + Thread.sleep(100); + } catch (InterruptedException e) { + logger.error("Stop server failed!", e); + } + } + + @Test + public void testSyncHandle() { + RequestBody b1 = new RequestBody(1, "hello world sync"); + try { + Object ret = client.invokeSync(addr, b1, 3000); + logger.warn("Result received in sync: " + ret); + Assert.assertEquals("test", ret); + } catch (RemotingException e) { + String errMsg = "RemotingException caught in testSyncPreHandle!"; + logger.error(errMsg, e); + Assert.fail(errMsg); + } catch (InterruptedException e) { + String errMsg = "InterruptedException caught in testSyncPreHandle!"; + logger.error(errMsg, e); + Assert.fail(errMsg); + } + + Assert.assertTrue(serverPreHandlerResult[0]); + Assert.assertTrue(serverPostHandlerResult[0]); + Assert.assertTrue(clientPreHandlerResult[0]); + Assert.assertTrue(clientPostHandlerResult[0]); + } +} diff --git a/src/test/java/com/alipay/remoting/rpc/serializer/ClassCustomSerializerTest.java b/src/test/java/com/alipay/remoting/rpc/serializer/ClassCustomSerializerTest.java index c69f8b60..eeab283b 100644 --- a/src/test/java/com/alipay/remoting/rpc/serializer/ClassCustomSerializerTest.java +++ b/src/test/java/com/alipay/remoting/rpc/serializer/ClassCustomSerializerTest.java @@ -59,11 +59,8 @@ public class ClassCustomSerializerTest { RpcClient client; int port = PortScan.select(); - String ip = "127.0.0.1"; String addr = "127.0.0.1:" + port; - int invokeTimes = 5; - SimpleServerUserProcessor serverUserProcessor = new SimpleServerUserProcessor(); SimpleClientUserProcessor clientUserProcessor = new SimpleClientUserProcessor(); CONNECTEventProcessor clientConnectProcessor = new CONNECTEventProcessor(); diff --git a/src/test/java/com/alipay/remoting/util/ThreadLocalArriveTimeHolderTest.java b/src/test/java/com/alipay/remoting/util/ThreadLocalArriveTimeHolderTest.java new file mode 100644 index 00000000..9d218cd6 --- /dev/null +++ b/src/test/java/com/alipay/remoting/util/ThreadLocalArriveTimeHolderTest.java @@ -0,0 +1,78 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alipay.remoting.util; + +import io.netty.channel.embedded.EmbeddedChannel; +import org.junit.Assert; +import org.junit.Test; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +/** + * @author zhaowang + * @version : ThreadLocalArriveTimeHolderTest.java, v 0.1 2021年07月07日 5:45 下午 zhaowang + */ +public class ThreadLocalArriveTimeHolderTest { + @Test + public void test() { + EmbeddedChannel channel = new EmbeddedChannel(); + long start = System.nanoTime(); + ThreadLocalArriveTimeHolder.arrive(channel, 1); + long end = System.nanoTime(); + ThreadLocalArriveTimeHolder.arrive(channel, 1); + long time = ThreadLocalArriveTimeHolder.getAndClear(channel, 1); + Assert.assertTrue(time >= start); + Assert.assertTrue(time <= end); + Assert.assertEquals(-1, ThreadLocalArriveTimeHolder.getAndClear(channel, 1)); + } + + @Test + public void testRemoveNull() { + EmbeddedChannel channel = new EmbeddedChannel(); + Assert.assertEquals(-1, ThreadLocalArriveTimeHolder.getAndClear(channel, 1)); + } + + @Test + public void testMultiThread() throws InterruptedException { + final EmbeddedChannel channel = new EmbeddedChannel(); + final CountDownLatch countDownLatch = new CountDownLatch(1); + long start = System.nanoTime(); + ThreadLocalArriveTimeHolder.arrive(channel, 1); + long end = System.nanoTime(); + ThreadLocalArriveTimeHolder.arrive(channel, 1); + long time = ThreadLocalArriveTimeHolder.getAndClear(channel, 1); + Assert.assertTrue(time >= start); + Assert.assertTrue(time <= end); + Assert.assertEquals(-1, ThreadLocalArriveTimeHolder.getAndClear(channel, 1)); + Runnable runnable = new Runnable() { + @Override + public void run() { + long start = System.nanoTime(); + ThreadLocalArriveTimeHolder.arrive(channel, 1); + long end = System.nanoTime(); + long time = ThreadLocalArriveTimeHolder.getAndClear(channel, 1); + Assert.assertTrue(time >= start); + Assert.assertTrue(time <= end); + Assert.assertEquals(-1, ThreadLocalArriveTimeHolder.getAndClear(channel, 1)); + countDownLatch.countDown(); + } + }; + new Thread(runnable).start(); + Assert.assertTrue(countDownLatch.await(2, TimeUnit.SECONDS)); + } +} diff --git a/src/test/resources/README.md b/src/test/resources/README.md index ba74a561..dd5352b7 100644 --- a/src/test/resources/README.md +++ b/src/test/resources/README.md @@ -13,16 +13,20 @@ keytool -genkey -alias securebolt -keysize 2048 -validity 365 -keyalg RSA -dnam keytool -export -alias securebolt -keystore bolt.pfx -storepass sfbolt -file bolt.cer ``` -Then generate client keystore: +Then, generate client keystore and export it's certificate file: ```sh keytool -genkey -alias smcc -keysize 2048 -validity 365 -keyalg RSA -dname "CN=localhost" -keypass sfbolt -storepass sfbolt -keystore cbolt.pfx -deststoretype pkcs12 + +keytool -export -alias smcc -keystore cbolt.pfx -storepass sfbolt -file cbolt.cer ``` -Finally, import server's certificate into client's keystore: +Finally, import server's certificate into client's keystore, and import the client's certificate into the server's keystore: ```sh keytool -import -trustcacerts -alias securebolt -file bolt.cer -storepass sfbolt -keystore cbolt.pfx + +keytool -import -trustcacerts -alias smcc -file cbolt.cer -storepass sfbolt -keystore bolt.pfx ``` diff --git a/src/test/resources/bolt.cer b/src/test/resources/bolt.cer index 075b3ac1..8043c2aa 100644 Binary files a/src/test/resources/bolt.cer and b/src/test/resources/bolt.cer differ diff --git a/src/test/resources/bolt.pfx b/src/test/resources/bolt.pfx index 491865cc..1d42814a 100644 Binary files a/src/test/resources/bolt.pfx and b/src/test/resources/bolt.pfx differ diff --git a/src/test/resources/cbolt.cer b/src/test/resources/cbolt.cer new file mode 100644 index 00000000..b37f40cd Binary files /dev/null and b/src/test/resources/cbolt.cer differ diff --git a/src/test/resources/cbolt.pfx b/src/test/resources/cbolt.pfx index b4cf4edd..f76e6898 100644 Binary files a/src/test/resources/cbolt.pfx and b/src/test/resources/cbolt.pfx differ