Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >遗留非springboot传统项目接入eureka注册与服务发现

遗留非springboot传统项目接入eureka注册与服务发现

作者头像
vakinge
发布于 2023-02-22 07:22:36
发布于 2023-02-22 07:22:36
35200
代码可运行
举报
文章被收录于专栏:伯约架构思维伯约架构思维
运行总次数:0
代码可运行

推荐: jeesuite开发框架,免费开源、一站式解决方案。

最近规划自动化运维以及统一监控需求,鉴于目前公司内部大部分项目采用spring cloud体系架构、另外还有一些老的传统spring web的项目,于是就考虑把老的项目通过低成本改造的方式接入spring cloud体系,也就是可以通过eureka注册和服务发现、通过zuul服务路由

说干就干,通过eureka官方实例和研究spring boot注册eureka源码发现这个也很容易实现,所以废话不多说,直接贴代码了 。

首先加入项目依赖(maven为例)
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<dependency>
    <groupId>com.netflix.eureka</groupId>
    <artifactId>eureka-client</artifactId>
    <version>1.4.12</version>
    <exclusions>
        <exclusion>
          <groupId>javax.servlet</groupId>
          <artifactId>servlet-api</artifactId>
        </exclusion>
        <exclusion>
          <groupId>com.google.guava</groupId>
          <artifactId>guava</artifactId>
        </exclusion>
        <exclusion>
          <groupId>com.fasterxml.jackson.core</groupId>
          <artifactId>jackson-annotations</artifactId>
        </exclusion>
        <exclusion>
          <groupId>javax.ws.rs</groupId>
          <artifactId>jsr311-api</artifactId>
        </exclusion>
    </exclusions>
</dependency>

    <dependency>
      <groupId>com.netflix.archaius</groupId>
      <artifactId>archaius-core</artifactId>
      <version>0.7.4</version>
      <exclusions>
        <exclusion>
          <groupId>com.fasterxml.jackson.core</groupId>
          <artifactId>jackson-annotations</artifactId>
        </exclusion>
      </exclusions>
    </dependency>

    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-netflix-core</artifactId>
      <version>1.2.6.RELEASE</version>
      <exclusions>
        <exclusion>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-autoconfigure</artifactId>
        </exclusion>
      </exclusions>
    </dependency>
加入配置文件
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
eureka.region=default
eureka.registration.enabled=true
eureka.preferSameZone=true
eureka.shouldUseDns=false
eureka.serviceUrl.default=http://192.168.1.100:7861/eureka
eureka.decoderName=JacksonJson

eureka.name=demo
eureka.vipAddress=${eureka.name}-service
eureka.port=8081
eureka.homePageUrl=http://192.168.1.101:${eureka.port}
eureka.healthCheckUrl=http://192.168.1.101:${eureka.port}/service/health
eureka.statusPageUrl=http://192.168.1.101:${eureka.port}/service/info
  • spring.cloud.client.ipAddress :为自定义变量
  • healthCheckUrl,statusPageUrl接口可以不要,但是为了监控可以自己实现一个简单的接口即可
初始化eureka客户端
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
private void initEurekaClient() throws Exception{

        Properties properties = new Properties();

        InputStream inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("eureka.properties");
        properties.load(inputStream);

        //
        properties.setProperty("eureka.ipAddr", IpUtils.getLocalIpAddr());
        instanceId = properties.getProperty("eureka.ipAddr") + ":" + properties.getProperty("eureka.ipAddr") + "/" + properties.getProperty("eureka.name");
        properties.setProperty("eureka.instanceId", instanceId);

        ConfigurationManager.loadProperties(properties);

        MyDataCenterInstanceConfig instanceConfig = new MyDataCenterInstanceConfig();
        InstanceInfo instanceInfo = new EurekaConfigBasedInstanceInfoProvider(instanceConfig).get();
        applicationInfoManager = new ApplicationInfoManager(instanceConfig, instanceInfo);

        DefaultEurekaClientConfig clientConfig = new DefaultEurekaClientConfig();

        eurekaClient = new DiscoveryClient(applicationInfoManager, clientConfig);

}
注册服务
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
private void waitForRegistrationWithEureka() {

        applicationInfoManager.setInstanceStatus(InstanceInfo.InstanceStatus.STARTING);
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
        }
        applicationInfoManager.setInstanceStatus(InstanceInfo.InstanceStatus.UP);

        long startTime = System.currentTimeMillis();
        //开启一个线程验证注册结果
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    if (System.currentTimeMillis() - startTime > VERIFY_WAIT_MILLIS) {
                        log.warn(" >>>> service registration status not verify,please check it!!!!");
                        return;
                    }
                    try {
                        List<InstanceInfo> serverInfos = eurekaClient.getInstancesByVipAddress(vipAddress, false);
                        for (InstanceInfo nextServerInfo : serverInfos) {
                            if (nextServerInfo.getIPAddr().equals(IpUtils.LOCAL_BACK_IP)
                                    || nextServerInfo.getIPAddr().equals(IpUtils.getLocalIpAddr())) {
                                String instanceInfoJson = JsonUtils.getMapper().writerWithDefaultPrettyPrinter()
                                        .writeValueAsString(nextServerInfo);
                                log.info("verifying service registration with eureka finished,instance:\n{}",
                                        instanceInfoJson);
                                return;
                            }
                        }
                    } catch (Throwable e) {
                    }
                    try {
                        Thread.sleep(5000);
                    } catch (Exception e1) {
                    }
                    log.info("Waiting 5s... verifying service registration with eureka ...");
                }
            }
        }).start();
    }

通过这几步就完成了eureka的注册,登录eureka控制台你将能看到对应注册信息。但是在zuul转发调用过程发现一个问题:无法识别hostname,如果你们的服务器之间没有做hostname同步就需要继续改造,于是就看了下springboot注册eureka有一个配置项eureka.instance.preferIpAddress,所以我们也可以模仿他的实现。于是在初始化客户端的时候我们需要这样改造:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
MyDataCenterInstanceConfig instanceConfig = new MyDataCenterInstanceConfig(){
            @Override
            public String getHostName(boolean refresh) {
                String hostName = super.getHostName(refresh);
                if(ResourceUtils.getBoolean("eureka.preferIpAddress")){
                    hostName = IpUtils.getLocalIpAddr();
                }
                return hostName;
            }

            @Override
            public String getIpAddress() {
                return IpUtils.getLocalIpAddr();
            }

};

这样,注册的真实服务地址就是ip了。服务注册就搞定收工了。

接下来就是服务发现,及与其他springboot项目一样通过注册中心vipAddress互相调用。实际过程就是调用前去eureka拿一个真实地址替换vipAddress变量。

获取真实服务地址

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public String getRealServerHost(String serviceId){
    InstanceInfo serverInfo = eurekaClient.getNextServerFromEureka(serviceId, false);
    String realServerName = serverInfo.getIPAddr() + ":" + serverInfo.getPort();
    return realServerName;
}

下面是我实现的几个resttemplate

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class EurekaRestTemplateBuilder {

    private static Map<String, RestTemplate> restTemplates = new HashMap<>();

    public static synchronized RestTemplate build(ClientHttpRequestInterceptor ...interceptors ){
        return build("default", interceptors);
    }

    public static synchronized RestTemplate build(String name,ClientHttpRequestInterceptor ...interceptors ){

        if(restTemplates.containsKey(name))return restTemplates.get(name);

        SimpleClientHttpRequestFactory factory = new EurekaClientHttpRequestFactory();  
        factory.setReadTimeout(15000);//ms  
        factory.setConnectTimeout(5000);//ms 

        RestTemplate restTemplate = new RestTemplate(factory);
        List<ClientHttpRequestInterceptor> interceptorList = new ArrayList<>();
        interceptorList.add(new RestTemplateAutoHeaderInterceptor());
        if(interceptors != null && interceptors.length > 0){
            for (ClientHttpRequestInterceptor interceptor : interceptors) {
                interceptorList.add(interceptor);
            }
        }
        restTemplate.setInterceptors(interceptorList);
        //
        restTemplate.setErrorHandler(new CustomResponseErrorHandler());
        //
        restTemplates.put(name, restTemplate);

        return restTemplate;
    }

    private static class EurekaClientHttpRequestFactory extends SimpleClientHttpRequestFactory{

        @Override
        public ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) throws IOException {
            uri = convertToRealUri(uri);
            return super.createRequest(uri, httpMethod);
        }

        @Override
        public AsyncClientHttpRequest createAsyncRequest(URI uri, HttpMethod httpMethod) throws IOException {
            uri = convertToRealUri(uri);
            return super.createAsyncRequest(uri, httpMethod);
        }

        private URI convertToRealUri(URI uri){
            String serviceId = uri.getHost();
            try {               
                String realHost = EurekaRegistry.getInstance().getRealServerHost(serviceId);
                uri = new URI(uri.toString().replace(serviceId, realHost));
                return uri;
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }

    }
}

接下来就可以调用其他eureka注册服务了。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
private RestTemplate restTemplate = EurekaRestTemplateBuilder.build();

  public List<IdNamePair> getProvinces() {
    ParameterizedTypeReference<List<IdNamePair>> arearesponseType = new ParameterizedTypeReference<List<IdNamePair>>() {
    };
    List<IdNamePair> lists = restTemplate
        .exchange("http://DEMO-SERVICE/region/provinces", HttpMethod.GET, null, arearesponseType)
        .getBody();
    return lists;
  }
ZUUL转发配置
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
zuul.routes.demo.path=/demo/**
zuul.routes.demo.serviceId=demo-service

到此,服务注册和服务发现都完成了。 这里是一个demo

有任何问题,请加技术群:230192763讨论
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2017-12-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
程序与数学:牛顿迭代法与平方根近似计算
这个等式是一元二次方程,解方程即可求得x。现在正实数平方根计算问题已转换为解一元二次方程问题。
郎宏林
2021/10/08
1.5K0
程序与数学:牛顿迭代法与平方根近似计算
算法--迭代法
版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
奋飛
2019/08/15
1K0
牛顿迭代法(Newton's Method)
牛顿迭代法(Newton's Method)                    简介 牛顿迭代法(简称牛顿法)由英国著名的数学家牛顿爵士最早提出。但是,这一方法在牛顿生前并未公开发表。 牛顿法的
Angel_Kitty
2018/04/08
2K0
牛顿迭代法(Newton's Method)
大厂面试题:求根号2简单?高级算法你肯定不会
前两天逛github看到一道很简单的面试题——如何不用库函数快速求出\sqrt2的值,精确到小数点后10位! 第一反应这不很简单嘛,大学数据结构课讲二分查找的时候老师还用这个做过示例。但转念一想,能作为大厂的面试题,背后绝对没有那么简单,于是我google了下,结果找到了更巧妙的数学方法,甚至发现了一件奇闻趣事…… 一道简简单单的面试题,不仅能考察到候选人的编程能力,还能间接考察到候选人的数学素养,难怪很多大厂都会问这个。。。 回到正题,求\sqrt2究竟有多少种解法,我们由简入难一步步来看下我们是如何让计算机更快计算sqrt的。
xindoo
2021/01/22
1.8K0
大厂面试题:求根号2简单?高级算法你肯定不会
牛顿迭代解方程 ax^3+bX^2+cx+d=0
$$ x1 \times x2 + x1 \times x3 + x2 \times x3 = \frac{c}{a} $$
owent
2018/08/01
1.5K0
牛顿法
复习go语言基础的时候,看到一个算法题,求特定值的平方根(不使用特定库函数的前提下),常见的方法要么是二分法要么是牛顿法。
f1sh
2024/07/25
1550
用不动点法和牛顿迭代法求解函数根-Julia
对方程 [68e2e51cef848d1909d348e71d828c8400e.jpg] 不动点迭代法undefined原方程可转换为 [7a84526e766abd12c36903ff023681b5eca.jpg] 由不动点迭代法得 [688355d352ab40cc232b5a3e3a04ce88ad4.jpg] 牛顿迭代法undefined给定一个初始x0,做一条垂线与函数f(x)相交,得到的交点为(x0,y0),过该点在f(x)上作一条切线,得到该切线与x轴的交点为(x1
Pulsar-V
2018/11/29
1.7K0
[Leetcode][python]Sqrt(x)/x 的平方根
二分搜索:值得注意的是右边可以直接设置为j=x/2+1,因为在(x/2+1)^2 > x。
蛮三刀酱
2019/03/26
9040
[Leetcode][python]Sqrt(x)/x 的平方根
算法细节系列(3):梯度下降法,牛顿法,拟牛顿法
话不多说,直接进入主题。在我看来,不管是梯度下降法还是牛顿法,它们都可以归结为一个式子,即
用户1147447
2019/05/26
2.3K0
C++版 - Leetcode 69. Sqrt(x) 解题报告【C库函数sqrt(x)模拟-求平方根】
Total Accepted: 93296 Total Submissions: 368340 Difficulty: Medium
Enjoy233
2019/03/05
2.5K0
C++版 - Leetcode 69. Sqrt(x) 解题报告【C库函数sqrt(x)模拟-求平方根】
牛顿迭代法与二分法计算平方根
因为不是科班出身,所以即使编程一段时间也时常感觉自身基础知识非常不扎实,于是在最近开始补习算法和计算机理论的基础知识。
Originalee
2018/08/30
1.8K0
牛顿迭代法与二分法计算平方根
算法浅谈——走迷宫问题与广度优先搜索
我们都知道,工业上的很多问题经过抽象和建模之后,本质还是数学问题。而说到数学问题就离不开方程,在数学上我们可以用各种推算、公式,但是有没有想过在计算机领域我们如何解一个比较复杂的方程?
TechFlow-承志
2020/03/19
9150
算法浅谈——走迷宫问题与广度优先搜索
【趣学C语言和数据结构100例】6-10
【趣学C语言和数据结构100例】 问题描述 6.一个球从 100m 高度自由落下,每次落地后反弹回原高度的一半,再落下,求它在第 10 次时共经过多少米,第 10 次反弹多高。 7.猴子吃桃问题。猴子第 1 天摘下若干个桃子,当即吃了一半,还不过瘾,又多吃了一个。第 2 天早上又将剩下的桃子吃掉一半,又多吃了一个。以后每天早上都吃了前一天剩下的一半零一个。到第 10 天早上想再吃时,就只剩一个桃子了。求第 1 天共摘多少个桃子。 8.迭代法求 x = 根号 a。求平方根的迭代公式为 x(n+1) = 1/2 * (xn + a/xn) 9.用牛顿迭代法求下面方程在 1.5 附近的根: 2x³ - 4x² + 3x - 6 = 0 70.用筛选法求 100 之内的素数。 代码分析 6. 物理公式的规律应用 每次落地后反弹回原高度的一半,初始total_m,第一次为total_m *= 0.5,for循环计算n次的,共经过,使用sum来计数。 7. 数学公式的规律应用 已知结果,找倒推规律,求初始。由后一天 = ( 前一天 / 2 ) -1 可知,前一天 = ( 后一天 + 1 ) *2,定义天数day,使用while(day–),求第一天。 8. 巴比伦法 迭代公式为 x(n+1) = 1/2 (xn + a/xn) 初次猜测,x0=a/2,那么,代入公式得到x1 使用while开始代法,令x0=x1,代入公式得到x1 当 ∣xn+1−xn∣∣xn+1−xn∣ 小于某个设定的精度(例如 1e−51e−5)时停止迭代。 9. 牛顿迭代法的求解 牛顿迭代法 :x(n+1) = x(n) - f(x(n)) / f’(x(n)) 对于本题,方程在 1.5 附近的根: 2x³ - 4x² + 3x - 6 = 0 x0,x1=1.5,f,f1 f(x(n))=2x³ - 4x² + 3x - 6 f’(x(n)) =6x² -8x +3 每次令 x0 = x1; f = ( ( 2 * x0 - 4 ) * x0 + 3 ) * x0 -6; f1 = ( 6 * x0 - 8 ) * x0 + 3; x1 = x0 - f / f1; 当 ∣xn+1−xn∣∣xn+1−xn∣ 小于某个设定的精度(例如 1e−51e−5)时停止迭代。 10. 筛选法 筛选法:又称为筛法。先把以个自然数按次序排列起来。1不是质数,也不是合数,要划去第二个数2是质数留不来,而把2后面所有能被2整除的数都划去。2后面第一个没划去的数是3,把3留下,再把3后面所有能被3整除的数都划去。3后面第一个没划去的数是5,再把与后面所有能被5整除的数都划去。这样一直做下去,就会把不超过N的把5留下,全部合数都筛掉,留下的就是不超过N的全部质数。 具体思路:先初始化数组,初始化为数字本身,如果访问过,则赋值为0。定义两个for循环,第一个访问到100,然后判断为0,则跳过。否则进行,从该数开始,到100,找到该数的倍数,并赋值为0。 代码实现 #include<stdio.h> #include<math.h> int main(){ // 6.一个球从100m高度自由落下,每次落地后反弹回原高度的一半,再落下,再反弹求它在第10次时共经过多少米,第10次反弹多高。 double total_m = 100.0,sum = 0.0; for(int i = 0; i < 10; i++) { sum += total_m; total_m /= 2; sum += total_m; } printf("第10次时共经过%f米,第10次反弹%f米",sum,total_m); // 7.猴子吃桃问题。猴子第1天摘下若干个桃子,当即吃了一半,还不过瘾,又多吃了一个。第2天早上又将剩下的桃子吃掉一半,又多吃了一个。以后每天早上都吃了前一天剩下的一半零一个。到第 10天早上想再吃时,就只剩一个桃子了。求第1天共摘多少个桃子。) 分析:后一天 = ( 前一天 / 2 ) -1 --> 前一天 = ( 后一天 + 1 ) * 2 int day = 9; int prev , cur = 1; while( day > 0) { prev = ( cur + 1 ) * 2; cur = prev; day--; } printf("第1天共摘%d个桃子",cur); // 8.迭代法求x=根号a。求平方根的迭代公式为x(n+1)=1/2 * (xn+a/xn) // 分析:牛顿迭代法 :x(n+1) = x(n) - f(x(n)) / f'(x(n)) https://blog.csdn.net/SanyHo/article/details/106365314 float a ,
LucianaiB
2024/10/23
1040
【趣学C语言和数据结构100例】6-10
每日一问之初识牛顿迭代法(Newton's method)
今天在刷 LeetCode 的 sqrt(x) 这道题的时候,看到别人的解法中有使用牛顿迭代法。之前也看到这个方法很多次,但都没有去了解。今天正好就这个问题来稍微整理一下:
caoqi95
2019/03/28
1.6K0
每日一问之初识牛顿迭代法(Newton's method)
Leetcode 题目069-求平方根
二分法 c++版 class Solution { public: int mySqrt(int x) { if(x==0) return 0; int left = 0; int right = 65535; int mid = 32767; //std::cout << INT_MAX<<endl; while(left < right){ if(mid< x/mid )
用户6021899
2022/11/18
6020
Leetcode 题目069-求平方根
华为机试题 HJ107 求解立方根
如果输入的x>1,那么立方根一定在1到x之间,这是有序的,我们可以用二分法查找这之间三次方接近于x的值,当区间范围不超过0.0001表示找到了这个值。
ccf19881030
2023/02/26
6270
华为机试题 HJ107 求解立方根
4.2 非线性方程求解
这里主要以简单的牛顿迭代法介绍非线性方程的求解,维基百科对“牛顿迭代法”的解释:
周星星9527
2018/08/08
9390
4.2 非线性方程求解
六十八、快速幂算法、牛顿迭代法、累加数组+二分查找的变形
题目是来自Leetcode:50. Pow(x, n),https://leetcode-cn.com/problems/powx-n/
润森
2022/08/17
8290
六十八、快速幂算法、牛顿迭代法、累加数组+二分查找的变形
MATLAB非线性可视化(引2)牛顿迭代分形
牛顿迭代法是一种非常简单的求解根的方法,利用该点处导数的信息,通过每一次的迭代,使得点逐渐向解靠近。
巴山学长
2021/09/18
9960
MATLAB非线性可视化(引2)牛顿迭代分形
LeetCode 69 题
这道题很明显不是让我们调用 Math.sqrt() 方法来计算,而是自己实现一个求平方根的算法。第一反应想到的方法是暴力循环求解!从 1 开始依次往后求平方数,当平方数等于 x 时,返回 i ;当平方数大于 x 时,返回 i - 1。
Carlos Ouyang
2019/08/19
6910
LeetCode 69 题
推荐阅读
相关推荐
程序与数学:牛顿迭代法与平方根近似计算
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验