-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit e26d283
Showing
10 changed files
with
582 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
/cygwin/ | ||
/libs/ | ||
/cmake-build-debug/ | ||
.idea | ||
*.iml |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
cmake_minimum_required(VERSION 3.14) | ||
project(apollo C) | ||
|
||
set(CMAKE_C_STANDARD 99) | ||
|
||
add_library(apollo SHARED apolloclient.c global.c) | ||
target_link_libraries(apollo curl json-c) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
CC=gcc | ||
INCLIDE=. | ||
CFLAGS= -Wall -std=c99 | ||
TARGET = libapollo.so | ||
LIBPATH = ./libs/ | ||
OBJS=global.o apolloclient.o apollo.o | ||
SRCS=global.c apolloclient.c apollo.c | ||
|
||
all:$(OBJS) | ||
$(CC) $(CFLAGS) -shared -fPIC -o $(TARGET) $(OBJS) -lcurl -ljson-c | ||
mkdir -p $(LIBPATH) | ||
mv $(TARGET) $(LIBPATH) | ||
#$^代表所有依赖也就是上面的main.o mmath.o syso.o $@代表目标也就是上面main | ||
$(OBJS):$(SRCS) | ||
$(CC) $(CFLAGS) -fPIC -I$(INCLIDE) -c $^ | ||
install: | ||
cp $(LIBPATH)$(TARGET) /lib64 | ||
mkdir -p /usr/include/apollo | ||
cp ./*.h /usr/include/apollo | ||
uninstall: | ||
rm -rf /lib64/$(TARGET) | ||
rm -rf /usr/include/apollo | ||
clean: | ||
rm -rf *.o | ||
rm -f $(LIBPATH)* |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
// | ||
// Created by GVT on 2020/4/2. | ||
// | ||
#include "string.h" | ||
#include <apollo.h> | ||
#include <curl/curl.h> | ||
#include <json-c/json.h> | ||
|
||
|
||
|
||
String getApolloConfig(ApolloConf apolloConf,String envName,String appId,String clusterName,String namespaceName){ | ||
CURL *curl = curl_easy_init(); | ||
if(curl) { | ||
CURLcode res; | ||
static char str[10000]; | ||
strcpy(str, ""); | ||
if(clusterName==NULL){ | ||
clusterName=DEFAULT_CLUSTER_NAME; | ||
} | ||
String urlDest=sprintfStr(LATESTREKEASE_URL, \ | ||
apolloConf.config_server_url,envName,appId,clusterName,namespaceName); | ||
String tokenHeader=sprintfStr(TOKEN_PATTERN,apolloConf.token); | ||
struct curl_slist *headers =setCommonHeader(&res,tokenHeader); | ||
curl_easy_setopt(curl, CURLOPT_URL, urlDest); | ||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_memory_callback); | ||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, str); | ||
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); | ||
res = curl_easy_perform(curl); | ||
curl_easy_cleanup(curl); | ||
free(tokenHeader); | ||
free(urlDest); | ||
return str; | ||
} | ||
return NULL; | ||
} | ||
void getApolloClusterEnv(ApolloConf apolloConf,String appId,envclusters* ec){ | ||
CURL *curl = curl_easy_init(); | ||
if(curl) { | ||
CURLcode res; | ||
static char str[10000]; | ||
strcpy(str, ""); | ||
String urlDest=sprintfStr(CLUSTERENV_URL, \ | ||
apolloConf.config_server_url,appId); | ||
String tokenHeader=sprintfStr(TOKEN_PATTERN,apolloConf.token); | ||
struct curl_slist *headers =setCommonHeader(&res,tokenHeader); | ||
curl_easy_setopt(curl, CURLOPT_URL, urlDest); | ||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_memory_callback); | ||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, str); | ||
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); | ||
res = curl_easy_perform(curl); | ||
curl_easy_cleanup(curl); | ||
free(tokenHeader); | ||
free(urlDest); | ||
json_object* jsonObject=json_tokener_parse(str); | ||
size_t objectSize=json_object_array_length(jsonObject); | ||
ec->len=objectSize; | ||
envcluster* envc=(envcluster*)malloc(objectSize*sizeof(envcluster)); | ||
for(int v=0;v<objectSize;v++){ | ||
json_object* clusterObj=json_object_array_get_idx(jsonObject,v); | ||
json_object* env; | ||
json_object_object_get_ex(clusterObj,"env",&env); | ||
json_object* clusters; | ||
json_object_object_get_ex(clusterObj,"clusters",&clusters); | ||
String clustersArray[json_object_array_length(clusters)]; | ||
for(int i=0;i<json_object_array_length(clusters);i++){ | ||
json_object* clusterObj=json_object_array_get_idx(clusters,i); | ||
clustersArray[i]=json_object_to_json_string(clusterObj); | ||
} | ||
envcluster envclusterTmp={ | ||
env:json_object_to_json_string(env), | ||
clusters:clustersArray | ||
}; | ||
*(envc+v)=envclusterTmp; | ||
} | ||
ec->clusters=envc; | ||
} | ||
} | ||
void getProperties(ApolloConf apolloConf,String envName,String appId,String clusterName,String namespaceName,Properties* properties){ | ||
String str=getApolloConfig(apolloConf,envName,appId,clusterName,namespaceName); | ||
json_object* jsonObject=json_tokener_parse(str); | ||
json_object* configurations; | ||
json_object_object_get_ex(jsonObject,"configurations",&configurations); | ||
int i=0; | ||
size_t configurationsLength=json_object_object_length(configurations); | ||
String* keys=newString(sizeof(String)*configurationsLength); | ||
String* values=newString(sizeof(String)*configurationsLength); | ||
properties->len=configurationsLength; | ||
json_object_object_foreach(configurations,json_key,jsonValue){ | ||
keys[i]=json_key; | ||
values[i]=json_object_get_string(jsonValue); | ||
i++; | ||
} | ||
properties->keys=keys; | ||
properties->values=values; | ||
} | ||
void getYamlOrJson(ApolloConf apolloConf,String envName,String appId,String clusterName,String namespaceName,String yamlStr){ | ||
Properties* properties; | ||
getProperties(apolloConf,envName,appId,clusterName,namespaceName,properties); | ||
for(int i=0;i<properties->len;i++){ | ||
if(strcmp(*(properties+i)->keys,"content")==0){ | ||
strcat(yamlStr,*(properties)->values); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
// | ||
// Created by jiaozi<[email protected]> on 2020/4/2. | ||
// | ||
|
||
#include "global.h" | ||
#ifndef NGINX_APOLLO_H | ||
#define NGINX_APOLLO_H | ||
|
||
#endif //NGINX_APOLLO_H | ||
#define TOKEN_PATTERN "Authorization:%s" | ||
|
||
#define LATESTREKEASE_URL "http://%s/openapi/v1/envs/%s/apps/%s/clusters/%s/namespaces/%s/releases/latest" | ||
#define CLUSTERENV_URL "http://%s/openapi/v1/apps/%s/envclusters" | ||
|
||
|
||
|
||
typedef struct{ | ||
String config_server_url; | ||
String token; | ||
} ApolloConf; | ||
/** | ||
* 获取apollo配置 | ||
* properties输出结果是: | ||
* { | ||
"appId": "test-0620-01", | ||
"clusterName": "test", | ||
"namespaceName": "application", | ||
"name": "2016-08-11", | ||
"configurations": { | ||
"timeout": "3000", | ||
} | ||
},只需要获取configurations所有key即可。 | ||
* yaml和json输出的结果是: | ||
直接获取["configurations"]["content"] | ||
* @param apolloConf Apollo配置服务的地址和token | ||
* @param envName 环境名称 | ||
* @param appId 应用的appId | ||
* @param clusterName 集群名 | ||
* @param namespaceName Namespace的名字 | ||
* @param ip 应用部署的机器ip | ||
* @return 字符串结果,其他逻辑自行处理 | ||
*/ | ||
char* getApolloConfig(ApolloConf apolloConf,String envName,String appId,String clusterName,String namespaceName); | ||
typedef struct{ | ||
String env; | ||
String* clusters; | ||
} envcluster; | ||
typedef struct{ | ||
size_t len; | ||
envcluster* clusters; | ||
} envclusters; | ||
/** | ||
* 获取App的环境,集群信息 | ||
* [ | ||
{ | ||
"env":"FAT", | ||
"clusters":[ //集群列表 | ||
"default", | ||
"FAT381" | ||
] | ||
}, | ||
{ | ||
"env":"UAT", | ||
"clusters":[ | ||
"default" | ||
] | ||
}, | ||
{ | ||
"env":"PRO", | ||
"clusters":[ | ||
"default", | ||
"SHAOY", | ||
"SHAJQ" | ||
] | ||
} | ||
] | ||
* @param apolloConf Apollo配置服务的地址和token | ||
* @param appId 应用id | ||
* @param envclusters 集群环境信息,返回引用 | ||
* @return | ||
*/ | ||
void getApolloClusterEnv(ApolloConf apolloConf,String appId,envclusters* ec); | ||
|
||
|
||
/** | ||
* 获取properties,可以获取所有类型 yaml和properties其实是在content这个key下面 | ||
* @param apolloConf | ||
* @param envName | ||
* @param appId | ||
* @param clusterName | ||
* @param namespaceName | ||
* @return | ||
*/ | ||
void getProperties(ApolloConf apolloConf,String envName,String appId,String clusterName,String namespaceName,Properties* properties); | ||
/** | ||
* 获取yaml | ||
* @param apolloConf | ||
* @param envName | ||
* @param appId | ||
* @param clusterName | ||
* @param namespaceName | ||
* @return | ||
*/ | ||
void getYamlOrJson(ApolloConf apolloConf,String envName,String appId,String clusterName,String namespaceName,String yamlStr); | ||
|
||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
// | ||
// Created by GVT on 2020/4/7. | ||
// | ||
#include "apolloclient.h" | ||
#include "pthread.h" | ||
String getNoCachePropertyString(apollo_env apolloEnv){ | ||
CURL *curl = curl_easy_init(); | ||
if(curl) { | ||
CURLcode res; | ||
String str=newString(10000); | ||
memset(str, 0, 10000); | ||
if(apolloEnv.clusterName==NULL){ | ||
apolloEnv.clusterName=DEFAULT_CLUSTER_NAME; | ||
} | ||
String urlDest=sprintfStr(APOLLO_CONFIG_NOCACHE_URL, \ | ||
apolloEnv.meta,apolloEnv.appId,apolloEnv.clusterName,apolloEnv.namespaceName); | ||
struct curl_slist *headers =setCommonHeader(&res,NULL); | ||
curl_easy_setopt(curl, CURLOPT_URL, urlDest); | ||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_memory_callback); | ||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, str); | ||
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); | ||
res = curl_easy_perform(curl); | ||
curl_easy_cleanup(curl); | ||
free(urlDest); | ||
return str; | ||
} | ||
} | ||
void getNoCacheProperty(apollo_env apolloEnv,Properties* properties){ | ||
String properStr=getNoCachePropertyString(apolloEnv); | ||
jsonStrToProperties(properStr,"configurations",properties); | ||
} | ||
CURLcode checkNotifications(apollo_env apolloEnv,notification notifications,long* response_code,String notificationReturn){ | ||
CURL *curl = curl_easy_init(); | ||
char* buf=malloc(200); | ||
if(curl) { | ||
CURLcode res; | ||
if(apolloEnv.clusterName==NULL){ | ||
apolloEnv.clusterName=DEFAULT_CLUSTER_NAME; | ||
} | ||
String notification=newString(200); | ||
memset(notification, 0, 200); | ||
strcat(notification,"["); | ||
strcat(notification,"{"); | ||
strcat(notification,"\"namespaceName\": \""); | ||
strcat(notification,notifications.namespaceName); | ||
strcat(notification,"\","); | ||
strcat(notification,"\"notificationId\": \""); | ||
strcat(notification,sprintfStr("%d",notifications.notificationId)); | ||
strcat(notification,"\""); | ||
strcat(notification,"}"); | ||
strcat(notification,"]"); | ||
notification=curl_escape(notification,strlen(notification)); | ||
String urlDest=sprintfStr(APOLLO_CONFIG_NOTI_URL, \ | ||
apolloEnv.meta,apolloEnv.appId,apolloEnv.clusterName,notification); | ||
struct curl_slist *headers =setCommonHeader(&res,NULL); | ||
curl_easy_setopt(curl, CURLOPT_URL, urlDest); | ||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_memory_callback); | ||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, notificationReturn); | ||
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); | ||
res = curl_easy_perform(curl); | ||
if(res == CURLE_OK) { | ||
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, response_code); | ||
} | ||
curl_easy_cleanup(curl); | ||
free(urlDest); | ||
return res; | ||
} | ||
|
||
} | ||
|
||
typedef struct | ||
{ | ||
void *arg[4]; /* 参数*/ | ||
}ThreadParam; | ||
void *notificationRun(void *arg) | ||
{ | ||
ThreadParam* param=(ThreadParam*)arg; | ||
apollo_env apolloEnv=*(apollo_env*)param->arg[0]; | ||
notification notifications=*(notification*)param->arg[1]; | ||
int* flag=(int*)param->arg[2]; | ||
void (*callback)(Properties* old,Properties* new); | ||
callback=param->arg[3]; | ||
submitNotifications(apolloEnv,notifications,flag,callback); | ||
return NULL; | ||
} | ||
|
||
int submitNotificationsAsync(apollo_env apolloEnv,notification notifications,int* flag,void (*callback)(Properties* old,Properties* new)){ | ||
ThreadParam param={0}; | ||
param.arg[0]=&apolloEnv; | ||
param.arg[1]=¬ifications; | ||
param.arg[2]=flag; | ||
param.arg[3]=callback; | ||
pthread_t tid; | ||
int tret = pthread_create(&tid, NULL, notificationRun, (void *)¶m); | ||
return tret; | ||
} | ||
|
||
void submitNotifications(apollo_env apolloEnv,notification notifications,int* flag,void (*callback)(Properties* old,Properties* new)){ | ||
//第一次获取资源信息。 | ||
Properties oldProperties; | ||
getNoCacheProperty(apolloEnv,&oldProperties); | ||
callback(NULL,&oldProperties); | ||
long responseCode; | ||
String notiStr=newString(1000); | ||
memset(notiStr, 0, 1000); | ||
Properties newProperties; | ||
CURLcode res=checkNotifications(apolloEnv,notifications,&responseCode,notiStr); | ||
//根据动态flag决定是否需要继续long pooling | ||
while(flag>0) { | ||
if (res == CURLE_OK) { | ||
//304直接使用当前数据直接调用当前方法继续递归 | ||
if (res == 304) { | ||
res=checkNotifications(apolloEnv,notifications,&responseCode,notiStr); | ||
continue; | ||
} else { | ||
//200不管是否都需要获取最新的配置项 | ||
if (responseCode == 200) { | ||
//获取最新的配置。 | ||
getNoCacheProperty(apolloEnv,&newProperties); | ||
json_object *jsonObject = json_tokener_parse(notiStr); | ||
json_object *notifyObj = json_object_array_get_idx(jsonObject, 0); | ||
json_object *notificationIdObject; | ||
json_object_object_get_ex(notifyObj, "notificationId", ¬ificationIdObject); | ||
int notificationId = json_object_get_int(notificationIdObject); | ||
if(notifications.notificationId>NOTIFICATION_ID_PLACEHOLDER){ | ||
callback(&oldProperties, &newProperties); | ||
} | ||
notifications.notificationId = notificationId; | ||
oldProperties=newProperties; | ||
// newProperties.len=0; | ||
// free(newProperties.keys); | ||
// free(newProperties.values); | ||
memset(notiStr, 0, 1000); | ||
res=checkNotifications(apolloEnv,notifications,&responseCode,notiStr); | ||
} | ||
} | ||
|
||
} | ||
} | ||
} |
Oops, something went wrong.