msb protocol synch change
[msb/apigateway.git] / msb-core / apiroute / apiroute-service / src / main / java / org / openo / msb / wrapper / util / MicroServiceDB.java
1 /**
2  * Copyright 2016 ZTE Corporation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package org.openo.msb.wrapper.util;
17
18 import java.sql.Date;
19 import java.util.ArrayList;
20 import java.util.HashMap;
21 import java.util.HashSet;
22 import java.util.List;
23 import java.util.Map;
24 import java.util.Set;
25 import java.util.regex.Matcher;
26 import java.util.regex.Pattern;
27
28 import org.apache.commons.lang3.StringUtils;
29 import org.openo.msb.api.MicroServiceFullInfo;
30 import org.openo.msb.api.MicroServiceInfo;
31 import org.openo.msb.api.Node;
32 import org.openo.msb.api.NodeInfo;
33 import org.openo.msb.api.Service;
34 import org.openo.msb.wrapper.serviceListener.IMicroServiceChangeListener;
35 import org.slf4j.Logger;
36 import org.slf4j.LoggerFactory;
37
38 import redis.clients.jedis.Jedis;
39
40 public class MicroServiceDB {
41
42     private static final Logger LOGGER = LoggerFactory.getLogger(MicroServiceDB.class);
43
44     private static MicroServiceDB instance = new MicroServiceDB();
45
46     private List<IMicroServiceChangeListener> serviceListenerlist =
47             new ArrayList<IMicroServiceChangeListener>();
48
49     private MicroServiceDB() {}
50
51     public static MicroServiceDB getInstance() {
52         return instance;
53     }
54
55    
56     public void addServiceChangeListener(IMicroServiceChangeListener listener) {
57         synchronized (serviceListenerlist) {
58             serviceListenerlist.add(listener);
59         }
60     }
61
62    
63     public void removeServiceChangeListener(IMicroServiceChangeListener listener) {
64         synchronized (serviceListenerlist) {
65             serviceListenerlist.remove(listener);
66         }
67     }
68     
69     
70     public MicroServiceFullInfo[] getAllMicroServiceInstances() throws Exception {
71         Jedis jedis = null;
72         MicroServiceFullInfo[] microServiceList;
73         try {
74             jedis = JedisUtil.getJedis();
75
76             String routekey =
77                     MicroServiceUtil.getPrefixedKey("","*", MicroServiceUtil.SUFFIX_PATH_INFO);
78             Set<String> serviceSet = jedis.keys(routekey);
79             microServiceList = new MicroServiceFullInfo[serviceSet.size()];
80
81             Pattern redisKeyPattern = MicroServiceUtil.getRedisKeyPattern();
82             int i = 0;
83             for (String servicePath : serviceSet) {
84                 Matcher matcher = redisKeyPattern.matcher(servicePath);
85                 if (matcher.matches()) {
86                     microServiceList[i] = getMicroServiceByJedis(jedis, matcher.group("servicename"),matcher.group("version"), "");
87                     i++;
88                 }
89             }
90         } catch (Exception e) {
91             LOGGER.error("call redis throw exception", e);
92             throw new Exception("call redis throw exception:"+e.getMessage());       
93        } finally {
94             JedisUtil.returnJedisInstance(jedis);
95         }
96         
97         return microServiceList;
98     }
99
100     public void saveMicroServiceInfo2Redis(MicroServiceInfo microServiceInfo,String serverPort) throws Exception {
101         // 1.1 set info
102         String serviceInfokey =
103                 MicroServiceUtil.getServiceInfoKey(serverPort,microServiceInfo.getServiceName(),
104                         microServiceInfo.getVersion());
105         Map<String, String> serviceInfoMap = new HashMap<String, String>();
106         serviceInfoMap.put("url", microServiceInfo.getUrl());
107         serviceInfoMap.put("protocol", microServiceInfo.getProtocol());
108         serviceInfoMap.put("visualRange",microServiceInfo.getVisualRange());
109         serviceInfoMap.put("lb_policy",microServiceInfo.getLb_policy());
110         serviceInfoMap.put("status", "1");
111         
112         
113
114         // 1.2 set lb info
115         String serviceLBkey =
116                 MicroServiceUtil.getPrefixedKey(serverPort,microServiceInfo.getServiceName(),
117                         microServiceInfo.getVersion(), MicroServiceUtil.ROUTE_PATH_LOADBALANCE);
118
119
120         Jedis jedis = null;
121         try {
122             jedis = JedisUtil.getJedis();
123             // 2.1 save info
124             jedis.hmset(serviceInfokey, serviceInfoMap);
125
126
127             for(Node node:microServiceInfo.getNodes()){
128                
129                 String key=serviceLBkey+":"+node.getIp()+"-"+node.getPort();
130                 
131                 Map<String,String> nodeMap = new HashMap<String,String>();
132                
133                 nodeMap.put("ip", node.getIp());
134                 nodeMap.put("port", node.getPort());
135                 nodeMap.put("ttl", Integer.toString(node.getTtl()));
136                 long expiration_time=System.currentTimeMillis()+node.getTtl()*1000;
137                 nodeMap.put("expiration", Long.toString(expiration_time));
138                 
139                 if(jedis.keys(key).isEmpty()){
140                     nodeMap.put("created_at",  Long.toString(System.currentTimeMillis()));
141                 }
142 //                else{
143 //                    Map<String,String> nodeLBmap = jedis.hgetAll(key); 
144 //                    nodeMap.put("created_at", nodeLBmap.get("created_at"));
145 //                }
146                 nodeMap.put("updated_at", Long.toString(System.currentTimeMillis()));
147                 
148                 jedis.hmset(key, nodeMap);
149             }
150             
151 //            jedis.sadd(serviceLBkey, nodeArray);
152
153         } catch (Exception e) {
154             LOGGER.error("save to redis throw exception", e);
155             throw new Exception("save to  redis throw exception:"+e.getMessage());
156         } finally {
157             JedisUtil.returnJedisInstance(jedis);
158         }
159
160
161
162     }
163     
164     public void updateMicroServiceStatus(String serviceName, String version,String status) throws Exception{
165         
166         
167         String serviceInfokey = MicroServiceUtil.getServiceInfoKey("",serviceName, version);
168         Map<String, String> serviceInfoMap = new HashMap<String, String>();
169         serviceInfoMap.put("status", status);
170
171
172         Jedis jedis = null;
173         try {
174             jedis = JedisUtil.borrowJedisInstance();
175             if (jedis == null) {
176                 throw new Exception("fetch from jedis pool failed,null object!");
177             }
178             jedis.hmset(serviceInfokey, serviceInfoMap);
179         }
180         catch (Exception e) {
181             LOGGER.error("update MicroService status throw exception", e);
182             throw new Exception("update MicroService status throw exception:"+e.getMessage());
183         } finally {
184             JedisUtil.returnJedisInstance(jedis);
185         }
186         
187     }
188     
189     
190     public void  updateMicroServiceNode2Redis(String serviceName, String version,String ip,String port,int ttl) throws Exception {
191         String serviceLBkey =
192                 MicroServiceUtil.getPrefixedKey("",serviceName,version, MicroServiceUtil.ROUTE_PATH_LOADBALANCE);
193
194
195         Jedis jedis = null;
196         try {
197             jedis = JedisUtil.getJedis();
198           
199                
200                 String nodeKey=serviceLBkey+":"+ip+"-"+port;                
201                 Map<String,String> nodeLBmap = jedis.hgetAll(nodeKey);
202                 
203                 if(nodeLBmap.isEmpty()){
204                     throw new NullPointerException(" MicroService Node not fond ");  
205                 }
206                 
207                
208                 nodeLBmap.put("ttl", Integer.toString(ttl));
209                 long expiration_time=System.currentTimeMillis()+ttl*1000;
210                 nodeLBmap.put("expiration", Long.toString(expiration_time));
211                 nodeLBmap.put("updated_at", Long.toString(System.currentTimeMillis()));
212                 
213                 jedis.hmset(nodeKey, nodeLBmap);
214
215
216         } 
217         catch (NullPointerException e){
218             throw e;  
219         }
220         catch (Exception e) {
221             LOGGER.error("update MicroService Node throw exception", e);
222             throw new Exception("update MicroService Node throw exception:"+e.getMessage());
223         } finally {
224             JedisUtil.returnJedisInstance(jedis);
225         }
226     }
227     
228     
229     public void noticeUpdateApiListener(String serviceName,String version,Service microServiceInfo,String serverPort) {
230         if (isNeedNotify(microServiceInfo)) {
231             for (IMicroServiceChangeListener serviceListener : serviceListenerlist) {
232                 serviceListener.onChange(serviceName,version, microServiceInfo,serverPort);
233             }
234         }
235         
236     }
237     
238     public void noticeUpdateStatusListener(Service microServiceInfo,String status) {
239        
240         for (IMicroServiceChangeListener serviceListener : serviceListenerlist) {
241             serviceListener.onStatusChange(microServiceInfo.getServiceName(),microServiceInfo.getUrl(),
242                     microServiceInfo.getVersion(),microServiceInfo.getProtocol(),status);
243         }
244     }
245     
246  
247
248     public void noticeApiListener(Service microServiceInfo, String type,String serverPort) {
249         if (isNeedNotify(microServiceInfo)) {
250
251             if ("ADD".equals(type)) {
252                 for (IMicroServiceChangeListener serviceListener : serviceListenerlist) {
253                     serviceListener.onSave(microServiceInfo,serverPort);
254                 }
255             } else if ("DELETE".equals(type)) {
256                 for (IMicroServiceChangeListener serviceListener : serviceListenerlist) {
257                     serviceListener.onDelete(microServiceInfo.getServiceName(),microServiceInfo.getUrl(),
258                             microServiceInfo.getVersion(),microServiceInfo.getProtocol(),serverPort);
259                 }
260             } 
261
262         }
263     }
264
265
266     public MicroServiceFullInfo getMicroServiceInstance(String serviceName, String version,String serverPort)
267             throws Exception {
268         if (null == version || "null".equals(version)) {
269             version = "";
270         }
271
272         Jedis jedis = null;
273         MicroServiceFullInfo microServiceInfo = null;
274        
275         try {
276             jedis = JedisUtil.getJedis();
277             
278             microServiceInfo= getMicroServiceByJedis(jedis,serviceName,version, serverPort);
279
280            
281         } catch (Exception e) {
282             LOGGER.error("call redis throw exception", e);
283             throw new Exception("call redis throw exception:"+e.getMessage());
284         } finally {
285             JedisUtil.returnJedisInstance(jedis);
286         }
287         
288         return microServiceInfo;
289        
290     }
291
292     private MicroServiceFullInfo getMicroServiceByJedis(Jedis jedis,String serviceName, String version,String serverPort){
293         MicroServiceFullInfo microServiceInfo = null;
294         String serviceInfoKey = MicroServiceUtil.getServiceInfoKey(serverPort,serviceName, version);
295         Map<String, String> infomap = jedis.hgetAll(serviceInfoKey);
296         if (!infomap.isEmpty()) {
297             microServiceInfo = new MicroServiceFullInfo();
298             microServiceInfo.setServiceName(serviceName);
299             microServiceInfo.setVersion(version);
300             microServiceInfo.setUrl(infomap.get("url"));
301             microServiceInfo.setProtocol(infomap.get("protocol"));
302             microServiceInfo.setVisualRange(infomap.get("visualRange"));
303             microServiceInfo.setStatus(infomap.get("status"));
304             microServiceInfo.setLb_policy(infomap.get("lb_policy"));
305
306             String nodeLBkey =
307                     MicroServiceUtil.getPrefixedKey(serverPort,microServiceInfo.getServiceName(),
308                             microServiceInfo.getVersion(),
309                             MicroServiceUtil.ROUTE_PATH_LOADBALANCE);
310             
311             Set<String>  nodeKeys=jedis.keys(nodeLBkey+":*");
312             
313             Set<NodeInfo> nodes=new HashSet<NodeInfo>();
314             for(String nodeKey:nodeKeys){
315                 Map<String,String> nodeLBmap = jedis.hgetAll(nodeKey);
316                 NodeInfo nodeInfo=new NodeInfo();
317                 nodeInfo.setNodeId(serviceName+"_"+nodeLBmap.get("ip")+"_"+nodeLBmap.get("port"));
318                 nodeInfo.setIp(nodeLBmap.get("ip"));
319                 nodeInfo.setPort(nodeLBmap.get("port"));
320                 nodeInfo.setTtl(Integer.parseInt(nodeLBmap.get("ttl")));
321                 nodeInfo.setCreated_at(new Date(Long.parseLong(nodeLBmap.get("created_at"))));
322                 nodeInfo.setUpdated_at(new Date(Long.parseLong(nodeLBmap.get("updated_at"))));
323                 nodeInfo.setExpiration(new Date(Long.parseLong(nodeLBmap.get("expiration"))));
324               
325                 nodes.add(nodeInfo);
326             }
327             
328             microServiceInfo.setNodes(nodes);
329         }
330             
331            
332            
333             
334             return microServiceInfo;
335     }
336         
337
338     public void deleteMicroService(String serviceName, String version,String serverPort) throws Exception {
339         if (null == version || "null".equals(version)) {
340             version = "";
341         }
342         
343         Jedis jedis = null;
344         try {
345             jedis = JedisUtil.getJedis();
346             String routekey = MicroServiceUtil.getPrefixedKey(serverPort,serviceName, version, "*");
347             Set<String> infoSet = jedis.keys(routekey);
348
349             if (infoSet.isEmpty()) {
350               LOGGER.error("delete MicroService FAIL:serviceName-"
351                   + serviceName + ",version:" + version + " not fond ");
352             }
353             else{
354             String[] paths = new String[infoSet.size()];
355
356             infoSet.toArray(paths);
357
358             jedis.del(paths);
359             }
360         } catch (Exception e) {
361             LOGGER.error("call redis throw exception", e);
362             throw new Exception("call redis throw exception:"+e.getMessage());
363         } finally {
364             JedisUtil.returnJedisInstance(jedis);
365         }
366     }
367
368     public void deleteNode(String serviceName, String version, String ip,String port) throws Exception {
369         if (null == version || "null".equals(version)) {
370             version = "";
371         }
372         
373         Jedis jedis = null;
374         try {
375             jedis = JedisUtil.getJedis();
376             String serviceLBkey =
377                     MicroServiceUtil.getPrefixedKey("",serviceName, version,
378                             MicroServiceUtil.ROUTE_PATH_LOADBALANCE,ip+"-"+port);
379             jedis.del(serviceLBkey);
380         } catch (Exception e) {
381             LOGGER.error("call redis throw exception", e);
382             throw new Exception("call redis throw exception:"+e.getMessage());
383         } finally {
384             JedisUtil.returnJedisInstance(jedis);
385         }
386
387     }
388
389
390     /**
391      * Determine whether the service needs to send a notification 
392      * TODO: filter according to the agreement,
393      * the only notice of agreement for REST \ UI interface MSB - REST     
394      * @param protocol
395      * @return
396      */
397     private boolean isNeedNotifyByProtocol(String protocol) {
398         return "UI".equalsIgnoreCase(protocol) || "REST".equalsIgnoreCase(protocol)  || "HTTP".equalsIgnoreCase(protocol);
399     }
400     
401     /**
402      * Determine whether the service needs to send a notification 
403      * TODO: according to the visual range filter conditions   
404      * @param visualRange
405      * @return
406      */
407     private boolean isNeedNotifyByVisualRange(String visualRange) {
408         String[] rangeArray=StringUtils.split(visualRange, "|");
409         return RouteUtil.contain(RouteUtil.visualRangeMatches, rangeArray);
410     }
411
412     /**
413      * According to the MicroServiceInfo entity information to judge whether need to send a notification
414      * @param microServiceInfo
415      * @return
416      */
417     private boolean isNeedNotify(Service microServiceInfo) {
418         if (null != microServiceInfo) {
419             return isNeedNotifyByProtocol(microServiceInfo.getProtocol()) &&
420                    isNeedNotifyByVisualRange(microServiceInfo.getVisualRange());
421         } else {
422             return false;
423         }
424     }
425     
426     
427     
428 }