Обеспечение сервиса WCF с помощью basicHttpBinding, который поддерживает потоковую передачу

Существует библиотека libvips для отслеживания и отладки количества ссылок - вы можете попробовать включить это и посмотреть, есть ли у вас утечки.

https://libvips.github.io/libvips/API/current/libvips-vips.html#vips-leak-set

Хотя из вашего комментария выше о bimg memory Похоже, что все в порядке.

Легко протестировать память libvips из Python. Я сделал эту небольшую программу:

#!/usr/bin/python3

import pyvips
import sys

# disable libvips operation caching ... without this, it'll cache all the
# thumbnail operations and we'll just be testing the jpg write
pyvips.cache_set_max(0)

for i in range(0, 10000):
    print("loop {} ...".format(i))
    for filename in sys.argv[1:]:
        # thumbnail to fit 128x128 box
        image = pyvips.Image.thumbnail(filename, 128)
        thumb = image.write_to_buffer(".jpg")

т.е. несколько раз миниатюрный набор исходных изображений. Я запустил это так:

$ for i in {1..100}; do cp ~/pics/k2.jpg $i.jpg; done
$ ../fing.py *

И смотрел RES наверху. Я видел:

loop | RES (kb)
  -- | --
 100 | 39220
 250 | 39324
 300 | 39276
 400 | 39316
 500 | 39396
 600 | 39464
 700 | 39404
1000 | 39420

Пока у вас нет утечек на счетах, я думаю, что вы видите ожидаемое поведение. Процессы Linux могут выпускать страницы только в конце кучи обратно в ОС (посмотрите вызовы srs brk и sbrk):

https://en.wikipedia.org/wiki/ Sbrk

Теперь представьте, если 1) libvips выделяет 6 ГБ, 2) среда выполнения Go выделяет 100 КБ, 3) libvips выпускает 6 ГБ. Ваша libc (вещь в вашем процессе, которая будет вызывать sbrk и brk от вашего имени) не может вернуть 6 ГБ обратно в ОС из-за выделения 100 КБ в конце кучи. Некоторые реализации malloc демонстрируют лучшее поведение при фрагментации памяти, чем другие, но стандартная версия linux довольно хороша.

1114 На практике это не имеет значения. malloc будет повторно использовать дыры в вашем пространстве памяти, и даже если этого не произойдет, они все равно будут выгружены под давлением памяти и не будут в конечном итоге съедать оперативную память. Попробуйте запустить ваш процесс в течение нескольких часов, и посмотрите RES. Вы должны увидеть, как оно подкрадывается, но затем стабилизируется.

(Я совсем не специалист по ядру, вышеизложенное - только мое понимание, исправления очень приветствуются, конечно)

12
задан Community 23 May 2017 в 11:45
поделиться

4 ответа

Ну, я нашел много проблемы, связанные с безопасностью / потоковой передачей при работе над этой проблемой. Хак (э ... гм ... Обходной путь) В конце концов, я решил создать новый DataContract, который наследует MemoryStream и украсил его свойством BaseStream (для хранения данных, которые я хочу передать в потоковом режиме) вместе с соответствующими свойствами, используемыми для простой аутентификации.

Вот полученный DataContract. :

[DataContract]
[KnownType( typeof( MemoryStream ) )] 
public class StreamWithCredentials : MemoryStream
{
    [DataMember]
    public Stream BaseStream { get; set; }

    [DataMember]
    public string Username { get; set; }

    [DataMember]
    public string Password { get; set; }
}

Приведенный выше DataContract становится входным параметром моего метода службы. Первое действие, которое предпринимает моя служба, - это аутентифицировать предоставленные учетные данные по известным действительным значениям и продолжить при необходимости.

Теперь я знаю , что это не самый безопасный вариант, но моя директива заключалась в том, чтобы избегать использования SSL (, в котором я даже не уверен, что это вообще возможно - как указано здесь ) для этого внутреннего процесса.

При этом,

6
ответ дан 2 December 2019 в 22:23
поделиться

There's a number of things you could do:

  • add a certificate to each and every machine that's allowed to use your service, and check for that certificate. That only allows you to exclude "unauthorized" machines - you cannot limit it to a specific application
  • same as above, but include the certificate embedded in your winforms app and send it from there (do not store it in the machine's certificate store)
  • require a username / password that only that particular app of yours knows about and can transmit to your service; e.g. someone else would not be able to present the appropriate credentials

EDIT 2: OK, so the username/password approach seems to get out of hand.... what if you just have basic transport security (SSL) for basic protection, and then use the MessageContract to define header and body of your SOAP message, include a specific value in the header, and then just check for that presence of the element in the header in your service?

Something like that:

[DataContract]
class YourRequestData
{
 ...
}

[MessageContract]
public class YourRequest
{
  [MessageBodyMember]
  public YourRequestData bodyData { get; set; }

  [MessageHeader]
  public string AppThumbprint { get; set; }
}

And then on your server in your code just check for the presence and the validity of that AppThumbprint code:

public Stream RequestStream(YourRequest request)
{
  if(AppThumbprintIsValid(request.AppThumbprint))
  {
     .... begin your streaming
  }
}

That might end up being a lot easier than the username/password security scenario.

Marc

1
ответ дан 2 December 2019 в 22:23
поделиться

Если это будет приложение, живущее в интрасети, может быть проще всего просто создать новую группу в вашей Active Directory и предоставить только членам этой группы возможность использовать службу ,

Вы можете добавить аутентификацию (используя учетные данные Windows) примерно так:

<basicHttpBinding> 
 <security mode="TransportCredentialOnly"> 
  <transport clientCredentialType="Windows" /> 
 </security> 
</basicHttpBinding> 

Затем можно авторизовать, украсив интерфейс для ваших методов службы:

<PrincipalPermission(SecurityAction.Demand, Role:="MyAppsUsers")> _ 
Public Function MyMethod() As String Implements IService.MyMethod 

Вот хорошая ссылка на безопасность в WCF. В конце он содержит множество инструкций (один под названием «Как использовать базовую привязку Http с проверкой подлинности Windows и TransportCreditals» может быть вам полезен).
Wcf Secruity

[Заявление об ограничении ответственности: я тоже новичок в WCF и раньше не делал этого, поэтому извиняюсь, если это немного не так!]

0
ответ дан 2 December 2019 в 22:23
поделиться

Если вы хотите использовать basicHttpBinding (для interop), вы можете передавать учетные данные только на уровне сообщения. Вы должны установить конфигурацию безопасности на TransportWithMessageCredential.

Для этого вы должны создать SSL-канал, поэтому вам нужен сертификат на стороне сервера, и не обязательно, чтобы он был у клиента.

1
ответ дан 2 December 2019 в 22:23
поделиться
Другие вопросы по тегам:

Похожие вопросы: