diff --git a/jobs/cc_deployment_updater/templates/bin/cc_deployment_updater.erb b/jobs/cc_deployment_updater/templates/bin/cc_deployment_updater.erb index 9f8ec58615..ea1a6a475c 100644 --- a/jobs/cc_deployment_updater/templates/bin/cc_deployment_updater.erb +++ b/jobs/cc_deployment_updater/templates/bin/cc_deployment_updater.erb @@ -7,6 +7,8 @@ cd /var/vcap/packages/cloud_controller_ng/cloud_controller_ng export RUBYOPT='--yjit' <% end %> -export LD_PRELOAD=/var/vcap/packages/jemalloc/lib/libjemalloc.so +<% if link("cloud_controller_internal").p('cc.experimental.use_jemalloc_memory_allocator') %> + export LD_PRELOAD=/var/vcap/packages/jemalloc/lib/libjemalloc.so +<% end %> exec bundle exec rake deployment_updater:start diff --git a/jobs/cloud_controller_clock/templates/bin/cloud_controller_clock.erb b/jobs/cloud_controller_clock/templates/bin/cloud_controller_clock.erb index 05c7daa5b5..12ffb37234 100644 --- a/jobs/cloud_controller_clock/templates/bin/cloud_controller_clock.erb +++ b/jobs/cloud_controller_clock/templates/bin/cloud_controller_clock.erb @@ -7,6 +7,8 @@ cd /var/vcap/packages/cloud_controller_ng/cloud_controller_ng export RUBYOPT='--yjit' <% end %> +<% if link("cloud_controller_internal").p('cc.experimental.use_jemalloc_memory_allocator') %> export LD_PRELOAD=/var/vcap/packages/jemalloc/lib/libjemalloc.so +<% end %> exec bundle exec rake clock:start diff --git a/jobs/cloud_controller_ng/spec b/jobs/cloud_controller_ng/spec index 307ff1b302..c817d72faf 100644 --- a/jobs/cloud_controller_ng/spec +++ b/jobs/cloud_controller_ng/spec @@ -163,6 +163,7 @@ provides: - cc.external_port - cc.external_protocol - cc.experimental.use_yjit_compiler + - cc.experimental.use_jemalloc_memory_allocator - cc.internal_service_hostname - cc.jobs.enable_dynamic_job_priorities - cc.log_db_queries @@ -223,11 +224,11 @@ provides: - ssl.skip_cert_verify - system_domain - uaa.clients.cc_routing.secret + - cc.experimental.use_puma_webserver - cc.experimental.use_redis - cc.app_log_revision - cc.app_instance_stopping_state - cc.deprecated_stacks - - cc.temporary_enable_deprecated_thin_webserver consumes: - name: database @@ -1252,21 +1253,28 @@ properties: description: "Use Ruby's YJIT compiler when running Cloud Controller API servers and workers. This feature is experimental and not recommended. Please review the drawbacks and benefits of YJIT before enabling." default: false + cc.experimental.use_jemalloc_memory_allocator: + description: "Enables jemalloc rather than malloc for Cloud Controller API servers and workers; however, it's experimental and not typically recommended, so review its pros and cons before use." + default: false + + cc.experimental.use_puma_webserver: + description: "Use Puma in place of Thin as the webserver. This may increase performance as Puma forks Cloud Controller processes to avoid relying on threads" + default: false + cc.experimental.use_redis: description: "Use co-deployed Valkey (Redis fork) for rate limiting and metrics. If the Puma webserver is enabled, Valkey will automatically be used." default: false cc.puma.workers: description: "Number of workers for Puma webserver." - default: 2 + default: 3 cc.puma.max_threads: description: "Maximum number of threads per Puma webserver worker." - default: 10 + default: 2 cc.puma.max_db_connections_per_process: - description: "Maximum database connections for Puma per process (main + Puma workers)." - default: 10 + description: "Maximum database connections for Puma per process (main + Puma workers), if not set the ccng value is used (default)" cc.update_metric_tags_on_rename: description: "Enable sending a Desired LRP update when an app is renamed" @@ -1275,7 +1283,3 @@ properties: cc.legacy_md5_buildpack_paths_enabled: description: "Enable legacy MD5 buildpack paths. If disabled, xxhash64 is used for calculating paths in buildpack image layers." default: false - - cc.temporary_enable_deprecated_thin_webserver: - description: "Use deprecated Thin webserver. Please note that when using Thin instead of Puma you miss out on the following benefits: Better resource utilization, well maintained and more performant. Thin will be removed in a future release." - default: false diff --git a/jobs/cloud_controller_ng/templates/bin/cloud_controller_ng.erb b/jobs/cloud_controller_ng/templates/bin/cloud_controller_ng.erb index eccf57c9b6..c207804091 100644 --- a/jobs/cloud_controller_ng/templates/bin/cloud_controller_ng.erb +++ b/jobs/cloud_controller_ng/templates/bin/cloud_controller_ng.erb @@ -18,7 +18,9 @@ echo 'Finished migrations and seeds' export RUBYOPT='--yjit' <% end %> +<% if p('cc.experimental.use_jemalloc_memory_allocator') %> export LD_PRELOAD=/var/vcap/packages/jemalloc/lib/libjemalloc.so +<% end %> exec /var/vcap/packages/cloud_controller_ng/cloud_controller_ng/bin/cloud_controller \ -c /var/vcap/jobs/cloud_controller_ng/config/cloud_controller_ng.yml diff --git a/jobs/cloud_controller_ng/templates/bin/local_worker.erb b/jobs/cloud_controller_ng/templates/bin/local_worker.erb index f7ba28477c..54a34ce580 100644 --- a/jobs/cloud_controller_ng/templates/bin/local_worker.erb +++ b/jobs/cloud_controller_ng/templates/bin/local_worker.erb @@ -9,7 +9,9 @@ wait_for_blobstore export RUBYOPT='--yjit' <% end %> +<% if p('cc.experimental.use_jemalloc_memory_allocator') %> export LD_PRELOAD=/var/vcap/packages/jemalloc/lib/libjemalloc.so +<% end %> cd /var/vcap/packages/cloud_controller_ng/cloud_controller_ng exec bundle exec rake "jobs:local[cc_api_worker.<%= spec.job.name %>.<%= spec.index %>.${INDEX}]" diff --git a/jobs/cloud_controller_ng/templates/bpm.yml.erb b/jobs/cloud_controller_ng/templates/bpm.yml.erb index 1cc185da1a..8f93ef2928 100644 --- a/jobs/cloud_controller_ng/templates/bpm.yml.erb +++ b/jobs/cloud_controller_ng/templates/bpm.yml.erb @@ -13,7 +13,7 @@ def mount_nfs_volume!(config) end def mount_valkey_volume!(config) - unless p("cc.temporary_enable_deprecated_thin_webserver") && !p("cc.experimental.use_redis") + if p("cc.experimental.use_puma_webserver") || p("cc.experimental.use_redis") config['additional_volumes'] = [] unless config.key?('additional_volumes') config['additional_volumes'] << { "path" => "/var/vcap/data/valkey", diff --git a/jobs/cloud_controller_ng/templates/cloud_controller_ng.yml.erb b/jobs/cloud_controller_ng/templates/cloud_controller_ng.yml.erb index 62fd5235fb..a94dd1ef2a 100644 --- a/jobs/cloud_controller_ng/templates/cloud_controller_ng.yml.erb +++ b/jobs/cloud_controller_ng/templates/cloud_controller_ng.yml.erb @@ -53,7 +53,7 @@ local_route: <%= p('cc.nginx.ip') %> external_port: <%= p("cc.external_port") %> tls_port: <%= p("cc.tls_port") %> internal_service_hostname: <%= p("cc.internal_service_hostname") %> -webserver: <%= p("cc.temporary_enable_deprecated_thin_webserver") ? 'thin' : 'puma' %> +webserver: <%= p("cc.experimental.use_puma_webserver") ? 'puma' : 'thin' %> puma: workers: <%= p("cc.puma.workers") %> max_threads: <%= p("cc.puma.max_threads") %> @@ -490,7 +490,7 @@ rate_limiter_v2_api: temporary_enable_v2: <%= p("cc.temporary_enable_v2") %> -<% unless p("cc.temporary_enable_deprecated_thin_webserver") && !p("cc.experimental.use_redis") %> +<% if p("cc.experimental.use_puma_webserver") || p("cc.experimental.use_redis") %> redis: socket: "/var/vcap/data/valkey/valkey.sock" <% end %> diff --git a/jobs/cloud_controller_worker/templates/bin/cloud_controller_worker.erb b/jobs/cloud_controller_worker/templates/bin/cloud_controller_worker.erb index 03ae14eff2..f220aab114 100644 --- a/jobs/cloud_controller_worker/templates/bin/cloud_controller_worker.erb +++ b/jobs/cloud_controller_worker/templates/bin/cloud_controller_worker.erb @@ -9,7 +9,9 @@ wait_for_blobstore export RUBYOPT='--yjit' <% end %> +<% if link("cloud_controller_internal").p('cc.experimental.use_jemalloc_memory_allocator') %> export LD_PRELOAD=/var/vcap/packages/jemalloc/lib/libjemalloc.so +<% end %> cd /var/vcap/packages/cloud_controller_ng/cloud_controller_ng diff --git a/jobs/rotate_cc_database_key/templates/bin/run.erb b/jobs/rotate_cc_database_key/templates/bin/run.erb index 3d4fd03ae9..deef575606 100644 --- a/jobs/rotate_cc_database_key/templates/bin/run.erb +++ b/jobs/rotate_cc_database_key/templates/bin/run.erb @@ -2,7 +2,9 @@ set -eu -export LD_PRELOAD=/var/vcap/packages/jemalloc/lib/libjemalloc.so +<% if link("cloud_controller_internal").p('cc.experimental.use_jemalloc_memory_allocator') %> + export LD_PRELOAD=/var/vcap/packages/jemalloc/lib/libjemalloc.so +<% end %> rotate() { export CLOUD_CONTROLLER_NG_CONFIG=/var/vcap/jobs/rotate_cc_database_key/config/cloud_controller_ng.yml diff --git a/jobs/valkey/monit b/jobs/valkey/monit index d71b56612b..ca00165486 100644 --- a/jobs/valkey/monit +++ b/jobs/valkey/monit @@ -1,6 +1,6 @@ <% cloud_controller_internal = link("cloud_controller_internal") - unless cloud_controller_internal.p("cc.temporary_enable_deprecated_thin_webserver") && !cloud_controller_internal.p("cc.experimental.use_redis") + if cloud_controller_internal.p("cc.experimental.use_puma_webserver") || cloud_controller_internal.p("cc.experimental.use_redis") %> check process valkey diff --git a/spec/cloud_controller_ng/bpm_spec.rb b/spec/cloud_controller_ng/bpm_spec.rb index df9345758e..51e5991e33 100644 --- a/spec/cloud_controller_ng/bpm_spec.rb +++ b/spec/cloud_controller_ng/bpm_spec.rb @@ -112,40 +112,33 @@ def valkey_volume_mounted?(process) end end - describe 'valkey config' do - context 'when the puma webserver is used' do - it 'mounts the valkey volume into the ccng job container' do - template_hash = YAML.safe_load(template.render({}, consumes: {})) - - results = template_hash['processes'].select { |p| p['name'].include?('cloud_controller_ng') } - expect(results.length).to eq(1) - expect(valkey_volume_mounted?(results[0])).to be_truthy - end + context 'when the puma webserver is used' do + it 'mounts the valkey volume into the ccng job container' do + template_hash = YAML.safe_load(template.render({ 'cc' => { 'experimental' => { 'use_puma_webserver' => true } } }, consumes: {})) + + results = template_hash['processes'].select { |p| p['name'].include?('cloud_controller_ng') } + expect(results.length).to eq(1) + expect(valkey_volume_mounted?(results[0])).to be_truthy end + end - context 'when thin webserver is used' do - context "when 'cc.experimental.use_redis' is set to 'true'" do - it 'mounts the valkey volume into the ccng job container' do - template_hash = YAML.safe_load( - template.render({ 'cc' => { 'temporary_enable_deprecated_thin_webserver' => true, - 'experimental' => { 'use_redis' => true } } }, consumes: {}) - ) - - results = template_hash['processes'].select { |p| p['name'].include?('cloud_controller_ng') } - expect(results.length).to eq(1) - expect(valkey_volume_mounted?(results[0])).to be_truthy - end - end - - context "when 'cc.experimental.use_redis' is not set'" do - it 'mounts the valkey volume into the ccng job container' do - template_hash = YAML.safe_load(template.render({ 'cc' => { 'temporary_enable_deprecated_thin_webserver' => true } }, consumes: {})) - - results = template_hash['processes'].select { |p| p['name'].include?('cloud_controller_ng') } - expect(results.length).to eq(1) - expect(valkey_volume_mounted?(results[0])).to be_falsey - end - end + context "when 'cc.experimental.use_redis' is set to 'true'" do + it 'mounts the valkey volume into the ccng job container' do + template_hash = YAML.safe_load(template.render({ 'cc' => { 'experimental' => { 'use_redis' => true } } }, consumes: {})) + + results = template_hash['processes'].select { |p| p['name'].include?('cloud_controller_ng') } + expect(results.length).to eq(1) + expect(valkey_volume_mounted?(results[0])).to be_truthy + end + end + + context "when neither the puma webserver is used nor 'cc.experimental.use_redis' is set to 'true'" do + it 'does not mount the valkey volume into the ccng job container' do + template_hash = YAML.safe_load(template.render({}, consumes: {})) + + results = template_hash['processes'].select { |p| p['name'].include?('cloud_controller_ng') } + expect(results.length).to eq(1) + expect(valkey_volume_mounted?(results[0])).to be_falsey end end end diff --git a/spec/cloud_controller_ng/cloud_controller_ng_spec.rb b/spec/cloud_controller_ng/cloud_controller_ng_spec.rb index 4a87faec6b..41792e496e 100644 --- a/spec/cloud_controller_ng/cloud_controller_ng_spec.rb +++ b/spec/cloud_controller_ng/cloud_controller_ng_spec.rb @@ -53,7 +53,6 @@ module Test 'private_endpoint' => 'https://blobstore.service.cf.internal:4443', 'public_endpoint' => 'https://blobstore.brook-sentry.capi.land', 'username' => 'blobstore-user' } }, - 'experimental' => {}, 'install_buildpacks' => [{ 'name' => 'staticfile_buildpack', 'package' => 'staticfile-buildpack' }, { 'name' => 'java_buildpack', 'package' => 'java-buildpack' }, @@ -590,27 +589,24 @@ module Test describe 'valkey config' do context 'when the puma webserver is used' do it 'renders the valkey socket into the ccng config' do + merged_manifest_properties['cc']['experimental'] = { 'use_puma_webserver' => true } template_hash = YAML.safe_load(template.render(merged_manifest_properties, consumes: links)) expect(template_hash['redis']['socket']).to eq('/var/vcap/data/valkey/valkey.sock') end end - context 'when thin webserver is used' do - context "when 'cc.experimental.use_redis' is set to 'true'" do - it 'renders the valkey socket into the ccng config' do - merged_manifest_properties['cc']['temporary_enable_deprecated_thin_webserver'] = true - merged_manifest_properties['cc']['experimental']['use_redis'] = true - template_hash = YAML.safe_load(template.render(merged_manifest_properties, consumes: links)) - expect(template_hash['redis']['socket']).to eq('/var/vcap/data/valkey/valkey.sock') - end + context "when 'cc.experimental.use_redis' is set to 'true'" do + it 'renders the redis socket into the ccng config' do + merged_manifest_properties['cc']['experimental'] = { 'use_redis' => true } + template_hash = YAML.safe_load(template.render(merged_manifest_properties, consumes: links)) + expect(template_hash['redis']['socket']).to eq('/var/vcap/data/valkey/valkey.sock') end + end - context "when 'cc.experimental.use_redis' is not set'" do - it 'does not render the valkey socket into the ccng config' do - merged_manifest_properties['cc']['temporary_enable_deprecated_thin_webserver'] = true - template_hash = YAML.safe_load(template.render(merged_manifest_properties, consumes: links)) - expect(template_hash).not_to have_key('redis') - end + context "when neither the puma webserver is used nor 'cc.experimental.use_redis' is set to 'true'" do + it 'does not render the redis socket into the ccng config' do + template_hash = YAML.safe_load(template.render(merged_manifest_properties, consumes: links)) + expect(template_hash).not_to have_key('redis') end end end diff --git a/spec/valkey/monit_spec.rb b/spec/valkey/monit_spec.rb index 9b20b5ba7f..fbcbe19ac8 100644 --- a/spec/valkey/monit_spec.rb +++ b/spec/valkey/monit_spec.rb @@ -12,7 +12,7 @@ module Test let(:job) { release.job('valkey') } let(:spec) { job.instance_variable_get(:@spec) } let(:job_path) { job.instance_variable_get(:@job_path) } - let(:cc_internal_properties) { { 'cc' => { 'temporary_enable_deprecated_thin_webserver' => false, 'experimental' => { 'use_redis' => false } } } } + let(:cc_internal_properties) { { 'cc' => { 'experimental' => { 'use_puma_webserver' => false, 'use_redis' => false } } } } let(:link) { Link.new(name: 'cloud_controller_internal', properties: cc_internal_properties) } describe 'monit' do @@ -20,27 +20,24 @@ module Test context 'when the puma webserver is used' do it 'renders the monit directives' do + cc_internal_properties['cc']['experimental']['use_puma_webserver'] = true result = template.render({}, consumes: [link]) expect(result).to include('check process valkey') end end - context 'when thin webserver is used' do - context "when 'cc.experimental.use_redis' is set to 'true'" do - it 'renders the monit directives' do - cc_internal_properties['cc']['temporary_enable_deprecated_thin_webserver'] = true - cc_internal_properties['cc']['experimental']['use_redis'] = true - result = template.render({}, consumes: [link]) - expect(result).to include('check process valkey') - end + context "when 'cc.experimental.use_redis' is set to 'true'" do + it 'renders the monit directives' do + cc_internal_properties['cc']['experimental']['use_redis'] = true + result = template.render({}, consumes: [link]) + expect(result).to include('check process valkey') end + end - context "when 'cc.experimental.use_redis' is set to 'false'" do - it 'does not render the monit directives' do - cc_internal_properties['cc']['temporary_enable_deprecated_thin_webserver'] = true - result = template.render({}, consumes: [link]) - expect(result.strip).to eq('') - end + context "when neither the puma webserver is used nor 'cc.experimental.use_redis' is set to 'true'" do + it 'does not render the monit directives' do + result = template.render({}, consumes: [link]) + expect(result.strip).to eq('') end end end