所有文章
https://www.cnblogs.com/lay2017/p/11908715.html
正文
入口
上文我們說到,eureka是使用jersey來對外提供restful風格的rpc調用的。我們得找到注冊服務的Resource(對應springmvc的controller)
ApplicationResource類中的addInstance方法將作為服務端注冊服務的入口
private final PeerAwareInstanceRegistry registry; @POST @Consumes({"application/json", "application/xml"}) public Response addInstance(InstanceInfo info, @HeaderParam(PeerEurekaNode.HEADER_REPLICATION) String isReplication) { //... registry.register(info, "true".equals(isReplication)); return Response.status(204).build(); }
可以看到,是調用了PeerAwareInstanceRegistry的register方法
跟進register方法
@Override public void register(final InstanceInfo info, final boolean isReplication) { // ... super.register(info, leaseDuration, isReplication); replicateToPeers(Action.Register, info.getAppName(), info.getId(), info, null, isReplication); }
register方法主要做了兩件事
1)注冊實例信息
2)復制到其它節點
我們關注注冊實例,跟進super.register方法
register方法很長,我們看看核心的流程
private final ConcurrentHashMap<String, Map<String, Lease<InstanceInfo>>> registry = new ConcurrentHashMap<String, Map<String, Lease<InstanceInfo>>>(); public void register(InstanceInfo registrant, int leaseDuration, boolean isReplication) { try { Map<String, Lease<InstanceInfo>> gMap = registry.get(registrant.getAppName()); if (gMap == null) { final ConcurrentHashMap<String, Lease<InstanceInfo>> gNewMap = new ConcurrentHashMap<String, Lease<InstanceInfo>>(); gMap = registry.putIfAbsent(registrant.getAppName(), gNewMap); if (gMap == null) { gMap = gNewMap; } } Lease<InstanceInfo> lease = new Lease<InstanceInfo>(registrant, leaseDuration); gMap.put(registrant.getId(), lease); // 省略 } finally { // } }
看起來比較簡單,其實就是將InstanceInfo給添加到了registry集合當中。我們重點關注一下registry的存儲結構
它是由兩層Map組合而成,我們用一個json示例來表示改registry結構
{ "商品服務": { // 服務名 "實例的唯一ID": { // 實例標識符 "lease": { // 持有實例信息 "instanceInfo": { // 實例信息 "appName": "商品服務", "instanceId": "實例的唯一ID", "ipAddr": "IP地址", "port": "調用端口" } } } } }
其實就是根據服務與實例一對多的結構來存放服務的集群信息的。
總結
eureka采用jersey來提供rpc服務,注冊服務實際上就是向registry添加了一份實例信息。不過我們可以看到Eureka並沒有對實例數據進行持久化,所以實例數據都是瞬時態的,這與zookeeper的做法存在區別。