通过我自己的 RESTful API 路由 API 调用是否被视为可接受的策略?

pas*_*alH 7 java rest spring

这个问题可能被认为是自以为是,但我似乎真的找不到直接的答案。所以要么我遗漏了什么,要么我问错了问题。所以,我是一名本科生,并且是整个 Spring 应用程序开发的新手,我目前正在创建一个以 React 作为前端的应用程序,并使用 Spring 构建一个 RESTful API,以便通过后端的必要操作来支持它。在其他服务中,我正在构建的后端 API 用作中间人,将调用转发到Google Geocoding API和其他 3rd 方 API。**自从我开始这个以来,我最大的问题是,这是一个有效的策略吗?**(至少,行业专业人士可以接受的东西)

我的研究

  • 这种方法最大的优点是它允许我有效地向客户端隐藏我的 API 密钥,从而不可能进行任何攻击。
  • 同时,这整个过程增加了(我相信)不必要的复杂性和整体响应的延迟,从而可能会阻碍用户体验。
  • 我还不太确定的是,我必须向async我自己的 API 公开的服务添加功能,以便为多个用户提供便利。(最后一部分可能完全错误,但我无法理解在同时查询同一个端点时如何处理多个用户。)
  • 我已经使用Apache JMeter来测试应用程序在并发 POST 调用上的性能,它似乎能够在 170 毫秒左右处理它们。(我将在下面发布结果的屏幕截图。)

代码

我将尝试包含演示负责调用Geocoding API的控制器的代码。

@RestController
@RequestMapping("/api")
@Slf4j
@RequiredArgsConstructor
@Component
public class GeocodingController {
    private final OkHttpClient httpClient = new OkHttpClient();

    @PostMapping(value = "/reversegeocoding")
    public String getReverseGeocode(@RequestBody LatLng latlng) throws IOException, ExecutionException, InterruptedException {
        String encodedLatLng = latlng.toString();
        Request request  = new Request.Builder()
                .url("https://maps.googleapis.com/maps/api/geocode/json?" +
                        "language=en&result_type=street_address&latlng=" + encodedLatLng +
                        "&key=MY_API_KEY")
                .build();

        CallbackFuture future = new CallbackFuture();
        httpClient.newCall(request).enqueue(future);
        Response response = future.get();
        return response.body().string();

    }
}
Run Code Online (Sandbox Code Playgroud)

getReverseGeocode()方法将以下对象作为参数:

@Data
@AllArgsConstructor
@NoArgsConstructor
public class LatLng {

    double lat;
    double lng;

    public String toString() {
        return lat + "," + lng;
    }
}

Run Code Online (Sandbox Code Playgroud)

因此,Request Body一旦请求到达,就会映射到上述对象上。
最后,CallbackFuture它只是一个基于答案的适配器类。

public class CallbackFuture extends CompletableFuture<Response> implements Callback {

    @Override
    public void onFailure(Call call, IOException e) {
        super.completeExceptionally(e);
    }

    @Override
    public void onResponse(Call call, Response response) {
        super.complete(response);
    }
}
Run Code Online (Sandbox Code Playgroud)

JMeter 结果

JMeter 结果

持续时间断言设置

线程组设置 - 10 个线程(用户)

Stu*_*ion 3

是的,这是一个完全有效的策略。使用这种方法有很多好处,虽然感觉像是增加了不必要的复杂性,但好处往往超过成本。

首先,您要避免“抽象泄漏”,客户不应该关心您如何实现特定的功能,他们只关心它是否有效!这也意味着您将来应该能够在客户不知情的情况下更改实现。

其次,您正在将您的 API 与其他 API 解耦。如果包装的 API 发生变化,您可以自己处理,而无需客户端更改其代码(有时无法做到这一点,但它对此提供了很好的防御)。

此外,它还为您提供了一个方便的点来围绕这些 API 实现您自己的功能(例如速率限制、访问控制和日志记录)。

@Async问题并不特定于包装第​​三方 API,它是您拥有的所有具有阻塞 IO 的端点的问题。