We are deploying a spring-boot application using spring-session-hazelcast + hazelcast-kubernetes on an OpenShift/Kubernetes cluster.
Due to the nature of our platform, we can only use service-dns configuration. We expose a service on port 5701 for multicasting and set service-dns property to the multicast service name.
Below is a snippet for creation of the Hazelcast instance.
#Bean
public HazelcastInstance hazelcastInstance() {
var config = new Config();
config.setClusterName("spring-session-cluster");
var join = config.getNetworkConfig().getJoin();
join.getTcpIpConfig().setEnabled(false);
join.getMulticastConfig().setEnabled(false);
join.getKubernetesConfig().setEnabled(true)
.setProperty("service-dns", "<multicast-service-name>");
var attribute = new AttributeConfig()
.setName(Hazelcast4IndexedSessionRepository.PRINCIPAL_NAME_ATTRIBUTE)
.setExtractorClassName(Hazelcast4PrincipalNameExtractor.class.getName());
config.getMapConfig(Hazelcast4IndexedSessionRepository.DEFAULT_SESSION_MAP_NAME)
.addAttributeConfig(attribute)
.addIndexConfig(new IndexConfig(IndexType.HASH, Hazelcast4IndexedSessionRepository.PRINCIPAL_NAME_ATTRIBUTE));
var serializer = new SerializerConfig();
serializer.setImplementation(new HazelcastSessionSerializer())
.setTypeClass(MapSession.class);
config.getSerializationConfig().addSerializerConfig(serializer);
return Hazelcast.newHazelcastInstance(config);
}
When we run 2 pods for this application, we see the below ERROR log:
com.hazelcast.internal.cluster.impl.operations.SplitBrainMergeValidationOp
Message: [<private-ip>]:5701 [spring-session-cluster] [4.2] Target is this node! -> [<private-ip>]:5701
Can someone please explain how to fix this error, still using "service-dns" configuration?
You need to enable headless mode for your service in openshift.
https://github.com/hazelcast/hazelcast-kubernetes#dns-lookup
Just add configuration for split brain protection
SplitBrainProtectionConfig splitBrainProtectionConfig = new SplitBrainProtectionConfig();
splitBrainProtectionConfig.setName("splitBrainProtectionRuleWithFourMembers")
.setEnabled(true)
.setMinimumClusterSize(4);
MapConfig mapConfig = new MapConfig();
mapConfig.setSplitBrainProtectionName("splitBrainProtectionRuleWithFourMembers");
Config config = new Config();
config.addSplitBrainProtectionConfig(splitBrainProtectionConfig);
config.addMapConfig(mapConfig);
You can read more about this in hazelcast documentation:
https://docs.hazelcast.com/imdg/4.2/network-partitioning/split-brain-protection.html
Related
I am trying to handle websocket wss:// in a gateway application. By spring integration all I want to do is accept from a client and route it to another backend server only changing the host and port with this uri template wss://host:port/{server-id}/{session-id}/websocket. proxy/reverse proxy with various message content text/binary.
ServerWebSocketContainer serverWebSocketContainer =
new ServerWebSocketContainer("/{server-id}/{session-id}/websocket")
.setHandshakeHandler(serverContext.getBean(HandshakeHandler.class))
.withSockJs();
WebSocketInboundChannelAdapter webSocketInboundChannelAdapter =
new WebSocketInboundChannelAdapter(serverWebSocketContainer);
QueueChannel dynamicRequestsChannel = new QueueChannel();
IntegrationFlow serverFlow =
IntegrationFlows.from(webSocketInboundChannelAdapter)
.channel(dynamicRequestsChannel)
.get();
IntegrationFlowContext.IntegrationFlowRegistration dynamicServerFlow =
serverIntegrationFlowContext.registration(serverFlow)
.addBean(serverWebSocketContainer)
.register();
// Dynamic client flow
ClientWebSocketContainer clientWebSocketContainer =
new ClientWebSocketContainer(this.webSocketClient, this.server.getWsBaseUrl() + "/{server-id}/{session-id}/websocket");
clientWebSocketContainer.setAutoStartup(true);
WebSocketOutboundMessageHandler webSocketOutboundMessageHandler =
new WebSocketOutboundMessageHandler(clientWebSocketContainer);
IntegrationFlow clientFlow = flow -> flow.handle(webSocketOutboundMessageHandler);
IntegrationFlowContext.IntegrationFlowRegistration dynamicClientFlow =
this.integrationFlowContext.registration(clientFlow)
.addBean(clientWebSocketContainer)
.register();
dynamicClientFlow.getInputChannel().send(new GenericMessage<>("dynamic test"));
I am working on a Xamarin project with Prism and DryIoC.
Currently I am setting up some custom environment-specific configuration, however I am struggling with the IoC syntax for this.
I have the following code as part of my App.xaml.cs:
private void SetConfiguration(IContainerRegistry containerRegistry)
{
// Get and deserialize config.json file from Configuration folder.
var embeddedResourceStream = Assembly.GetAssembly(typeof(IConfiguration)).GetManifestResourceStream("MyVismaMobile.Configurations.Configuration.config.json");
if (embeddedResourceStream == null)
return;
using (var streamReader = new StreamReader(embeddedResourceStream))
{
var jsonString = streamReader.ReadToEnd();
var configuration = JsonConvert.DeserializeObject<Configuration.Configuration>(jsonString);
What to do with configuration, in order to DI it?
}
What should I do with the configuration variable to inject it?
I have tried the following:
containerRegistry.RegisterSingleton<IConfiguration, Configuration>(c => configuration);
containerRegistry.Register<IConfiguration, Configuration>(c => configuration));
But the syntax is wrong with dryIoC.
RegisterSingleton and Register are meant for registering types where the container will then create the instances. You have your instance already, so you use
containerRegistry.RegisterInstance<IConfiguration>( configuration );
Instances are always singleton, obviously, so there's only no separate RegisterInstanceSingleton...
I have successfully created a connection between client and server(localhost) in ignite.But while trying to connect the ignite server which is running in remote IP(eg: 192.168.33.44), I am not able to establish connection. The client side configuration given below.
#Bean(name = "igniteConfiguration")
public IgniteConfiguration igniteConfiguration() {
IgniteConfiguration igniteConfiguration = new IgniteConfiguration();
igniteConfiguration.setClientMode(true);
igniteConfiguration.setPeerClassLoadingEnabled(true);
igniteConfiguration.setLocalHost("127.0.0.1");
TcpDiscoverySpi tcpDiscoverySpi = new TcpDiscoverySpi();
TcpDiscoveryMulticastIpFinder ipFinder = new TcpDiscoveryMulticastIpFinder();
ipFinder.setAddresses(Collections.singletonList("127.0.0.1:47500..47509"));
tcpDiscoverySpi.setIpFinder(ipFinder);
tcpDiscoverySpi.setLocalPort(47500);
// Changing local port range. This is an optional action.
tcpDiscoverySpi.setLocalPortRange(9);
tcpDiscoverySpi.setLocalAddress("localhost");
igniteConfiguration.setDiscoverySpi(tcpDiscoverySpi);
TcpCommunicationSpi communicationSpi = new TcpCommunicationSpi();
communicationSpi.setLocalAddress("localhost");
communicationSpi.setLocalPort(48100);
communicationSpi.setSlowClientQueueLimit(1000);
igniteConfiguration.setCommunicationSpi(communicationSpi);
igniteConfiguration.setCacheConfiguration(cacheConfiguration());
return igniteConfiguration;
}
Can anyone help me to make code change for creating a successful client-server connecion.Thanks in advance.
Since you are moving from localhost deployment, you need to do the following changes:
TcpDiscoveryMulticastIpFinder ipFinder = new TcpDiscoveryMulticastIpFinder();
ipFinder.setAddresses(Collections.singletonList("192.168.33.44:47500..47509"));
Most likely, the server configurations need to be changed as well.
I have developed a conversation service using IBM Watson and deployed. I am able to access my service using the IBM Watson API explorer. I tried connecting the service using a Java API as explained in https://developer.ibm.com/recipes/tutorials/integration-of-ibm-watson-conversation-service-to-your-java-application/ I am working on a corporate network, so using proxy to access internet. Now I am not able to access the service from my Java API. I am getting below error.
Exception in thread "main" java.lang.RuntimeException: java.net.ConnectException: Failed to connect to gateway.watsonplatform.net/169.48.66.222:443
at com.ibm.watson.developer_cloud.service.WatsonService$1.execute(WatsonService.java:182)
at com.chat.CustomerChat.conversationAPI(CustomerChat.java:47)
at com.chat.CustomerChat.main(CustomerChat.java:32)
Caused by: java.net.ConnectException: Failed to connect to gateway.watsonplatform.net/169.48.66.222:443
at okhttp3.internal.io.RealConnection.connectSocket(RealConnection.java:187)
at okhttp3.internal.io.RealConnection.buildConnection(RealConnection.java:170)
at okhttp3.internal.io.RealConnection.connect(RealConnection.java:111)
at okhttp3.internal.http.StreamAllocation.findConnection(StreamAllocation.java:187)
at okhttp3.internal.http.StreamAllocation.findHealthyConnection(StreamAllocation.java:123)
at okhttp3.internal.http.StreamAllocation.newStream(StreamAllocation.java:93)
at okhttp3.internal.http.HttpEngine.connect(HttpEngine.java:296)
at okhttp3.internal.http.HttpEngine.sendRequest(HttpEngine.java:248)
at okhttp3.RealCall.getResponse(RealCall.java:243)
at okhttp3.RealCall$ApplicationInterceptorChain.proceed(RealCall.java:201)
at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:163)
at okhttp3.RealCall.execute(RealCall.java:57)
How do we set proxy connection in IBM watson Connection service?
My code:(Modified the user credentials and workspace id here)
ConversationService service = new ConversationService("2017-05-26");
service.setUsernameAndPassword("dfgdfg-578a-46b6-55hgg-ghgg4343", "ssdsd455gfg");
MessageRequest newMessage = new MessageRequest.Builder().inputText(input).context(context).build();
String workspaceId = "fgfdgfgg-ce7a-422b-af23-gfgf56565";
MessageResponse response = service.message(workspaceId, newMessage).execute();
Not completely sure about work around for Java, but when i had similar issue with Node, i had to set up proxy variables and that helped. I would recommend you to give a try by setting up proxy variables in eclipse and JVM. And also i think this Java file must be helpful.
After going though IBM API documentation I found below method to set the proxy. It should work.
HttpConfigOptions config = new HttpConfigOptions
.Builder()
.proxy(new Proxy(Proxy.Type.HTTP,
new InetSocketAddress("<Proxy IP>", <Proxy Port>)))
.build();
service.configureClient(config);
I implemented this code with Java-sdk 6.14.0. IBM has discontinued ConversationService package and deprecated Conversation package in this version of SDK. Instead Assistant package has been introduced. My working code is as below.
Assistant service = null;
Context context = null;
if (watsonUser.equalsIgnoreCase(APIKEY_AS_USERNAME))
{
IamOptions iamOptions = new IamOptions.Builder().apiKey(watsonApikey).build();
service = new Assistant(watsonVersion, iamOptions);
}
else
{
service = new Assistant(watsonVersion, watsonUser,watsonPassword);
}
service.setEndPoint(watsonUrl);
if(watsonProxy != null)
{
HttpConfigOptions config = new HttpConfigOptions
.Builder()
.proxy(new Proxy(Proxy.Type.HTTP,
new InetSocketAddress(watsonProxyIP, watsonProxyPort)))
.build();
service.configureClient(config);
}
String workspaceId = watsonWorkspace_id;
InputData input = new InputData.Builder(inputStr).build();
MessageOptions options = new MessageOptions.Builder(workspaceId)
.context(context)
.input(input)
.build();
MessageResponse response = service.message(options).execute();
context = response.getContext();
I have checked the code with Conversation package based implementation. It worked. I couldn't checked with code given in the question as ConversationService package is no more in the current SDK.
I'm trying to use an existing Consul cluster as the membership provider for a test Orleans application.
I get this error when connecting my client app to the Silo
Could not find any gateway in Orleans.Runtime.Host.ConsulBasedMembershipTable. Orleans client cannot initialize.
Digging into the ConsulUtils class, the entries being retrieved have no ProxyPort defined - and are discarded - hence the empty result set.
I initialize the silo like this:
var clusterConfiguration = new ClusterConfiguration();
clusterConfiguration.Globals.DataConnectionString = "http://localhost:8500";
clusterConfiguration.Globals.DeploymentId = "OrleansPlayground";
clusterConfiguration.Globals.LivenessType = GlobalConfiguration.LivenessProviderType.Custom;
clusterConfiguration.Globals.MembershipTableAssembly = "OrleansConsulUtils";
clusterConfiguration.Globals.ReminderServiceType = GlobalConfiguration.ReminderServiceProviderType.Disabled;
var silohost = new SiloHost("Fred", clusterConfiguration);
silohost.InitializeOrleansSilo();
startup = Task.Factory.StartNew(() =>
{
return silohost.StartOrleansSilo();
});
return true;
And I set my client app up like this:
var config = new ClientConfiguration();
config.CustomGatewayProviderAssemblyName = "OrleansConsulUtils";
config.DataConnectionString = "http://localhost:8500";
config.DeploymentId = "OrleansPlayground";
config.GatewayProvider = ClientConfiguration.GatewayProviderType.Custom;
GrainClient.Initialize(config);
Looking at the code in ConsulUtils I can see that the ProxyPort isn't set (i.e. is 0) when the entry is saved. So I'm assuming I have a problem when initializing the silo - but I can't figure out what it is!
Without digging deep in, does sound like a bug. Please repost on GitHub and we will try to help you.