摘要: 介绍 最近在做一个基于netcore的实时消息服务。最初选用的是ASP.NET Core SignalR,但是后来发现目前它并没有支持IOS的客户端,所以自己只好又基于websocket重新搭建了一套服务。 因为前期已经使用了SignalR,所以我直接在原本的项目里面重新扩展了一套自定义websoc 阅读全文
posted @ 2018-12-03 16:03 木~木 阅读(3026) 评论(3) 推荐(5) 编辑

序言

准备写这一个系列也挺久了,但一直未动手,一方面自身积累不足,另一方面也不知从何处下手。直到最近稍微得空一些,另一方面也有一些新的体验。

在此纯粹作为自己个人的一个回顾记录吧。正所谓好记性不如烂笔头么。

总览

目前规划的整个微服务体系分为三层。

最外面一层就是Ocelot,负责路由转发,统一认证、限流熔断等。

然后第二层是各个应用服务,也可以说是聚合服务,webapi形式对外提供接口能力,支撑PC、H5、APP等。

最后面一层就是基于领域驱动划分的各个小的服务,grpc形式互相调用。

但是目前来说其实只做到第一层、第二层。有项目工期很紧的原因,但最主要还是业务场景不够熟悉。这一次才体会到抛开业务场景,谈微服务的话,有点儿耍流氓。

尤其在做微服务拆分的时候相当痛苦,没有领域专家参与,拆分过程相当痛苦,后来只能做更多的妥协。后续再专门开一篇讲一讲,回归正题了。

准备工作

我使用的是Ocelot最新版本,园子里也有关于Ocelot集成K8s的分享,但是最新的Ocelot版本,在集成k8s的过程中,还是存在一些问题的。

下面简单讲述一下具体的操作步骤了。

(1)根据Oclelot版本,引入对应的K8s Provider。我这里因为用的是最新版本的Ocelot,所以直接选用最新版的K8s Provider。

  

 

(2)在StartUp类的ConfigureService方法中添加以下代码:

 

1
2
3
services.AddOcelot()
            .AddPolly()
            .AddKubernetes();

 (3)配置文件中,配置k8s支持。在最新版中,已经不需要配置Host、Port、Token信息。只需配置好k8s服务对应的命名空间即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
  {
"ReRoutes": [
  {
    "DownstreamPathTemplate": "/api/values",
    "DownstreamScheme": "http",
    "UpstreamPathTemplate": "/values",
    "ServiceName": "testapiservice",
    "UpstreamHttpMethod": [ "Get" ]
  }
],
"GlobalConfiguration": {
  "ServiceDiscoveryProvider": {
    "Namespace": "dev",
    "Type": "kube"
  }
}

(4)ocelot中通过k8s服务名转发,具体的实现机制就是通过KubeClient这个K8s的C#语言客户端。具体信息在张队的博客中已经有介绍。因为我们的ocelot网关最终也是运行在pod中的,

在pod中通过api访问集群服务,是需要经过k8s内部认证的。我们可以通过给serviceaccount进行授权,来解决认证问题。关于k8s中的serviceaccount概念就不多展开了。

在k8s集群节点中执行以下命令:

1
kubectl create clusterrolebinding permissive-binding –clusterrole=cluster-admin –user=admin –user=kubelet –group=system:serviceaccounts

至此,本来可以开开心心的部署服务,愉快的进行路由转发了。嗯,等会儿,Unable to find service discovery provider for type: kube。嗯哼,这是个什么鬼,心态爆炸有木有!!!

解决办法

 一开始,我以为是配置问题,然后又觉着是k8s的问题。一通尝试无果,后来,通过在ocelot的issues中寻找到解决方案。原来这是ocelot最新版本的bug,通过以下扩展代码可修复。

官方也注意到这个问题,应该也会在后续的版本更新中修复掉。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
public static class OcelotBuilderExtensions
    {
        private static readonly ServiceDiscoveryFinderDelegate FixedKubernetesProviderFactoryGet = (provider, config, reroute) =>
        {
            var serviceDiscoveryProvider = KubernetesProviderFactory.Get(provider, config, reroute);
 
            if (serviceDiscoveryProvider is KubernetesServiceDiscoveryProvider)
            {
                serviceDiscoveryProvider = new Kube(serviceDiscoveryProvider);
            }
            else if (serviceDiscoveryProvider is PollKubernetes)
            {
                serviceDiscoveryProvider = new PollKube(serviceDiscoveryProvider);
            }
 
            return serviceDiscoveryProvider;
        };
 
        public static IOcelotBuilder AddKubernetesFixed(this IOcelotBuilder builder, bool usePodServiceAccount = true)
        {
            builder.Services.AddSingleton(FixedKubernetesProviderFactoryGet);
            builder.Services.AddKubeClient(usePodServiceAccount);
 
            return builder;
        }
 
        private class Kube : IServiceDiscoveryProvider
        {
            private readonly IServiceDiscoveryProvider serviceDiscoveryProvider;
 
            public Kube(IServiceDiscoveryProvider serviceDiscoveryProvider)
            {
                this.serviceDiscoveryProvider = serviceDiscoveryProvider;
            }
 
            public Task<List<Service>> Get()
            {
                return this.serviceDiscoveryProvider.Get();
            }
        }
 
        private class PollKube : IServiceDiscoveryProvider
        {
            private readonly IServiceDiscoveryProvider serviceDiscoveryProvider;
 
            public PollKube(IServiceDiscoveryProvider serviceDiscoveryProvider)
            {
                this.serviceDiscoveryProvider = serviceDiscoveryProvider;
            }
 
            public Task<List<Service>> Get()
            {
                return this.serviceDiscoveryProvider.Get();
            }
        }
    }

添加此扩展代码后,在我们上述步骤中的:AddKubernetes()  需替换成AddKubernetesFixed()

至此,终于可以在k8s中愉快的使用ocelot了。

尾声

ocelot第一阶段的工作可以说是完成了。但在整个体系中,网关还需集成认证。认证我使用的是ids4,在请求到达网关时,直接在网关层进行认证,认证通过后再转发到下游服务。

所以第二阶段是需配置ocelot集成ids4.

然后因为我的所有服务都是通过apollo来进行配置的,而且打包成镜像后,在通过修改json文件来修改配置也实在繁琐。

所以第三阶段就是ocelot使用apollo来进行配置管理。

posted @ 2020-08-02 18:08 木~木 阅读(1780) 评论(6) 推荐(1) 编辑
摘要: ## 特别特别严肃的申明 (正经的) 未免引起误解,标题已修改。 我一开始写这篇文章,也纯粹是有感而发。实在没想到会引起如此多的关注。甚至还被社区大佬翻牌。说实话,诚惶诚恐。 再次申明一遍,我写的也仅仅只是我个人的感受,我就是万万千千的普通码农中的一个,所写文章也仅仅是从自我角度出发。 不具备任何普 阅读全文
posted @ 2019-11-21 15:17 木~木 阅读(9152) 评论(94) 推荐(88) 编辑
摘要: 一、消息队列 消息队列作为分布式系统中的重要组件,常用的有MSMQ,RabbitMq,Kafa,ActiveMQ,RocketMQ。至于各种消息队列的优缺点比较,在这里就不做扩展了,网上资源很多。 更多内容可参考 消息队列及常见消息队列介绍。我在这里选用的是RabbitMq。 官网地址:http:/ 阅读全文
posted @ 2018-12-11 12:00 木~木 阅读(5702) 评论(10) 推荐(7) 编辑
摘要: 最近因工作需要,开始学习Ocelot。首先简单介绍一下,Ocelot是一个基于.net core的开源webapi 服务网关项目,目前已经支持了IdentityServer认证。根据 作者介绍,Ocelot本质上是一堆中间件的集合,当HttpRequest请求到达后由一堆中间件进行处理,处理完毕,请 阅读全文
posted @ 2017-08-29 11:19 木~木 阅读(12616) 评论(4) 推荐(3) 编辑
摘要: .net core 其实是自宿主性质的web应用程序,而不再是web网站,所以.net core是可以直接单独作为系统服务部署。但是实际情况中,为了同个一个端口能支持多个web应用和统一管理,还是应该与某个服务器整合,比如iis,Jexus。所以.net core 不再是由iis工作进程进行托管,而 阅读全文
posted @ 2017-08-27 22:19 木~木 阅读(2448) 评论(0) 推荐(0) 编辑
点击右上角即可分享
微信分享提示