简体   繁体   English

在一段时间后重试功能的最佳方法,然后重试

[英]Best approach to timeout a function after a certain period of time and retry

Just a little bit of background. 只是一点点背景。 We are moving away from storing our user passwords hashed in a database to authenticating directly against Active Directory. 我们正在从将散列在数据库中的用户密码存储到直接针对Active Directory进行身份验证。 Unfortunately we have so many internal applications that updating every application is not an option at this point. 不幸的是,我们有太多内部应用程序,以至于此时无法更新每个应用程序。

So instead of requiring all our developers to change their code, I thought I could just build a .NET CLR Assembly for SQL and just modify the existing authentication stored procedure to validate the users password against our domain controllers instead of a table. 因此,我认为我可以只为SQL构建一个.NET CLR程序集,并修改现有的身份验证存储过程,以针对我们的域控制器(而不是表)验证用户密码,而不是要求所有开发人员更改其代码。

This has been successful in our initial testing, except when the domain controller cannot be communicated with for whatever reason (shutdown, restart, network, etc). 这在我们的初始测试中是成功的,除了由于某种原因(关闭,重新启动,网络等)无法与域控制器通信时。 When this happens we get timeouts. 发生这种情况时,我们会超时。 I added a try/catch and while loop to just skip to the next domain controller and attempt to authenticate against it, but it still takes the first attempt well over 20 seconds to fail before it tries to authenticate against the next server. 我添加了一个try / catch和while循环,以仅跳到下一个域控制器并尝试对其进行身份验证,但是在尝试对下一个服务器进行身份验证之前,它仍然需要20秒钟以上的首次尝试失败。 Since this is a SQL assembly/function and is being called in a stored procedure 20 seconds is way too long. 因为这是SQL程序集/函数,并且在存储过程中被调用,所以20秒太长了。

What is the best approach to modify my code and fail the authentication attempt against a server and try the next server, say, after 3 seconds? 什么是修改我的代码并使对服务器的身份验证尝试失败并在3秒钟后尝试下一个服务器的最佳方法? Threading somehow? 以某种方式穿线?

Imports System
Imports System.Data
Imports System.Collections
Imports System.Text
Imports Microsoft.SqlServer.Server
Imports System.Data.SqlTypes
Imports System.Runtime.InteropServices
Imports System.DirectoryServices.AccountManagement

Partial Public Class UserDefinedFunctions

    <SqlFunction(Name:="ValidCredentials")>
    Public Shared Function ValidCredentials(ByVal Domain As SqlString, ByVal Username As SqlString, ByVal Password As SqlString) As SqlBoolean
        'Validates the username and password are correct against the domain.

        Dim ServerNum As Integer = 1
        Dim Success As Boolean = False
        Dim ValidCreds As SqlBoolean = False

        'Loop through all 4 domain controllers to attempt authentication against each of them.
        While Success = False And ServerNum <= 4

            Try

                Dim pc As PrincipalContext
                If Domain = "employees" Then
                    pc = New PrincipalContext(ContextType.Domain, "DC-E-0" & ServerNum.ToString & ".employees.ourdomain.loc", "EMPLOYEES\BindAcct", "PASS")
                Else
                    pc = New PrincipalContext(ContextType.Domain, "DC-S-0" & ServerNum.ToString & ".students.ourdomain.loc", "STUDENTS\BindAcct", "PASS")
                End If

                ValidCreds = pc.ValidateCredentials(Username, Password)
                Success = True
                Return ValidCreds

            Catch ex As Exception

                ValidCreds = False
                Success = False
                ServerNum += 1

            End Try

        End While

        Return ValidCreds

    End Function

End Class

You can set timeout value for your function on sql server 2008 or above with the following lines of code. 您可以使用以下代码行在sql server 2008或更高版本上为函数设置超时值。 Just put it on the top of your block: 只需将其放在块的顶部即可:

SET LOCK_TIMEOUT 3000;  
GO

The value of the timeout is expressed in milliseconds . 超时值以milliseconds

According to MS Documentation : 根据MS文档

When a wait for a lock exceeds the time-out value, an error is returned. 当等待锁的时间超过超时值时,将返回错误。

That will cause that your function takes less than 3 seconds or fail. 这将导致您的功能花费少于3秒或失败。 Then you should catch the exception and rollback if needed. 然后,您应该捕获异常并在需要时回滚。

You can do this with a separate thread: 您可以使用单独的线程执行此操作:

Set timeout to an operation 设置操作超时

The code is in C#, but it should be straightforward to convert. 代码在C#中,但是转换起来应该很简单。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM