35

I'm currently working on a Spring Boot microservices project. I have created services and each service is running separately. With this, I need some services to communicate with other services. How can i achieve that?

I saw some blogs about this which use Netflix, Eureka cloud servers to achieve this. Is there any way I can achieve this in my local environment without using cloud servers?

Thirumaran
  • 459
  • 1
  • 6
  • 12
  • 11
    You can run Eureka locally, however, Eureka isn't about communication between microservices, it's about discovering other microservices. After you discovered a microservice, it's up to you to decide how to communicate with it, Eureka doesn't tell you how to do that. That means that your question is really broad, theoretically you can even communicate in morse code in binary over TCP if you want. – g00glen00b May 24 '18 at 11:00
  • Perhaps the asker meant about trusted communication? How does one service trust another? How does the service registry trust a service that is trying to register to it? – AlikElzin-kilaka Apr 21 '22 at 04:46

9 Answers9

21

Of course you can. Microservices are just REST-Services. You need to understand how REST-Services work. After that just write 2 Microservices (2 Rest-Services: producer-service and consumer-service) with Spring-boot, let them run under different server-ports, call the consumer-service from the other, and that's it: you have your Microservices. Now this is the primitive way to write Microservices.

To make them evolve, you need to add some "magic" (no rocket science), for example using Ribbon to distribute load between two instances of your "producer-service".

You may use a discovery service which is just a spring-boot application with the annotation @EnableEurekaServer (You need to add the appropriate dependency in your pom) Now add to your first (primitive) Microservices the annotation @EnableDiscoveryClient to the main classes and the defaultZone pointing to your eureka-service in the application.properties (or application.yml) of both, start your eureka-service (discovery service) and the 2 Microservices: those will register on the discovery-service. Of course now you don't need to hard-code the http address of the producer-service in the consumer-service.
Take a look at this tutorial

Edited on 21th of November 2018 at 12:41 GMT

Suppose that your first (trivial) microservice (a pure rest-service) is running on your PC under port 8091.

In the controller of your second (trivial) microservice you call your first service using the RestTemplate.getForEntity(url,responseType,uriVariables) like so for the example in the linked tutorial:

ResponseEntity<CurrencyConversionBean> responseEntity = 
   new RestTemplate().getForEntity(
        "http://localhost:8091/currency-exchange/from/{from}/to/{to}", CurrencyConversionBean.class,  uriVariables);

Where url: the url of your first (micro)(rest)service. responseType: the class/type of the object awaited as response. uriVariables: is a map containing variables for the URI template.

Meziane
  • 1,586
  • 1
  • 12
  • 22
  • If you are using more modern Spring versions (5+), it's better to start using [WebClient](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/reactive/function/client/WebClient.html) instead of RestTemplate. – lcs_godoy Feb 25 '23 at 19:11
  • What do you mean by Producer and Consumer in this context? – Chris A Apr 04 '23 at 21:34
14

There are different ways to communicate between microservices. But which one to use: depends on the usecase.

  1. Api call: That is making actual rest api call to the other service using RestTemplate , FeignClient etc as.
ResponseType obj=  new RestTemplate().getForObject(URL, ResponseType.class, params);
  1. But what if the usecase is different, like, you have customer microservice and orders microservice both are using separate database . You have customer name and other details in orders database as well. Once the customer update their name, you have to update the details in Orders database as well . How this can be done. Through API call? Then what if account microservice also needs this update. So Rest api will be an overhead. In this use case we can use MessageQueues like RabbitMQ. Customer microservice will create an event of customer update and which ever microservice is interested in this can subscribe.

Communication through message queue like RabbitMQ

Spring.io rabbit mq guide

Vipin CP
  • 3,642
  • 3
  • 33
  • 55
  • I am interested to know about fetch data from different microservices. I want to get the customer's name from the product microservice. In my case product service has to call order service to get order id, based on order id I need to call customer microservice to get customer name. in my case not only one filed it contains many fileds to get data like that. will you suggest any solution on problem? – Narasimha A Apr 13 '20 at 13:53
  • @vipin how different services would subscribe with the same queue and get same customer update event? because in rabbitmq, a particular message from a queue cannot be consumed by more than one consumer. – Muhammad Abu Bakr Sep 08 '22 at 04:21
7

That depends on your choice, weather you want sync communication or async communication between your services. For sync services you can use either of these 3rd party tools:

  1. Hashcorp Consul
  2. Netflix Eureka [You may client load balancing using Netflix RIBBON ]
  3. NATS etc

For Async you can use messaging solutions like:

  1. Redis [use list/streams]
  2. ActiveMQ
  3. RabitMQ
  4. Kafka
  5. NATS etc
mwangox
  • 389
  • 5
  • 4
3

As mentioned by @g00glen00b in comments Eureka is not used for communication between microservices. Its for service discovery. There are two ways that I know ofthrough which you can communicate with other Microservices :

  1. RestTemplate
  2. Feign Client

RestTemplate is very simple to use. It does not require configurations.

e.g.

   ResponseType obj=  new RestTemplate().getForObject(URL, ResponseType.class, params);

url - the URL

responseType - the type of the return value

params- the variables to expand the template

Spring Doc link for your reference

Abhijeet
  • 4,069
  • 1
  • 22
  • 38
2

the post seems old but I will try to share my experiences with the new developers who searches solutions for the same problem.

You will need these libraries: Zuul Gateway, Eureka Discovery Server, Eureka Discovery Client, Rest Template (if you develop REST API).

Gateway can manage all the routing for spring boot microservice applications. Using only annotations and application.properties you can set up the whole server. You do NOT need to write single line of Java code.

Discovery server listens evens when new microservice is started or stopped. It registers all microservices which are annotated with @EnableEurekaClient.

Rest Template is a mature rest client library which is very much flexible in terms of custom http request and http response configurations. For instance, you can use client http interceptors configurations to intercept the http request and responses to add more data, or log info etc.

I have open-sourced microservice application on my GitHub page. Free to distribute, fork, clone, commercialize.. Free from desire :-)

All the best..

2

Two ways to achieve communication b/w two services by making a REST call infact any service over internet consuming REST WebService can be consumed using;

Muhammad Taha
  • 137
  • 1
  • 6
1
@Autowired
    private RestTemplate restTemplate;

@Autowired
    private EurekaClient eurekaClient;


@RequestMapping("/dashboard/{myself}")
    public EmployeeInfo findme(@PathVariable Long myself) {
        Application application = eurekaClient.getApplication(employeeSearchServiceId);
        InstanceInfo instanceInfo = application.getInstances().get(0);
        String url = "http://" + instanceInfo.getIPAddr() + ":" + instanceInfo.getPort() + "/" + "employee/find/" + myself;
        System.out.println("URL" + url);
        EmployeeInfo emp = restTemplate.getForObject(url, EmployeeInfo.class);
        System.out.println("RESPONSE " + emp);
        return emp;
    }

source: https://dzone.com/articles/microservices-communication-service-to-service

Gex
  • 2,092
  • 19
  • 26
  • 1
    Answers including code should have at least a minumum description explaining how the code works and why it answers to the question. Furthermore the code formatting has to be improved. I've suggested an edit for the latter issue, please fix the code description part. – Roberto Caboni Jan 03 '20 at 13:11
1

We can also use https://cloud.spring.io/spring-cloud-openfeign/reference/html/ which is being developed on top of Netflix Feign project.

  • 2
    While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. - [From Review](/review/late-answers/30375443) – Procrastinator Nov 19 '21 at 06:54
0

Although REST is familiar and therefore easy to implement, if you need more flexible and Java-like communications, Spring's (Spring-to-Spring) HTTP Invoker may be a good choice.

Spring's HTTP invoker is a good choice if you need HTTP-based remoting but also rely on Java serialization. It shares the basic infrastructure with RMI invokers, just using HTTP as transport. Note that HTTP invokers are not only limited to Java-to-Java remoting but also to Spring on both the client and server side. (The latter also applies to Spring's RMI invoker for non-RMI interfaces.)

sparkyspider
  • 13,195
  • 10
  • 89
  • 133