
com.alibaba.spring.boot.rsocket.broker.cluster.RSocketBrokerManagerGossipImpl Maven / Gradle / Ivy
package com.alibaba.spring.boot.rsocket.broker.cluster;
import com.alibaba.rsocket.ServiceLocator;
import com.alibaba.rsocket.observability.RsocketErrorCode;
import com.alibaba.rsocket.route.RSocketFilter;
import com.alibaba.rsocket.transport.NetworkUtil;
import com.alibaba.spring.boot.rsocket.broker.RSocketBrokerProperties;
import com.alibaba.spring.boot.rsocket.broker.cluster.jsonrpc.JsonRpcRequest;
import com.alibaba.spring.boot.rsocket.broker.cluster.jsonrpc.JsonRpcResponse;
import com.alibaba.spring.boot.rsocket.broker.events.AppConfigEvent;
import com.alibaba.spring.boot.rsocket.broker.events.RSocketFilterEnableEvent;
import com.alibaba.spring.boot.rsocket.broker.services.ConfigurationService;
import io.cloudevents.v1.CloudEventImpl;
import io.micrometer.core.instrument.Metrics;
import io.scalecube.cluster.Cluster;
import io.scalecube.cluster.ClusterImpl;
import io.scalecube.cluster.ClusterMessageHandler;
import io.scalecube.cluster.Member;
import io.scalecube.cluster.membership.MembershipEvent;
import io.scalecube.cluster.transport.api.Message;
import io.scalecube.net.Address;
import org.eclipse.collections.api.block.function.primitive.DoubleFunction;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import reactor.core.publisher.EmitterProcessor;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import javax.annotation.PostConstruct;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* RSocket Broker Manager Gossip implementation
*
* @author leijuan
*/
public class RSocketBrokerManagerGossipImpl implements RSocketBrokerManager, ClusterMessageHandler, DisposableBean {
private Logger log = LoggerFactory.getLogger(RSocketBrokerManagerGossipImpl.class);
/**
* Gossip listen port
*/
private static int gossipListenPort = 42254;
/**
* seed members
*/
@Value("${rsocket.broker.seeds}")
private String[] seeds;
@Autowired
private ApplicationContext applicationContext;
@Autowired
private RSocketBrokerProperties brokerProperties;
private Mono monoCluster;
private RSocketBroker localBroker;
/**
* rsocket brokers, key is ip address
*/
private Map brokers = new HashMap<>();
/**
* brokers changes emitter processor
*/
private EmitterProcessor> brokersEmitterProcessor = EmitterProcessor.create();
private KetamaConsistentHash consistentHash;
@PostConstruct
public void init() {
final String localIp = NetworkUtil.LOCAL_IP;
monoCluster = new ClusterImpl()
.config(clusterConfig -> clusterConfig.externalHost(localIp).externalPort(gossipListenPort))
.membership(membershipConfig -> membershipConfig.seedMembers(seedMembers()).syncInterval(5_000))
.transport(transportConfig -> transportConfig.port(gossipListenPort))
.handler(cluster1 -> this)
.start();
//subscribe and start & join the cluster
monoCluster.subscribe();
this.localBroker = new RSocketBroker(localIp, brokerProperties.getExternalDomain());
this.consistentHash = new KetamaConsistentHash<>(12, Collections.singletonList(localIp));
brokers.put(localIp, localBroker);
log.info(RsocketErrorCode.message("RST-300002"));
Metrics.globalRegistry.gauge("cluster.broker.count", this, (DoubleFunction) brokerManagerGossip -> brokerManagerGossip.brokers.size());
}
@Override
public Flux> requestAll() {
return brokersEmitterProcessor;
}
@Override
public Collection currentBrokers() {
return this.brokers.values();
}
@Override
public RSocketBroker localBroker() {
return this.localBroker;
}
@Override
public Mono findByIp(String ip) {
if (brokers.containsKey(ip)) {
return Mono.just(this.brokers.get(ip));
} else {
return Mono.empty();
}
}
@Override
public Flux findServices(String ip) {
return Flux.empty();
}
@Override
public Boolean isStandAlone() {
return false;
}
public List seedMembers() {
return Stream.of(seeds)
.map(host -> Address.create(host, gossipListenPort))
.collect(Collectors.toList());
}
@Override
public void onMessage(Message message) {
if (message.header("jsonrpc") != null) {
JsonRpcRequest request = message.data();
Message replyMessage = Message.builder()
.correlationId(message.correlationId())
.data(onJsonRpcCall(request))
.build();
this.monoCluster.flatMap(cluster -> cluster.send(message.sender(), replyMessage)).subscribe();
}
}
public JsonRpcResponse onJsonRpcCall(JsonRpcRequest request) {
Object result;
if (request.getMethod().equals("BrokerService.getConfiguration")) {
Map config = new HashMap<>();
config.put("rsocket.broker.externalDomain", brokerProperties.getExternalDomain());
result = config;
} else {
result = "";
}
return new JsonRpcResponse(request.getId(), result);
}
public Mono makeJsonRpcCall(@NotNull Member member, @NotNull String methodName, @Nullable Object params) {
String uuid = UUID.randomUUID().toString();
Message jsonRpcMessage = Message.builder()
.correlationId(uuid)
.header("jsonrpc", "2.0")
.data(new JsonRpcRequest(methodName, params, uuid))
.build();
return monoCluster.flatMap(cluster -> cluster.requestResponse(member, jsonRpcMessage)).map(Message::data);
}
@Override
public void onGossip(Message gossip) {
if (gossip.header("cloudevents") != null) {
onCloudEvent(gossip.data());
}
}
public void onCloudEvent(CloudEventImpl
© 2015 - 2025 Weber Informatics LLC | Privacy Policy