@fastcar/template-microservices 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +124 -0
- package/package.json +35 -0
- package/template/.prettierrc +9 -0
- package/template/.vscode/launch.json +183 -0
- package/template/README.md +1 -0
- package/template/package.json +47 -0
- package/template/resource/application-dev.yml +56 -0
- package/template/resource/application.yml +2 -0
- package/template/src/annotation/AuthServiceRole.ts +76 -0
- package/template/src/annotation/EnableHotConfig.ts +13 -0
- package/template/src/app-node.ts +94 -0
- package/template/src/app-pm2.ts +191 -0
- package/template/src/common/Code.ts +26 -0
- package/template/src/common/Constant.ts +28 -0
- package/template/src/common/Result.ts +40 -0
- package/template/src/common/TaskAsync.ts +17 -0
- package/template/src/hotconfig/ExampleConfigService.ts +29 -0
- package/template/src/hotconfig/HotConfigInterface.ts +43 -0
- package/template/src/middleware/checkForm.ts +20 -0
- package/template/src/middleware/checkLogin.ts +25 -0
- package/template/src/middleware/parseSession.ts +44 -0
- package/template/src/servers/base/BaseServer.ts +120 -0
- package/template/src/servers/base/common/BackSessionEntryController.ts +33 -0
- package/template/src/servers/base/common/RemoteController.ts +70 -0
- package/template/src/servers/base/service/BackSessionService.ts +97 -0
- package/template/src/servers/base/service/CenterClient.ts +457 -0
- package/template/src/servers/base/service/DataService.ts +85 -0
- package/template/src/servers/base/service/RouterService.ts +185 -0
- package/template/src/servers/center/app.ts +14 -0
- package/template/src/servers/center/controller/EntryController.ts +89 -0
- package/template/src/servers/center/controller/ServerController.ts +62 -0
- package/template/src/servers/center/service/ServerManager.ts +336 -0
- package/template/src/servers/chat/RoomHandler.ts +65 -0
- package/template/src/servers/chat/RoomService.ts +24 -0
- package/template/src/servers/chat/app.ts +11 -0
- package/template/src/servers/connector/app.ts +13 -0
- package/template/src/servers/connector/controller/AccountHandler.ts +80 -0
- package/template/src/servers/connector/controller/ChannelRemote.ts +63 -0
- package/template/src/servers/connector/middleware/forwardMsg.ts +54 -0
- package/template/src/servers/web/HelloController.ts +51 -0
- package/template/src/servers/web/SyncConfigService.ts +13 -0
- package/template/src/servers/web/app.ts +15 -0
- package/template/src/types/ClientSimpleSession.ts +3 -0
- package/template/src/types/ForwardRpcContext.ts +3 -0
- package/template/src/types/ReqSession.ts +8 -0
- package/template/src/types/ResultType.ts +5 -0
- package/template/src/types/ServerMeta.ts +48 -0
- package/template/src/types/SessionAttribute.ts +13 -0
- package/template/src/utils/ConnectorUtils.ts +25 -0
- package/template/src/utils/MicroservicesUtils.ts +101 -0
- package/template/src/utils/NetWork.ts +31 -0
- package/template/src/utils/SessionUtil.ts +46 -0
- package/template/test/connector-test.ts +64 -0
- package/template/test/hello.ts +71 -0
- package/template/tsconfig.json +39 -0
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { Autowired, Controller, Rule, ValidForm } from "@fastcar/core/annotation";
|
|
2
|
+
import { InteractiveMode } from "@fastcar/rpc";
|
|
3
|
+
import { RPC, RPCMethod } from "@fastcar/rpc/annotation";
|
|
4
|
+
import RoomService from "./RoomService";
|
|
5
|
+
import Result from "@/common/Result";
|
|
6
|
+
import { SessionAttribute } from "@/types/SessionAttribute";
|
|
7
|
+
import { ForwardRpcContext } from "@/types/ForwardRpcContext";
|
|
8
|
+
import AuthServiceRole from "@/annotation/AuthServiceRole";
|
|
9
|
+
import { ServerKind } from "@/common/Constant";
|
|
10
|
+
import RouterService from "@/servers/base/service/RouterService";
|
|
11
|
+
|
|
12
|
+
@Controller
|
|
13
|
+
@RPC("/room")
|
|
14
|
+
export default class RoomHandler {
|
|
15
|
+
@Autowired
|
|
16
|
+
private roomService!: RoomService;
|
|
17
|
+
|
|
18
|
+
@Autowired
|
|
19
|
+
private routerService!: RouterService;
|
|
20
|
+
|
|
21
|
+
//加入世界
|
|
22
|
+
@RPCMethod()
|
|
23
|
+
@AuthServiceRole(ServerKind.remote)
|
|
24
|
+
join({}, { session }: ForwardRpcContext) {
|
|
25
|
+
this.roomService.add(session.settings.get(SessionAttribute.uid), session);
|
|
26
|
+
return Result.ok();
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
//离开世界
|
|
30
|
+
@RPCMethod()
|
|
31
|
+
@AuthServiceRole(ServerKind.remote)
|
|
32
|
+
leave({}, { session }: ForwardRpcContext) {
|
|
33
|
+
this.roomService.del(session.settings.get(SessionAttribute.uid));
|
|
34
|
+
return Result.ok();
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
//向别人发送消息
|
|
38
|
+
@RPCMethod()
|
|
39
|
+
@ValidForm
|
|
40
|
+
@AuthServiceRole(ServerKind.front)
|
|
41
|
+
sendMsg(
|
|
42
|
+
@Rule({
|
|
43
|
+
msg: { maxSize: 1000, required: true },
|
|
44
|
+
toUid: { required: true, type: "number" },
|
|
45
|
+
})
|
|
46
|
+
{ msg, toUid }: { toUid: number; msg: string }
|
|
47
|
+
) {
|
|
48
|
+
let otherSession = this.roomService.getSid(toUid);
|
|
49
|
+
if (!otherSession) {
|
|
50
|
+
return Result.ok();
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
this.routerService.request({
|
|
54
|
+
url: "/channelRemote/broadcastBySessionId",
|
|
55
|
+
serverType: "connector",
|
|
56
|
+
data: {
|
|
57
|
+
data: { data: msg, url: "/room/notify", mode: InteractiveMode.notify },
|
|
58
|
+
sessionId: otherSession.sessionId,
|
|
59
|
+
},
|
|
60
|
+
session: otherSession,
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
return Result.ok();
|
|
64
|
+
}
|
|
65
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Service } from "@fastcar/core/annotation";
|
|
2
|
+
import { DataMap } from "@fastcar/core";
|
|
3
|
+
import { ClientSession } from "@fastcar/rpc";
|
|
4
|
+
|
|
5
|
+
@Service
|
|
6
|
+
export default class RoomService {
|
|
7
|
+
private onlineMap: DataMap<number, ClientSession>;
|
|
8
|
+
|
|
9
|
+
constructor() {
|
|
10
|
+
this.onlineMap = new DataMap();
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
add(uid: number, session: ClientSession) {
|
|
14
|
+
this.onlineMap.set(uid, session);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
getSid(uid: number) {
|
|
18
|
+
return this.onlineMap.get(uid);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
del(uid: number) {
|
|
22
|
+
this.onlineMap.delete(uid);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import checkForm from "@/middleware/checkForm";
|
|
2
|
+
import parseSession from "@/middleware/parseSession";
|
|
3
|
+
import { Application } from "@fastcar/core/annotation";
|
|
4
|
+
import { RPCMiddleware } from "@fastcar/rpc/annotation";
|
|
5
|
+
import BaseServer from "../base/BaseServer";
|
|
6
|
+
|
|
7
|
+
@Application
|
|
8
|
+
@RPCMiddleware(checkForm, parseSession)
|
|
9
|
+
class APP extends BaseServer {}
|
|
10
|
+
|
|
11
|
+
export default new APP();
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import checkForm from "@/middleware/checkForm";
|
|
2
|
+
import checkLogin from "@/middleware/checkLogin";
|
|
3
|
+
import parseSession from "@/middleware/parseSession";
|
|
4
|
+
import { Application } from "@fastcar/core/annotation";
|
|
5
|
+
import { RPCMiddleware } from "@fastcar/rpc/annotation";
|
|
6
|
+
import forwardMsg from "./middleware/forwardMsg";
|
|
7
|
+
import BaseServer from "../base/BaseServer";
|
|
8
|
+
|
|
9
|
+
@Application
|
|
10
|
+
@RPCMiddleware(checkForm, parseSession, checkLogin, forwardMsg)
|
|
11
|
+
class APP extends BaseServer {}
|
|
12
|
+
|
|
13
|
+
export default new APP();
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { Autowired, Controller, Rule, ValidForm } from "@fastcar/core/annotation";
|
|
2
|
+
import { ClientSession, RpcContext, RpcServer } from "@fastcar/rpc";
|
|
3
|
+
import { RPC, RPCMethod } from "@fastcar/rpc/annotation";
|
|
4
|
+
import Result from "@/common/Result";
|
|
5
|
+
import { SessionAttribute } from "@/types/SessionAttribute";
|
|
6
|
+
import RouterService from "@/servers/base/service/RouterService";
|
|
7
|
+
import { ChannelKind, ServerKind } from "@/common/Constant";
|
|
8
|
+
import Code from "@/common/Code";
|
|
9
|
+
import DataService from "@/servers/base/service/DataService";
|
|
10
|
+
|
|
11
|
+
type DisconnectType = {
|
|
12
|
+
session: ClientSession;
|
|
13
|
+
reason: string;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
@Controller
|
|
17
|
+
export default class AccountHandler {
|
|
18
|
+
@Autowired
|
|
19
|
+
private rpcServer!: RpcServer;
|
|
20
|
+
|
|
21
|
+
@Autowired
|
|
22
|
+
private routerService!: RouterService;
|
|
23
|
+
|
|
24
|
+
@Autowired
|
|
25
|
+
private dataService!: DataService;
|
|
26
|
+
|
|
27
|
+
@RPCMethod("/account/login")
|
|
28
|
+
@ValidForm
|
|
29
|
+
async login(
|
|
30
|
+
@Rule({
|
|
31
|
+
uid: { required: true, type: "number" },
|
|
32
|
+
})
|
|
33
|
+
{ uid }: { uid: number },
|
|
34
|
+
ctx: RpcContext
|
|
35
|
+
) {
|
|
36
|
+
//这边做一个校验 如果当前不是front连进来的则拒绝
|
|
37
|
+
let socketMgr = this.rpcServer.getSocketManager();
|
|
38
|
+
let socketServer = socketMgr.getSocketServerBySessionId(ctx.sessionId);
|
|
39
|
+
|
|
40
|
+
if (!socketServer?.getConfig().extra?.front) {
|
|
41
|
+
this.rpcServer.kickSessionId(ctx.sessionId, Code.COMMON.SERVER_CONNECT_FORBID.toString());
|
|
42
|
+
return Result.errorCode(Code.COMMON.SERVER_CONNECT_FORBID);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
//这边可以进行校验
|
|
46
|
+
//加入频道 绑定会话
|
|
47
|
+
socketMgr.bindCustomID(uid.toString(), ctx.sessionId);
|
|
48
|
+
socketMgr.joinChannelByCustomId(uid.toString(), ChannelKind.FRONT);
|
|
49
|
+
ctx.settings.set(SessionAttribute.logged, true);
|
|
50
|
+
ctx.settings.set(SessionAttribute.uid, uid);
|
|
51
|
+
ctx.settings.set(SessionAttribute.serverKind, ServerKind.front);
|
|
52
|
+
ctx.settings.set(SessionAttribute.serviceId, this.dataService.getCurrServiceId());
|
|
53
|
+
ctx.settings.set(SessionAttribute.loginTime, Date.now());
|
|
54
|
+
|
|
55
|
+
this.routerService.request({
|
|
56
|
+
url: "/room/join",
|
|
57
|
+
serverType: "chat",
|
|
58
|
+
session: ctx,
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
//便于客户端同步
|
|
62
|
+
return Result.ok();
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
@RPCMethod()
|
|
66
|
+
async disconnect({ session, reason }: DisconnectType, ctx: RpcContext) {
|
|
67
|
+
let uid: number = ctx.settings.get(SessionAttribute.uid);
|
|
68
|
+
if (!!uid) {
|
|
69
|
+
this.rpcServer.getSocketManager().removeCustomID(uid.toString());
|
|
70
|
+
|
|
71
|
+
this.routerService.request({
|
|
72
|
+
url: "/room/leave",
|
|
73
|
+
serverType: "chat",
|
|
74
|
+
session,
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return Result.ok();
|
|
79
|
+
}
|
|
80
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { Autowired, Controller, Log } from "@fastcar/core/annotation";
|
|
2
|
+
import { RpcServer, RpcMessage, InteractiveMode } from "@fastcar/rpc";
|
|
3
|
+
import { RPC, RPCMethod } from "@fastcar/rpc/annotation";
|
|
4
|
+
import AuthServiceRole from "@/annotation/AuthServiceRole";
|
|
5
|
+
import { ServerKind } from "@/common/Constant";
|
|
6
|
+
import Result from "@/common/Result";
|
|
7
|
+
import { Logger } from "@fastcar/core";
|
|
8
|
+
|
|
9
|
+
@Controller
|
|
10
|
+
@RPC("/channelRemote")
|
|
11
|
+
@AuthServiceRole(ServerKind.remote)
|
|
12
|
+
export default class ChannelRemote {
|
|
13
|
+
@Autowired
|
|
14
|
+
private rpcServer!: RpcServer;
|
|
15
|
+
|
|
16
|
+
@Log()
|
|
17
|
+
private logger!: Logger;
|
|
18
|
+
|
|
19
|
+
@RPCMethod()
|
|
20
|
+
addChannelByUid(data: { channel: string; uid: number }) {
|
|
21
|
+
this.rpcServer.getSocketManager().joinChannelByCustomId(data.uid.toString(), data.channel);
|
|
22
|
+
return Result.ok();
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
@RPCMethod()
|
|
26
|
+
delChannelByUid(data: { channel: string; uid: string }) {
|
|
27
|
+
this.rpcServer.getSocketManager().leaveChannelByCustomId(data.uid.toString(), data.channel);
|
|
28
|
+
return Result.ok();
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
//根据渠道广播
|
|
32
|
+
@RPCMethod()
|
|
33
|
+
broadcastByChannel(data: { channel: string; msg: RpcMessage; excludeIds?: string[] }) {
|
|
34
|
+
this.rpcServer.getSocketManager().sendMsgToCustomIdByChannel(data.channel, Object.assign(data.msg, { firstPriority: true }), data.excludeIds);
|
|
35
|
+
return Result.ok();
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
//根据单用户广播消息
|
|
39
|
+
@RPCMethod()
|
|
40
|
+
broadcastByUid(data: { data: RpcMessage; uid: number }) {
|
|
41
|
+
this.rpcServer.getSocketManager().sendMsgByCustomId(data.uid.toString(), Object.assign(data.data, { firstPriority: true }));
|
|
42
|
+
return Result.ok();
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
//消息踢掉
|
|
46
|
+
@RPCMethod()
|
|
47
|
+
logoutKick({ sessionId }: { sessionId: string }) {
|
|
48
|
+
this.rpcServer.getSocketManager().sendMsg(sessionId, {
|
|
49
|
+
url: "/logout/kick",
|
|
50
|
+
mode: InteractiveMode.notify,
|
|
51
|
+
});
|
|
52
|
+
//这边不强制删除
|
|
53
|
+
return Result.ok();
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
//强制踢掉
|
|
57
|
+
@RPCMethod()
|
|
58
|
+
forceKick({ sessionId }: { sessionId: string }) {
|
|
59
|
+
this.rpcServer.kickSessionId(sessionId, "force kick");
|
|
60
|
+
//这边不强制删除
|
|
61
|
+
return Result.ok();
|
|
62
|
+
}
|
|
63
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import Code from "@/common/Code";
|
|
2
|
+
import RouterService from "@/servers/base/service/RouterService";
|
|
3
|
+
import { SessionAttribute } from "@/types/SessionAttribute";
|
|
4
|
+
import { CommonConstant, FastCarApplication } from "@fastcar/core";
|
|
5
|
+
import { RpcContext } from "@fastcar/rpc";
|
|
6
|
+
|
|
7
|
+
//转发消息
|
|
8
|
+
export default async function forwardMsg(context: RpcContext, next?: Function) {
|
|
9
|
+
let serverType: string = context.data?.serverType;
|
|
10
|
+
|
|
11
|
+
if (!serverType) {
|
|
12
|
+
//如果namespace是以://开头的
|
|
13
|
+
let index = context.url.indexOf(":/");
|
|
14
|
+
if (index != -1) {
|
|
15
|
+
serverType = context.url.substring(0, index);
|
|
16
|
+
context.url = context.url.substring(index + 2);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
if (!!serverType) {
|
|
21
|
+
//这边加个二次重定向
|
|
22
|
+
let customServiceId = "";
|
|
23
|
+
let app: FastCarApplication = Reflect.get(global, CommonConstant.FastcarApp);
|
|
24
|
+
let selfServerType = app.getSetting(SessionAttribute.serverType);
|
|
25
|
+
//本地网关请求
|
|
26
|
+
if (selfServerType != serverType) {
|
|
27
|
+
//计算请求
|
|
28
|
+
let routerService = app.getComponentByTarget<RouterService>(RouterService);
|
|
29
|
+
if (!routerService) {
|
|
30
|
+
return (context.body = {
|
|
31
|
+
code: Code.SYS.NOT_FOUND,
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
let res = await routerService.request<{ [key: string]: any }, any>({
|
|
36
|
+
url: context.url,
|
|
37
|
+
data: context.data,
|
|
38
|
+
session: {
|
|
39
|
+
sessionId: context.sessionId,
|
|
40
|
+
settings: context.settings,
|
|
41
|
+
connectedTime: context.connectedTime,
|
|
42
|
+
},
|
|
43
|
+
serverType,
|
|
44
|
+
forward: true,
|
|
45
|
+
customServiceId,
|
|
46
|
+
});
|
|
47
|
+
context.body = res;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (next) {
|
|
52
|
+
await next();
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { Autowired, Controller } from "@fastcar/core/annotation";
|
|
2
|
+
import { GET } from "@fastcar/koa/annotation";
|
|
3
|
+
import CenterClient from "../base/service/CenterClient";
|
|
4
|
+
import Result from "../../common/Result";
|
|
5
|
+
import RouterService from "../base/service/RouterService";
|
|
6
|
+
|
|
7
|
+
@Controller
|
|
8
|
+
export default class HelloController {
|
|
9
|
+
@Autowired
|
|
10
|
+
private centerClient!: CenterClient;
|
|
11
|
+
|
|
12
|
+
@Autowired
|
|
13
|
+
private routerService!: RouterService;
|
|
14
|
+
|
|
15
|
+
@GET("/")
|
|
16
|
+
hello() {
|
|
17
|
+
return this.routerService.request({
|
|
18
|
+
url: "/room/join",
|
|
19
|
+
serverType: "chat",
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
@GET("/serverList")
|
|
24
|
+
getServerList() {
|
|
25
|
+
return Result.ok(this.centerClient.getServerMap().toValues());
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
@GET("/test/rebalance")
|
|
29
|
+
async rebalance() {
|
|
30
|
+
let res = await this.centerClient.sendBalance();
|
|
31
|
+
return res;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
@GET("/test/syncconfig")
|
|
35
|
+
syncConfig() {
|
|
36
|
+
this.routerService
|
|
37
|
+
.request({
|
|
38
|
+
url: "/center/syncConfig",
|
|
39
|
+
serverType: "center",
|
|
40
|
+
data: {
|
|
41
|
+
key: "SyncConfigService",
|
|
42
|
+
data: "hello world",
|
|
43
|
+
},
|
|
44
|
+
})
|
|
45
|
+
.then((res) => {
|
|
46
|
+
console.log(res);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
return Result.ok();
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Logger } from "@fastcar/core";
|
|
2
|
+
import { BeanName, Log, Service } from "@fastcar/core/annotation";
|
|
3
|
+
|
|
4
|
+
@BeanName("SyncConfigService")
|
|
5
|
+
@Service
|
|
6
|
+
export default class SyncConfigService {
|
|
7
|
+
@Log()
|
|
8
|
+
private logger!: Logger;
|
|
9
|
+
|
|
10
|
+
load(m: Object) {
|
|
11
|
+
this.logger.debug(`同步配置更新`, m);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Application } from "@fastcar/core/annotation";
|
|
2
|
+
import { EnableKoa, KoaMiddleware } from "@fastcar/koa/annotation";
|
|
3
|
+
import { ExceptionGlobalHandler, KoaBodyParser } from "@fastcar/koa";
|
|
4
|
+
import BaseServer from "../base/BaseServer";
|
|
5
|
+
|
|
6
|
+
@Application
|
|
7
|
+
//开启koa
|
|
8
|
+
//开启异常捕捉 可自定义 通常是放在中间件第一个
|
|
9
|
+
@KoaMiddleware(ExceptionGlobalHandler)
|
|
10
|
+
//开启参数解析
|
|
11
|
+
// @KoaMiddleware(KoaBody)
|
|
12
|
+
@KoaMiddleware(KoaBodyParser)
|
|
13
|
+
class APP extends BaseServer {}
|
|
14
|
+
|
|
15
|
+
export default new APP();
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { CodeProtocolEnum, DecodeMsg, EncodeMsg, RetryConfig, SecureClientOptions, SocketEnum } from "@fastcar/rpc";
|
|
2
|
+
import { ServerConfig } from "@fastcar/server";
|
|
3
|
+
|
|
4
|
+
export type ServerItemConfig = {
|
|
5
|
+
front: boolean;
|
|
6
|
+
domainName?: string; //对外访问域名
|
|
7
|
+
type: SocketEnum; //具体为哪一种型号的连接器
|
|
8
|
+
server: ServerConfig;
|
|
9
|
+
extra?: any; //第三方拓展配置 用于灵活的调用第三方
|
|
10
|
+
clientExtra?: any; //客户端拓展配置
|
|
11
|
+
encode?: EncodeMsg; //编码解码
|
|
12
|
+
decode?: DecodeMsg;
|
|
13
|
+
codeProtocol?: CodeProtocolEnum; //约定协议 json protobuf 默认json
|
|
14
|
+
secure?: SecureClientOptions;
|
|
15
|
+
maxConnections?: number; //最大连接数 默认1024
|
|
16
|
+
disconnectInterval?: number;
|
|
17
|
+
connectionLimit?: number; //连接数限制 默认1
|
|
18
|
+
retry?: RetryConfig;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export type ServerMeta = {
|
|
22
|
+
host: string;
|
|
23
|
+
debugPort?: number; //调试端口号
|
|
24
|
+
serviceId: string;
|
|
25
|
+
clusters?: number; //集群数量
|
|
26
|
+
list: ServerItemConfig[];
|
|
27
|
+
retry?: RetryConfig;
|
|
28
|
+
id: number; //服务唯一ID
|
|
29
|
+
units?: number; //单元数量 默认100
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
type ServiceType = string;
|
|
33
|
+
|
|
34
|
+
export type ServerGroupType = {
|
|
35
|
+
[key: ServiceType]: {
|
|
36
|
+
token: string; //当前服务的token 用于认证使用的
|
|
37
|
+
servers: ServerMeta[];
|
|
38
|
+
};
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export type ServerStatus = {
|
|
42
|
+
serviceId: string;
|
|
43
|
+
status: boolean;
|
|
44
|
+
createTime: number;
|
|
45
|
+
updateTime: number;
|
|
46
|
+
serverType: string;
|
|
47
|
+
centerId: string;
|
|
48
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
//session的属性key值
|
|
2
|
+
export enum SessionAttribute {
|
|
3
|
+
logged = "logged", //是否登录
|
|
4
|
+
serviceId = "serviceId", //服务索引id
|
|
5
|
+
serverType = "serverType", //自定义服务器类型
|
|
6
|
+
uid = "uid",
|
|
7
|
+
serverKind = "serverKind", //服务器分类
|
|
8
|
+
tid = "tid", //桌子分类
|
|
9
|
+
gameServerType = "gameServerType", //桌子的gameKey
|
|
10
|
+
logLoginId = "loginId", //登录日志id
|
|
11
|
+
loginTime = "loginTime", //登录时间
|
|
12
|
+
center_serviceId = "center_serviceId", //注册中心服务id
|
|
13
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { ServerItemConfig } from "@/types/ServerMeta";
|
|
2
|
+
import { SocketEnum } from "@fastcar/rpc";
|
|
3
|
+
|
|
4
|
+
export default class ConnectorUtils {
|
|
5
|
+
static getConnectUrl(item: ServerItemConfig, host: string = "localhost") {
|
|
6
|
+
let sslFlag = !!item.server.ssl;
|
|
7
|
+
let defaultPort = sslFlag ? "443" : "80";
|
|
8
|
+
|
|
9
|
+
switch (item.type) {
|
|
10
|
+
case SocketEnum.SocketIO:
|
|
11
|
+
case SocketEnum.WS: {
|
|
12
|
+
return `${sslFlag ? "wss" : "ws"}://${host}:${item.server.port || defaultPort}`;
|
|
13
|
+
}
|
|
14
|
+
case SocketEnum.MQTT: {
|
|
15
|
+
return `mqtt://${host}:${item.server.port || defaultPort}`;
|
|
16
|
+
}
|
|
17
|
+
case SocketEnum.Grpc: {
|
|
18
|
+
return `${host}:${item.server.port || defaultPort}`;
|
|
19
|
+
}
|
|
20
|
+
default: {
|
|
21
|
+
return "";
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { ServerMicroservices } from "@/common/Constant";
|
|
2
|
+
import { ServerGroupType, ServerItemConfig, ServerMeta } from "@/types/ServerMeta";
|
|
3
|
+
import { CommonConstant } from "@fastcar/core";
|
|
4
|
+
import { FileUtil, MixTool } from "@fastcar/core/utils";
|
|
5
|
+
import * as path from "path";
|
|
6
|
+
|
|
7
|
+
//格式化微服务配置
|
|
8
|
+
export default class MicroservicesUtils {
|
|
9
|
+
static getMicroservicesConfig(): ServerGroupType {
|
|
10
|
+
let resPath = path.join(__dirname, "../../", "resource");
|
|
11
|
+
let sysConfig = FileUtil.getApplicationConfig(resPath, CommonConstant.Application);
|
|
12
|
+
let env = sysConfig.application.env;
|
|
13
|
+
sysConfig = FileUtil.getApplicationConfig(resPath, `${CommonConstant.Application}-${env}`, sysConfig);
|
|
14
|
+
|
|
15
|
+
const microservices: ServerGroupType = sysConfig.settings.get(ServerMicroservices);
|
|
16
|
+
if (!microservices) {
|
|
17
|
+
throw new Error("not found microservices");
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return microservices;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
static format(microservices: ServerGroupType): ServerGroupType {
|
|
24
|
+
let newMicroservices = {};
|
|
25
|
+
Object.keys(microservices).forEach((serverType) => {
|
|
26
|
+
//判断是否为
|
|
27
|
+
let item = microservices[serverType];
|
|
28
|
+
let servers = item.servers;
|
|
29
|
+
|
|
30
|
+
let n: {
|
|
31
|
+
token: string; //当前服务的token 用于认证使用的
|
|
32
|
+
servers: ServerMeta[];
|
|
33
|
+
} = {
|
|
34
|
+
token: item.token,
|
|
35
|
+
servers: [],
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
servers.forEach((citem, index) => {
|
|
39
|
+
let clusters = citem.clusters || 1;
|
|
40
|
+
let units = citem.units || 100;
|
|
41
|
+
let [stype, proto] = citem?.serviceId?.split("-") || "";
|
|
42
|
+
let commonBody: ServerMeta = {
|
|
43
|
+
host: citem.host,
|
|
44
|
+
serviceId: `${stype || serverType}-${proto || "server"}-`,
|
|
45
|
+
list: citem.list,
|
|
46
|
+
retry: citem.retry,
|
|
47
|
+
id: 0,
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
if (citem.debugPort) {
|
|
51
|
+
commonBody.debugPort = commonBody.debugPort;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
let addNum = citem.list.length;
|
|
55
|
+
|
|
56
|
+
for (let i = 0; i < clusters; i++) {
|
|
57
|
+
let newItem: ServerMeta = Object.create(commonBody); //copy原型链
|
|
58
|
+
MixTool.copyProperties(newItem, JSON.parse(JSON.stringify(commonBody))); //copy序列化的值
|
|
59
|
+
|
|
60
|
+
if (newItem.debugPort) {
|
|
61
|
+
newItem.debugPort = newItem.debugPort + i;
|
|
62
|
+
}
|
|
63
|
+
newItem.serviceId = newItem.serviceId + ((index + 1) * units + (i + 1));
|
|
64
|
+
newItem.id = i;
|
|
65
|
+
|
|
66
|
+
newItem.list = newItem.list.map((n) => {
|
|
67
|
+
let t: ServerItemConfig = Object.assign({}, n);
|
|
68
|
+
let skipNum = i * addNum;
|
|
69
|
+
|
|
70
|
+
if (!!t.server.port) {
|
|
71
|
+
t.server.port = t.server.port + skipNum;
|
|
72
|
+
} else {
|
|
73
|
+
t.server.port = t.server.ssl ? 443 + skipNum : 80 + skipNum;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return t;
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
n.servers.push(newItem);
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
Reflect.set(newMicroservices, serverType, Object.assign({}, item, n));
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
return newMicroservices;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
//格式化命令行参数
|
|
90
|
+
static parseArgs(args: string[]) {
|
|
91
|
+
let proto: { [key: string]: string } = {};
|
|
92
|
+
args.forEach((item: string) => {
|
|
93
|
+
let list = item.split("=");
|
|
94
|
+
if (list.length == 2) {
|
|
95
|
+
Reflect.set(proto, list[0].trim(), list[1].trim());
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
return proto;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Context } from "koa";
|
|
2
|
+
import * as os from "os";
|
|
3
|
+
|
|
4
|
+
const localIps: string[] = ["127.0.0.1", "localhost", "0.0.0.0"];
|
|
5
|
+
(function () {
|
|
6
|
+
let ifaces = os.networkInterfaces();
|
|
7
|
+
for (let key in ifaces) {
|
|
8
|
+
let details = ifaces[key];
|
|
9
|
+
details?.forEach((item) => {
|
|
10
|
+
if (item.family === "IPv4" && !localIps.includes(item.address)) {
|
|
11
|
+
localIps.push(item.address);
|
|
12
|
+
}
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
})();
|
|
16
|
+
|
|
17
|
+
export default class NetWork {
|
|
18
|
+
//判断是否为本地ip
|
|
19
|
+
static isLocalIP(host: string): boolean {
|
|
20
|
+
return localIps.includes(host);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function getIP(ctx: Context): string {
|
|
25
|
+
let req = ctx.request;
|
|
26
|
+
let ips = req.headers["x-forwarded-for"] || req.headers["x-real-ip"] || ctx.ip;
|
|
27
|
+
if (Array.isArray(ips)) {
|
|
28
|
+
return ips[0] || "";
|
|
29
|
+
}
|
|
30
|
+
return ips;
|
|
31
|
+
}
|