2012-05-31 3 views
4

JGroups가 특정 서버를 코디네이터로 사용하도록하고, 해당 서버가없는 경우 지정된 코디네이터가 클러스터에 다시 가입 할 때까지 새 코디네이터를 선출하고 코디네이터를 인계합니다.JGroups에서 어떤 노드를 코디네이터로 만들려고합니까?

이 경우 우리는 코디네이터가 업데이트를 위해 수신하는 코디네이터의 정보를 가지고 있지만 업데이트를 처리하는 &을 가져 오는 것은 리소스 집약적 일 수 있으므로 아무 것도 서버에 보내지 않으려 고합니다. 바깥 세상. 따라서 클러스터 앞의로드 밸런서에서는 코디네이터에게 보내지 않도록 설정했습니다. 그러나 코디네이터가 무작위로 선출되었으므로 기본적으로 단일 시스템 만 들어 올 때까지 클러스터를 종료 한 다음 나머지 클러스터를 다시 시작해야합니다.

+1

'org.jgroups.protocols.pbcast.GMS'를 확장하고 determineCoordinator 주소'오버라이드()' . getter/setter를 추가하고 코디네이터로 기본 주소를 지정할 수 있습니다. 노드가 온라인 (멤버의 일부) 인 경우 super.determineCoordinator()를 호출하지 않으면 노드가 선택됩니다. 그 정도면 충분합니다. – bestsss

답변

5

현재 이렇게 할 방법이 없습니다. Jgroups는 코디네이터가 그룹의 노드 중 하나가 될 수 있도록 상당한 시간을 들였습니다. 그룹 구성원 목록의 상태를 유지 관리하고 모니터링하는 모든 작업은 그룹의 모든 구성원간에 공유되어 코디네이터 직무가 코디네이터의 성과에 영향을주지 않도록합니다. 표준 GMS (Group MembershipService) 프로토콜 스택 클래스는 코디네이터 선택을 담당합니다. 현재 그것은보기 목록의 첫 번째 호스트 일뿐입니다.

이 동작을 얻으려면 자체 프로토콜 스택을 구현해야합니다. 흥미롭게도, 나는 Jgroups를위한 프로토콜 스택을 작업 해왔다. Jgroups는 당신이 요구하는 것을 구현하지만, 프라임 타임에는 준비가되어 있지 않다.

그러나 다른 사람들은이 문제를 해결하지 못했을 수 있습니다. jgroups mailing list에 게시하고 같은 질문을하는 것이 좋습니다.

0

원하는 노드를 코디네이터로 설정할 수 있습니다. : github sample

그리고 난 모든 노드 및 전체 코드에서 완전한 변화를 동기화 블록을 추가 오전 :

public static final String GMS_DELTA_VIEW_FIELD_NAME = "use_delta_views"; 

/** 
* Change coordinator to {@code desiredCoordinator}. Must be invoked from coordinator. 
* @param desiredCoordinator 
* @return {@code true} if changes success, {@code false} overwise 
*/ 
boolean changeCoordinator(JChannel currentChannel, Address desiredCoordinator) { 

    if(!Util.isCoordinator(currentChannel.getAddress)) { 
     throw new RuntimeException("The current node is not coordinator."); 
    } 

    ArrayList<Address> newMembersOrder = Lists.newArrayList(currentView.getMembers());   

    // Switch desired node to first place 
    Collections.swap(newMembersOrder, 0, newMembersOrder.indexOf(desiredCoordinator));   

    // Create new view 
    long newId = currentView.getViewId().getId() + 1; 
    View newView = new View(newMembersOrder.get(0), newId, newMembersOrder); 

    GMS gms = (GMS)clusterChannel.getProtocolStack().findProtocol(GMS.class); 
    CustomProtocol protocol = new CustomProtocol(newMembersOrder.stream() 
      .filter(item -> !item.equals(currentChannel.getAddress())) 
      .collect(Collectors.toSet())); 

    boolean oldUseDeltaViews = (Boolean)gms.getValue(GMS_DELTA_VIEW_FIELD_NAME); 
    try { 
     // Disable using_delta_views at GMS 
     gms.setValue(GMS_DELTA_VIEW_FIELD_NAME, false); 

     // Insert custom protocol below GMS for synchronizing with VIEW_ACK events 
     currentChannel.getProtocolStack().insertProtocolInStack(protocol, gms, ProtocolStack.BELOW); 
     gms.castViewChange(newView, null, newMembersOrder); 

     // Wait no more than 30 seconds to all VIEW_ACK responses 
     if (!protocol.collector.waitForAllAcks(TimeUnit.SECONDS.toMillis(30))) {     
      return false; 
     } 

     return true; 
    } 
    finally { 
     // Repair old state 
     gms.setValue(GMS_DELTA_VIEW_FIELD_NAME, oldUseDeltaViews); 
     currentChannel.getProtocolStack().removeProtocol(protocol); 
    } 
} 

private class CustomProtocol extends Protocol implements UpHandler { 

    AckCollector collector; 

    public CustomProtocol(Collection<Address> waitedAddresses) { 
     collector = new AckCollector(waitedAddresses); 
    } 

    @Override 
    public Object up(Event evt) { 

     if(evt.getType() == Event.MSG) { 
      final Message msg=(Message)evt.getArg(); 
      GmsHeader hdr=(GmsHeader)msg.getHeader(proto_id); 
      if(hdr != null && hdr.getType() == GmsHeader.VIEW_ACK) {      
       collector.ack(msg.getSrc()); 
      } 
     } 

     return super.up(evt); 
    } 
} 
관련 문제