Completely disable rpc workers when rpc_workers=0

Currently at least 1 rpc worker is launched even when a user requests
zero workers by setting rpc_workers=0. The setting of rpc_workers=0 is
used when ml2-ovn plugin is used without any additional agent, and in
this deployment pattern the single rpc worker is not at all used.

This change ensures no rpc worker is launched when rpc_workers options
is explicitly set to 0. This may be classified as a breaking change,
but is consistent with the earlier change[1] for rpc_workers=0.

[1] 3e1e2d63b3

Closes-Bug: #2052484
Change-Id: I878e50c3192ecd3b145ded0ab8394845a089696e
This commit is contained in:
Takashi Kajinami 2024-02-07 01:46:47 +09:00
parent 33b5af695b
commit b38f72b212
5 changed files with 45 additions and 9 deletions

View File

@ -150,3 +150,13 @@ events from the various neutron agents. Signs that there are too few
can be agent heartbeats arriving late, nova vif bindings timing out can be agent heartbeats arriving late, nova vif bindings timing out
on the hypervisors, or rpc message timeout exceptions in agent logs on the hypervisors, or rpc message timeout exceptions in agent logs
(for example, "broken pipe" errors). (for example, "broken pipe" errors).
There is also the rpc_state_report_workers option, which determines
the number fo RPC worker processes dedicated to process state reports
from the various agents. This may be increased to resolve frequent delay
in processing agents heartbeats.
.. note::
If OVN ML2 plugin is used without any additional agents, neutron requires
no worker for RPC message processing. Set both rpc_workers and
rpc_state_report_workers to 0, to disable RPC workers.

View File

@ -31,7 +31,8 @@ SERVICE_OPTS = [
cfg.IntOpt('rpc_workers', cfg.IntOpt('rpc_workers',
help=_('Number of RPC worker processes for service. ' help=_('Number of RPC worker processes for service. '
'If not specified, the default is equal to half the ' 'If not specified, the default is equal to half the '
'number of API workers.')), 'number of API workers. If set to 0, no RPC worker '
'is launched.')),
cfg.IntOpt('rpc_state_report_workers', cfg.IntOpt('rpc_state_report_workers',
default=1, default=1,
help=_('Number of RPC worker processes dedicated to the state ' help=_('Number of RPC worker processes dedicated to the state '

View File

@ -175,7 +175,7 @@ def _get_rpc_workers(plugin=None):
if workers is None: if workers is None:
# By default, half as many rpc workers as api workers # By default, half as many rpc workers as api workers
workers = int(_get_api_workers() / 2) workers = int(_get_api_workers() / 2)
workers = max(workers, 1) workers = max(workers, 1)
# If workers > 0 then start_rpc_listeners would be called in a # If workers > 0 then start_rpc_listeners would be called in a
# subprocess and we cannot simply catch the NotImplementedError. It is # subprocess and we cannot simply catch the NotImplementedError. It is
@ -189,9 +189,15 @@ def _get_rpc_workers(plugin=None):
workers) workers)
raise NotImplementedError() raise NotImplementedError()
# passing service plugins only, because core plugin is among them rpc_workers = []
rpc_workers = [RpcWorker(service_plugins,
worker_process_count=workers)] if workers > 0:
# passing service plugins only, because core plugin is among them
rpc_workers.append(
RpcWorker(service_plugins, worker_process_count=workers))
else:
LOG.warning('No rpc workers are launched. Make sure no agent is used '
'in this deployment.')
if (cfg.CONF.rpc_state_report_workers > 0 and if (cfg.CONF.rpc_state_report_workers > 0 and
plugin.rpc_state_report_workers_supported()): plugin.rpc_state_report_workers_supported()):

View File

@ -54,12 +54,15 @@ class TestRunRpcWorkers(base.BaseTestCase):
with mock.patch('neutron.service.RpcReportsWorker'): with mock.patch('neutron.service.RpcReportsWorker'):
service._get_rpc_workers(plugin=mock.Mock()) service._get_rpc_workers(plugin=mock.Mock())
init_call = mock_rpc_worker.call_args init_call = mock_rpc_worker.call_args
expected_call = mock.call( if expected_passed_value > 0:
mock.ANY, worker_process_count=expected_passed_value) expected_call = mock.call(
self.assertEqual(expected_call, init_call) mock.ANY, worker_process_count=expected_passed_value)
self.assertEqual(expected_call, init_call)
else:
mock_rpc_worker.assert_not_called()
def test_rpc_workers_zero(self): def test_rpc_workers_zero(self):
self._test_rpc_workers(0, 1) self._test_rpc_workers(0, 0)
def test_rpc_workers_default_api_workers_default(self): def test_rpc_workers_default_api_workers_default(self):
workers = max(int(self.worker_count / 2), 1) workers = max(int(self.worker_count / 2), 1)

View File

@ -0,0 +1,16 @@
---
upgrade:
- |
Now setting ``[DEFAULT] rpc_workers = 0`` completely disables rpc workers.
In a deployment with additional agents, like the dhcp-agent, this option
should be set to a positive value. Note that all notifications from
neutron-server to agents were disabled when ``[DEFAULT] rpc_workers = 0``
is set in 22.0.0 release, so this was the requiremenet actually added in
that release.
fixes:
- |
[`bug 2052484 <https://bugs.launchpad.net/neutron/+bug/2002484>`_]
Now setting ``[DEFAULT] rpc_workers = 0`` completely disables rpc workers.
Previously one rpc worker was launched even though ``0`` is specifically
requested.