Zookeeper構成センターサービスガバナンス実装
Zookeeper構成センターサービスガバナンス実装
背景
前回のブログでは、EurekaではなくZookeeperをサービス発見フレームワークとして選択した理由を詳しく説明しました.このブログを参考にして、どのように実現するかを説明し続けます.中には大量のコードのコピーがあります.具体的なアーキテクチャは前のブログのアーキテクチャの進化図を参考にすることができます.本編では主に実現過程を説明する.
準備作業 Spring MavenプロジェクトはZookeeperの依存パッケージを追加し、ZookeeperのSDKを使用することができます.
football-serverサービス登録機能を実現
Zookeeperを作成します.propertiesはresourcesディレクトリの下にあり、パラメータを書き込みます.
Zookeeperを作成します.propertiesはファイルのクラスを読み込みます.
サービス起動に成功した後、Zookeeperを呼び出したJavaSDKはZookeeperに自分を登録する.
fooball-metaサービス発見機能の実現
Zookeeperを作成します.propertiesと読み取りの作成propertiesファイルのクラスはfootball-serverと一致しています.
Zookeeperから登録サービスのパラメータを取得する
背景
前回のブログでは、EurekaではなくZookeeperをサービス発見フレームワークとして選択した理由を詳しく説明しました.このブログを参考にして、どのように実現するかを説明し続けます.中には大量のコードのコピーがあります.具体的なアーキテクチャは前のブログのアーキテクチャの進化図を参考にすることができます.本編では主に実現過程を説明する.
準備作業
<dependency>
<groupId>org.apache.zookeepergroupId>
<artifactId>zookeeperartifactId>
<version>3.3.6version>
dependency>
football-serverサービス登録機能を実現
Zookeeperを作成します.propertiesはresourcesディレクトリの下にあり、パラメータを書き込みます.
server.parent.name = football ( )
server.instance.name = football-server ( )
server.port = 8081 ( )
zookeeper.host = Your zookeeper address
zookeeper.port = Your zookeeper port
Zookeeperを作成します.propertiesはファイルのクラスを読み込みます.
@Component
public class ZookeeperProperties {
@Value("${zookeeper.host}")
private String host;
@Value("${zookeeper.port}")
private String zkPort;
@Value("${server.parent.name}")
private String parentName;
@Value("${server.port}")
private String serverPort;
@Value("${server.instance.name}")
private String instanceName;
public String getZookeeperAddress(){
return String.format("%s:%s",host,zkPort);
}
public String getParentName() {
parentName=parentName.replace("/","");
return parentName;
}
public String getServerPort() {
return serverPort;
}
public String getInstanceName() {
parentName=parentName.replace("/","");
return instanceName;
}
}
サービス起動に成功した後、Zookeeperを呼び出したJavaSDKはZookeeperに自分を登録する.
@Service
public class ZookeeperRegistrar implements ApplicationListener {
@Autowired
ZookeeperProperties zookeeperProperties;
private static Logger log = LoggerFactory.getLogger(ZookeeperRegistrar.class);
@Override
public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
if(contextRefreshedEvent.getApplicationContext().getParent()==null){
try {
registry();
} catch (IOException e) {
log.error("fooball-server registry to zookeeper fault ,{}",e.getMessage());
e.printStackTrace();
} catch (InterruptedException e) {
log.error("fooball-server registry to zookeeper fault ,{}",e.getMessage());
e.printStackTrace();
} catch (KeeperException e) {
log.error("fooball-server registry to zookeeper fault ,{}",e.getMessage());
e.printStackTrace();
}
}
}
public void registry() throws IOException, KeeperException, InterruptedException {
Watcher watcher=new Watcher() {
@Override
public void process(WatchedEvent watchedEvent) {
log.info("zookeeper watcher ,{}",watchedEvent.toString());
}
};
ZooKeeper zooKeeper = new ZooKeeper(zookeeperProperties.getZookeeperAddress(),200000,watcher);
initParentPath(zooKeeper,watcher);
createInstancePath(zooKeeper,watcher);
}
public void initParentPath(ZooKeeper zookeeper,Watcher watcher) throws KeeperException, InterruptedException, UnknownHostException {
String parentPath = String.format("/%s",zookeeperProperties.getParentName());
log.info("fooball-server parentPath:{}",parentPath);
if(zookeeper.exists(parentPath,watcher)==null){
zookeeper.create(parentPath,null,ZooDefs.Ids.OPEN_ACL_UNSAFE,CreateMode.PERSISTENT);
log.info("create parentPath {} success.",parentPath);
}
}
public void createInstancePath(ZooKeeper zooKeeper,Watcher watcher) throws KeeperException, InterruptedException, UnknownHostException {
String instancePath = String.format("/%s/%s",zookeeperProperties.getParentName(),zookeeperProperties.getInstanceName());
zooKeeper.create(instancePath,instanceInfoToByte(),ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
log.info("create path {} success.",zookeeperProperties.getInstanceName());
}
public String getHost() throws UnknownHostException {
InetAddress address = InetAddress.getLocalHost();
return address.getHostAddress();
}
public InstanceInfo createInstanceInfo() throws UnknownHostException {
String host = String.format("%s:%s",getHost(),zookeeperProperties.getServerPort());
log.info("current instance host {}",host);
return new InstanceInfo(zookeeperProperties.getInstanceName(),host);
}
public byte[] instanceInfoToByte() throws UnknownHostException {
Gson gson=new Gson();
InstanceInfo instanceInfo = createInstanceInfo();
return gson.toJson(instanceInfo).getBytes();
}
}
fooball-metaサービス発見機能の実現
Zookeeperを作成します.propertiesと読み取りの作成propertiesファイルのクラスはfootball-serverと一致しています.
Zookeeperから登録サービスのパラメータを取得する
@Service
public class MetaService implements IMetaService {
@Autowired
ZooKeeper zooKeeper;
@Autowired
ZookeeperProperties zookeeperProperties;
@Autowired
Watcher watcher;
private static Logger log = LoggerFactory.getLogger(MetaService.class);
@Override
public List getServiceInfo() {
try {
String parentPath = String.format("/%s",zookeeperProperties.getParentName());
List childs = zooKeeper.getChildren(parentPath,false);
return getInstancesByName(childs);
} catch (KeeperException e) {
log.error("Zookeeper getChildren error!");
e.printStackTrace();
} catch (InterruptedException e) {
log.error("Zookeeper getChildren error!");
e.printStackTrace();
}
return Collections.emptyList();
}
public List getInstancesByName(List childs) throws KeeperException, InterruptedException {
List instanceInfos =new ArrayList();
for(String childName:childs){
String childPath = String.format("/%s/%s",zookeeperProperties.getParentName(),childName);
instanceInfos.add(getInstanceFromZK(childPath));
}
return instanceInfos;
}
public InstanceInfo getInstanceFromZK(String path) throws KeeperException, InterruptedException {
byte[] data = zooKeeper.getData(path,watcher,null);
String instanceJson = new String(data);
return new Gson().fromJson(instanceJson,InstanceInfo.class);
}
}