166 lines
6.6 KiB
VB.net
166 lines
6.6 KiB
VB.net
#Region "Microsoft.VisualBasic::6864ab1abde87b67480f1e6467ea0b9e, Microsoft.VisualBasic.Core\ApplicationServices\Parallel\Threads\ServicesFolk.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 <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
' /********************************************************************************/
|
|
|
|
' Summaries:
|
|
|
|
' Module ServicesFolk
|
|
'
|
|
' Function: Folk, ReturnPortal
|
|
' Class __getChildPortal
|
|
'
|
|
' Function: HandleRequest, WaitForPortal
|
|
'
|
|
'
|
|
'
|
|
'
|
|
' /********************************************************************************/
|
|
|
|
#End Region
|
|
|
|
Imports System.Reflection
|
|
Imports Microsoft.VisualBasic.Net.Http
|
|
Imports Microsoft.VisualBasic.Net.Protocols
|
|
Imports Microsoft.VisualBasic.Win32
|
|
Imports SetValueAction = Microsoft.VisualBasic.Linq.SetValue(Of Microsoft.VisualBasic.Net.TcpSynchronizationServicesSocket)
|
|
|
|
Namespace Parallel
|
|
|
|
''' <summary>
|
|
''' 主服务和子服务之间的相互作用的特点是子服务不会知道主服务节点的数据接口,所有的交互都是通过子服务上面的一个模块来监听主服务来实现的
|
|
''' 当主服务有数据需要向子服务更新的时候,会主动发送数据请求至子服务节点
|
|
''' </summary>
|
|
''' <remarks>当前的用户规模还比较小这里仅仅是实现了本地的调用,后面考虑到业务吞吐量的问题,会将服务的调用分开到两台物理主机之上</remarks>
|
|
Public Module ServicesFolk
|
|
|
|
''' <summary>
|
|
''' 函数返回子进程的交互数据通信的端口号
|
|
''' </summary>
|
|
''' <param name="assm"></param>
|
|
''' <param name="CLI">命令行参数字符串,可以在这里加入一些其他的自定义数据</param>
|
|
''' <returns>函数返回子服务的交互端口</returns>
|
|
Public Function Folk(assm As String, ByRef CLI As String, Optional ByRef folked As Process = Nothing) As Integer
|
|
Dim Portal As Integer
|
|
|
|
'开通一个临时的端口用来和子服务交互
|
|
Using TempListen As New Net.TcpSynchronizationServicesSocket(
|
|
Net.TCPExtensions.GetFirstAvailablePort,
|
|
Sub(ex) App.LogException(ex, MethodBase.GetCurrentMethod.GetFullName))
|
|
|
|
Dim __getChildPortal As New __getChildPortal
|
|
|
|
Call SetValueAction.InvokeSet(Of Net.Abstract.DataRequestHandler)(
|
|
TempListen,
|
|
NameOf(TempListen.Responsehandler),
|
|
AddressOf __getChildPortal.HandleRequest)
|
|
|
|
Call RunTask(AddressOf TempListen.Run)
|
|
Call TempListen.WaitForStart()
|
|
|
|
Dim path As String =
|
|
If(assm.FileExists, FileIO.FileSystem.GetFileInfo(assm).FullName, $"{App.HOME}/{assm}")
|
|
#If DEBUG Then
|
|
Call $"Invoke start {path.ToFileURL} @{MethodBase.GetCurrentMethod.GetFullName}".__DEBUG_ECHO
|
|
#End If
|
|
Dim FolkSvr As Process =
|
|
Process.Start(path, $"{CLI} {ParentPortal} {TempListen.LocalPort}")
|
|
|
|
__getChildPortal.PID = FolkSvr.Id
|
|
Portal = __getChildPortal.WaitForPortal
|
|
folked = FolkSvr
|
|
CLI = __getChildPortal.addArgs
|
|
End Using
|
|
|
|
Dim msg As String = $"Get folked child services {assm} local_services:={Portal}"
|
|
|
|
Call msg.__DEBUG_ECHO
|
|
|
|
If WindowsServices.Initialized Then
|
|
Call ServicesLogs.WriteEntry(msg, EventLogEntryType.SuccessAudit)
|
|
End If
|
|
|
|
Return Portal
|
|
End Function
|
|
|
|
Private Class __getChildPortal
|
|
|
|
Public PID As Integer
|
|
Public Portal As Integer = -100
|
|
''' <summary>
|
|
''' 所返回来的额外的参数信息
|
|
''' </summary>
|
|
Public addArgs As String
|
|
|
|
Public Function HandleRequest(uid As Long, request As RequestStream, remote As System.Net.IPEndPoint) As RequestStream
|
|
If uid <> PID Then
|
|
Return NetResponse.RFC_TOKEN_INVALID
|
|
End If
|
|
|
|
Dim result As String = request.GetUTF8String
|
|
|
|
Portal = Scripting.CTypeDynamic(Of Integer)(result)
|
|
addArgs = CommandLine.GetTokens(result).ElementAtOrDefault(1)
|
|
|
|
Return NetResponse.RFC_OK
|
|
End Function
|
|
|
|
Public Function WaitForPortal() As Integer
|
|
Do While Portal < 0
|
|
Call Threading.Thread.Sleep(1)
|
|
Loop
|
|
|
|
Return Portal
|
|
End Function
|
|
End Class
|
|
|
|
Const ParentPortal As String = "--portal"
|
|
|
|
''' <summary>
|
|
''' 子服务向服务主节点返回端口号数据,这个方法需要要在子服务上面的服务程序启动之后再调用
|
|
''' </summary>
|
|
''' <param name="CLI"></param>
|
|
''' <param name="Port"></param>
|
|
''' <param name="addArgs">额外返回的参数信息</param>
|
|
''' <returns></returns>
|
|
Public Function ReturnPortal(CLI As CommandLine.CommandLine, Port As Integer, Optional addArgs As String = "") As Boolean
|
|
Dim parentPortal As Integer = CLI.GetInt32(ServicesFolk.ParentPortal)
|
|
Dim Client As New Net.AsynInvoke("127.0.0.1", parentPortal)
|
|
#If DEBUG Then
|
|
Call $"{MethodBase.GetCurrentMethod.GetFullName} ==> ""{CLI}"" returns {Port}".__DEBUG_ECHO
|
|
#End If
|
|
Dim request As New RequestStream(Process.GetCurrentProcess.Id, 0, $"{CStr(Port)} ""{addArgs}""") With {
|
|
.uid = Process.GetCurrentProcess.Id
|
|
}
|
|
Dim response As RequestStream = Client.SendMessage(request)
|
|
Return response.Protocol = HTTP_RFC.RFC_OK
|
|
End Function
|
|
End Module
|
|
End Namespace
|