MXS-2122: Close listener socket on destruction
Even though directly closing the socket is not very neat in the architectural sense of things, it allows the best of both worlds: the socket is instantly closed and is open for reuse while the listener struct is still available as a reference. This change needs to be revised when the listeners are refactored into separate objects. Updated documentation to reflect the change in behavior.
This commit is contained in:
@ -323,9 +323,6 @@ all the listeners pointing to the service have been destroyed. This means that
|
|||||||
the `data.relationships` must be an empty object and `data.attributes.listeners`
|
the `data.relationships` must be an empty object and `data.attributes.listeners`
|
||||||
must be an empty array in order for the service to qualify for destruction.
|
must be an empty array in order for the service to qualify for destruction.
|
||||||
|
|
||||||
Once a service is destroyed, any listeners associated with it will be freed
|
|
||||||
after which the ports can be reused by other listeners.
|
|
||||||
|
|
||||||
If there are open client connections that use the service when it is destroyed,
|
If there are open client connections that use the service when it is destroyed,
|
||||||
they are allowed to gracefully close before the service is destroyed. This means
|
they are allowed to gracefully close before the service is destroyed. This means
|
||||||
that the destruction of a service can be acknowledged via the REST API before
|
that the destruction of a service can be acknowledged via the REST API before
|
||||||
@ -466,6 +463,9 @@ DELETE /v1/services/:service/listeners/:name
|
|||||||
In the URI , the _:name_ must map to a listener and the _:service_ must map to a
|
In the URI , the _:name_ must map to a listener and the _:service_ must map to a
|
||||||
service. Both names must have all whitespace replaced with hyphens.
|
service. Both names must have all whitespace replaced with hyphens.
|
||||||
|
|
||||||
|
When a listener is destroyed, the network port it listens on is available for
|
||||||
|
reuse.
|
||||||
|
|
||||||
#### Response
|
#### Response
|
||||||
|
|
||||||
Listener is destroyed:
|
Listener is destroyed:
|
||||||
|
|||||||
@ -1547,8 +1547,8 @@ Example: create listener my-service my-new-listener 192.168.0.101 4006
|
|||||||
|
|
||||||
You can destroy created listeners with the `destroy listener` command. This will
|
You can destroy created listeners with the `destroy listener` command. This will
|
||||||
remove the persisted configuration and it will not be created on the next
|
remove the persisted configuration and it will not be created on the next
|
||||||
startup. The listener is stopped but it will remain a part of the runtime
|
startup. The listener is destroyed and the listening port is immediately
|
||||||
configuration until the next restart.
|
available for reuse.
|
||||||
|
|
||||||
```
|
```
|
||||||
destroy listener - Destroy a listener
|
destroy listener - Destroy a listener
|
||||||
@ -1558,7 +1558,7 @@ Usage: destroy listener SERVICE NAME
|
|||||||
Parameters:
|
Parameters:
|
||||||
NAME Listener to destroy
|
NAME Listener to destroy
|
||||||
|
|
||||||
The listener is stopped and it will be removed on the next restart of MaxScale
|
The listener is deleted
|
||||||
|
|
||||||
Example: destroy listener my-listener
|
Example: destroy listener my-listener
|
||||||
```
|
```
|
||||||
@ -1615,9 +1615,7 @@ Example: alter monitor my-monitor user=maxuser password=maxpwd
|
|||||||
### Destroying Monitors
|
### Destroying Monitors
|
||||||
|
|
||||||
To destroy a monitor, use the `destroy monitor` command. All servers need to be
|
To destroy a monitor, use the `destroy monitor` command. All servers need to be
|
||||||
removed from the monitor before it can be destroyed. Only created monitors
|
removed from the monitor before it can be destroyed.
|
||||||
should be destroyed and they will remain a part of the runtime configuration
|
|
||||||
until the next restart.
|
|
||||||
|
|
||||||
```
|
```
|
||||||
destroy monitor - Destroy a monitor
|
destroy monitor - Destroy a monitor
|
||||||
@ -1627,7 +1625,7 @@ Usage: destroy monitor NAME
|
|||||||
Parameters:
|
Parameters:
|
||||||
NAME Monitor to destroy
|
NAME Monitor to destroy
|
||||||
|
|
||||||
The monitor is stopped and it will be removed on the next restart of MaxScale
|
The monitor is destroyed
|
||||||
|
|
||||||
Example: destroy monitor my-monitor
|
Example: destroy monitor my-monitor
|
||||||
```
|
```
|
||||||
|
|||||||
@ -523,10 +523,7 @@ The monitor must be unlinked from all servers before it can be destroyed.
|
|||||||
|
|
||||||
`Usage: destroy listener <service> <name>`
|
`Usage: destroy listener <service> <name>`
|
||||||
|
|
||||||
Destroying a monitor causes it to be removed on the next restart. Destroying a
|
Destroying a listener closes the listening socket, opening it up for reuse.
|
||||||
listener at runtime stops it from accepting new connections but it will still be
|
|
||||||
bound to the listening socket. This means that new listeners cannot be created
|
|
||||||
to replace destroyed listeners without restarting MaxScale.
|
|
||||||
|
|
||||||
### destroy service
|
### destroy service
|
||||||
|
|
||||||
|
|||||||
@ -34,11 +34,7 @@ exports.builder = function(yargs) {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
.command('listener <service> <name>', 'Destroy an unused listener', function(yargs) {
|
.command('listener <service> <name>', 'Destroy an unused listener', function(yargs) {
|
||||||
return yargs.epilog('Destroying a monitor causes it to be removed on the next restart. ' +
|
return yargs.epilog('Destroying a listener closes the listening socket, opening it up for reuse.')
|
||||||
'Destroying a listener at runtime stops it from accepting new ' +
|
|
||||||
'connections but it will still be bound to the listening socket. This ' +
|
|
||||||
'means that new listeners cannot be created to replace destroyed listeners ' +
|
|
||||||
'without restarting MaxScale.')
|
|
||||||
.usage('Usage: destroy listener <service> <name>')
|
.usage('Usage: destroy listener <service> <name>')
|
||||||
}, function(argv) {
|
}, function(argv) {
|
||||||
maxctrl(argv, function(host) {
|
maxctrl(argv, function(host) {
|
||||||
|
|||||||
@ -1274,6 +1274,11 @@ void dcb_final_close(DCB* dcb)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Only listeners are closed with a fd of -1
|
||||||
|
mxb_assert(dcb->dcb_role == DCB_ROLE_SERVICE_LISTENER);
|
||||||
|
}
|
||||||
|
|
||||||
dcb->state = DCB_STATE_DISCONNECTED;
|
dcb->state = DCB_STATE_DISCONNECTED;
|
||||||
dcb_remove_from_list(dcb);
|
dcb_remove_from_list(dcb);
|
||||||
|
|||||||
@ -751,6 +751,11 @@ bool service_remove_listener(Service* service, const char* target)
|
|||||||
{
|
{
|
||||||
listener->listener->session->state = SESSION_STATE_LISTENER_STOPPED;
|
listener->listener->session->state = SESSION_STATE_LISTENER_STOPPED;
|
||||||
rval = true;
|
rval = true;
|
||||||
|
|
||||||
|
// TODO: This is not pretty but it works, revise when listeners are refactored. This is
|
||||||
|
// thread-safe as the listener is freed on the same thread that closes the socket.
|
||||||
|
close(listener->listener->fd);
|
||||||
|
listener->listener->fd = -1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user