С учетом двух или более клиентов finagle с разными именами получателей, если эти имена разрешаются по одному и тому же адресу inet, как заставить finagle поддерживать только один пул соединений с этой конечной точкой?
Слишком простой пример кода
Приведенный ниже код регистрирует очень простой (и в основном бесполезный) Resolver , который всегда разрешается по одному и тому же адресу. На практике это больше похоже на отношения многие к одному (а не все к одному). Есть еще одно простое приложение, которое запускает сервер и два клиента, которые оба используют распознаватель, чтобы найти адрес для связи с сервером.
// Registered with finagle Resolver via META-INF/services
class SmartResolver extends AbstractResolver {
@Override public String scheme() { return "smart"; }
@Override public Var<Addr> bind(String arg) {
return Vars.newConstVar(Addrs.newBoundAddr(Addresses.newInetAddress(
// assume this is more complicated and maps many names to
// one address
new InetSocketAddress("127.0.0.1", 9000)))));
}
}
class Main {
public static void main(String[] args) {
// Create a server, we record stats so we can see how many connections
// there are
InMemoryStatsReceiver stats = new InMemoryStatsReceiver();
ListeningServer server = Thrift.server()
.withStatsReceiver(stats)
.serveIface(":9000", (EchoService.ServiceIface) Future::value);
// create a few clients that all connect to a resolved server, the
// resolver ensures that they all are communicating with our server
EchoService.ServiceIface c1 = Thrift.client()
.newIface("smart!c1", EchoService.ServiceIface.class);
EchoService.ServiceIface c2 = Thrift.client()
.newIface("smart!c2", EchoService.ServiceIface.class);
// make sure any lazy connections have been opened
Await.result(c1.echo("c1"));
Await.result(c2.echo("c2"));
// I'm not sure how to see how many physical connections there are
// incoming to the server, or if it's possible to do this.
assertEquals(1, stats.counter(JavaConversions.asScalaBuffer(Arrays.asList("connects"))))
Await.result(server.close());
}
}
// echo.thrift
service EchoService {
string echo(1: string quack);
}
Все детали
Там, где я работаю, у нас есть микросервисная архитектура, использующая finagle и thrift, мы используем Consul для обнаружения сервисов. Некоторые из внешних систем, с которыми мы взаимодействуем, очень ограничивают количество и частоту принимаемых ими tcp-соединений, поэтому некоторые экземпляры служб «несут ответственность» за эти соединения. Чтобы убедиться, что запросы, которым необходимо использовать определенные соединения, отправляются в правильную службу, эта служба регистрирует новое имя службы в консуле, представляющее соединение, за которое она отвечает. Затем клиенты ищут службу по имени соединения, а не по имени службы.
Чтобы сделать это более понятным: скажем, у вас есть device-service
, который открывает TCP-соединения с настроенным списком устройств, устройства поддерживают только одно соединение одновременно. У вас может быть несколько экземпляров этого device-service
с определенной схемой разделения устройств между device-service
. Таким образом, экземпляр A
подключается к устройствам foo
и bar
, экземпляр B
подключается к baz
.
Теперь у вас есть другая служба, скажем, poke-service
, которая должна общаться с определенными устройствами (через device-service
). Я решил эту проблему так: регистр device-service
экземпляр A
foo
и bar
и экземпляр B
регистр baz
, все по своему локальному адресу. Таким образом, поиск foo
разрешает адреса для device-service
экземпляра A
вместо более общего кластера из всех device-service
экземпляров.
Проблема, которую я хотел бы решить, - это проблема оптимизации, я хотел бы, чтобы finagle признал, что и foo
, и bar
фактически разрешают по одному и тому же адресу и повторно использует все ресурсы, которые он выделяет и поддерживает как часть связи. Кроме того, если foo
и bar
будут переназначены на другие device-service
экземпляры, я бы хотел, чтобы все просто работали на основе информации в Консуле, которая отражала бы это изменение.