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