My first attempt to solve the DoS vulnerability used the approach suggested by Gulzar, which is basically to limit the number of calls allowed from the same IP address. I think it's a good approach, but, unfortunately, it caused my code to fail a performance test.
Since I was unable to get the performance test group to change their test (a political problem, not a technical one), I changed to limiting the number of calls allowed during a configurable interval. I made both the maximum number of calls and the time interval configurable. I also allowed setting a value of 0 or a negative number which disables the limits.
The code that needed to be protected is used internally by several products. So, I had each product group run their QA and performance test suites and came up with default values that were as small as possible to limit a real DoS attack but still passed all the tests.
FWIW, the time interval was 30 seconds and the maximum number of calls was 100. This is not a completely satisfactory approach, but it is simple and practical and was approved by the corporate security team (another political consideration).