yuanrw / im Goto Github PK
View Code? Open in Web Editor NEWIM server based on netty. Provides a client jar. Integrate with your own login system.基于netty实现的IM服务端,提供客户端jar包,可集成自己的登录系统
IM server based on netty. Provides a client jar. Integrate with your own login system.基于netty实现的IM服务端,提供客户端jar包,可集成自己的登录系统
com.github.yuanrw.im.common.util.IdWorker
public static Long nextId(Serializable connectorId) {
return sessionMap.computeIfAbsent(connectorId,
key -> new AtomicLong(0)).incrementAndGet();
}
dalao,
这个ID生成的策略是不是还没完成呀?
这个根据ID判断消息是否顺序的,是不是要根据自己ID的生成策略,然后才能继续编写?
com.github.yuanrw.im.common.domain.ack.ClientAckWindow
private boolean isContinuous(Long msgId) {
//如果是本次会话的第一条消息
if (first.compareAndSet(true, false)) {
return true;
} else {
//不是第一条消息,则按照公式算(如果同时有好几条第一条消息,除了真正的第一条,其他会返回false)
return msgId - lastId.get() == 1;
}
}
rest-web | wait-for-it.sh: im-mysql:3306 is available after 10 seconds
rest-web | wait-for-it.sh: waiting for im-redis:6379 without a timeout
rest-web | wait-for-it.sh: im-redis:6379 is available after 0 seconds
rest-web | wait-for-it.sh: waiting for im-rabbit:5672 without a timeout
rest-web | wait-for-it.sh: im-rabbit:5672 is available after 0 seconds
rest-web | JAVA_HOME: /opt/java/openjdk
rest-web | OpenJDK 64-Bit Server VM warning: Ignoring option PermSize; support was removed in 8.0
rest-web | OpenJDK 64-Bit Server VM warning: Ignoring option MaxPermSize; support was removed in 8.0
rest-web | 2020-08-23 22:55:10.399 rest [main] ERROR o.s.boot.SpringApplication - Application run failed
rest-web | java.lang.IllegalStateException: Logback configuration error detected:
rest-web | ERROR in ch.qos.logback.core.rolling.RollingFileAppender[file] - openFile(/tmp/IM_logs/rest.log,true) call failed. java.io.FileNotFoundException: /tmp/IM_logs/rest.
log (Is a directory)
rest-web | at org.springframework.boot.logging.logback.LogbackLoggingSystem.loadConfiguration(LogbackLoggingSystem.java:169) ~[spring-boot-2.1.2.RELEASE.jar:2.1.2.RELEASE]
rest-web | at org.springframework.boot.logging.AbstractLoggingSystem.initializeWithConventions(AbstractLoggingSystem.java:82) ~[spring-boot-2.1.2.RELEASE.jar:2.1.2.RELEASE
]
rest-web | at org.springframework.boot.logging.AbstractLoggingSystem.initialize(AbstractLoggingSystem.java:60) ~[spring-boot-2.1.2.RELEASE.jar:2.1.2.RELEASE]
rest-web | at org.springframework.boot.logging.logback.LogbackLoggingSystem.initialize(LogbackLoggingSystem.java:117) ~[spring-boot-2.1.2.RELEASE.jar:2.1.2.RELEASE]
rest-web | at org.springframework.boot.context.logging.LoggingApplicationListener.initializeSystem(LoggingApplicationListener.java:293) ~[spring-boot-2.1.2.RELEASE.jar:2.1
.2.RELEASE]
rest-web | at org.springframework.boot.context.logging.LoggingApplicationListener.initialize(LoggingApplicationListener.java:266) ~[spring-boot-2.1.2.RELEASE.jar:2.1.2.REL
EASE]
rest-web | at org.springframework.boot.context.logging.LoggingApplicationListener.onApplicationEnvironmentPreparedEvent(LoggingApplicationListener.java:229) ~[spring-boot-
2.1.2.RELEASE.jar:2.1.2.RELEASE]
rest-web | at org.springframework.boot.context.logging.LoggingApplicationListener.onApplicationEvent(LoggingApplicationListener.java:202) ~[spring-boot-2.1.2.RELEASE.jar:2
.1.2.RELEASE]
rest-web | at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:172) ~[spring-context-5.1.4.RELEA
SE.jar:5.1.4.RELEASE]
rest-web | at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:165) ~[spring-context-5.1.4.RELEASE
.jar:5.1.4.RELEASE]
rest-web | at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139) ~[spring-context-5.1.4.RELEASE
.jar:5.1.4.RELEASE]
rest-web | at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:127) ~[spring-context-5.1.4.RELEASE
.jar:5.1.4.RELEASE]
rest-web | at org.springframework.boot.context.event.EventPublishingRunListener.environmentPrepared(EventPublishingRunListener.java:75) ~[spring-boot-2.1.2.RELEASE.jar:2.1
.2.RELEASE]
rest-web | at org.springframework.boot.SpringApplicationRunListeners.environmentPrepared(SpringApplicationRunListeners.java:54) ~[spring-boot-2.1.2.RELEASE.jar:2.1.2.RELEA
SE]
rest-web | at org.springframework.boot.SpringApplication.prepareEnvironment(SpringApplication.java:347) ~[spring-boot-2.1.2.RELEASE.jar:2.1.2.RELEASE]
rest-web | at org.springframework.boot.SpringApplication.run(SpringApplication.java:306) ~[spring-boot-2.1.2.RELEASE.jar:2.1.2.RELEASE]
rest-web | at org.springframework.boot.SpringApplication.run(SpringApplication.java:1260) ~[spring-boot-2.1.2.RELEASE.jar:2.1.2.RELEASE]
rest-web | at org.springframework.boot.SpringApplication.run(SpringApplication.java:1248) ~[spring-boot-2.1.2.RELEASE.jar:2.1.2.RELEASE]
rest-web | at com.github.yuanrw.im.rest.web.RestStarter.main(RestStarter.java:19) ~[rest-web-1.0.0.jar:na]
rest-web | Exception in thread "main" java.lang.IllegalStateException: Logback configuration error detected:
rest-web | ERROR in ch.qos.logback.core.rolling.RollingFileAppender[file] - openFile(/tmp/IM_logs/rest.log,true) call failed. java.io.FileNotFoundException: /tmp/IM_logs/rest.
log (Is a directory)
rest-web | at org.springframework.boot.logging.logback.LogbackLoggingSystem.loadConfiguration(LogbackLoggingSystem.java:169)
rest-web | at org.springframework.boot.logging.AbstractLoggingSystem.initializeWithConventions(AbstractLoggingSystem.java:82)
rest-web | at org.springframework.boot.logging.AbstractLoggingSystem.initialize(AbstractLoggingSystem.java:60)
rest-web | at org.springframework.boot.logging.logback.LogbackLoggingSystem.initialize(LogbackLoggingSystem.java:117)
rest-web | at org.springframework.boot.context.logging.LoggingApplicationListener.initializeSystem(LoggingApplicationListener.java:293)
rest-web | at org.springframework.boot.context.logging.LoggingApplicationListener.initialize(LoggingApplicationListener.java:266)
rest-web | at org.springframework.boot.context.logging.LoggingApplicationListener.onApplicationEnvironmentPreparedEvent(LoggingApplicationListener.java:229)
rest-web | at org.springframework.boot.context.logging.LoggingApplicationListener.onApplicationEvent(LoggingApplicationListener.java:202)
rest-web | at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:172)
rest-web | at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:165)
rest-web | at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139)
rest-web | at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:127)
rest-web | at org.springframework.boot.context.event.EventPublishingRunListener.environmentPrepared(EventPublishingRunListener.java:75)
rest-web | at org.springframework.boot.SpringApplicationRunListeners.environmentPrepared(SpringApplicationRunListeners.java:54)
rest-web | at org.springframework.boot.SpringApplication.prepareEnvironment(SpringApplication.java:347)
rest-web | at org.springframework.boot.SpringApplication.run(SpringApplication.java:306)
rest-web | at org.springframework.boot.SpringApplication.run(SpringApplication.java:1260)
rest-web | at org.springframework.boot.SpringApplication.run(SpringApplication.java:1248)
rest-web | at com.github.yuanrw.im.rest.web.RestStarter.main(RestStarter.java:19)
rest-web | SERVICE_NAME started....
rest-web exited with code 0
transfer | nc: bad address 'rest-web'
transfer | nc: bad address 'rest-web'
transfer | nc: bad address '
学习下im聊天编程,谢谢分享
大概粗略的看下你的代码,似乎不具备分布式部署的条件?不知道你这块有什么建议规划
connector发送的Ack.AckMsg 或者Chat.ChatMsg无法被客户端Ack,connector后面会一直发送
com.github.yuanrw.im.connector.service.ConnectorToClientService
public void doChatToClientOrTransferAndFlush(Chat.ChatMsg chat) {
boolean onTheMachine = sendMsg(chat.getDestId(), chat.getId(),
cid -> Chat.ChatMsg.newBuilder().mergeFrom(chat).setId(IdWorker.nextId(cid)).build());
//send ack to from id
if (onTheMachine) {
ClientConn conn = clientConnContext.getConnByUserId(chat.getFromId());
if (conn == null) {
ChannelHandlerContext ctx = ConnectorTransferHandler.getOneOfTransferCtx(System.currentTimeMillis());
ctx.writeAndFlush(getDelivered(ctx.channel().attr(Conn.NET_ID).get(), chat));
} else {
//need wait for ack
Ack.AckMsg delivered = getDelivered(conn.getNetId(), chat);
ServerAckWindow.offer(conn.getUserId(), delivered.getId(), delivered, m -> conn.getCtx().writeAndFlush(m));
}
}
}
private boolean sendMsg(String destId, Long msgId, Function<Serializable, Message> generateMsg) {
Conn conn = clientConnContext.getConnByUserId(destId);
if (conn == null) {
ChannelHandlerContext ctx = ConnectorTransferHandler.getOneOfTransferCtx(System.currentTimeMillis());
ctx.writeAndFlush(generateMsg.apply(ctx.channel().attr(Conn.NET_ID).get()));
return false;
} else {
//the user is connected to this machine
//won 't save chat histories
Message message = generateMsg.apply(conn.getNetId());
ServerAckWindow.offer(conn.getNetId(), msgId, message, m -> conn.getCtx().writeAndFlush(m));
return true;
}
}
doChatToClientOrTransferAndFlush()发送delivered ack时,ServerAckWindow.offer的第一个参数是conn.getNetId()
sendMsg()的ServerAckWindow.offer的msgId参数应该是message的新id吗?
com.github.yuanrw.im.client.handler.ClientConnectorHandler
public void channelActive(ChannelHandlerContext ctx) throws Exception {
this.ctx = ctx;
serverAckWindow = new ServerAckWindow(IdWorker.uuid(), 10, Duration.ofSeconds(5));
clientAckWindow = new ClientAckWindow(5);
clientMsgListener.online();
}
这里生成了connectId,com.github.yuanrw.im.client.ImClient也生成了connnectId,两个不一样,后面ChatApi发送消息时拿不到ServerAckWindow实例
优秀
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.