Nova postagem

Pesquisar

Artigo
· Dez. 17, 2024 10min de leitura

Optimizing Performance of Apache Web Server and Web Gateway

 


Optimizing Performance of Apache Web Server and Web Gateway

By Patrick Jamieson, M.D., Product Technical Manager, InterSystems IRIS for Health

When working with InterSystems IRIS or IRIS for Health, an external web server like Apache2 or NGINX is essential for managing HTTP workloads, especially for FHIR servers. Starting with version 2023.3, the private Apache server was removed from the installation kit (except for Community Editions and Health Connect). This article provides practical tips to test and optimize the performance of your Apache web server and InterSystems Web Gateway configuration.


📋 Why Performance Optimization Matters

Out-of-the-box configurations are rarely ideal for production workloads. Optimizing Apache and the Web Gateway can significantly reduce response times, improve throughput, and handle higher concurrency under load.


🛠️ Testing Performance Using Apache Bench

Apache Bench (ab) is a powerful benchmarking tool that can simulate high load, identify bottlenecks, and measure metrics like response time and concurrency.

Installing Apache Bench

On Linux, install it with:

sudo apt-get install apache2-utils

Running Tests

Start by using a simple load test:

ab -n 100 -c 10 https://yourserver/endpoint
  • -n: Number of requests (e.g., 100)
  • -c: Concurrent requests (e.g., 10)

Apache Bench (bench) will now make 100 requests with a maximum of 10 requests running concurrently.

Here are my results using the Apache2 server with a default IRIS for Health server and gateway configuration settings with a FHIR server deployed on AWS.

Server Software:       

Server Hostname:        fhir.testintersystems.com

Document Length:        2303 bytes

Concurrency Level:      10

Time taken for tests:   1.161 seconds

Complete requests:     100

Failed requests:            0

Total transferred:         264500 bytes

HTML transferred:       230300 bytes

Requests per second:    86.11 [#/sec] (mean)

Time per request:       116.126 [ms] (mean)

Time per request:       11.613 [ms] (mean, across all concurrent requests)

Transfer rate:                222.43 [Kbytes/sec] received

*Connection Times (ms)

                         min      mean[+/-sd]    median            max

Connect:          4          20        8.6       18                     57

Processing:     3          87        177.9    17                    705

Waiting:           3          85        178.1    14                    701

Total:                19        107      180.0    38                    762

 

*Connect: How long it takes ab to establish a TCP connection with the target server before writing the request to the connection (ctime)

Processing: How long the connection was open after being created (time - ctime)

Waiting: How long ab waits after sending the request before beginning to read a response from the connection (waittime)

Total: The time elapsed from the moment ab attempts to make the connection to the time the connection closes (time)

 

* https://www.datadoghq.com/blog/apachebench/

So far, these statistics look good, but when then I increased the load on the server.

ab -n 2000 -c 75 https://fhir.testintersystems.com/csp/healthshare/demo/fhir/r4/Patient/1

 

Now I saw:

Server Hostname:        fhir.testintersystems.com

Document Length:        2303 bytes

Concurrency Level:      75

Time taken for tests:   10.811 seconds

Complete requests:      2000

Failed requests:        12

(Connect: 0, Receive: 0, Length: 12, Exceptions: 0)

Non-2xx responses:      12

Total transferred:      5265484 bytes

HTML transferred:       4583092 bytes

Requests per second:    185.00 [#/sec] (mean)

Time per request:       405.401 [ms] (mean)

Time per request:       5.405 [ms] (mean, across all concurrent requests)

Transfer rate:          475.65 [Kbytes/sec] received

 

Connection Times (ms)

                         min      mean[+/-sd]                median            max

Connect:           5         118      63.9                 120                  310

Processing:       7          284     835.4               86                    5397

Waiting:           3          262      838.6               65                    5384

Total:                12        402      831.5               205                  5417

 

Percentage of the requests served within a certain time (ms)

  50%    205

  66%    226

  75%    276

  80%    296

  90%    379

  95%   2069

  98%   4195

  99%   4832

 100%   5417 (longest request)

 

Notice with many more requests per second, the time to process each request has increased significantly to over 400 ms. I saw that a few of the requests didn't even return a response -- a failed request.

The bottlenecks required I modify specific configuration settings in Apache2 to address these performance issues. The Apache2 server ships with a selection of Multi-Processing Modules (MPMs) which are responsible for binding to network ports on the machine, accepting requests, and dispatching children to handle the requests. For instance, I  could adjust the MaxClients or ServerLimit directive to improve the number of concurrent connections the server can handle. I could also tweak the KeepAliveTimeout or Timeout settings to optimize how long connections are kept open.
 

⚙️ Identifying and Addressing Bottlenecks

Here are key optimization steps:

1. Modify Apache2 MPM Configuration

Edit /etc/apache2/mods-enabled/mpm_worker.conf:

<IfModule mpm_worker_module>
    ServerLimit            200
    StartServers           25
    MaxRequestWorkers      5000
    MinSpareThreads        75
    MaxSpareThreads        250
    ThreadsPerChild        25
</IfModule>

2. Tune Web Gateway Settings

  • Max Server Connections: 8000
  • Server Response Timeout: 900
  • No Activity Timeout: 86401

Restart Apache after changes:

sudo service apache2 restart

🚀 Retesting Performance

Re-run ab with higher concurrency:

ab -n 2000 -c 75 https://yourserver/endpoint

Monitor improvements in:

  • Requests per second
  • Failed requests
  • Connection times

Repeating the earlier bench command:
ab -n 2000 -c 75 https://fhir.testintersystems.com/csp/healthshare/demo/fhir/r4/Patient/1

I now saw the following statistics

Server Hostname:        fhir.testintersystems.com

Concurrency Level:      75

Time taken for tests:   5.975 seconds

Complete requests:      2000

Failed requests:        0

Total transferred:      5290000 bytes

HTML transferred:       4606000 bytes

Requests per second:    334.75 [#/sec] (mean)

Time per request:       224.045 [ms] (mean)

Time per request:       2.987 [ms] (mean, across all concurrent requests)

Transfer rate:          864.67 [Kbytes/sec] received

 

Connection Times (ms)

                                     min                  mean[+/-sd]                median                        max

Connect:                      6                      136      24.6                 135                              286

Processing:                  7                      84        23.4                 82                                171

Waiting:                       3                      47        18.8                 45                                160

Total:                            13                    221      28.3                 219                              363

 

Percentage of the requests served within a certain time (ms)

  50%    219

  66%    223

  75%    227

  80%    229

  90%    257

  95%    281

  98%    296

  99%    312

 100%    363 (longest request)

Notice with the retest (after performance tuning) the total connection time has dropped by 50%, and 99% of our requests are being completed within 312 ms, compared to the previous 4.8 sec. Notice also we are no longer seeing any failed requests.

 

📊 Monitor System Performance

This short post mentioned a few factors that could limit overall HTTP performance. Memory, CPU, and disk utilization could also create performance limitations. To understand these performance bottlenecks, it may be necessary to monitor system performance over 30 minutes to several hours.

Use the IRIS system performance tool to identify server-side bottlenecks:

Do ^SystemPerformance

📝 Key Takeaways

  • Optimize Apache’s MPM settings for higher concurrency.
  • Fine-tune Web Gateway configurations to align with Apache limits.
  • Use Apache Bench iteratively to test and validate changes.

Performance optimization is an ongoing process—continuously monitor, test, and refine your configurations to meet growing demands.


For further details, refer to IRIS Web Gateway Documentation.

Happy optimizing! 🚀

Discussão (0)1
Entre ou crie uma conta para continuar
Pergunta
· Dez. 17, 2024

Production pooled component index

I have a business service which is responsible for some batch operations with an SQL table. The process is generally slow but it is possible to scale the performance using multithreading and/or parallel processing and logical partitioning (postgres):

6 Comments
Discussão (6)2
Entre ou crie uma conta para continuar
Pergunta
· Dez. 17, 2024

How To Give a Condition To Data Row based on First and Next Data?

Hello my Friends,

I have a question, I have a data like this

And I want to create a display like this, which I can put a status column beside the Item Column

The status become new, if there's no previous item, and if there's a same item after the first one, the status become Old

Does anyone could help me ?

I need to display it without subquery if possible

Thank You

Best Regards,

Steven Henry

9 Comments
Discussão (9)2
Entre ou crie uma conta para continuar
Pergunta
· Dez. 17, 2024

SSL Issues on Mac OS 15.2 when IRIS is running within a Docker container

Hi,

I recently had a company-enforced OS upgrade, and ever since going from mac OS 14.x to 15.x, I am currently having issues with SSL in IRIS.

An ARM (M3 pro) machine running OS 15.2, with the latest Docker Desktop (at the time of writing, 4.37.0). The Docker container runs IRIS for UNIX (Ubuntu Server LTS for x86-64 Containers) 2022.1.2 (Build 574_0_22161U). This container has not changed.

When attempting to run some local API tests of our software, I am hosting a Wiremock (https://github.com/wiremock/wiremock) server locally on the mac, in order to mock HTTP requests/responses. The IRIS server communicates with this wiremock server via `host.docker.internal` as a hostname, to talk from the container to the host machine. This was working before the OS upgrade without issue.

Ever since the OS upgrade, there seems to be some issue with SSL and I am unsure where the fault lies, hence asking for any advice or opinions here.

The basic structure of the tests which fail involve creating a simple http request, which will be pointed towards `host.docker.internal` and appropriate ports. Each individual test will add specific Wiremock mappings to the request, but as these all worked fine before the OS upgrade I don't think code for this needs to be included.

Method createHttpRequest() As %Net.HttpRequest [ Private ]
{
    set req = ##class(%Net.HttpRequest).%New()
    set req.Server = ..Host
    set req.Port = ..Port
    return req
}

Method IsHealthy() As %Boolean
{
    #dim req as %Net.HttpRequest = ..createHttpRequest()
    $$$ThrowOnError(req.Get("/__admin/health"))
    if ((req.HttpResponse.StatusCode = 200) && ($isobject(req.HttpResponse.Data)) && (req.HttpResponse.Data.Size > 0) ) {
        #dim json as %DynamicObject = {}.%FromJSON(req.HttpResponse.Data.Read())
        return (json.status = "healthy")
    }
    return 0
}

As mentioned, this all functioned without issue and contains nothing specific to our company. However now since the OS upgrade, IRIS errors out when running such tests with this message:

"ERROR <Ens>ErrGeneral: (RootCause "ERROR #6085: Unable to write to socket with SSL/TLS configuration 'ISC.FeatureTracker.SSL.Config', error reported 'SSL/TLS configuration 'ISC.FeatureTracker.SSL.Config' is not activated.'"

Looking at the management portal, this configuration is indeed enabled.

I have read online that other users have experienced SSL issues with various software since upgrading OS, so I am wondering if this is an IRIS issue, a Docker issue, or something else? I found a few discussions that seem to blame Microsoft Defender as the source of SSL issues. Our company does have Microsoft Defender enabled as policy, so I cannot disable this.

Has anyone else experienced similar? Is this an IRIS issue, or does the blame lie elsewhere (docker, microsoft defender, other)?

In the meantime, I am running Wiremock within the docker container and IRIS can communicate with that instance without issue. But, as every other team member has code pointing to `host.docker.internal`, it would be good to not require to patch our codebase only on my development machine.

I'm aware IRIS has not been yet released for mac os 15.x, but as the actual IRIS software is running within a unix docker container in my development environment, I figured I could ask for any insights here. Thanks in advance.

3 Comments
Discussão (3)2
Entre ou crie uma conta para continuar
Artigo
· Dez. 16, 2024 2min de leitura

Edit your Globals with VSCode and YAML

The best way to list, edit, save and delete globals is using an IDE. Now, it is possible if you use VSCode. It is also possible to save globals using yaml files. Perform the following steps:

1. Get an InterSystems IRIS instance and install the application iris-global-yaml: 

zpm:USER>install iris-global-yaml

2. If you just to want an InterSystems IRIS trial for tests git clone and run on docker:

git clone https://github.com/yurimarx/iris-global-yaml.git
docker-compose up -d --build

3. Go to https://openexchange.intersystems.com/package/IRIS-Global-VSCode-Editor, click GitHub button, look for iris-global-editor-0.0.1.vsix file, and save it in your local disk.

4. Now, open your VSCode IDE and click extensions:

 

5. Click the button ... and select Install from VSIX...:

 

6. Select the vsix file from your local disk to install (if installation fails, update your VSCode for the most recent VSCode binary and try again):

7. Go to View > Explorer:

8. Create or edit the file .vscode/settings.json with connections settings (edit with your host, port, namespace and credentials):

"conf.irisGlobalEditor.serverconfig": { 
      "host": "http://localhost:52773", 
      "namespace": "USER", 
      "username": "_SYSTEM", 
      "password": "SYS"
}

9. Go to the tab INTERSYSTEMS IRIS GLOBALS and click the button refresh:

10. The VSCode list all globals in the configured namespace:

11. On top of the tab, click the plus button to create a new global:

12. Write the global name and your value and press enter:

13. Click refresh button again and see your new global on bottom:

14. Now click the editor button (last button) to create a yaml file to edit your global:

15. A new yaml file is created with the global content:

16. Edit the yaml to insert subscripts into your global (it is very important use indentation with 4 spaces):

# IRIS-Global-YAML
USER:
 ^test:
     value: InterSystems IRIS
     subscripts:
        - ^test(1): 1
        - ^test(1,1): 1.1
        - ^test(1,2): 1.2
        - ^test(2,1): 2.1
        - ^test(2,2): 2.2
        - ^test(2,3): 2.3
        - ^test(2,4): 2.4

17. Save the file on any project folder and the global content will be saved on IRIS Server:

18. Try the delete buttom also and enjoy!

11 Comments
Discussão (11)2
Entre ou crie uma conta para continuar