#Region "Microsoft.VisualBasic::396a7f884d25d310d332f7135525c582, ComputingServices\Asymmetric\Master.vb"
' Author:
'
' asuka (amethyst.asuka@gcmodeller.org)
' xie (genetics@smrucc.org)
' xieguigang (xie.guigang@live.com)
'
' Copyright (c) 2018 GPL3 Licensed
'
'
' GNU GENERAL PUBLIC LICENSE (GPL3)
'
'
' This program is free software: you can redistribute it and/or modify
' it under the terms of the GNU General Public License as published by
' the Free Software Foundation, either version 3 of the License, or
' (at your option) any later version.
'
' This program is distributed in the hope that it will be useful,
' but WITHOUT ANY WARRANTY; without even the implied warranty of
' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
' GNU General Public License for more details.
'
' You should have received a copy of the GNU General Public License
' along with this program. If not, see .
' /********************************************************************************/
' Summaries:
' Class Master
'
' Properties: IPAddress, Nodes, Portal
'
' Constructor: (+1 Overloads) Sub New
'
' Function: __folk, __getLoad, __getPreferNode, Folk, GetInstances
' NodeRegister, ToString
'
' Sub: Run
'
'
' /********************************************************************************/
#End Region
Imports Microsoft.VisualBasic.Net
Imports Microsoft.VisualBasic.Net.Http
Imports Microsoft.VisualBasic.Net.Protocols
Imports Microsoft.VisualBasic.Net.Protocols.Reflection
Imports Microsoft.VisualBasic.Net.SSL
Imports Microsoft.VisualBasic.Win32
Imports sciBASIC.ComputingServices.ComponentModel
Imports NodeAbstract = System.Collections.Generic.KeyValuePair(Of String, Microsoft.VisualBasic.Net.SSL.Certificate)
Namespace Asymmetric
'''
''' 非对等网络里面的中心主节点
'''
'''
Public Class Master : Inherits IMasterBase(Of SSLSynchronizationServicesSocket)
'''
''' 键名是IP地址,由于一台物理主机上面只会有一个管理节点,所以端口号都是固定了的
'''
Dim _nodes As SortedDictionary(Of String, Net.SSL.Certificate) =
New SortedDictionary(Of String, Net.SSL.Certificate)
Dim _protocol As ProtocolHandler
'''
''' 获取在当前的服务器上面注册了的所有的管理节点的位置
'''
'''
Public ReadOnly Property Nodes As String()
Get
Return _nodes.Keys.ToArray
End Get
End Property
Public Shared ReadOnly Property IPAddress As String = GetMyIPAddress()
Public Overrides ReadOnly Property Portal As IPEndPoint
Get
Return New IPEndPoint(IPAddress, __host.LocalPort)
End Get
End Property
'''
'''
'''
''' 计算自于宿主节点的证书哈希值
Sub New(PublicToken As String)
Dim [public] = Net.SSL.Certificate.Install(PublicToken, uid:=0)
__host = New Net.SSL.SSLSynchronizationServicesSocket(Protocols.MasterSvr, [public], container:=Me)
_protocol = New ProtocolHandler(Me)
__host.Responsehandler = AddressOf _protocol.HandleRequest
End Sub
Public Sub Run()
Call __host.Run()
End Sub
Public Overrides Function ToString() As String
Return __host.ToString
End Function
'''
''' 创建出一个新的计算节点里面的服务实例
'''
'''
'''
Public Function Folk(CLI As String) As Asymmetric.DDM.Instance
Dim Node As String = __getPreferNode()
If String.IsNullOrEmpty(Node) Then
Return Nothing
End If
Dim request As RequestStream = Protocols.FolkInstance(CLI)
Try
Return __folk(Node, request)
Catch ex As Exception
If WindowsServices.Initialized Then
Call ServicesLogs.LogException(ex)
Else
Call App.LogException(ex)
End If
Return Nothing
End Try
End Function
Private Function __folk(node As String, request As RequestStream) As Asymmetric.DDM.Instance
Dim socket As New Net.AsynInvoke(node, Protocols.ParasitiferSvr)
Dim CA As Net.SSL.Certificate = _nodes(node)
Dim response As RequestStream = socket.SendMessage(request, CA)
Dim instance = response.GetRawStream(Of DDM.Instance)
Return instance
End Function
'''
''' 获取当前网络之中的所有的已经运行的计算服务实例
'''
'''
Public Function GetInstances() As Microsoft.VisualBasic.Net.IPEndPoint()
Dim request As RequestStream = Protocols.GetInstanceList
Dim LQuery As Microsoft.VisualBasic.Net.IPEndPoint()() = (
From node As NodeAbstract In _nodes.AsParallel
Let result As RequestStream =
New Net.AsynInvoke(node.Key, Protocols.ParasitiferSvr) _
.SendMessage(request, node.Value) ' 请注意这里需要使用节点的证书来加密请求,否则节点会直接拒绝请求
Where result.Protocol = HTTP_RFC.RFC_OK
Select result.LoadObject(Of Microsoft.VisualBasic.Net.IPEndPoint())(AddressOf LoadFromXml)).ToArray
Dim list As Microsoft.VisualBasic.Net.IPEndPoint() = LQuery.ToVector
Return list
End Function
'''
''' 获取得到最优先的物理机来开启新的计算节点,优先级别是和分布式计算网络之中的物理主机节点的CPU,内存负载量成反比的(本机的节点优先级别最低)
'''
'''
Private Function __getPreferNode() As String
If _nodes.Count = 0 Then
Return ""
End If
Dim LQuery = (From node As NodeAbstract In _nodes
Let load As Double = __getLoad(node.Key, node.Value)
Where load >= 0
Select load, node.Key
Order By load Ascending).ToArray
If LQuery.IsNullOrEmpty Then
Return ""
End If
Dim prefer = (From node In LQuery
Where Not String.Equals(IPAddress, node.Key)
Select node).FirstOrDefault
If prefer Is Nothing Then ' LQuery查询结果不为空,但是不是本机IP的节点却没有,说明都是本机节点,直接返回第一个
Return LQuery.First.Key ' 本机节点的优先级最低,这个是处于管理中心节点的性能的影响来考虑的
Else
Return prefer.Key ' 优先利用其他节点的空闲的计算资源
End If
End Function
'''
'''
'''
'''
'''
''' 可能得到的是内网IP,所以不太准确,不是用这个参数来标记节点的位置
'''
Private Function NodeRegister(CA As Long, request As RequestStream, remote As System.Net.IPEndPoint) As RequestStream
Dim post As Protocols.RegisterPost = Protocols.GetPostData(request)
Dim nodeCA = __host.PrivateKeys(post.uid)
Dim IPAddr As String = post.IPAddress
If Me._nodes.ContainsKey(IPAddr) Then
Call Me._nodes.Remove(IPAddr)
Call $"There is a duplicated machine entry ""{IPAddr}"" in the manager's hash table, this probably is a node services restart event...".__DEBUG_ECHO
End If
Call Me._nodes.Add(post.IPAddress, nodeCA)
#If DEBUG Then
Call $"{post.IPAddress} ===> {nodeCA.ToString}".__DEBUG_ECHO
#End If
Return NetResponse.RFC_OK
End Function
'''
'''
'''
''' IP地址
'''
Private Function __getLoad(Node As String, CA As Net.SSL.Certificate) As Double
Dim request As RequestStream = Protocols.GetLoad
Dim socket = New Net.AsynInvoke(Node, Protocols.ParasitiferSvr)
Dim response As RequestStream = socket.SafelySendMessage(request, CA, 5 * 1000)
If Not response.Protocol = HTTP_RFC.RFC_OK Then
Return -100
Else
Return Val(response.GetUTF8String)
End If
End Function
End Class
End Namespace