client/Apache.ShenYu.Client/Registers/ShenyuConsulRegister.cs (124 lines of code) (raw):
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Apache.ShenYu.Client.Models.DTO;
using Apache.ShenYu.Client.Options;
using Apache.ShenYu.Client.Utils;
using Consul;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using static Apache.ShenYu.Client.Utils.Constants;
namespace Apache.ShenYu.Client.Registers
{
public class ShenyuConsulRegister : ShenyuAbstractRegister
{
private readonly ILogger<ShenyuConsulRegister> _logger;
private ShenyuOptions _shenyuOptions;
private ConsulClient _client;
private AgentServiceRegistration _service;
private static char SEPARATOR = '-';
public ShenyuConsulRegister(ILogger<ShenyuConsulRegister> logger)
{
_logger = logger;
}
public override Task Init(ShenyuOptions shenyuOptions)
{
if (string.IsNullOrEmpty(shenyuOptions.Register.ServerList))
{
throw new System.ArgumentException("serverList can not be null.");
}
this._shenyuOptions = shenyuOptions;
ConsulClientConfiguration config = new ConsulClientConfiguration();
config.Address = new Uri(this._shenyuOptions.Register.ServerList);
config.Token = shenyuOptions.Register.Props.GetValueOrDefault(RegisterConstants.Token, "");
this._client = new ConsulClient(config);
_service = GetAgentService();
return Task.CompletedTask;
}
public override async Task PersistInterface(MetaDataRegisterDTO metadata)
{
string contextPath = ContextPathUtils.BuildRealNode(metadata.contextPath, metadata.appName);
string metadataNodeName = BuildMetadataNodeName(metadata);
string metaDataPath = RegisterPathConstants.BuildMetaDataParentPath(metadata.rpcType, contextPath);
string realNode = RegisterPathConstants.BuildRealNode(metaDataPath, metadataNodeName);
realNode = UriUtils.RemovePrefix(realNode);//remove prefix /
var metadataStr = JsonConvert.SerializeObject(metadata, Formatting.None,
new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });
var putPair = new KVPair(realNode) { Value = Encoding.UTF8.GetBytes(metadataStr) };
await this._client.KV.Put(putPair);
_logger.LogInformation($"{metadata.rpcType} Consul client register success: {metadataStr}");
}
public override Task PersistURI(URIRegisterDTO registerDTO)
{
var uriRegString = JsonConvert.SerializeObject(registerDTO, Formatting.None,
new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });
var dic = new Dictionary<string, string> { { Constants.UriType, uriRegString } };
_service.Meta = dic;
this._client.Agent.ServiceRegister(_service);
return Task.CompletedTask;
}
public override async Task Close()
{
await this._client.Agent.ServiceDeregister(this._shenyuOptions.Register.Props[Constants.RegisterConstants.Id]);
}
private AgentServiceRegistration GetAgentService()
{
var props = this._shenyuOptions.Register.Props;
//check data
string appName = NormalizeForDns(props[Constants.RegisterConstants.Name]);
string instanceId = NormalizeForDns(props[Constants.RegisterConstants.Id]);
string portStr = props[Constants.RegisterConstants.Port];
if (string.IsNullOrEmpty(portStr))
{
throw new System.ArgumentException("Port can not be null.");
}
string tagsStr = props[Constants.RegisterConstants.Tags];
string[] tags = null ;
if (!string.IsNullOrEmpty(tagsStr))
{
tags = tagsStr.Split(',');
}
string address = props.GetValueOrDefault(Constants.RegisterConstants.HostName,"localhost");
_service = new AgentServiceRegistration
{
ID = instanceId,
Name = appName,
Tags = tags,
Port = Int32.Parse(portStr),
Address = address,
EnableTagOverride = Boolean.Parse(props.GetValueOrDefault(Constants.RegisterConstants.EnableTagOverride, "false"))
};
return _service;
}
private string NormalizeForDns(string s)
{
if (string.ReferenceEquals(s, null) || !char.IsLetter(s[0]) || !char.IsLetterOrDigit(s[s.Length - 1]))
{
throw new System.ArgumentException("Consul service ids must not be empty, must start "
+ "with a letter, end with a letter or digit, "
+ "and have as interior characters only letters, "
+ "digits, and hyphen: " + s);
}
StringBuilder normalized = new StringBuilder();
char? prev = null;
foreach (char curr in s.ToCharArray())
{
char? toAppend = null;
if (char.IsLetterOrDigit(curr))
{
toAppend = curr;
}
else if (prev == null || !(prev == SEPARATOR))
{
toAppend = SEPARATOR;
}
if (toAppend != null)
{
normalized.Append(toAppend);
prev = toAppend;
}
}
return normalized.ToString();
}
}
}