Spring Cloud - HystrixCommand - 如何正确启用共享库
Spring Cloud - HystrixCommand - How to properly enable with shared libraries
使用 Springboot 1.5.x、Spring 云和 JAX-RS:
我可以使用第二双眼睛,因为我不清楚 Spring 配置的 Javanica HystrixCommand 是否适用于所有用例,或者我的代码是否有错误。下面是我正在做的事情的近似值,下面的代码实际上不会编译。
从下面看,WebService 位于一个库中,该库具有指向主应用程序的独立包路径。同时 MyWebService 位于与 Springboot 应用程序相同的上下文路径中的应用程序中。 MyWebService 也可以正常运行,没有问题。这仅与 HystrixCommand 注释在 Spring 基于引导的配置方面的可见性有关。
在运行时,我注意到当像下面这样的代码运行时,我确实在响应中看到 "commandKey=A"。这是我没想到的,因为在获取数据时它仍然是 运行。因为我们记录了 HystrixRequestLog,所以我也在我的日志中看到了这个命令键。
但是所有其他命令键根本不可见,无论我将它们放在文件中的什么位置。如果我删除 CommandKey-A 那么任何命令都不可见。
想法?
// Example WebService that we use as a shared component for performing a backend call that is the same across different resources
@RequiredArgsConstructor
@Accessors(fluent = true)
@Setter
public abstract class WebService {
private final @Nonnull Supplier<X> backendFactory;
@Setter(AccessLevel.PACKAGE)
private @Nonnull Supplier<BackendComponent> backendComponentSupplier = () -> new BackendComponent();
@GET
@Produces("application/json")
@HystrixCommand(commandKey="A")
public Response mainCall() {
Object obj = new Object();
try {
otherCommandMethod();
} catch (Exception commandException) {
// do nothing (for this example)
}
// get the hystrix request information so that we can determine what was executed
Optional<Collection<HystrixInvokableInfo<?>>> executedCommands = hystrixExecutedCommands();
// set the hystrix data, viewable in the response
obj.setData("hystrix", executedCommands.orElse(Collections.emptyList()));
if(hasError(obj)) {
return Response.serverError()
.entity(obj)
.build();
}
return Response.ok()
.entity(healthObject)
.build();
}
@HystrixCommand(commandKey="B")
private void otherCommandMethod() {
backendComponentSupplier
.get()
.observe()
.toBlocking()
.subscribe();
}
Optional<Collection<HystrixInvokableInfo<?>>> hystrixExecutedCommands() {
Optional<HystrixRequestLog> hystrixRequest = Optional
.ofNullable(HystrixRequestLog.getCurrentRequest());
// get the hystrix executed commands
Optional<Collection<HystrixInvokableInfo<?>>> executedCommands = Optional.empty();
if (hystrixRequest.isPresent()) {
executedCommands = Optional.of(hystrixRequest.get()
.getAllExecutedCommands());
}
return executedCommands;
}
@Setter
@RequiredArgsConstructor
public class BackendComponent implements ObservableCommand<Void> {
@Override
@HystrixCommand(commandKey="Y")
public Observable<Void> observe() {
// make some backend call
return backendFactory.get()
.observe();
}
}
}
// then later this component gets configured in the specific applications with sample configuraiton that looks like this:
@SuppressWarnings({ "unchecked", "rawtypes" })
@Path("resource/somepath")
@Component
public class MyWebService extends WebService {
@Inject
public MyWebService(Supplier<X> backendSupplier) {
super((Supplier)backendSupplier);
}
}
mainCall() 调用 otherCommandMethod() 时出现问题。不能从同一个 class 中调用带有 @HystrixCommand 的方法。
如 问题的答案中所述,这是 Spring 的 AOP 的限制。
使用 Springboot 1.5.x、Spring 云和 JAX-RS:
我可以使用第二双眼睛,因为我不清楚 Spring 配置的 Javanica HystrixCommand 是否适用于所有用例,或者我的代码是否有错误。下面是我正在做的事情的近似值,下面的代码实际上不会编译。
从下面看,WebService 位于一个库中,该库具有指向主应用程序的独立包路径。同时 MyWebService 位于与 Springboot 应用程序相同的上下文路径中的应用程序中。 MyWebService 也可以正常运行,没有问题。这仅与 HystrixCommand 注释在 Spring 基于引导的配置方面的可见性有关。
在运行时,我注意到当像下面这样的代码运行时,我确实在响应中看到 "commandKey=A"。这是我没想到的,因为在获取数据时它仍然是 运行。因为我们记录了 HystrixRequestLog,所以我也在我的日志中看到了这个命令键。
但是所有其他命令键根本不可见,无论我将它们放在文件中的什么位置。如果我删除 CommandKey-A 那么任何命令都不可见。
想法?
// Example WebService that we use as a shared component for performing a backend call that is the same across different resources
@RequiredArgsConstructor
@Accessors(fluent = true)
@Setter
public abstract class WebService {
private final @Nonnull Supplier<X> backendFactory;
@Setter(AccessLevel.PACKAGE)
private @Nonnull Supplier<BackendComponent> backendComponentSupplier = () -> new BackendComponent();
@GET
@Produces("application/json")
@HystrixCommand(commandKey="A")
public Response mainCall() {
Object obj = new Object();
try {
otherCommandMethod();
} catch (Exception commandException) {
// do nothing (for this example)
}
// get the hystrix request information so that we can determine what was executed
Optional<Collection<HystrixInvokableInfo<?>>> executedCommands = hystrixExecutedCommands();
// set the hystrix data, viewable in the response
obj.setData("hystrix", executedCommands.orElse(Collections.emptyList()));
if(hasError(obj)) {
return Response.serverError()
.entity(obj)
.build();
}
return Response.ok()
.entity(healthObject)
.build();
}
@HystrixCommand(commandKey="B")
private void otherCommandMethod() {
backendComponentSupplier
.get()
.observe()
.toBlocking()
.subscribe();
}
Optional<Collection<HystrixInvokableInfo<?>>> hystrixExecutedCommands() {
Optional<HystrixRequestLog> hystrixRequest = Optional
.ofNullable(HystrixRequestLog.getCurrentRequest());
// get the hystrix executed commands
Optional<Collection<HystrixInvokableInfo<?>>> executedCommands = Optional.empty();
if (hystrixRequest.isPresent()) {
executedCommands = Optional.of(hystrixRequest.get()
.getAllExecutedCommands());
}
return executedCommands;
}
@Setter
@RequiredArgsConstructor
public class BackendComponent implements ObservableCommand<Void> {
@Override
@HystrixCommand(commandKey="Y")
public Observable<Void> observe() {
// make some backend call
return backendFactory.get()
.observe();
}
}
}
// then later this component gets configured in the specific applications with sample configuraiton that looks like this:
@SuppressWarnings({ "unchecked", "rawtypes" })
@Path("resource/somepath")
@Component
public class MyWebService extends WebService {
@Inject
public MyWebService(Supplier<X> backendSupplier) {
super((Supplier)backendSupplier);
}
}
mainCall() 调用 otherCommandMethod() 时出现问题。不能从同一个 class 中调用带有 @HystrixCommand 的方法。
如