-
Notifications
You must be signed in to change notification settings - Fork 2k
Spring Cloud Azure Core Design
Spring Cloud Azure 4.0 will organize our projects by different Spring abstractions, such as Spring Boot, Spring Data and etc. But all these different abstractions will sit on top of different kinds of Azure SDKs and if they talk directly to the SDKs it will bring us challenges of dealing with heterogeneous SDKs. This urges us to bring in an Spring Cloud Azure Core
project which to provide an abstraction layer between upper Azure Spring projects and Azure SDKs. Since all Azure SDKs build on top of the Azure Core
project, and Spring
projects on top of the Spring Framework
project, so our Spring Cloud Azure Core
project will take dependency on these two projects.
The goals of this project are:
- Provide a common template of configuring all the Azure SDK clients, no matter which protocol it uses, HTTP or AMQP.
- Provide the ability to configure every single configuration item the Azure SDK clients expose. To be more specific:
- All the authentication methods each Service or SDK supports.
- Proxy configurations.
- Retry configurations.
- Logging configurations.
- Underlying client configurations, for example, HttpClient.
- Other sdk configurations.
- Provide an extensible way for replacing Azure SDK provided implementations with Spring common implementations, such as using WebClient as HttpClient and configuring loggings with Spring properties.
- Provide abstraction support for upper-layer functions, such as:
-
spring-retry
support - micrometer
- tracing
-
The project will take dependency on spring-core
, spring-context
, azure-core
, azure-identity
, and azure-core-management
.
Define an AzureProperties
class that contains all the common properties Azure SDK clients use.
For each specific client define a service properties class
extends the AzureProperties
, such as StorageBlobProperties
.
Define a couple of Aware
interfaces, when a specific service properties class
implements these interfaces it indicates this service has such ability. For example the Storage Blob could configure SAS token and connection string, the StorageBlobProperties
could implement SasTokenAware
and ConnectionStringAware
.
Since the Azure SDKs use a builder pattern to build all clients, so it's natural for us to provide a template to configure the builders. So we define the top interface:
public interface AzureServiceClientBuilderFactory<T> {
T build();
}
The output of this factory is a client builder.
Creating an abstract implementation of the AzureServiceClientBuilderFactory
to provide the template for configuring client builders for all SDK clients.
public abstract class AbstractAzureServiceClientBuilderFactory<T> implements AzureServiceClientBuilderFactory<T> {
public T build() {
T builder = createBuilderInstance();
configureCore(builder);
configureService(builder);
customizeBuilder(builder);
return builder;
}
protected void configureCore(T builder) {
configureApplicationId(builder);
configureAzureEnvironment(builder);
configureRetry(builder);
configureProxy(builder);
configureCredential(builder);
configureConnectionString(builder);
configureDefaultCredential(builder);
}
}
!
Each Service/SDK supports a bunch of authentication methods, such as use TokenCredential
as a bearer token, SasCredential
as a shared access signature, and etc. We need to provide a way to let each builder factory define the supported authentication methods, the way to resolve such credentials from AzureProperties
, and at last how to set the credential to the builder.
To achieve this, we define an interface called AuthenticationDescriptor
describing the three elements mentioned above.
public interface AuthenticationDescriptor<T extends AzureCredentialProvider<?>> {
AzureCredentialType azureCredentialType();
AzureCredentialResolver<T> azureCredentialResolver();
Consumer<T> consumer();
}
Each builder factory provides a list of AuthenticationDescriptor
so the builder factory will try to resolve the first available authentication credential and set it to the builder.
protected void configureCredential(T builder) {
List<AuthenticationDescriptor<?>> descriptors = getAuthenticationDescriptors(builder);
AzureCredentialProvider<?> azureCredentialProvider = resolveAzureCredential(getAzureProperties(), descriptors);
final Consumer consumer = descriptors.stream()
.filter(d -> d.azureCredentialType() == azureCredentialProvider.getType())
.map(AuthenticationDescriptor::consumer)
.findFirst()
.orElseThrow(
() -> new IllegalArgumentException("Consumer should not be null"));
consumer.accept(azureCredentialProvider.getCredential());
}
- Spring Credential
- Spring Cloud Azure 4.0 Design
- Spring Cloud Azure AutoConfigure Design
- Spring Cloud Azure Core Design
- Spring Cloud Azure Messaging Design
- Spring Cloud Azure Service Bus Spring Jms Support Design
- Design for directory, module name and package path for Spring Cloud Azure messaging
- Design for Remove warning logs of unknown configs for Kafka Passwordless
- Design for Enhance AAD token authentication converter to customized granted authorities converter
- Design for Enhance the ObjectMapper to support Spring Boot's pattern to enable autoconfiguration
- Passwordless connection support for Spring Cloud Azure
- Passwordless connection support for MySQL
- Passwordless connection support for Event Hubs Kafka
- Remove warning logs of unknown configs for Kafka Passwordless