I'm trying to make a chat, but I can't connect.
server use node.js and socket.io version 3.1.1
I'm using the most recent version of Swift socket client, is it two versions of the error?
It's been weeks now without knowing the cause.
help me plz,,TT
When the connection is connected, when the connection is disconnected, when there is an error, it is on and shown in the log window.
emit ("test") is a test event that returns "test" from the server if the test event succeeds.
class SocketIOManager: NSObject {
static let shared = SocketIOManager()
var manager = SocketManager(socketURL: URL(string: "http://myUrl.com")!, config: [.log(true), .compress])
var socket: SocketIOClient!
override init() {
super.init()
socket = manager.defaultSocket
socket = manager.socket(forNamespace: "/")
}
func establishConnection() {
socket.connect()
test()
}
func closeConnection() {
socket.disconnect()
}
func test() {
socket.on(clientEvent: .error) { (data, eck) in
print(data)
print(eck)
print(self.socket.status)
print("socket error")
}
socket.on("test") { (data, eck) in
print("hihihihi")
print(data)
print("socket test")
}
socket.on(clientEvent: .connect) { (data, eck) in
print(data)
print("socket connect!!")
self.socket.emit("test")
}
socket.on(clientEvent: .disconnect) { (data, eck) in
print(data)
print("socket disconnect")
}
}
}
2021-02-09 18:41:26.292366+0900 TikiTaka[17730:854101] LOG SocketIOClient{/}: Handling event: statusChange with data: [connecting, 2]
2021-02-09 18:41:26.292608+0900 TikiTaka[17730:854101] LOG SocketIOClient{/}: Joining namespace /
2021-02-09 18:41:26.292800+0900 TikiTaka[17730:854101] LOG SocketManager: Tried connecting socket when engine isn't open. Connecting
2021-02-09 18:41:26.292927+0900 TikiTaka[17730:854101] LOG SocketManager: Adding engine
2021-02-09 18:41:26.293654+0900 TikiTaka[17730:854101] LOG SocketIOClient{/}: Adding handler for event: error
2021-02-09 18:41:26.293666+0900 TikiTaka[17730:854295] LOG SocketEngine: Starting engine. Server: http://54.180.2.226:3000
2021-02-09 18:41:26.293785+0900 TikiTaka[17730:854101] LOG SocketIOClient{/}: Adding handler for event: test
2021-02-09 18:41:26.293796+0900 TikiTaka[17730:854295] LOG SocketEngine: Handshaking
2021-02-09 18:41:26.293892+0900 TikiTaka[17730:854101] LOG SocketIOClient{/}: Adding handler for event: connect
2021-02-09 18:41:26.294001+0900 TikiTaka[17730:854101] LOG SocketIOClient{/}: Adding handler for event: disconnect
2021-02-09 18:41:26.294320+0900 TikiTaka[17730:854295] LOG SocketEnginePolling: Doing polling GET http://54.180.2.226:3000/socket.io/?transport=polling&b64=1
af
2021-02-09 18:41:26.364252+0900 TikiTaka[17730:854298] LOG SocketEnginePolling: Got polling response
2021-02-09 18:41:26.364448+0900 TikiTaka[17730:854298] LOG SocketEnginePolling: Got poll message: 0{"sid":"8K5NIimNyRJ-oQ33AAFh","upgrades":["websocket"],"pingInterval":25000,"pingTimeout":5000}
2021-02-09 18:41:26.364897+0900 TikiTaka[17730:854298] LOG SocketEngine: Got message: 0{"sid":"8K5NIimNyRJ-oQ33AAFh","upgrades":["websocket"],"pingInterval":25000,"pingTimeout":5000}
2021-02-09 18:41:26.369022+0900 TikiTaka[17730:854101] LOG SocketIOClient{/}: Handling event: ping with data: []
2021-02-09 18:41:26.369032+0900 TikiTaka[17730:854298] LOG SocketEnginePolling: Doing polling GET http://54.180.2.226:3000/socket.io/?transport=polling&b64=1&sid=8K5NIimNyRJ-oQ33AAFh
2021-02-09 18:41:26.369268+0900 TikiTaka[17730:854101] LOG SocketManager: Engine opened Connect
2021-02-09 18:41:26.369646+0900 TikiTaka[17730:854101] LOG SocketIOClient{/}: Socket connected
2021-02-09 18:41:26.369886+0900 TikiTaka[17730:854101] LOG SocketIOClient{/}: Handling event: statusChange with data: [connected, 3]
2021-02-09 18:41:26.370293+0900 TikiTaka[17730:854101] LOG SocketIOClient{/}: Handling event: connect with data: ["/"]
["/"]
socket connect!!
2021-02-09 18:41:26.371367+0900 TikiTaka[17730:854101] LOG SocketIOClient{/}: Emitting: 2["test"], Ack: false
2021-02-09 18:41:26.371442+0900 TikiTaka[17730:854298] LOG SocketEngine: Writing poll: has data: false
2021-02-09 18:41:26.371803+0900 TikiTaka[17730:854298] LOG SocketEnginePolling: Sending poll: as type: 2
2021-02-09 18:41:26.372298+0900 TikiTaka[17730:854298] LOG SocketEnginePolling: Created POST string: 1:2
2021-02-09 18:41:26.372767+0900 TikiTaka[17730:854298] LOG SocketEnginePolling: POSTing
2021-02-09 18:41:26.372966+0900 TikiTaka[17730:854298] LOG SocketEnginePolling: Doing polling POST http://54.180.2.226:3000/socket.io/?transport=polling&b64=1&sid=8K5NIimNyRJ-oQ33AAFh
2021-02-09 18:41:26.373433+0900 TikiTaka[17730:854298] LOG SocketEngine: Writing poll: 2["test"] has data: false
2021-02-09 18:41:26.373660+0900 TikiTaka[17730:854298] LOG SocketEnginePolling: Sending poll: 2["test"] as type: 4
2021-02-09 18:41:26.409725+0900 TikiTaka[17730:854301] LOG SocketEnginePolling: Created POST string: 10:42["test"]
2021-02-09 18:41:26.410041+0900 TikiTaka[17730:854301] LOG SocketEnginePolling: POSTing
2021-02-09 18:41:26.410198+0900 TikiTaka[17730:854301] LOG SocketEnginePolling: Doing polling POST http://54.180.2.226:3000/socket.io/?transport=polling&b64=1&sid=8K5NIimNyRJ-oQ33AAFh
2021-02-09 18:41:26.411327+0900 TikiTaka[17730:854298] LOG SocketEnginePolling: Got polling response
2021-02-09 18:41:26.411533+0900 TikiTaka[17730:854298] LOG SocketEnginePolling: Doing polling GET http://54.180.2.226:3000/socket.io/?transport=polling&b64=1&sid=8K5NIimNyRJ-oQ33AAFh
2021-02-09 18:41:26.412691+0900 TikiTaka[17730:854101] LOG SocketIOClient{/}: Handling event: websocketUpgrade with data: [["content-length": "18", "content-type": "text/html", "connection": "close"]]
2021-02-09 18:41:26.412823+0900 TikiTaka[17730:854296] LOG SocketEngine: Flushing probe wait
2021-02-09 18:41:26.422164+0900 TikiTaka[17730:854301] ERROR SocketEnginePolling: Error during long poll request
2021-02-09 18:41:26.422278+0900 TikiTaka[17730:854301] ERROR SocketEngine: Error
2021-02-09 18:41:26.422413+0900 TikiTaka[17730:854101] ERROR SocketManager: Error
2021-02-09 18:41:26.422436+0900 TikiTaka[17730:854301] LOG SocketEngine: Engine is being closed.
2021-02-09 18:41:26.422533+0900 TikiTaka[17730:854101] LOG SocketIOClient{/}: Handling event: error with data: ["Error"]
2021-02-09 18:41:26.422547+0900 TikiTaka[17730:854301] LOG SocketEnginePolling: Created POST string: 1:1
["Error"]
<SocketIO.SocketAckEmitter: 0x60000148cb40>
connected
socket error
Related
I have a NestJS and TypeORM project going. I am trying to connect it to my MongoDB database.
Here is the list of my MongoDB projects from the https://cloud.mongodb.com/ website:
The only name I can see for these is "cluster0" like here:
And then in my .env file I have:
MONGODB_CONNECTION_STRING=mongodb+srv://roland:<myActualPassword>#cluster0.7llne.mongodb.net/?retryWrites=true&w=majority
MONGODB_DATABASE=cluster0
and then the entrypoint to the application:
import { Module } from "#nestjs/common";
import { SchedulingController } from "./scheduling.controller";
import { SchedulingService } from "./scheduling.service";
import { ConfigModule } from "#nestjs/config";
import { TypeOrmModule } from "#nestjs/typeorm";
import { Meeting } from "./db/Meeting.entity";
#Module({
imports: [
ConfigModule.forRoot(),
TypeOrmModule.forRoot({
type: "mongodb",
url: process.env.MONGODB_CONNECTION_STRING,
database: process.env.MONGODB_DATABASE,
entities: [__dirname + "/**/*.entity{.ts,.js}"],
ssl: true,
useUnifiedTopology: true,
useNewUrlParser: true,
}),
TypeOrmModule.forFeature([Meeting]),
],
controllers: [SchedulingController],
providers: [SchedulingService],
})
export class SchedulingModule {}
But I see these errors:
[Nest] 16760 - 2022-05-16, 10:05:09 p.m. ERROR [TypeOrmModule] Unable to connect to the database. Retrying (5)...
MongoServerSelectionError: read ECONNRESET
at Timeout._onTimeout (C:\Users\jenfr\Documents\Code2022\TakeHomeTests\bluescape\bluescape\node_modules\mongodb\src\sdam\topology.ts:594:30)
at listOnTimeout (node:internal/timers:557:17)
at processTimers (node:internal/timers:500:7)
[Nest] 16760 - 2022-05-16, 10:05:42 p.m. ERROR [TypeOrmModule] Unable to connect to the database. Retrying (6)...
MongoServerSelectionError: read ECONNRESET
at Timeout._onTimeout (C:\Users\jenfr\Documents\Code2022\TakeHomeTests\bluescape\bluescape\node_modules\mongodb\src\sdam\topology.ts:594:30)
at listOnTimeout (node:internal/timers:557:17)
at processTimers (node:internal/timers:500:7)
[Nest] 16760 - 2022-05-16, 10:06:15 p.m. ERROR [TypeOrmModule] Unable to connect to the database. Retrying (7)...
MongoServerSelectionError: read ECONNRESET
at Timeout._onTimeout (C:\Users\jenfr\Documents\Code2022\TakeHomeTests\bluescape\bluescape\node_modules\mongodb\src\sdam\topology.ts:594:30)
at listOnTimeout (node:internal/timers:557:17)
at processTimers (node:internal/timers:500:7)
edit: I'm fairly certain my MONGODB_CONNECTION_STRING and MONGODB_DATABASE are set properly, anyone know what else could be causing these errors?
Try to set useUnifiedTopology=false.
I am trying to implement an Google AdMob banner ad in my swift application and it simply doesn't show up. I extended the plist to the following.
<key>GADApplicationIdentifier</key>
<string>ca-app-pub-???</string>
<key>SKAdNetworkItems</key>
<array>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>cstr6suwn9.skadnetwork</string>
</dict>
...
</array>
Edited AppDelegate.swift...
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
GADMobileAds.sharedInstance().start(completionHandler: nil)
return true
}
And implemented the banner in my ViewController...
import UIKit
import GoogleMobileAds
class ViewController: UIViewController {
...
private let banner: GADBannerView = {
let banner = GADBannerView()
banner.adUnitID = "ca-app-pub-???/???"
banner.load(GADRequest())
banner.backgroundColor = .secondarySystemBackground
return banner
}()
override func viewDidLoad() {
super.viewDidLoad()
banner.rootViewController = self
view.addSubview(banner)
...
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
banner.frame = CGRect(x: 0, y: view.frame.size.height-50, width: view.frame.size.width, height: 50)
}
...
}
This code causes the following error and the banner doesn't show up:
2022-02-18 19:12:45.453836+0100 TestApp[70970:5163578] <Google> To get test ads on this device, set:
Objective-C
GADMobileAds.sharedInstance.requestConfiguration.testDeviceIdentifiers = #[ GADSimulatorID ];
Swift
GADMobileAds.sharedInstance().requestConfiguration.testDeviceIdentifiers = [ GADSimulatorID ]
2022-02-18 19:12:45.464778+0100 TestApp[70970:5163713] - <Google>[I-ACS025031] AdMob App ID changed. Original, new: (nil), ca-app-pub-???
2022-02-18 19:12:45.520401+0100 TestApp[70970:5163714] [Client] Synchronous remote object proxy returned error: Error Domain=NSCocoaErrorDomain Code=4099 "The connection to service named com.apple.commcenter.coretelephony.xpc was invalidated: failed at lookup with error 3 - No such process." UserInfo={NSDebugDescription=The connection to service named com.apple.commcenter.coretelephony.xpc was invalidated: failed at lookup with error 3 - No such process.}
2022-02-18 19:12:45.520411+0100 TestApp[70970:5163713] [Client] Updating selectors failed with: Error Domain=NSCocoaErrorDomain Code=4099 "The connection to service named com.apple.commcenter.coretelephony.xpc was invalidated: failed at lookup with error 3 - No such process." UserInfo={NSDebugDescription=The connection to service named com.apple.commcenter.coretelephony.xpc was invalidated: failed at lookup with error 3 - No such process.}
2022-02-18 19:12:45.520643+0100 TestApp[70970:5163714] [Client] Synchronous remote object proxy returned error: Error Domain=NSCocoaErrorDomain Code=4099 "The connection to service named com.apple.commcenter.coretelephony.xpc was invalidated: failed at lookup with error 3 - No such process." UserInfo={NSDebugDescription=The connection to service named com.apple.commcenter.coretelephony.xpc was invalidated: failed at lookup with error 3 - No such process.}
2022-02-18 19:12:45.520657+0100 TestApp[70970:5163718] [Client] Updating selectors failed with: Error Domain=NSCocoaErrorDomain Code=4099 "The connection to service named com.apple.commcenter.coretelephony.xpc was invalidated: failed at lookup with error 3 - No such process." UserInfo={NSDebugDescription=The connection to service named com.apple.commcenter.coretelephony.xpc was invalidated: failed at lookup with error 3 - No such process.}
2022-02-18 19:12:45.520824+0100 TestApp[70970:5163714] [Client] Synchronous remote object proxy returned error: Error Domain=NSCocoaErrorDomain Code=4099 "The connection to service named com.apple.commcenter.coretelephony.xpc was invalidated: failed at lookup with error 3 - No such process." UserInfo={NSDebugDescription=The connection to service named com.apple.commcenter.coretelephony.xpc was invalidated: failed at lookup with error 3 - No such process.}
2022-02-18 19:12:45.520939+0100 TestApp[70970:5163718] [Client] Updating selectors failed with: Error Domain=NSCocoaErrorDomain Code=4099 "The connection to service named com.apple.commcenter.coretelephony.xpc was invalidated: failed at lookup with error 3 - No such process." UserInfo={NSDebugDescription=The connection to service named com.apple.commcenter.coretelephony.xpc was invalidated: failed at lookup with error 3 - No such process.}
2022-02-18 19:12:45.522075+0100 TestApp[70970:5163718] [Client] Updating selectors failed with: Error Domain=NSCocoaErrorDomain Code=4099 "The connection to service named com.apple.commcenter.coretelephony.xpc was invalidated: failed at lookup with error 3 - No such process." UserInfo={NSDebugDescription=The connection to service named com.apple.commcenter.coretelephony.xpc was invalidated: failed at lookup with error 3 - No such process.}
2022-02-18 19:12:45.522129+0100 TestApp[70970:5163718] [Client] Updating selectors after delegate addition failed with: Error Domain=NSCocoaErrorDomain Code=4099 "The connection to service named com.apple.commcenter.coretelephony.xpc was invalidated: failed at lookup with error 3 - No such process." UserInfo={NSDebugDescription=The connection to service named com.apple.commcenter.coretelephony.xpc was invalidated: failed at lookup with error 3 - No such process.}
2022-02-18 19:12:45.522084+0100 TestApp[70970:5163714] - <Google>[I-ACS023007] Analytics v.81200000 started
2022-02-18 19:12:45.522389+0100 TestApp[70970:5163714] - <Google>[I-ACS023008] To enable debug logging set the following application argument: -APMAnalyticsDebugEnabled (see xxx)
2022-02-18 19:12:45.552092+0100 TestApp[70970:5163578] Writing analzed variants.
2022-02-18 19:12:45.588346+0100 TestApp[70970:5163718] - <Google>[I-ACS800023] No pending snapshot to activate. SDK name: app_measurement
2022-02-18 19:12:45.616229+0100 TestApp[70970:5163578] Writing analzed variants.
2022-02-18 19:12:45.636629+0100 TestApp[70970:5163578] [plugin] AddInstanceForFactory: No factory registered for id <CFUUID 0x60000178d2c0> F8BB1C28-BAE8-???
2022-02-18 19:12:45.692429+0100 TestApp[70970:5163721] - <Google>[I-ACS023012] Analytics collection enabled
2022-02-18 19:12:45.912031+0100 TestApp[70970:5163717] [boringssl] boringssl_metrics_log_metric_block_invoke(144) Failed to log metrics
Initialisation of GADBannerView is might be wrong in your project as they need adSize as frame
this working fine on my application , I have working production ads,
class HomePageViewController: UIViewController {
private var adMobBannerView1: GADBannerView!
private var adMobBannerView2: GADBannerView!
override func viewDidLoad() {
setupAdMobBannerAD()
}
private func setupAdMobBannerAD() {
let sizeForBanner = GADAdSizeFromCGSize(.init(width: view.frame.width, height: 50))
// here you need to intilise GADBannerView with adSize of GADAdSizeFromCGSize
adMobBannerView1 = GADBannerView(adSize: sizeForBanner)
adMobBannerView2 = GADBannerView(adSize: sizeForBanner)
adMobBannerView1.translatesAutoresizingMaskIntoConstraints = false
adMobBannerView2.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(adMobBannerView1)
view.addSubview(adMobBannerView2)
adMobBannerView1.delegate = self
adMobBannerView2.delegate = self
NSLayoutConstraint.activate([
adMobBannerView1.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor),
adMobBannerView1.centerXAnchor.constraint(equalTo: view.safeAreaLayoutGuide.centerXAnchor),
adMobBannerView2.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor , constant: 20 ),
adMobBannerView2.centerXAnchor.constraint(equalTo: view.safeAreaLayoutGuide.centerXAnchor),
])
adMobBannerView2.adUnitID = Constants.secondAdBannerString
// I have saved my bannerID String in another class don't worry about this
adMobBannerView2.rootViewController = self
adMobBannerView1.adUnitID = Constants.firstAdBannerString
// I have saved my bannerID String in another class don't worry about this
adMobBannerView1.rootViewController = self
adMobBannerView2.load(GADRequest())
adMobBannerView1.load(GADRequest())
}
}
you want to add some delegate to get informed by admob if there is any problem with your ad account or something
extension HomePageViewController : GADBannerViewDelegate {
func bannerView(_ bannerView: GADBannerView, didFailToReceiveAdWithError error: Error) {
print("admob banner ad failecd to show going to represent adolony \n")
if DataModel.shared.showAdmobAd {
self.requestAdColonyBanners()
// any alternative method can be performed here as we this function will be called by admob incase you didn't get banner ad , in my case I m launching ads form another ad service called adcolony
}
}
}
I have a Spring Cloud Gateway (eureka client) app that uses Spring Cloud Load Balancer (Spring Cloud version: Hoxton.SR6) and I have an instance of a spring boot app (spring boot 2.3 with enabled graceful shutdown, (eureka client).
When I shutdown a spring boot service and perform a request through the gateway then the gateway throws 500 error (connection refused), instead of 503. 503 appears after a 1-2 minutes.
Can anyone clarify if it is an expected behavior?
It seems that the problem comes from eureka-client (1.9.21 version in my case)
AtomicReference<Applications> localRegionApps isn't frequently updated
Thanks!
UPDATE:
I decided to check deeper this 500 error. The result is that my system (ubuntu) gives this error if the port is not used:
curl -v localhost:9722
Rebuilt URL to: localhost:9722/
Trying 127.0.0.1...
TCP_NODELAY set
connect to 127.0.0.1 port 9722 failed: Connection refused
Failed to connect to localhost port 9722: Connection refused
Closing connection 0
So I put in my application.yml:
spring:
cloud:
gateway:
routes:
- id: my_route
uri: http://localhost:9722/
Then when my request is routed to my_route and none of apps uses 9722 then I get an error:
io.netty.channel.AbstractChannel$AnnotatedConnectException: finishConnect(..) failed: Connection refused: localhost/127.0.0.1:9722
Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException:
Error has been observed at the following site(s):
|_ checkpoint ⇢ org.springframework.cloud.gateway.filter.WeightCalculatorWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ org.springframework.boot.actuate.metrics.web.reactive.server.MetricsWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ HTTP GET "/internal/mail/internal/health-check" [ExceptionHandlingWebHandler]
Stack trace:
Caused by: java.net.ConnectException: finishConnect(..) failed: Connection refused
at io.netty.channel.unix.Errors.throwConnectException(Errors.java:124)
at io.netty.channel.unix.Socket.finishConnect(Socket.java:251)
at io.netty.channel.epoll.AbstractEpollChannel$AbstractEpollUnsafe.doFinishConnect(AbstractEpollChannel.java:672)
at io.netty.channel.epoll.AbstractEpollChannel$AbstractEpollUnsafe.finishConnect(AbstractEpollChannel.java:649)
at io.netty.channel.epoll.AbstractEpollChannel$AbstractEpollUnsafe.epollOutReady(AbstractEpollChannel.java:529)
at io.netty.channel.epoll.EpollEventLoop.processReady(EpollEventLoop.java:465)
at io.netty.channel.epoll.EpollEventLoop.run(EpollEventLoop.java:378)
at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989)
at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.base/java.lang.Thread.run(Thread.java:834)
It seems to be an unexpected exception, since it isn't possible to handle it using a circuit breaker or any gateway filter.
Is it possible to handle this error correctly? I would like to return 503 in this case
One of the easiest ways to map particular exception to particular HTTP status code is providing a custom bean of type org.springframework.boot.web.reactive.error.ErrorAttributes. Here is an example:
#Bean
public ErrorAttributes errorAttributes() {
return new CustomErrorAttributes(httpStatusExceptionTypeMapper);
}
public class CustomErrorAttributes extends DefaultErrorAttributes {
#Override
public Map<String, Object> getErrorAttributes(ServerRequest request, ErrorAttributeOptions options) {
Map<String, Object> attributes = super.getErrorAttributes(request, options);
Throwable error = getError(request);
MergedAnnotation<ResponseStatus> responseStatusAnnotation = MergedAnnotations
.from(error.getClass(), MergedAnnotations.SearchStrategy.TYPE_HIERARCHY).get(ResponseStatus.class);
HttpStatus errorStatus = determineHttpStatus(error, responseStatusAnnotation);
attributes.put("status", errorStatus.value());
return attributes;
}
private HttpStatus determineHttpStatus(Throwable error, MergedAnnotation<ResponseStatus> responseStatusAnnotation) {
if (error instanceof ResponseStatusException) {
return ((ResponseStatusException) error).getStatus();
}
return responseStatusAnnotation.getValue("code", HttpStatus.class).orElseGet(() -> {
if (error instanceof java.net.ConnectException) {
return HttpStatus.SERVICE_UNAVAILABLE;
}
return HttpStatus.INTERNAL_SERVER_ERROR;
}
}
}
hava a try to define your custom ErrorWebExceptionHandler.
see:
org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler
org.springframework.boot.autoconfigure.web.reactive.error.DefaultErrorWebExceptionHandler
You should use Cloud Circuit Breaker.
For that:
Declare corresponding starter in your pom:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-circuitbreaker-reactor-resilience4j</artifactId>
</dependency>
Declare circuit breaker in application.yaml
spring:
cloud:
gateway:
routes:
- id: my_route
uri: http://localhost:9722/
filters:
- name: CircuitBreaker
args:
name: myCircuitBreaker
fallbackUri: forward:/inCaseOfFailureUseThis
Declare the endpoint which will be called in the case of failure (a connection error, for example)
#RequestMapping("/inCaseOfFailureUseThis")
public Mono<ResponseEntity<String>> inCaseOfFailureUseThis() {
return Mono.just(ResponseEntity.status(HttpStatus.SERVICE_UNAVAILABLE).body("body for service failure case"));
}
We are having some troubles with Spring Cloud and Kafka, at sometimes our microservice throws an UnkownProducerIdException, this is caused if the parameter transactional.id.expiration.ms is expired in the broker side.
My question, could it be possible to catch that exception and retry the failed message? If yes, what could be the best option to handle it?
I have took a look at:
- https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=89068820
- Kafka UNKNOWN_PRODUCER_ID exception
We are using Spring Cloud Hoxton.RELEASE version and Spring Kafka version 2.2.4.RELEASE
We are using AWS Kafka solution so we can't set a new value on that property I mentioned before.
Here is some trace of the exception:
2020-04-07 20:54:00.563 ERROR 5188 --- [ad | producer-2] o.a.k.c.p.internals.TransactionManager : [Producer clientId=producer-2] The broker returned org.apache.kafka.common.errors.UnknownProducerIdException: This exception is raised by the broker if it could not locate the producer metadata associated with the producerId in question. This could happen if, for instance, the producer's records were deleted because their retention time had elapsed. Once the last records of the producerId are removed, the producer's metadata is removed from the broker, and future appends by the producer will return this exception. for topic-partition test.produce.another-2 with producerId 35000, epoch 0, and sequence number 8
2020-04-07 20:54:00.563 INFO 5188 --- [ad | producer-2] o.a.k.c.p.internals.TransactionManager : [Producer clientId=producer-2] ProducerId set to -1 with epoch -1
2020-04-07 20:54:00.565 ERROR 5188 --- [ad | producer-2] o.s.k.support.LoggingProducerListener : Exception thrown when sending a message with key='null' and payload='{...}' to topic <some-topic>:
To reproduce this exception:
- I have used the confluent docker images and set the environment variable KAFKA_TRANSACTIONAL_ID_EXPIRATION_MS to 10 seconds so I wouldn't wait too much for this exception to be thrown.
- In another process, send one by one in interval of 10 seconds 1 message in the topic the java will listen.
Here is a code example:
File Bindings.java
import org.springframework.cloud.stream.annotation.Input;
import org.springframework.cloud.stream.annotation.Output;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.SubscribableChannel;
public interface Bindings {
#Input("test-input")
SubscribableChannel testListener();
#Output("test-output")
MessageChannel testProducer();
}
File application.yml (don't forget to set the environment variable KAFKA_HOST):
spring:
cloud:
stream:
kafka:
binder:
auto-create-topics: true
brokers: ${KAFKA_HOST}
transaction:
producer:
error-channel-enabled: true
producer-properties:
acks: all
retry.backoff.ms: 200
linger.ms: 100
max.in.flight.requests.per.connection: 1
enable.idempotence: true
retries: 3
compression.type: snappy
request.timeout.ms: 5000
key.serializer: org.apache.kafka.common.serialization.StringSerializer
consumer-properties:
session.timeout.ms: 20000
max.poll.interval.ms: 350000
enable.auto.commit: true
allow.auto.create.topics: true
auto.commit.interval.ms: 12000
max.poll.records: 5
isolation.level: read_committed
configuration:
auto.offset.reset: latest
bindings:
test-input:
# contentType: text/plain
destination: test.produce
group: group-input
consumer:
maxAttempts: 3
startOffset: latest
autoCommitOnError: true
queueBufferingMaxMessages: 100000
autoCommitOffset: true
test-output:
# contentType: text/plain
destination: test.produce.another
group: group-output
producer:
acks: all
debug: true
The listener handler:
#SpringBootApplication
#EnableBinding(Bindings.class)
public class PocApplication {
private static final Logger log = LoggerFactory.getLogger(PocApplication.class);
public static void main(String[] args) {
SpringApplication.run(PocApplication.class, args);
}
#Autowired
private BinderAwareChannelResolver binderAwareChannelResolver;
#StreamListener(Topics.TESTLISTENINPUT)
public void listen(Message<?> in, String headerKey) {
final MessageBuilder builder;
MessageChannel messageChannel;
messageChannel = this.binderAwareChannelResolver.resolveDestination("test-output");
Object payload = in.getPayload();
builder = MessageBuilder.withPayload(payload);
try {
log.info("Event received: {}", in);
if (!messageChannel.send(builder.build())) {
log.error("Something happend trying send the message! {}", in.getPayload());
}
log.info("Commit success");
} catch (UnknownProducerIdException e) {
log.error("UnkownProducerIdException catched ", e);
} catch (KafkaException e) {
log.error("KafkaException catched ", e);
}catch (Exception e) {
System.out.println("Commit failed " + e.getMessage());
}
}
}
Regards
} catch (UnknownProducerIdException e) {
log.error("UnkownProducerIdException catched ", e);
To catch exceptions there, you need to set the sync kafka producer property (https://cloud.spring.io/spring-cloud-static/spring-cloud-stream-binder-kafka/3.0.3.RELEASE/reference/html/spring-cloud-stream-binder-kafka.html#kafka-producer-properties). Otherwise, the error comes back asynchronously
You should not "eat" the exception there; it must be thrown back to the container so the container will roll back the transaction.
Also,
}catch (Exception e) {
System.out.println("Commit failed " + e.getMessage());
}
The commit is performed by the container after the stream listener returns to the container so you will never see a commit error here; again, you must let the exception propagate back to the container.
The container will retry the delivery according to the consumer binding's retry configuration.
probably you can also use the callback function to handle the exception, not sure about the springframework lib for kafka, if using kafka client, you can something like this:
producer.send(record, new Callback() {
public void onCompletion(RecordMetadata metadata, Exception e) {
if(e != null) {
e.printStackTrace();
if(e.getClass().equals(UnknownProducerIdException.class)) {
logger.info("UnknownProducerIdException caught");
while(--retry>=0) {
send(topic,partition,msg);
}
}
} else {
logger.info("The offset of the record we just sent is: " + metadata.offset());
}
}
});
I implemented curator leader election example which is given in this site
Instead of having number of curator clients I added only one curator client as follows
public void selectLeader() {
CuratorFramework client = null;
try {
client = CuratorFrameworkFactory.newClient("localhost:2181", new ExponentialBackoffRetry(1000, 3));
LeaderSelectorService service = new LeaderSelectorService(client, "/leaderSelections", "LeaderElector");
client.start();
Thread.sleep(10000);
service.start();
} catch (Exception e) {
System.out.println("error"+e);
}finally
{
System.out.println("Shutting down...");
// CloseableUtils.closeQuietly(client);
}
}
public class LeaderSelectorService extends LeaderSelectorListenerAdapter implements Closeable {
private final String name;
private final LeaderSelector leaderSelector;
public LeaderSelectorService(CuratorFramework client, String path, String name) {
this.name = name;
// create a leader selector using the given path for management
// all participants in a given leader selection must use the same path
// ExampleClient here is also a LeaderSelectorListener but this isn't required
leaderSelector = new LeaderSelector(client, path, this);
// for most cases you will want your instance to requeue when it relinquishes leadership
leaderSelector.autoRequeue();
}
public void start() throws IOException
{
// the selection for this instance doesn't start until the leader selector is started
// leader selection is done in the background so this call to leaderSelector.start() returns immediately
leaderSelector.start();
}
#Override
public void takeLeadership(CuratorFramework arg0) throws Exception {
// we are now the leader. This method should not return until we want to relinquish leadership
final int waitSeconds = (int)(5 * Math.random()) + 1;
System.out.println(name + " is now the leader. Waiting " + waitSeconds + " seconds...");
//System.out.println(name + " has been leader " + leaderCount.getAndIncrement() + " time(s) before.");
try
{
Thread.sleep(TimeUnit.SECONDS.toMillis(waitSeconds));
}
catch ( InterruptedException e )
{
System.err.println(name + " was interrupted.");
Thread.currentThread().interrupt();
}
finally
{
System.out.println(name + " relinquishing leadership.\n");
}
}
#Override
public void close() throws IOException {
leaderSelector.close();
}
}
I have only one zookeeper instance and I am using Zookeeper 3.4.6, curator-framework 4.0.0 and curator-recipes 4.0.0.
when I start the client, it connects to zookeeper and in the log I can see "State change : connected" message.
Then I wait 10s and start leader election which gives me below error repeatedly.
2017-09-06 09:34:22.727 INFO 1228 --- [localhost:2181)] org.apache.zookeeper.ClientCnxn : Unable to read additional data from server sessionid 0x15e555a719d0000, likely server has closed socket, closing socket connection and attempting reconnect
2017-09-06 09:34:22.830 INFO 1228 --- [c-1-EventThread] o.a.c.f.state.ConnectionStateManager : State change: SUSPENDED
2017-09-06 09:34:23.302 INFO 1228 --- [localhost:2181)] org.apache.zookeeper.ClientCnxn : Opening socket connection to server localhost/127.0.0.1:2181. Will not attempt to authenticate using SASL (unknown error)
2017-09-06 09:34:23.303 INFO 1228 --- [localhost:2181)] org.apache.zookeeper.ClientCnxn : Socket connection established, initiating session, client: /127.0.0.1:49594, server: localhost/127.0.0.1:2181
2017-09-06 09:34:23.305 INFO 1228 --- [localhost:2181)] org.apache.zookeeper.ClientCnxn : Session establishment complete on server localhost/127.0.0.1:2181, sessionid = 0x15e555a719d0000, negotiated timeout = 120000
2017-09-06 09:34:23.305 INFO 1228 --- [c-1-EventThread] o.a.c.f.state.ConnectionStateManager : State change: RECONNECTED
2017-09-06 09:34:23.310 WARN 1228 --- [localhost:2181)] org.apache.zookeeper.ClientCnxn : Session 0x15e555a719d0000 for server localhost/127.0.0.1:2181, unexpected error, closing socket connection and attempting reconnect
java.io.IOException: Connection reset by peer
at sun.nio.ch.FileDispatcherImpl.read0(Native Method) ~[na:1.8.0_131]
at sun.nio.ch.SocketDispatcher.read(SocketDispatcher.java:39) ~[na:1.8.0_131]
at sun.nio.ch.IOUtil.readIntoNativeBuffer(IOUtil.java:223) ~[na:1.8.0_131]
at sun.nio.ch.IOUtil.read(IOUtil.java:192) ~[na:1.8.0_131]
at sun.nio.ch.SocketChannelImpl.read(SocketChannelImpl.java:380) ~[na:1.8.0_131]
at org.apache.zookeeper.ClientCnxnSocketNIO.doIO(ClientCnxnSocketNIO.java:75) ~[zookeeper-3.5.3-beta.jar:3.5.3-beta-8ce24f9e675cbefffb8f21a47e06b42864475a60]
at org.apache.zookeeper.ClientCnxnSocketNIO.doTransport(ClientCnxnSocketNIO.java:363) ~[zookeeper-3.5.3-beta.jar:3.5.3-beta-8ce24f9e675cbefffb8f21a47e06b42864475a60]
at org.apache.zookeeper.ClientCnxn$SendThread.run(ClientCnxn.java:1214) ~[zookeeper-3.5.3-beta.jar:3.5.3-beta-8ce24f9e675cbefffb8f21a47e06b42864475a60]
after some time it started to give me below error message.
org.apache.zookeeper.KeeperException$ConnectionLossException: KeeperErrorCode = ConnectionLoss
at org.apache.zookeeper.KeeperException.create(KeeperException.java:99) ~[zookeeper-3.5.3-beta.jar:3.5.3-beta-8ce24f9e675cbefffb8f21a47e06b42864475a60]
at org.apache.curator.framework.imps.CuratorFrameworkImpl.checkBackgroundRetry(CuratorFrameworkImpl.java:831) [curator-framework-4.0.0.jar:4.0.0]
at org.apache.curator.framework.imps.CuratorFrameworkImpl.processBackgroundOperation(CuratorFrameworkImpl.java:623) [curator-framework-4.0.0.jar:4.0.0]
at org.apache.curator.framework.imps.WatcherRemovalFacade.processBackgroundOperation(WatcherRemovalFacade.java:152) [curator-framework-4.0.0.jar:4.0.0]
at org.apache.curator.framework.imps.GetConfigBuilderImpl$2.processResult(GetConfigBuilderImpl.java:222) [curator-framework-4.0.0.jar:4.0.0]
at org.apache.zookeeper.ClientCnxn$EventThread.processEvent(ClientCnxn.java:590) [zookeeper-3.5.3-beta.jar:3.5.3-beta-8ce24f9e675cbefffb8f21a47e06b42864475a60]
at org.apache.zookeeper.ClientCnxn$EventThread.run(ClientCnxn.java:499) [zookeeper-3.5.3-beta.jar:3.5.3-beta-8ce24f9e675cbefffb8f21a47e06b42864475a60]
2017-09-06 09:34:31.897 INFO 1228 --- [localhost:2181)] org.apache.zookeeper.ClientCnxn : Opening socket connection to server localhost/127.0.0.1:2181. Will not attempt to authenticate using SASL (unknown error)
2017-09-06 09:34:31.898 INFO 1228 --- [localhost:2181)] org.apache.zookeeper.ClientCnxn : Socket connection established, initiating session, client: /127.0.0.1:49611, server: localhost/127.0.0.1:2181
2017-09-06 09:34:31.899 INFO 1228 --- [localhost:2181)] org.apache.zookeeper.ClientCnxn : Session establishment complete on server localhost/127.0.0.1:2181, sessionid = 0x15e555a719d0000, negotiated timeout = 120000
2017-09-06 09:34:31.899 INFO 1228 --- [c-1-EventThread] o.a.c.f.state.ConnectionStateManager : State change: RECONNECTED
2017-09-06 09:34:31.907 WARN 1228 --- [localhost:2181)] org.apache.zookeeper.ClientCnxn : Session 0x15e555a719d0000 for server localhost/127.0.0.1:2181, unexpected error, closing socket connection and attempting reconnect
java.io.IOException: Xid out of order. Got Xid 41 with err -6 expected Xid 40 for a packet with details: clientPath:/leaderSelections serverPath:/leaderSelections finished:false header:: 40,12 replyHeader:: 0,0,-4 request:: '/leaderSelections,F response:: v{}
at org.apache.zookeeper.ClientCnxn$SendThread.readResponse(ClientCnxn.java:892) ~[zookeeper-3.5.3-beta.jar:3.5.3-beta-8ce24f9e675cbefffb8f21a47e06b42864475a60]
at org.apache.zookeeper.ClientCnxnSocketNIO.doIO(ClientCnxnSocketNIO.java:101) ~[zookeeper-3.5.3-beta.jar:3.5.3-beta-8ce24f9e675cbefffb8f21a47e06b42864475a60]
at org.apache.zookeeper.ClientCnxnSocketNIO.doTransport(ClientCnxnSocketNIO.java:363) ~[zookeeper-3.5.3-beta.jar:3.5.3-beta-8ce24f9e675cbefffb8f21a47e06b42864475a60]
at org.apache.zookeeper.ClientCnxn$SendThread.run(ClientCnxn.java:1214) ~[zookeeper-3.5.3-beta.jar:3.5.3-beta-8ce24f9e675cbefffb8f21a47e06b42864475a60]
I tried several solution in the internet but non got succeeded. Does anybody know the root cause of this issue.
I have fixed this issue. There was version number mismatch between zookeeper version and curator version. I used curator version 4.0.0 with zookeeper 3.4.6. According to apache curator site
Curator 4.0.0 - compatible with ZooKeeper 3.5.x. I changed my curator version to 2.8.0