@@ -1020,35 +1020,8 @@ func (ac *addrConn) resetTransport() {
1020
1020
reconnect := grpcsync .NewEvent ()
1021
1021
prefaceReceived := make (chan struct {})
1022
1022
newTr , err := ac .createTransport (addr , copts , connectDeadline , reconnect , prefaceReceived )
1023
- if err == nil {
1024
- ac .mu .Lock ()
1025
- ac .curAddr = addr
1026
- ac .transport = newTr
1027
- ac .mu .Unlock ()
1028
-
1029
- healthCheckConfig := ac .cc .healthCheckConfig ()
1030
- // LB channel health checking is only enabled when all the four requirements below are met:
1031
- // 1. it is not disabled by the user with the WithDisableHealthCheck DialOption,
1032
- // 2. the internal.HealthCheckFunc is set by importing the grpc/healthcheck package,
1033
- // 3. a service config with non-empty healthCheckConfig field is provided,
1034
- // 4. the current load balancer allows it.
1035
- healthcheckManagingState := false
1036
- if ! ac .cc .dopts .disableHealthCheck && healthCheckConfig != nil && ac .scopts .HealthCheckEnabled {
1037
- if ac .cc .dopts .healthCheckFunc == nil {
1038
- // TODO: add a link to the health check doc in the error message.
1039
- grpclog .Error ("the client side LB channel health check function has not been set." )
1040
- } else {
1041
- // TODO(deklerk) refactor to just return transport
1042
- go ac .startHealthCheck (hctx , newTr , addr , healthCheckConfig .ServiceName )
1043
- healthcheckManagingState = true
1044
- }
1045
- }
1046
- if ! healthcheckManagingState {
1047
- ac .mu .Lock ()
1048
- ac .updateConnectivityState (connectivity .Ready )
1049
- ac .mu .Unlock ()
1050
- }
1051
- } else {
1023
+ if err != nil {
1024
+ ac .cc .blockingpicker .updateConnectionError (err )
1052
1025
hcancel ()
1053
1026
if err == errConnClosing {
1054
1027
return
@@ -1061,55 +1034,46 @@ func (ac *addrConn) resetTransport() {
1061
1034
}
1062
1035
1063
1036
ac .mu .Lock ()
1064
- reqHandshake := ac .dopts .reqHandshake
1037
+ ac .curAddr = addr
1038
+ ac .transport = newTr
1065
1039
ac .mu .Unlock ()
1066
1040
1067
- <- reconnect .Done ()
1068
- hcancel ()
1069
-
1070
- if reqHandshake == envconfig .RequireHandshakeHybrid {
1071
- // In RequireHandshakeHybrid mode, we must check to see whether
1072
- // server preface has arrived yet to decide whether to start
1073
- // reconnecting at the top of the list (server preface received)
1074
- // or continue with the next addr in the list as if the
1075
- // connection were not successful (server preface not received).
1076
- select {
1077
- case <- prefaceReceived :
1078
- // We received a server preface - huzzah! We consider this
1079
- // a success and restart from the top of the addr list.
1080
- ac .mu .Lock ()
1081
- ac .backoffIdx = 0
1082
- ac .mu .Unlock ()
1083
- break addrLoop
1084
- default :
1085
- // Despite having set state to READY, in hybrid mode we
1086
- // consider this a failure and continue connecting at the
1087
- // next addr in the list.
1088
- ac .mu .Lock ()
1089
- if ac .state == connectivity .Shutdown {
1090
- ac .mu .Unlock ()
1091
- return
1092
- }
1093
-
1094
- ac .updateConnectivityState (connectivity .TransientFailure )
1095
- ac .mu .Unlock ()
1096
-
1097
- if tryNextAddrFromStart .HasFired () {
1098
- break addrLoop
1099
- }
1041
+ healthCheckConfig := ac .cc .healthCheckConfig ()
1042
+ // LB channel health checking is only enabled when all the four requirements below are met:
1043
+ // 1. it is not disabled by the user with the WithDisableHealthCheck DialOption,
1044
+ // 2. the internal.HealthCheckFunc is set by importing the grpc/healthcheck package,
1045
+ // 3. a service config with non-empty healthCheckConfig field is provided,
1046
+ // 4. the current load balancer allows it.
1047
+ healthcheckManagingState := false
1048
+ if ! ac .cc .dopts .disableHealthCheck && healthCheckConfig != nil && ac .scopts .HealthCheckEnabled {
1049
+ if ac .cc .dopts .healthCheckFunc == nil {
1050
+ // TODO: add a link to the health check doc in the error message.
1051
+ grpclog .Error ("the client side LB channel health check function has not been set." )
1052
+ } else {
1053
+ // TODO(deklerk) refactor to just return transport
1054
+ go ac .startHealthCheck (hctx , newTr , addr , healthCheckConfig .ServiceName )
1055
+ healthcheckManagingState = true
1100
1056
}
1101
- } else {
1102
- // In RequireHandshakeOn mode, we would have already waited for
1103
- // the server preface, so we consider this a success and restart
1104
- // from the top of the addr list. In RequireHandshakeOff mode,
1105
- // we don't care to wait for the server preface before
1106
- // considering this a success, so we also restart from the top
1107
- // of the addr list.
1057
+ }
1058
+ if ! healthcheckManagingState {
1108
1059
ac .mu .Lock ()
1109
- ac .backoffIdx = 0
1060
+ ac .updateConnectivityState ( connectivity . Ready )
1110
1061
ac .mu .Unlock ()
1111
- break addrLoop
1112
1062
}
1063
+
1064
+ <- reconnect .Done ()
1065
+ hcancel ()
1066
+
1067
+ // In RequireHandshakeOn mode, we would have already waited for
1068
+ // the server preface, so we consider this a success and restart
1069
+ // from the top of the addr list. In RequireHandshakeOff mode,
1070
+ // we don't care to wait for the server preface before
1071
+ // considering this a success, so we also restart from the top
1072
+ // of the addr list.
1073
+ ac .mu .Lock ()
1074
+ ac .backoffIdx = 0
1075
+ ac .mu .Unlock ()
1076
+ break addrLoop
1113
1077
}
1114
1078
1115
1079
// After exhausting all addresses, or after need to reconnect after a
@@ -1155,8 +1119,6 @@ func (ac *addrConn) createTransport(addr resolver.Address, copts transport.Conne
1155
1119
Authority : ac .cc .authority ,
1156
1120
}
1157
1121
1158
- prefaceTimer := time .NewTimer (time .Until (connectDeadline ))
1159
-
1160
1122
onGoAway := func (r transport.GoAwayReason ) {
1161
1123
ac .mu .Lock ()
1162
1124
ac .adjustParams (r )
@@ -1166,13 +1128,11 @@ func (ac *addrConn) createTransport(addr resolver.Address, copts transport.Conne
1166
1128
1167
1129
onClose := func () {
1168
1130
close (onCloseCalled )
1169
- prefaceTimer .Stop ()
1170
1131
reconnect .Fire ()
1171
1132
}
1172
1133
1173
1134
onPrefaceReceipt := func () {
1174
1135
close (prefaceReceived )
1175
- prefaceTimer .Stop ()
1176
1136
}
1177
1137
1178
1138
connectCtx , cancel := context .WithDeadline (ac .ctx , connectDeadline )
@@ -1182,38 +1142,8 @@ func (ac *addrConn) createTransport(addr resolver.Address, copts transport.Conne
1182
1142
}
1183
1143
1184
1144
newTr , err := transport .NewClientTransport (connectCtx , ac .cc .ctx , target , copts , onPrefaceReceipt , onGoAway , onClose )
1185
-
1186
- if err == nil {
1187
- if ac .dopts .reqHandshake == envconfig .RequireHandshakeOn {
1188
- select {
1189
- case <- prefaceTimer .C :
1190
- // We didn't get the preface in time.
1191
- newTr .Close ()
1192
- err = errors .New ("timed out waiting for server handshake" )
1193
- case <- prefaceReceived :
1194
- // We got the preface - huzzah! things are good.
1195
- case <- onCloseCalled :
1196
- // The transport has already closed - noop.
1197
- return nil , errors .New ("connection closed" )
1198
- }
1199
- } else if ac .dopts .reqHandshake == envconfig .RequireHandshakeHybrid {
1200
- go func () {
1201
- select {
1202
- case <- prefaceTimer .C :
1203
- // We didn't get the preface in time.
1204
- newTr .Close ()
1205
- case <- prefaceReceived :
1206
- // We got the preface just in the nick of time - huzzah!
1207
- case <- onCloseCalled :
1208
- // The transport has already closed - noop.
1209
- }
1210
- }()
1211
- }
1212
- }
1213
-
1214
1145
if err != nil {
1215
1146
// newTr is either nil, or closed.
1216
- ac .cc .blockingpicker .updateConnectionError (err )
1217
1147
ac .mu .Lock ()
1218
1148
if ac .state == connectivity .Shutdown {
1219
1149
// ac.tearDown(...) has been invoked.
@@ -1226,6 +1156,22 @@ func (ac *addrConn) createTransport(addr resolver.Address, copts transport.Conne
1226
1156
return nil , err
1227
1157
}
1228
1158
1159
+ if ac .dopts .reqHandshake == envconfig .RequireHandshakeOn {
1160
+ select {
1161
+ case <- time .After (connectDeadline .Sub (time .Now ())):
1162
+ // We didn't get the preface in time.
1163
+ newTr .Close ()
1164
+ grpclog .Warningf ("grpc: addrConn.createTransport failed to connect to %v: didn't receive server preface in time. Reconnecting..." , addr )
1165
+ return nil , errors .New ("timed out waiting for server handshake" )
1166
+ case <- prefaceReceived :
1167
+ // We got the preface - huzzah! things are good.
1168
+ case <- onCloseCalled :
1169
+ // The transport has already closed - noop.
1170
+ return nil , errors .New ("connection closed" )
1171
+ // TODO(deklerk) this should bail on ac.ctx.Done(). Add a test and fix.
1172
+ }
1173
+ }
1174
+
1229
1175
// Now there is a viable transport to be use, so set ac.transport to reflect the new viable transport.
1230
1176
ac .mu .Lock ()
1231
1177
if ac .state == connectivity .Shutdown {
0 commit comments