package com.alibaba.spring.boot.rsocket.broker; import com.alibaba.rsocket.discovery.DiscoveryService; import com.alibaba.rsocket.health.RSocketServiceHealth; import com.alibaba.rsocket.listen.RSocketListener; import com.alibaba.rsocket.listen.RSocketListenerCustomizer; import com.alibaba.rsocket.route.RSocketFilter; import com.alibaba.rsocket.route.RSocketFilterChain; import com.alibaba.rsocket.rpc.LocalReactiveServiceCaller; import com.alibaba.spring.boot.rsocket.broker.cluster.DefaultRSocketBrokerManager; import com.alibaba.spring.boot.rsocket.broker.cluster.RSocketBrokerManager; import com.alibaba.spring.boot.rsocket.broker.cluster.RSocketBrokerManagerGossipImpl; import com.alibaba.spring.boot.rsocket.broker.impl.BrokerRSocketServiceHealthImpl; import com.alibaba.spring.boot.rsocket.broker.impl.DiscoveryServiceImpl; import com.alibaba.spring.boot.rsocket.broker.responder.AppStatusCloudEventProcessor; import com.alibaba.spring.boot.rsocket.broker.responder.RSocketBrokerHandlerRegistry; import com.alibaba.spring.boot.rsocket.broker.responder.RSocketBrokerHandlerRegistryImpl; import com.alibaba.spring.boot.rsocket.broker.route.ServiceMeshInspector; import com.alibaba.spring.boot.rsocket.broker.route.ServiceRoutingSelector; import com.alibaba.spring.boot.rsocket.broker.route.impl.ServiceMeshInspectorImpl; import com.alibaba.spring.boot.rsocket.broker.route.impl.ServiceRoutingSelectorImpl; import com.alibaba.spring.boot.rsocket.broker.security.AuthenticationService; import com.alibaba.spring.boot.rsocket.broker.security.AuthenticationServiceJwtImpl; import com.alibaba.spring.boot.rsocket.broker.services.*; import com.alibaba.spring.boot.rsocket.broker.smi.TrafficAccessControl; import com.alibaba.spring.boot.rsocket.broker.smi.TrafficSplit; import com.alibaba.spring.boot.rsocket.broker.smi.impl.TrafficAccessControlImpl; import com.alibaba.spring.boot.rsocket.broker.smi.impl.TrafficSplitImpl; import com.alibaba.spring.boot.rsocket.broker.supporting.RSocketLocalServiceAnnotationProcessor; import com.alibaba.spring.boot.rsocket.broker.upstream.RSocketRequesterBySubBroker; import com.alibaba.spring.boot.rsocket.broker.upstream.UpstreamBrokerCluster; import io.cloudevents.v1.CloudEventImpl; import io.rsocket.RSocket; import org.springframework.beans.factory.ObjectProvider; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import org.springframework.core.annotation.Order; import org.springframework.core.env.Environment; import org.springframework.core.io.ResourceLoader; import reactor.extra.processor.TopicProcessor; import java.security.KeyStore; import java.security.PrivateKey; import java.security.cert.Certificate; import java.util.stream.Collectors; /** * RSocket broker auto configuration * * @author leijuan */ @SuppressWarnings("rawtypes") @Configuration @EnableConfigurationProperties(RSocketBrokerProperties.class) public class RSocketBrokerAutoConfiguration { @Bean public RSocketFilterChain rsocketFilterChain(ObjectProvider<RSocketFilter> rsocketFilters) { return new RSocketFilterChain(rsocketFilters.orderedStream().collect(Collectors.toList())); } @Bean public ServiceMeshInspector serviceMeshInspector(RSocketBrokerProperties brokerProperties) { return new ServiceMeshInspectorImpl(brokerProperties.isAuthRequired()); } @Bean public ServiceRoutingSelector serviceRoutingSelector() { return new ServiceRoutingSelectorImpl(); } @Bean @ConditionalOnMissingBean public ConfigurationService configurationService() { return new KVStorageServiceImpl(); } @Bean public ConfigController configController() { return new ConfigController(); } @Bean public AppQueryController appQueryController() { return new AppQueryController(); } @Bean public ServiceQueryController serviceQueryController() { return new ServiceQueryController(); } @Bean public MetricsScrapeController metricsScrapeController() { return new MetricsScrapeController(); } @Bean public RSocketBrokerHandlerRegistry rsocketResponderHandlerRegistry(@Autowired LocalReactiveServiceCaller localReactiveServiceCaller, @Autowired RSocketFilterChain rsocketFilterChain, @Autowired ServiceRoutingSelector routingSelector, @Autowired @Qualifier("reactiveCloudEventProcessor") TopicProcessor<CloudEventImpl> eventProcessor, @Autowired @Qualifier("notificationProcessor") TopicProcessor<String> notificationProcessor, @Autowired AuthenticationService authenticationService, @Autowired RSocketBrokerManager rSocketBrokerManager, @Autowired ServiceMeshInspector serviceMeshInspector, @Autowired RSocketBrokerProperties properties, @Autowired ApplicationContext applicationContext) { return new RSocketBrokerHandlerRegistryImpl(localReactiveServiceCaller, rsocketFilterChain, routingSelector, eventProcessor, notificationProcessor, authenticationService, rSocketBrokerManager, serviceMeshInspector, properties.isAuthRequired(), applicationContext); } @Bean public RSocketLocalServiceAnnotationProcessor rSocketServiceAnnotationProcessor() { return new RSocketLocalServiceAnnotationProcessor(); } @Bean(initMethod = "start", destroyMethod = "stop") public RSocketListener rsocketListener(ObjectProvider<RSocketListenerCustomizer> customizers) { RSocketListener.Builder builder = RSocketListener.builder(); customizers.orderedStream().forEach((customizer) -> customizer.customize(builder)); return builder.build(); } @Bean @Order(100) public RSocketListenerCustomizer defaultRSocketListenerCustomizer(@Autowired RSocketBrokerHandlerRegistry registry, @Autowired RSocketBrokerProperties properties) { return builder -> { builder.acceptor(registry); builder.listen("tcp", properties.getPort()); }; } @Bean @Order(101) @ConditionalOnProperty(name = "rsocket.broker.ssl.key-store") RSocketListenerCustomizer rSocketListenerSSLCustomizer(@Autowired RSocketBrokerProperties properties, @Autowired ResourceLoader resourceLoader) { return builder -> { RSocketBrokerProperties.RSocketSSL rSocketSSL = properties.getSsl(); if (rSocketSSL != null && rSocketSSL.isEnabled() && rSocketSSL.getKeyStore() != null) { try { KeyStore store = KeyStore.getInstance("PKCS12"); store.load(resourceLoader.getResource(rSocketSSL.getKeyStore()).getInputStream(), rSocketSSL.getKeyStorePassword().toCharArray()); String alias = store.aliases().nextElement(); Certificate certificate = store.getCertificate(alias); KeyStore.Entry entry = store.getEntry(alias, new KeyStore.PasswordProtection(rSocketSSL.getKeyStorePassword().toCharArray())); PrivateKey privateKey = ((KeyStore.PrivateKeyEntry) entry).getPrivateKey(); builder.sslContext(certificate, privateKey); builder.listen("tcps", properties.getPort()); } catch (Exception e) { throw new RuntimeException(e); } } }; } @Bean public DiscoveryService rsocketDiscoveryService() { return new DiscoveryServiceImpl(); } @Bean public AuthenticationService authenticationService() throws Exception { return new AuthenticationServiceJwtImpl(); } @Bean public RSocketServiceHealth brokRSocketServiceHealth(@Autowired ServiceRoutingSelector routingSelector) { return new BrokerRSocketServiceHealthImpl(routingSelector); } @Bean @ConditionalOnMissingBean(RSocketBrokerManager.class) public RSocketBrokerManager rsocketBrokerManager() { return new DefaultRSocketBrokerManager(); } @Bean @ConditionalOnExpression("'${rsocket.broker.topology}'=='gossip'") @Primary public RSocketBrokerManager rsocketGossipBrokerManager() { return new RSocketBrokerManagerGossipImpl(); } @Bean public TopicProcessor<CloudEventImpl> reactiveCloudEventProcessor() { return TopicProcessor.<CloudEventImpl>builder().name("cloud-events-processor").build(); } @Bean public TopicProcessor<String> notificationProcessor() { return TopicProcessor.<String>builder().name("notifications-processor").build(); } @Bean(initMethod = "init") public AppStatusCloudEventProcessor appStatusCloudEventProcessor() { return new AppStatusCloudEventProcessor(); } @Bean public TrafficAccessControl trafficAccessControl() { return new TrafficAccessControlImpl(); } @Bean public TrafficSplit trafficSplit() { return new TrafficSplitImpl(); } @Bean(initMethod = "init", destroyMethod = "close") @ConditionalOnProperty(name = "rsocket.broker.upstream-brokers") public UpstreamBrokerCluster upstreamBrokerCluster(@Autowired RSocketBrokerProperties properties, @Autowired Environment env, @Autowired RSocketFilterChain filterChain, @Autowired ServiceRoutingSelector serviceRoutingSelector, @Autowired RSocketBrokerHandlerRegistry rsocketResponderHandlerRegistry) { RSocketRequesterBySubBroker subBroker = new RSocketRequesterBySubBroker(properties, env, rsocketResponderHandlerRegistry, filterChain, serviceRoutingSelector); return new UpstreamBrokerCluster(subBroker); } @Bean @Qualifier("upstreamBrokerRSocket") @ConditionalOnProperty(name = "rsocket.broker.upstream-brokers") public RSocket upstreamBrokerRSocket(UpstreamBrokerCluster upstreamBrokerCluster) { return upstreamBrokerCluster.getLoadBalancedRSocket(); } }